144961713Sgirish /* 244961713Sgirish * CDDL HEADER START 344961713Sgirish * 444961713Sgirish * The contents of this file are subject to the terms of the 544961713Sgirish * Common Development and Distribution License (the "License"). 644961713Sgirish * You may not use this file except in compliance with the License. 744961713Sgirish * 844961713Sgirish * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 944961713Sgirish * or http://www.opensolaris.org/os/licensing. 1044961713Sgirish * See the License for the specific language governing permissions 1144961713Sgirish * and limitations under the License. 1244961713Sgirish * 1344961713Sgirish * When distributing Covered Code, include this CDDL HEADER in each 1444961713Sgirish * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1544961713Sgirish * If applicable, add the following below this CDDL HEADER, with the 1644961713Sgirish * fields enclosed by brackets "[]" replaced with your own identifying 1744961713Sgirish * information: Portions Copyright [yyyy] [name of copyright owner] 1844961713Sgirish * 1944961713Sgirish * CDDL HEADER END 2044961713Sgirish */ 2144961713Sgirish /* 2253560810Ssbehera * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 2344961713Sgirish * Use is subject to license terms. 2444961713Sgirish */ 2544961713Sgirish 2644961713Sgirish #pragma ident "%Z%%M% %I% %E% SMI" 2744961713Sgirish 2844961713Sgirish #include <sys/nxge/nxge_impl.h> 2944961713Sgirish #include <sys/nxge/nxge_mac.h> 30678453a8Sspeer #include <sys/nxge/nxge_hio.h> 3144961713Sgirish 3298ecde52Stm #define LINK_MONITOR_PERIOD (1000 * 1000) 3398ecde52Stm #define LM_WAIT_MULTIPLIER 8 3498ecde52Stm 35321febdeSsbehera #define SERDES_RDY_WT_INTERVAL 50 36321febdeSsbehera #define MAX_SERDES_RDY_RETRIES 10 37321febdeSsbehera 3800161856Syc #define TN1010_SPEED_1G 1 3900161856Syc #define TN1010_SPEED_10G 0 4000161856Syc #define TN1010_AN_IN_PROG 0 /* Auto negotiation in progress */ 4100161856Syc #define TN1010_AN_COMPLETE 1 4200161856Syc #define TN1010_AN_RSVD 2 4300161856Syc #define TN1010_AN_FAILED 3 4400161856Syc 4544961713Sgirish extern uint32_t nxge_no_link_notify; 4659ac0c16Sdavemq extern boolean_t nxge_no_msg; 4744961713Sgirish extern uint32_t nxge_lb_dbg; 4844961713Sgirish extern boolean_t nxge_jumbo_enable; 494202ea4bSsbehera extern uint32_t nxge_jumbo_mtu; 5044961713Sgirish 51678453a8Sspeer /* The following functions may be found in nxge_main.c */ 52678453a8Sspeer extern void nxge_mmac_kstat_update(p_nxge_t nxgep, mac_addr_slot_t slot, 53678453a8Sspeer boolean_t factory); 54678453a8Sspeer extern int nxge_m_mmac_add(void *arg, mac_multi_addr_t *maddr); 55678453a8Sspeer extern int nxge_m_mmac_remove(void *arg, mac_addr_slot_t slot); 56678453a8Sspeer 5798ecde52Stm typedef enum { 5898ecde52Stm CHECK_LINK_RESCHEDULE, 5998ecde52Stm CHECK_LINK_STOP 6098ecde52Stm } check_link_state_t; 6198ecde52Stm 6298ecde52Stm static check_link_state_t nxge_check_link_stop(nxge_t *); 6398ecde52Stm 6444961713Sgirish /* 6544961713Sgirish * Ethernet broadcast address definition. 6644961713Sgirish */ 6744961713Sgirish static ether_addr_st etherbroadcastaddr = 6844961713Sgirish {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}; 6959ac0c16Sdavemq /* 7059ac0c16Sdavemq * Ethernet zero address definition. 7159ac0c16Sdavemq */ 7256d930aeSspeer static ether_addr_st etherzeroaddr = 7356d930aeSspeer {{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; 7459ac0c16Sdavemq /* 7559ac0c16Sdavemq * Supported chip types 7659ac0c16Sdavemq */ 7752cdd236Ssbehera static uint32_t nxge_supported_cl45_ids[] = { 7852cdd236Ssbehera BCM8704_DEV_ID, 7952cdd236Ssbehera MARVELL_88X_201X_DEV_ID, 8000161856Syc BCM8706_DEV_ID, 8100161856Syc TN1010_DEV_ID 8252cdd236Ssbehera }; 8352cdd236Ssbehera 84*b1000363Sml static uint32_t nxge_supported_cl22_ids[] = { 85*b1000363Sml BCM5464R_PHY_ID, 86*b1000363Sml BCM5482_PHY_ID 87*b1000363Sml }; 8859ac0c16Sdavemq 8959ac0c16Sdavemq #define NUM_CLAUSE_45_IDS (sizeof (nxge_supported_cl45_ids) / \ 9059ac0c16Sdavemq sizeof (uint32_t)) 9159ac0c16Sdavemq #define NUM_CLAUSE_22_IDS (sizeof (nxge_supported_cl22_ids) / \ 9259ac0c16Sdavemq sizeof (uint32_t)) 9359ac0c16Sdavemq /* 9459ac0c16Sdavemq * static functions 9559ac0c16Sdavemq */ 962e59129aSraghus static uint32_t nxge_get_cl45_pma_pmd_id(p_nxge_t, int); 972e59129aSraghus static uint32_t nxge_get_cl45_pcs_id(p_nxge_t, int); 982e59129aSraghus static uint32_t nxge_get_cl22_phy_id(p_nxge_t, int); 9959ac0c16Sdavemq static boolean_t nxge_is_supported_phy(uint32_t, uint8_t); 1002d17280bSsbehera static boolean_t nxge_is_phy_present(p_nxge_t, int, uint32_t, uint32_t); 10159ac0c16Sdavemq static nxge_status_t nxge_n2_serdes_init(p_nxge_t); 10259ac0c16Sdavemq static nxge_status_t nxge_neptune_10G_serdes_init(p_nxge_t); 10359ac0c16Sdavemq static nxge_status_t nxge_1G_serdes_init(p_nxge_t); 10459ac0c16Sdavemq static nxge_status_t nxge_10G_link_intr_stop(p_nxge_t); 10559ac0c16Sdavemq static nxge_status_t nxge_10G_link_intr_start(p_nxge_t); 10659ac0c16Sdavemq static nxge_status_t nxge_1G_copper_link_intr_stop(p_nxge_t); 10759ac0c16Sdavemq static nxge_status_t nxge_1G_copper_link_intr_start(p_nxge_t); 10859ac0c16Sdavemq static nxge_status_t nxge_1G_fiber_link_intr_stop(p_nxge_t); 10959ac0c16Sdavemq static nxge_status_t nxge_1G_fiber_link_intr_start(p_nxge_t); 11059ac0c16Sdavemq static nxge_status_t nxge_check_mii_link(p_nxge_t); 11159ac0c16Sdavemq static nxge_status_t nxge_check_10g_link(p_nxge_t); 11259ac0c16Sdavemq static nxge_status_t nxge_10G_xcvr_init(p_nxge_t); 1132d17280bSsbehera static nxge_status_t nxge_BCM8704_xcvr_init(p_nxge_t); 1142d17280bSsbehera static nxge_status_t nxge_BCM8706_xcvr_init(p_nxge_t); 11559ac0c16Sdavemq static nxge_status_t nxge_1G_xcvr_init(p_nxge_t); 11659ac0c16Sdavemq static void nxge_bcm5464_link_led_off(p_nxge_t); 11700161856Syc static nxge_status_t nxge_check_mrvl88x2011_link(p_nxge_t, boolean_t *); 11852cdd236Ssbehera static nxge_status_t nxge_mrvl88x2011_xcvr_init(p_nxge_t); 11900161856Syc static nxge_status_t nxge_get_num_of_xaui(uint32_t *port_pma_pmd_dev_id, 12000161856Syc uint32_t *port_pcs_dev_id, uint32_t *port_phy_id, uint8_t *num_xaui); 12100161856Syc static nxge_status_t nxge_get_tn1010_speed(p_nxge_t nxgep, uint16_t *speed); 12200161856Syc static nxge_status_t nxge_set_tn1010_param(p_nxge_t nxgep); 12300161856Syc static nxge_status_t nxge_tn1010_check(p_nxge_t nxgep, 12400161856Syc nxge_link_state_t *link_up); 12500161856Syc static boolean_t nxge_is_tn1010_phy(p_nxge_t nxgep); 12600161856Syc static nxge_status_t nxge_tn1010_xcvr_init(p_nxge_t nxgep); 12700161856Syc 12800161856Syc nxge_status_t nxge_mac_init(p_nxge_t); 12900161856Syc static nxge_status_t nxge_mii_get_link_mode(p_nxge_t); 13000161856Syc 13100161856Syc #ifdef NXGE_DEBUG 13200161856Syc static void nxge_mii_dump(p_nxge_t); 13300161856Syc static nxge_status_t nxge_tn1010_reset(p_nxge_t nxgep); 13400161856Syc static void nxge_dump_tn1010_status_regs(p_nxge_t nxgep); 13500161856Syc #endif 13659ac0c16Sdavemq 13759ac0c16Sdavemq /* 13859ac0c16Sdavemq * xcvr tables for supported transceivers 13959ac0c16Sdavemq */ 14059ac0c16Sdavemq 14100161856Syc /* 14200161856Syc * nxge_n2_10G_table is for 10G fiber or serdes on N2-NIU systems. 14300161856Syc * The Teranetics TN1010 based copper XAUI card can also be used 14400161856Syc * on N2-NIU systems in 10G mode, but it uses its own table 14500161856Syc * nxge_n2_10G_tn1010_table below. 14600161856Syc */ 1472e59129aSraghus static nxge_xcvr_table_t nxge_n2_10G_table = { 14859ac0c16Sdavemq nxge_n2_serdes_init, 14959ac0c16Sdavemq nxge_10G_xcvr_init, 15059ac0c16Sdavemq nxge_10G_link_intr_stop, 15159ac0c16Sdavemq nxge_10G_link_intr_start, 15259ac0c16Sdavemq nxge_check_10g_link, 1532d17280bSsbehera PCS_XCVR 15459ac0c16Sdavemq }; 15559ac0c16Sdavemq 15600161856Syc /* 15700161856Syc * For the Teranetics TN1010 based copper XAUI card 15800161856Syc */ 15900161856Syc static nxge_xcvr_table_t nxge_n2_10G_tn1010_table = { 16000161856Syc nxge_n2_serdes_init, /* Handle both 1G and 10G */ 16100161856Syc nxge_tn1010_xcvr_init, /* Handle both 1G and 10G */ 16200161856Syc nxge_10G_link_intr_stop, 16300161856Syc nxge_10G_link_intr_start, 16400161856Syc nxge_check_tn1010_link, /* Will figure out speed */ 16500161856Syc XPCS_XCVR 16600161856Syc }; 16700161856Syc 1682e59129aSraghus static nxge_xcvr_table_t nxge_n2_1G_table = { 1692e59129aSraghus nxge_n2_serdes_init, 1702e59129aSraghus nxge_1G_xcvr_init, 1712e59129aSraghus nxge_1G_fiber_link_intr_stop, 1722e59129aSraghus nxge_1G_fiber_link_intr_start, 1732e59129aSraghus nxge_check_mii_link, 1742d17280bSsbehera PCS_XCVR 1752e59129aSraghus }; 1762e59129aSraghus 17700161856Syc static nxge_xcvr_table_t nxge_n2_1G_tn1010_table = { 17800161856Syc nxge_n2_serdes_init, 17900161856Syc nxge_tn1010_xcvr_init, 18000161856Syc nxge_1G_fiber_link_intr_stop, /* TN1010 is a Cu PHY, but it uses */ 18100161856Syc nxge_1G_fiber_link_intr_start, /* PCS for 1G, so call fiber func */ 18200161856Syc nxge_check_tn1010_link, 18300161856Syc PCS_XCVR 18400161856Syc }; 18500161856Syc 18600161856Syc static nxge_xcvr_table_t nxge_10G_tn1010_table = { 18700161856Syc nxge_neptune_10G_serdes_init, 18800161856Syc nxge_tn1010_xcvr_init, 18900161856Syc nxge_10G_link_intr_stop, 19000161856Syc nxge_10G_link_intr_start, 19100161856Syc nxge_check_tn1010_link, 19200161856Syc XPCS_XCVR 19300161856Syc }; 19400161856Syc 19500161856Syc static nxge_xcvr_table_t nxge_1G_tn1010_table = { 19600161856Syc nxge_1G_serdes_init, 19700161856Syc nxge_tn1010_xcvr_init, 19800161856Syc nxge_1G_fiber_link_intr_stop, 19900161856Syc nxge_1G_fiber_link_intr_start, 20000161856Syc nxge_check_tn1010_link, 20100161856Syc PCS_XCVR 20200161856Syc }; 20300161856Syc 20459ac0c16Sdavemq static nxge_xcvr_table_t nxge_10G_fiber_table = { 20559ac0c16Sdavemq nxge_neptune_10G_serdes_init, 20659ac0c16Sdavemq nxge_10G_xcvr_init, 20759ac0c16Sdavemq nxge_10G_link_intr_stop, 20859ac0c16Sdavemq nxge_10G_link_intr_start, 20959ac0c16Sdavemq nxge_check_10g_link, 2102d17280bSsbehera PCS_XCVR 21159ac0c16Sdavemq }; 21259ac0c16Sdavemq 21359ac0c16Sdavemq static nxge_xcvr_table_t nxge_1G_copper_table = { 21459ac0c16Sdavemq NULL, 21559ac0c16Sdavemq nxge_1G_xcvr_init, 21659ac0c16Sdavemq nxge_1G_copper_link_intr_stop, 21759ac0c16Sdavemq nxge_1G_copper_link_intr_start, 21859ac0c16Sdavemq nxge_check_mii_link, 2192d17280bSsbehera INT_MII_XCVR 22059ac0c16Sdavemq }; 22159ac0c16Sdavemq 22200161856Syc /* This table is for Neptune portmode == PORT_1G_SERDES cases */ 22359ac0c16Sdavemq static nxge_xcvr_table_t nxge_1G_fiber_table = { 22459ac0c16Sdavemq nxge_1G_serdes_init, 22559ac0c16Sdavemq nxge_1G_xcvr_init, 22659ac0c16Sdavemq nxge_1G_fiber_link_intr_stop, 22759ac0c16Sdavemq nxge_1G_fiber_link_intr_start, 22859ac0c16Sdavemq nxge_check_mii_link, 2292d17280bSsbehera PCS_XCVR 23059ac0c16Sdavemq }; 23159ac0c16Sdavemq 23259ac0c16Sdavemq static nxge_xcvr_table_t nxge_10G_copper_table = { 23359ac0c16Sdavemq nxge_neptune_10G_serdes_init, 23459ac0c16Sdavemq NULL, 23559ac0c16Sdavemq NULL, 23659ac0c16Sdavemq NULL, 2372e59129aSraghus NULL, 2382d17280bSsbehera PCS_XCVR 23959ac0c16Sdavemq }; 24044961713Sgirish 24100161856Syc /* 24200161856Syc * NXGE_PORT_TN1010 is defined as, 24300161856Syc * NXGE_PORT_SPD_NONE | (NXGE_PHY_TN1010 << NXGE_PHY_SHIFT) 24400161856Syc * = 0 | 5 << 16 = 0x50000 24500161856Syc * 24600161856Syc * So NEPTUNE_2_TN1010 = 24700161856Syc * (NXGE_PORT_TN1010 | 24800161856Syc * (NXGE_PORT_TN1010 << 4) | 24900161856Syc * (NXGE_PORT_NONE << 8) | 25000161856Syc * (NXGE_PORT_NONE << 12)), 25100161856Syc * = 0x50000 | (0x50000 << 4) 25200161856Syc * = 0x550000 25300161856Syc * 25400161856Syc * This function partitions nxgep->nxge_hw_p->niu_type (which may have 25500161856Syc * value NEPTUNE_2_TN1010) and checks if a port has type = NXGE_PORT_TN1010 25600161856Syc * = 0x50000 25700161856Syc */ 25800161856Syc static boolean_t nxge_is_tn1010_phy(p_nxge_t nxgep) 25900161856Syc { 26000161856Syc uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 26100161856Syc 26200161856Syc if (((nxgep->nxge_hw_p->niu_type >> (NXGE_PORT_TYPE_SHIFT * portn)) 26300161856Syc & NXGE_PHY_MASK) == NXGE_PORT_TN1010) { 26400161856Syc return (B_TRUE); 26500161856Syc } else { 26600161856Syc return (B_FALSE); 26700161856Syc } 26800161856Syc } 26944961713Sgirish 270d81011f0Ssbehera 27100161856Syc /* 27200161856Syc * Figure out nxgep->mac.portmode from nxge.conf, OBP's device properties, 27300161856Syc * serial EEPROM or VPD if possible. Note that not all systems could get 27400161856Syc * the portmode information by calling this function. For example, the 27500161856Syc * Maramba system figures out the portmode information by calling function 27600161856Syc * nxge_setup_xcvr_table. 27700161856Syc */ 2782e59129aSraghus nxge_status_t 2792e59129aSraghus nxge_get_xcvr_type(p_nxge_t nxgep) 2802e59129aSraghus { 2812e59129aSraghus nxge_status_t status = NXGE_OK; 2822e59129aSraghus char *phy_type; 2832e59129aSraghus char *prop_val; 28400161856Syc uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 2852e59129aSraghus 2862e59129aSraghus nxgep->mac.portmode = 0; 2872d17280bSsbehera nxgep->xcvr_addr = 0; 2882e59129aSraghus 2892d17280bSsbehera /* 2902d17280bSsbehera * First check for hot swappable phy property. 2912d17280bSsbehera */ 2922d17280bSsbehera if (nxgep->hot_swappable_phy == B_TRUE) { 2932d17280bSsbehera nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR; 2942d17280bSsbehera nxgep->mac.portmode = PORT_HSP_MODE; 2952d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Other: Hot Swappable")); 2962d17280bSsbehera } else if (ddi_prop_exists(DDI_DEV_T_ANY, nxgep->dip, 2972d17280bSsbehera DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 2982d17280bSsbehera "hot-swappable-phy") == 1) { 2992d17280bSsbehera nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR; 3002d17280bSsbehera nxgep->mac.portmode = PORT_HSP_MODE; 3012d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, ".conf: Hot Swappable")); 3022d17280bSsbehera } else if (nxgep->niu_type == N2_NIU && 3032d17280bSsbehera ddi_prop_exists(DDI_DEV_T_ANY, nxgep->dip, 0, 3042d17280bSsbehera "hot-swappable-phy") == 1) { 3052d17280bSsbehera nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR; 3062d17280bSsbehera nxgep->mac.portmode = PORT_HSP_MODE; 3072d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "OBP: Hot Swappable")); 3082d17280bSsbehera } 3092d17280bSsbehera 3102d17280bSsbehera /* 3112d17280bSsbehera * MDIO polling support for Monza RTM card, Goa NEM card 3122d17280bSsbehera */ 3132d17280bSsbehera if (nxgep->mac.portmode == PORT_HSP_MODE) { 3142d17280bSsbehera nxgep->hot_swappable_phy = B_TRUE; 3152d17280bSsbehera /* 3162d17280bSsbehera * If this is the 2nd NIU port, then check 2 addresses 3172d17280bSsbehera * to take care of the Goa NEM card. Port 1 can have addr 17 3182d17280bSsbehera * (in the eval board) or 20 (in the P0 board). 3192d17280bSsbehera */ 3202d17280bSsbehera if (portn == 1) { 3212d17280bSsbehera if (nxge_is_phy_present(nxgep, 32200161856Syc ALT_GOA_CLAUSE45_PORT1_ADDR, BCM8706_DEV_ID, 3232d17280bSsbehera BCM_PHY_ID_MASK)) { 3242d17280bSsbehera nxgep->xcvr_addr = 32500161856Syc ALT_GOA_CLAUSE45_PORT1_ADDR; 3262d17280bSsbehera goto found_phy; 3272d17280bSsbehera } 3282d17280bSsbehera } 3292d17280bSsbehera if (nxge_is_phy_present(nxgep, 33000161856Syc GOA_CLAUSE45_PORT_ADDR_BASE + portn, 3312d17280bSsbehera BCM8706_DEV_ID, BCM_PHY_ID_MASK)) { 33200161856Syc nxgep->xcvr_addr = GOA_CLAUSE45_PORT_ADDR_BASE + 3332d17280bSsbehera portn; 3342d17280bSsbehera goto found_phy; 3352d17280bSsbehera } 3362d17280bSsbehera 3372d17280bSsbehera nxgep->phy_absent = B_TRUE; 3382d17280bSsbehera goto check_phy_done; 3392d17280bSsbehera found_phy: 3402d17280bSsbehera nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 3412d17280bSsbehera nxgep->mac.portmode = PORT_10G_FIBER; 3422d17280bSsbehera nxgep->phy_absent = B_FALSE; 3432d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Fiber Xcvr " 3442d17280bSsbehera "found for hot swappable phy")); 3452d17280bSsbehera check_phy_done: 3462d17280bSsbehera return (status); 3472d17280bSsbehera } 3482d17280bSsbehera 34900161856Syc /* Get phy-type property (May have been set by nxge.conf) */ 3502e59129aSraghus if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip, 3512e59129aSraghus DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 3522e59129aSraghus "phy-type", &prop_val)) == DDI_PROP_SUCCESS) { 3532e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3542e59129aSraghus "found conf file: phy-type %s", prop_val)); 3552e59129aSraghus if (strcmp("xgsd", prop_val) == 0) { 3562e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 3572e59129aSraghus nxgep->mac.portmode = PORT_10G_SERDES; 3582e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3592e59129aSraghus "found: 10G Serdes")); 3602e59129aSraghus } else if (strcmp("gsd", prop_val) == 0) { 3612e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 3622e59129aSraghus nxgep->mac.portmode = PORT_1G_SERDES; 3632e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Serdes")); 3642e59129aSraghus } else if (strcmp("mif", prop_val) == 0) { 3652e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR; 3662e59129aSraghus nxgep->mac.portmode = PORT_1G_COPPER; 3672e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Copper Xcvr")); 3682e59129aSraghus } else if (strcmp("pcs", prop_val) == 0) { 3692e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 3702e59129aSraghus nxgep->mac.portmode = PORT_1G_FIBER; 3712e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G FIBER Xcvr")); 372321febdeSsbehera } else if (strcmp("xgf", prop_val) == 0) { 37300161856Syc /* 37400161856Syc * Before OBP supports new phy-type property 37500161856Syc * value "xgc", the 10G copper XAUI may carry 37600161856Syc * "xgf" instead of "xgc". If the OBP is 37700161856Syc * upgraded to a newer version which supports 37800161856Syc * "xgc", then the TN1010 related code in this 37900161856Syc * "xgf" case will not be used anymore. 38000161856Syc */ 38100161856Syc if (nxge_is_tn1010_phy(nxgep)) { 38200161856Syc if ((status = nxge_set_tn1010_param(nxgep)) 38300161856Syc != NXGE_OK) { 38400161856Syc return (status); 38500161856Syc } 38600161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, "TN1010 Xcvr")); 38700161856Syc } else { /* For Fiber XAUI */ 38800161856Syc nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 38900161856Syc nxgep->mac.portmode = PORT_10G_FIBER; 39000161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 39100161856Syc "10G Fiber Xcvr")); 39200161856Syc } 39300161856Syc } else if (strcmp("xgc", prop_val) == 0) { 39400161856Syc if ((status = nxge_set_tn1010_param(nxgep)) != NXGE_OK) 39500161856Syc return (status); 39600161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, "TN1010 Xcvr")); 3972e59129aSraghus } 3982e59129aSraghus 3992e59129aSraghus (void) ddi_prop_update_string(DDI_DEV_T_NONE, nxgep->dip, 4002e59129aSraghus "phy-type", prop_val); 4012e59129aSraghus ddi_prop_free(prop_val); 4022e59129aSraghus 4032e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: " 4042e59129aSraghus "Got phy type [0x%x] from conf file", 4052e59129aSraghus nxgep->mac.portmode)); 4062e59129aSraghus 4072e59129aSraghus return (NXGE_OK); 4082e59129aSraghus } 4092d17280bSsbehera 4102d17280bSsbehera /* Get phy-type property from OBP */ 4112e59129aSraghus if (nxgep->niu_type == N2_NIU) { 4122e59129aSraghus if (ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip, 0, 4132e59129aSraghus "phy-type", &prop_val) == DDI_PROP_SUCCESS) { 4142e59129aSraghus if (strcmp("xgf", prop_val) == 0) { 41500161856Syc /* 41600161856Syc * Before OBP supports new phy-type property 41700161856Syc * value "xgc", the 10G copper XAUI may carry 41800161856Syc * "xgf" instead of "xgc". If the OBP is 41900161856Syc * upgraded to a newer version which supports 42000161856Syc * "xgc", then the TN1010 related code in this 42100161856Syc * "xgf" case will not be used anymore. 42200161856Syc */ 42300161856Syc if (nxge_is_tn1010_phy(nxgep)) { 42400161856Syc if ((status = 42500161856Syc nxge_set_tn1010_param(nxgep)) 42600161856Syc != NXGE_OK) { 42700161856Syc return (status); 42800161856Syc } 42900161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 43000161856Syc "TN1010 Xcvr")); 43100161856Syc } else { /* For Fiber XAUI */ 43200161856Syc nxgep->statsp->mac_stats.xcvr_inuse 43300161856Syc = XPCS_XCVR; 43400161856Syc nxgep->mac.portmode = PORT_10G_FIBER; 43500161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 43600161856Syc "10G Fiber Xcvr")); 43700161856Syc } 4382e59129aSraghus } else if (strcmp("mif", prop_val) == 0) { 4392e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = 4402e59129aSraghus INT_MII_XCVR; 4412e59129aSraghus nxgep->mac.portmode = PORT_1G_COPPER; 4422e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4432e59129aSraghus "1G Copper Xcvr")); 4442e59129aSraghus } else if (strcmp("pcs", prop_val) == 0) { 4452e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 4462e59129aSraghus nxgep->mac.portmode = PORT_1G_FIBER; 4472e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4482e59129aSraghus "1G Fiber Xcvr")); 4492e59129aSraghus } else if (strcmp("xgc", prop_val) == 0) { 45000161856Syc status = nxge_set_tn1010_param(nxgep); 45100161856Syc if (status != NXGE_OK) 45200161856Syc return (status); 45300161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, "TN1010 Xcvr")); 4542e59129aSraghus } else if (strcmp("xgsd", prop_val) == 0) { 4552e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 4562e59129aSraghus nxgep->mac.portmode = PORT_10G_SERDES; 4572e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4582e59129aSraghus "OBP: 10G Serdes")); 4592e59129aSraghus } else if (strcmp("gsd", prop_val) == 0) { 4602e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 4612e59129aSraghus nxgep->mac.portmode = PORT_1G_SERDES; 4622e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4632e59129aSraghus "OBP: 1G Serdes")); 4642e59129aSraghus } else { 4652e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4662e59129aSraghus "Unknown phy-type: %s", prop_val)); 4672e59129aSraghus ddi_prop_free(prop_val); 4682e59129aSraghus return (NXGE_ERROR); 4692e59129aSraghus } 4702e59129aSraghus status = NXGE_OK; 4712e59129aSraghus (void) ddi_prop_update_string(DDI_DEV_T_NONE, 4722e59129aSraghus nxgep->dip, "phy-type", prop_val); 4732e59129aSraghus ddi_prop_free(prop_val); 4742e59129aSraghus 4752e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: " 4762e59129aSraghus "Got phy type [0x%x] from OBP", 4772e59129aSraghus nxgep->mac.portmode)); 4782e59129aSraghus 4792e59129aSraghus return (status); 4802e59129aSraghus } else { 4812e59129aSraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4822e59129aSraghus "Exiting...phy-type property not found")); 4832e59129aSraghus return (NXGE_ERROR); 4842e59129aSraghus } 4852e59129aSraghus } 4862e59129aSraghus 4872e59129aSraghus 4882e59129aSraghus if (!nxgep->vpd_info.present) { 4892e59129aSraghus return (NXGE_OK); 4902e59129aSraghus } 4912e59129aSraghus 4922e59129aSraghus if (!nxgep->vpd_info.ver_valid) { 4932e59129aSraghus goto read_seeprom; 4942e59129aSraghus } 4952e59129aSraghus 4962e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4972e59129aSraghus "Reading phy type from expansion ROM")); 4982e59129aSraghus /* 4992e59129aSraghus * Try to read the phy type from the vpd data read off the 5002e59129aSraghus * expansion ROM. 5012e59129aSraghus */ 5022e59129aSraghus phy_type = nxgep->vpd_info.phy_type; 5032e59129aSraghus 504d81011f0Ssbehera if (strncmp(phy_type, "mif", 3) == 0) { 5052e59129aSraghus nxgep->mac.portmode = PORT_1G_COPPER; 5062e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR; 507d81011f0Ssbehera } else if (strncmp(phy_type, "xgf", 3) == 0) { 5082e59129aSraghus nxgep->mac.portmode = PORT_10G_FIBER; 5092e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 510d81011f0Ssbehera } else if (strncmp(phy_type, "pcs", 3) == 0) { 5112e59129aSraghus nxgep->mac.portmode = PORT_1G_FIBER; 5122e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 513d81011f0Ssbehera } else if (strncmp(phy_type, "xgc", 3) == 0) { 51400161856Syc status = nxge_set_tn1010_param(nxgep); 51500161856Syc if (status != NXGE_OK) { 51600161856Syc NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 51700161856Syc "nxge_get_xcvr_type: Failed to set TN1010 param")); 51800161856Syc goto read_seeprom; 51900161856Syc } 520d81011f0Ssbehera } else if (strncmp(phy_type, "xgsd", 4) == 0) { 521d81011f0Ssbehera nxgep->mac.portmode = PORT_10G_SERDES; 522d81011f0Ssbehera nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 523d81011f0Ssbehera } else if (strncmp(phy_type, "gsd", 3) == 0) { 524d81011f0Ssbehera nxgep->mac.portmode = PORT_1G_SERDES; 525d81011f0Ssbehera nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 5262e59129aSraghus } else { 527d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5282e59129aSraghus "nxge_get_xcvr_type: Unknown phy type [%c%c%c] in EEPROM", 5292e59129aSraghus phy_type[0], phy_type[1], phy_type[2])); 5302e59129aSraghus goto read_seeprom; 5312e59129aSraghus } 5322e59129aSraghus 5332e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: " 5342e59129aSraghus "Got phy type [0x%x] from VPD", nxgep->mac.portmode)); 5352e59129aSraghus 5362e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_get_xcvr_type")); 5372e59129aSraghus return (status); 5382e59129aSraghus 5392e59129aSraghus read_seeprom: 5402e59129aSraghus /* 5412e59129aSraghus * read the phy type from the SEEPROM - NCR registers 5422e59129aSraghus */ 5432e59129aSraghus status = nxge_espc_phy_type_get(nxgep); 5442e59129aSraghus if (status != NXGE_OK) { 5452e59129aSraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5462e59129aSraghus "Failed to get phy type")); 5472e59129aSraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "EEPROM version " 5482e59129aSraghus "[%s] invalid...please update", nxgep->vpd_info.ver)); 5492e59129aSraghus } 5502e59129aSraghus 5512e59129aSraghus return (status); 5522e59129aSraghus 5532e59129aSraghus } 5542e59129aSraghus 55559ac0c16Sdavemq /* Set up the PHY specific values. */ 55659ac0c16Sdavemq 55759ac0c16Sdavemq nxge_status_t 55859ac0c16Sdavemq nxge_setup_xcvr_table(p_nxge_t nxgep) 55959ac0c16Sdavemq { 56059ac0c16Sdavemq nxge_status_t status = NXGE_OK; 56159ac0c16Sdavemq uint32_t port_type; 56259ac0c16Sdavemq uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 5632e59129aSraghus uint32_t pcs_id = 0; 5642e59129aSraghus uint32_t pma_pmd_id = 0; 5652e59129aSraghus uint32_t phy_id = 0; 5662d17280bSsbehera uint16_t chip_id = 0; 56759ac0c16Sdavemq 56859ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_setup_xcvr_table: port<%d>", 56959ac0c16Sdavemq portn)); 57059ac0c16Sdavemq 5712e59129aSraghus switch (nxgep->niu_type) { 5722e59129aSraghus case N2_NIU: 5732e59129aSraghus switch (nxgep->mac.portmode) { 5742e59129aSraghus case PORT_1G_FIBER: 5752e59129aSraghus case PORT_1G_SERDES: 5762e59129aSraghus nxgep->xcvr = nxge_n2_1G_table; 5772d17280bSsbehera nxgep->xcvr_addr = portn; 5782e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 1G %s Xcvr", 5792e59129aSraghus (nxgep->mac.portmode == PORT_1G_FIBER) ? "Fiber" : 5802e59129aSraghus "Serdes")); 5812e59129aSraghus break; 5822e59129aSraghus case PORT_10G_FIBER: 5832e59129aSraghus case PORT_10G_SERDES: 5842e59129aSraghus nxgep->xcvr = nxge_n2_10G_table; 5852d17280bSsbehera if (nxgep->nxge_hw_p->xcvr_addr[portn]) { 5862d17280bSsbehera nxgep->xcvr_addr = 5872d17280bSsbehera nxgep->nxge_hw_p->xcvr_addr[portn]; 5882d17280bSsbehera } 5892e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 10G %s Xcvr", 5902e59129aSraghus (nxgep->mac.portmode == PORT_10G_FIBER) ? "Fiber" : 5912e59129aSraghus "Serdes")); 5922e59129aSraghus break; 59300161856Syc case PORT_1G_TN1010: 59400161856Syc nxgep->xcvr = nxge_n2_1G_tn1010_table; 59500161856Syc nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 59600161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 59700161856Syc "TN1010 Copper Xcvr in 1G")); 59800161856Syc break; 59900161856Syc case PORT_10G_TN1010: 60000161856Syc nxgep->xcvr = nxge_n2_10G_tn1010_table; 60100161856Syc nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 60200161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 60300161856Syc "TN1010 Copper Xcvr in 10G")); 60400161856Syc break; 6052d17280bSsbehera case PORT_HSP_MODE: 6062d17280bSsbehera nxgep->xcvr = nxge_n2_10G_table; 6072d17280bSsbehera nxgep->xcvr.xcvr_inuse = HSP_XCVR; 6082d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 10G Hot " 6092d17280bSsbehera "Swappable Xcvr (not present)")); 6102d17280bSsbehera break; 6112e59129aSraghus default: 6122e59129aSraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6132e59129aSraghus "<== nxge_setup_xcvr_table: " 6142e59129aSraghus "Unable to determine NIU portmode")); 6152e59129aSraghus return (NXGE_ERROR); 6162e59129aSraghus } 6172e59129aSraghus break; 6182e59129aSraghus default: 6192e59129aSraghus if (nxgep->mac.portmode == 0) { 6202e59129aSraghus /* 6212e59129aSraghus * Would be the case for platforms like Maramba 6222e59129aSraghus * in which the phy type could not be got from conf 6232e59129aSraghus * file, OBP, VPD or Serial PROM. 6242e59129aSraghus */ 6252e59129aSraghus if (!NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) { 6262e59129aSraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6272e59129aSraghus "<== nxge_setup_xcvr_table:" 6282e59129aSraghus " Invalid Neptune type [0x%x]", 6292e59129aSraghus nxgep->niu_type)); 6302e59129aSraghus return (NXGE_ERROR); 6312e59129aSraghus } 6322e59129aSraghus 6332e59129aSraghus port_type = nxgep->niu_type >> 6342e59129aSraghus (NXGE_PORT_TYPE_SHIFT * portn); 6352e59129aSraghus port_type = port_type & (NXGE_PORT_TYPE_MASK); 6362e59129aSraghus 6372e59129aSraghus switch (port_type) { 6382e59129aSraghus 6392e59129aSraghus case NXGE_PORT_1G_COPPER: 6402e59129aSraghus nxgep->mac.portmode = PORT_1G_COPPER; 6412e59129aSraghus break; 6422e59129aSraghus case NXGE_PORT_10G_COPPER: 6432e59129aSraghus nxgep->mac.portmode = PORT_10G_COPPER; 6442e59129aSraghus break; 6452e59129aSraghus case NXGE_PORT_1G_FIBRE: 6462e59129aSraghus nxgep->mac.portmode = PORT_1G_FIBER; 6472e59129aSraghus break; 6482e59129aSraghus case NXGE_PORT_10G_FIBRE: 6492e59129aSraghus nxgep->mac.portmode = PORT_10G_FIBER; 6502e59129aSraghus break; 6512e59129aSraghus case NXGE_PORT_1G_SERDES: 6522e59129aSraghus nxgep->mac.portmode = PORT_1G_SERDES; 6532e59129aSraghus break; 6542e59129aSraghus case NXGE_PORT_10G_SERDES: 6552e59129aSraghus nxgep->mac.portmode = PORT_10G_SERDES; 6562e59129aSraghus break; 65700161856Syc /* Ports 2 and 3 of Alonso or ARTM */ 6582e59129aSraghus case NXGE_PORT_1G_RGMII_FIBER: 6592e59129aSraghus nxgep->mac.portmode = PORT_1G_RGMII_FIBER; 6602e59129aSraghus break; 66100161856Syc case NXGE_PORT_TN1010: 66200161856Syc /* 66300161856Syc * If this port uses the TN1010 copper 66400161856Syc * PHY, then its speed is not known yet 66500161856Syc * because nxge_scan_ports_phy could only 66600161856Syc * figure out the vendor of the PHY but 66700161856Syc * not its speed. nxge_set_tn1010_param 66800161856Syc * will read the PHY speed and set 66900161856Syc * portmode accordingly. 67000161856Syc */ 67100161856Syc if ((status = nxge_set_tn1010_param(nxgep)) 67200161856Syc != NXGE_OK) { 67300161856Syc NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 67400161856Syc "nxge_set_tn1010_param failed")); 67500161856Syc return (status); 67600161856Syc } 67700161856Syc break; 6782e59129aSraghus default: 6792e59129aSraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6802e59129aSraghus "<== nxge_setup_xcvr_table: " 6812e59129aSraghus "Unknown port-type: 0x%x", port_type)); 6822e59129aSraghus return (NXGE_ERROR); 6832e59129aSraghus } 6842e59129aSraghus } 6852e59129aSraghus 68600161856Syc /* 68700161856Syc * Above switch has figured out nxge->mac.portmode, now set 68800161856Syc * nxgep->xcvr (the table) and nxgep->xcvr_addr according 68900161856Syc * to portmode. 69000161856Syc */ 6912e59129aSraghus switch (nxgep->mac.portmode) { 6922e59129aSraghus case PORT_1G_COPPER: 6932e59129aSraghus case PORT_1G_RGMII_FIBER: 69459ac0c16Sdavemq nxgep->xcvr = nxge_1G_copper_table; 6952d17280bSsbehera nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 69659ac0c16Sdavemq /* 69759ac0c16Sdavemq * For Altas 4-1G copper, Xcvr port numbers are 69859ac0c16Sdavemq * swapped with ethernet port number. This is 6992e59129aSraghus * designed for better signal integrity in 7002e59129aSraghus * routing. This is also the case for the 7012e59129aSraghus * on-board Neptune copper ports on the Maramba 7022e59129aSraghus * platform. 70359ac0c16Sdavemq */ 7042e59129aSraghus switch (nxgep->platform_type) { 7052e59129aSraghus case P_NEPTUNE_ATLAS_4PORT: 7062e59129aSraghus case P_NEPTUNE_MARAMBA_P0: 7072e59129aSraghus case P_NEPTUNE_MARAMBA_P1: 7082e59129aSraghus switch (portn) { 7092e59129aSraghus case 0: 7102d17280bSsbehera nxgep->xcvr_addr += 3; 7112e59129aSraghus break; 7122e59129aSraghus case 1: 7132d17280bSsbehera nxgep->xcvr_addr += 1; 7142e59129aSraghus break; 7152e59129aSraghus case 2: 7162d17280bSsbehera nxgep->xcvr_addr -= 1; 7172e59129aSraghus break; 7182e59129aSraghus case 3: 7192d17280bSsbehera nxgep->xcvr_addr -= 3; 7202e59129aSraghus break; 7212e59129aSraghus default: 7222e59129aSraghus return (NXGE_ERROR); 7232e59129aSraghus } 72459ac0c16Sdavemq break; 72559ac0c16Sdavemq default: 7262e59129aSraghus break; 72759ac0c16Sdavemq } 728d81011f0Ssbehera 7292e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G %s Xcvr", 7302e59129aSraghus (nxgep->mac.portmode == PORT_1G_COPPER) ? 7312e59129aSraghus "Copper" : "RGMII Fiber")); 73259ac0c16Sdavemq break; 73300161856Syc 7342e59129aSraghus case PORT_10G_COPPER: 73559ac0c16Sdavemq nxgep->xcvr = nxge_10G_copper_table; 73659ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Copper Xcvr")); 73759ac0c16Sdavemq break; 73800161856Syc 73900161856Syc case PORT_1G_TN1010: 74000161856Syc nxgep->xcvr = nxge_1G_tn1010_table; 74100161856Syc nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 74200161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 74300161856Syc "1G TN1010 copper Xcvr")); 74400161856Syc break; 74500161856Syc 74600161856Syc case PORT_10G_TN1010: 74700161856Syc nxgep->xcvr = nxge_10G_tn1010_table; 74800161856Syc nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 74900161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 75000161856Syc "10G TN1010 copper Xcvr")); 75100161856Syc break; 75200161856Syc 7532e59129aSraghus case PORT_1G_FIBER: 7542e59129aSraghus case PORT_1G_SERDES: 75559ac0c16Sdavemq nxgep->xcvr = nxge_1G_fiber_table; 7562d17280bSsbehera nxgep->xcvr_addr = portn; 7572e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G %s Xcvr", 7582e59129aSraghus (nxgep->mac.portmode == PORT_1G_FIBER) ? 7592e59129aSraghus "Fiber" : "Serdes")); 76059ac0c16Sdavemq break; 7612e59129aSraghus case PORT_10G_FIBER: 7622e59129aSraghus case PORT_10G_SERDES: 76359ac0c16Sdavemq nxgep->xcvr = nxge_10G_fiber_table; 7642d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G xcvr " 7652d17280bSsbehera "nxgep->nxge_hw_p->xcvr_addr[portn] = [%d] " 7662d17280bSsbehera "nxgep->xcvr_addr = [%d]", 7672d17280bSsbehera nxgep->nxge_hw_p->xcvr_addr[portn], 7682d17280bSsbehera nxgep->xcvr_addr)); 7692d17280bSsbehera if (nxgep->nxge_hw_p->xcvr_addr[portn]) { 7702d17280bSsbehera nxgep->xcvr_addr = 7712d17280bSsbehera nxgep->nxge_hw_p->xcvr_addr[portn]; 7722d17280bSsbehera } 7732e59129aSraghus switch (nxgep->platform_type) { 7742e59129aSraghus case P_NEPTUNE_MARAMBA_P0: 7752e59129aSraghus case P_NEPTUNE_MARAMBA_P1: 77659ac0c16Sdavemq /* 77759ac0c16Sdavemq * Switch off LED for corresponding copper 77859ac0c16Sdavemq * port 77959ac0c16Sdavemq */ 78059ac0c16Sdavemq nxge_bcm5464_link_led_off(nxgep); 7812e59129aSraghus break; 7822e59129aSraghus default: 7832e59129aSraghus break; 78459ac0c16Sdavemq } 7852e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G %s Xcvr", 7862e59129aSraghus (nxgep->mac.portmode == PORT_10G_FIBER) ? 7872e59129aSraghus "Fiber" : "Serdes")); 78859ac0c16Sdavemq break; 7892d17280bSsbehera 7902d17280bSsbehera case PORT_HSP_MODE: 7912d17280bSsbehera nxgep->xcvr = nxge_10G_fiber_table; 7922d17280bSsbehera nxgep->xcvr.xcvr_inuse = HSP_XCVR; 7932d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Neptune 10G Hot " 7942d17280bSsbehera "Swappable Xcvr (not present)")); 7952d17280bSsbehera break; 79659ac0c16Sdavemq default: 79759ac0c16Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 79859ac0c16Sdavemq "Unknown port-type: 0x%x", port_type)); 79959ac0c16Sdavemq return (NXGE_ERROR); 80059ac0c16Sdavemq } 80159ac0c16Sdavemq } 80259ac0c16Sdavemq 8032d17280bSsbehera if (nxgep->mac.portmode == PORT_10G_FIBER) { 80452cdd236Ssbehera uint32_t pma_pmd_id; 80552cdd236Ssbehera pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, 80652cdd236Ssbehera nxgep->xcvr_addr); 80752cdd236Ssbehera if ((pma_pmd_id & BCM_PHY_ID_MASK) == MARVELL_88X201X_PHY_ID) { 80852cdd236Ssbehera chip_id = MRVL88X201X_CHIP_ID; 80952cdd236Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 81052cdd236Ssbehera "nxge_setup_xcvr_table: " 81152cdd236Ssbehera "Chip ID MARVELL [0x%x] for 10G xcvr", chip_id)); 81252cdd236Ssbehera } else if ((status = nxge_mdio_read(nxgep, nxgep->xcvr_addr, 8132d17280bSsbehera BCM8704_PCS_DEV_ADDR, BCM8704_CHIP_ID_REG, 8142d17280bSsbehera &chip_id)) == NXGE_OK) { 8152d17280bSsbehera 8162d17280bSsbehera switch (chip_id) { 8172d17280bSsbehera case BCM8704_CHIP_ID: 8182d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8192d17280bSsbehera "nxge_setup_xcvr_table: " 8202d17280bSsbehera "Chip ID 8704 [0x%x] for 10G xcvr", 8212d17280bSsbehera chip_id)); 8222d17280bSsbehera break; 8232d17280bSsbehera case BCM8706_CHIP_ID: 8242d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8252d17280bSsbehera "nxge_setup_xcvr_table: " 8262d17280bSsbehera "Chip ID 8706 [0x%x] for 10G xcvr", 8272d17280bSsbehera chip_id)); 8282d17280bSsbehera break; 8292d17280bSsbehera default: 8302d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 8312d17280bSsbehera "nxge_setup_xcvr_table: " 8322d17280bSsbehera "Unknown Chip ID [0x%x] for 10G xcvr", 8332d17280bSsbehera chip_id)); 8342d17280bSsbehera break; 8352d17280bSsbehera } 8362d17280bSsbehera } 8372d17280bSsbehera } 8382d17280bSsbehera 83959ac0c16Sdavemq nxgep->statsp->mac_stats.xcvr_inuse = nxgep->xcvr.xcvr_inuse; 8402d17280bSsbehera nxgep->statsp->mac_stats.xcvr_portn = nxgep->xcvr_addr; 8412d17280bSsbehera nxgep->chip_id = chip_id; 8422e59129aSraghus 8432e59129aSraghus /* 8442e59129aSraghus * Get the actual device ID value returned by MDIO read. 8452e59129aSraghus */ 8462e59129aSraghus nxgep->statsp->mac_stats.xcvr_id = 0; 8472e59129aSraghus 8482d17280bSsbehera pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, nxgep->xcvr_addr); 8492e59129aSraghus if (nxge_is_supported_phy(pma_pmd_id, CLAUSE_45_TYPE)) { 8502e59129aSraghus nxgep->statsp->mac_stats.xcvr_id = pma_pmd_id; 8512e59129aSraghus } else { 8522d17280bSsbehera pcs_id = nxge_get_cl45_pcs_id(nxgep, nxgep->xcvr_addr); 8532e59129aSraghus if (nxge_is_supported_phy(pcs_id, CLAUSE_45_TYPE)) { 8542e59129aSraghus nxgep->statsp->mac_stats.xcvr_id = pcs_id; 8552e59129aSraghus } else { 8562e59129aSraghus phy_id = nxge_get_cl22_phy_id(nxgep, 8572d17280bSsbehera nxgep->xcvr_addr); 8582e59129aSraghus if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) { 8592e59129aSraghus nxgep->statsp->mac_stats.xcvr_id = phy_id; 8602e59129aSraghus } 8612e59129aSraghus } 8622e59129aSraghus } 8632e59129aSraghus 86459ac0c16Sdavemq nxgep->mac.linkchkmode = LINKCHK_TIMER; 86559ac0c16Sdavemq 8662e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_setup_xcvr_table: niu_type" 8672d17280bSsbehera "[0x%x] platform type[0x%x] xcvr_arr[%d]", nxgep->niu_type, 8682d17280bSsbehera nxgep->platform_type, nxgep->xcvr_addr)); 8692e59129aSraghus 87059ac0c16Sdavemq return (status); 87159ac0c16Sdavemq } 87259ac0c16Sdavemq 87344961713Sgirish /* Initialize the entire MAC and physical layer */ 87444961713Sgirish 87544961713Sgirish nxge_status_t 87644961713Sgirish nxge_mac_init(p_nxge_t nxgep) 87744961713Sgirish { 87844961713Sgirish uint8_t portn; 87944961713Sgirish nxge_status_t status = NXGE_OK; 88044961713Sgirish portn = NXGE_GET_PORT_NUM(nxgep->function_num); 88144961713Sgirish 88244961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_init: port<%d>", portn)); 88344961713Sgirish 88444961713Sgirish nxgep->mac.portnum = portn; 88544961713Sgirish nxgep->mac.porttype = PORT_TYPE_XMAC; 88644961713Sgirish 88744961713Sgirish if ((portn == BMAC_PORT_0) || (portn == BMAC_PORT_1)) 88844961713Sgirish nxgep->mac.porttype = PORT_TYPE_BMAC; 88944961713Sgirish 89000161856Syc 89144961713Sgirish /* Initialize XIF to configure a network mode */ 89244961713Sgirish if ((status = nxge_xif_init(nxgep)) != NXGE_OK) { 89344961713Sgirish goto fail; 89444961713Sgirish } 89544961713Sgirish 89644961713Sgirish if ((status = nxge_pcs_init(nxgep)) != NXGE_OK) { 89744961713Sgirish goto fail; 89844961713Sgirish } 89944961713Sgirish 90044961713Sgirish /* Initialize TX and RX MACs */ 90144961713Sgirish /* 90244961713Sgirish * Always perform XIF init first, before TX and RX MAC init 90344961713Sgirish */ 90444961713Sgirish if ((status = nxge_tx_mac_reset(nxgep)) != NXGE_OK) 90544961713Sgirish goto fail; 90644961713Sgirish 90744961713Sgirish if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK) 90844961713Sgirish goto fail; 90944961713Sgirish 91044961713Sgirish if ((status = nxge_rx_mac_reset(nxgep)) != NXGE_OK) 91144961713Sgirish goto fail; 91244961713Sgirish 91344961713Sgirish if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK) 91444961713Sgirish goto fail; 91544961713Sgirish 91644961713Sgirish if ((status = nxge_tx_mac_enable(nxgep)) != NXGE_OK) 91744961713Sgirish goto fail; 91844961713Sgirish 91944961713Sgirish if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 92044961713Sgirish goto fail; 92144961713Sgirish 922cb9d3ae6Smisaki /* Initialize MAC control configuration */ 923cb9d3ae6Smisaki if ((status = nxge_mac_ctrl_init(nxgep)) != NXGE_OK) { 924cb9d3ae6Smisaki goto fail; 925cb9d3ae6Smisaki } 926cb9d3ae6Smisaki 92744961713Sgirish nxgep->statsp->mac_stats.mac_mtu = nxgep->mac.maxframesize; 92844961713Sgirish 929d81011f0Ssbehera /* The Neptune Serdes needs to be reinitialized again */ 930d81011f0Ssbehera if ((NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) && 931d81011f0Ssbehera ((nxgep->mac.portmode == PORT_1G_SERDES) || 93200161856Syc (nxgep->mac.portmode == PORT_1G_TN1010) || 933d81011f0Ssbehera (nxgep->mac.portmode == PORT_1G_FIBER)) && 934d81011f0Ssbehera ((portn == 0) || (portn == 1))) { 935d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 936d81011f0Ssbehera "nxge_mac_init: reinit Neptune 1G Serdes ")); 937d81011f0Ssbehera if ((status = nxge_1G_serdes_init(nxgep)) != NXGE_OK) { 938d81011f0Ssbehera goto fail; 939d81011f0Ssbehera } 940d81011f0Ssbehera } 941d81011f0Ssbehera 9422e59129aSraghus 94344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_init: port<%d>", portn)); 94444961713Sgirish 94544961713Sgirish return (NXGE_OK); 94644961713Sgirish fail: 94744961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 94844961713Sgirish "nxge_mac_init: failed to initialize MAC port<%d>", 94944961713Sgirish portn)); 95044961713Sgirish return (status); 95144961713Sgirish } 95244961713Sgirish 95344961713Sgirish /* Initialize the Ethernet Link */ 95444961713Sgirish 95544961713Sgirish nxge_status_t 95644961713Sgirish nxge_link_init(p_nxge_t nxgep) 95744961713Sgirish { 95844961713Sgirish nxge_status_t status = NXGE_OK; 9592e59129aSraghus nxge_port_mode_t portmode; 96044961713Sgirish #ifdef NXGE_DEBUG 96144961713Sgirish uint8_t portn; 96244961713Sgirish 96344961713Sgirish portn = nxgep->mac.portnum; 96444961713Sgirish 96544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_init: port<%d>", portn)); 96644961713Sgirish #endif 9672d17280bSsbehera if (nxgep->hot_swappable_phy && nxgep->phy_absent) { 9682d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_init: " 9692d17280bSsbehera "Phy not present, cannot initialize link")); 9702d17280bSsbehera return (status); 9712d17280bSsbehera } 97244961713Sgirish 9732e59129aSraghus portmode = nxgep->mac.portmode; 9742d17280bSsbehera 97500161856Syc /* 97600161856Syc * Workaround to get link up in both NIU ports. Some portmodes require 97700161856Syc * that the xcvr be initialized twice, the first time before calling 97800161856Syc * nxge_serdes_init. 97900161856Syc */ 9802e59129aSraghus if (nxgep->niu_type == N2_NIU && (portmode != PORT_10G_SERDES) && 98100161856Syc (portmode != PORT_10G_TN1010) && 98200161856Syc (portmode != PORT_1G_TN1010) && 9832e59129aSraghus (portmode != PORT_1G_SERDES)) { 9842e59129aSraghus if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK) { 98544961713Sgirish goto fail; 9862e59129aSraghus } 98744961713Sgirish } 98800161856Syc 98944961713Sgirish NXGE_DELAY(200000); 99044961713Sgirish /* Initialize internal serdes */ 99144961713Sgirish if ((status = nxge_serdes_init(nxgep)) != NXGE_OK) 99244961713Sgirish goto fail; 99344961713Sgirish NXGE_DELAY(200000); 99444961713Sgirish if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK) 99544961713Sgirish goto fail; 99644961713Sgirish 99744961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_init: port<%d>", portn)); 99844961713Sgirish 99944961713Sgirish return (NXGE_OK); 100044961713Sgirish 100144961713Sgirish fail: 100244961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 100344961713Sgirish "nxge_link_init: ", 100444961713Sgirish "failed to initialize Ethernet link on port<%d>", 100544961713Sgirish portn)); 100644961713Sgirish 100744961713Sgirish return (status); 100844961713Sgirish } 100944961713Sgirish 101044961713Sgirish 101144961713Sgirish /* Initialize the XIF sub-block within the MAC */ 101244961713Sgirish 101344961713Sgirish nxge_status_t 101444961713Sgirish nxge_xif_init(p_nxge_t nxgep) 101544961713Sgirish { 101644961713Sgirish uint32_t xif_cfg = 0; 101744961713Sgirish npi_attr_t ap; 101844961713Sgirish uint8_t portn; 101944961713Sgirish nxge_port_t portt; 102044961713Sgirish nxge_port_mode_t portmode; 102144961713Sgirish p_nxge_stats_t statsp; 102244961713Sgirish npi_status_t rs = NPI_SUCCESS; 102344961713Sgirish npi_handle_t handle; 102444961713Sgirish 102544961713Sgirish portn = NXGE_GET_PORT_NUM(nxgep->function_num); 102644961713Sgirish 102744961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xif_init: port<%d>", portn)); 102844961713Sgirish 102944961713Sgirish handle = nxgep->npi_handle; 103044961713Sgirish portmode = nxgep->mac.portmode; 103144961713Sgirish portt = nxgep->mac.porttype; 103244961713Sgirish statsp = nxgep->statsp; 103344961713Sgirish 1034d81011f0Ssbehera if ((NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) && 1035d81011f0Ssbehera ((nxgep->mac.portmode == PORT_1G_SERDES) || 103600161856Syc (nxgep->mac.portmode == PORT_1G_TN1010) || 1037d81011f0Ssbehera (nxgep->mac.portmode == PORT_1G_FIBER)) && 1038d81011f0Ssbehera ((portn == 0) || (portn == 1))) { 1039d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1040d81011f0Ssbehera "nxge_xcvr_init: set ATCA mode")); 1041d81011f0Ssbehera npi_mac_mif_set_atca_mode(nxgep->npi_handle, B_TRUE); 1042d81011f0Ssbehera } 1043d81011f0Ssbehera 104444961713Sgirish if (portt == PORT_TYPE_XMAC) { 104544961713Sgirish 104644961713Sgirish /* Setup XIF Configuration for XMAC */ 104744961713Sgirish 104844961713Sgirish if ((portmode == PORT_10G_FIBER) || 10492e59129aSraghus (portmode == PORT_10G_COPPER) || 105000161856Syc (portmode == PORT_10G_TN1010) || 10512e59129aSraghus (portmode == PORT_10G_SERDES)) 105244961713Sgirish xif_cfg |= CFG_XMAC_XIF_LFS; 105344961713Sgirish 105400161856Syc /* Bypass PCS so that RGMII will be used */ 105544961713Sgirish if (portmode == PORT_1G_COPPER) { 105644961713Sgirish xif_cfg |= CFG_XMAC_XIF_1G_PCS_BYPASS; 105744961713Sgirish } 105844961713Sgirish 105944961713Sgirish /* Set MAC Internal Loopback if necessary */ 106044961713Sgirish if (statsp->port_stats.lb_mode == nxge_lb_mac1000) 106144961713Sgirish xif_cfg |= CFG_XMAC_XIF_LOOPBACK; 106244961713Sgirish 106344961713Sgirish if (statsp->mac_stats.link_speed == 100) 106444961713Sgirish xif_cfg |= CFG_XMAC_XIF_SEL_CLK_25MHZ; 106544961713Sgirish 106644961713Sgirish xif_cfg |= CFG_XMAC_XIF_TX_OUTPUT; 106744961713Sgirish 10682e59129aSraghus if ((portmode == PORT_10G_FIBER) || 106900161856Syc (portmode == PORT_10G_TN1010) || 107000161856Syc (portmode == PORT_1G_TN1010) || 10712e59129aSraghus (portmode == PORT_10G_SERDES)) { 107200161856Syc /* Assume LED same for 1G and 10G */ 107344961713Sgirish if (statsp->mac_stats.link_up) { 107444961713Sgirish xif_cfg |= CFG_XMAC_XIF_LED_POLARITY; 107544961713Sgirish } else { 107644961713Sgirish xif_cfg |= CFG_XMAC_XIF_LED_FORCE; 107744961713Sgirish } 107844961713Sgirish } 107944961713Sgirish 108044961713Sgirish rs = npi_xmac_xif_config(handle, INIT, portn, xif_cfg); 108144961713Sgirish if (rs != NPI_SUCCESS) 108244961713Sgirish goto fail; 108344961713Sgirish 108444961713Sgirish nxgep->mac.xif_config = xif_cfg; 108544961713Sgirish 108644961713Sgirish /* Set Port Mode */ 108744961713Sgirish if ((portmode == PORT_10G_FIBER) || 10882e59129aSraghus (portmode == PORT_10G_COPPER) || 108900161856Syc (portmode == PORT_10G_TN1010) || 10902e59129aSraghus (portmode == PORT_10G_SERDES)) { 109144961713Sgirish SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE, 109244961713Sgirish MAC_XGMII_MODE, rs); 109344961713Sgirish if (rs != NPI_SUCCESS) 109444961713Sgirish goto fail; 109544961713Sgirish if (statsp->mac_stats.link_up) { 109644961713Sgirish if (nxge_10g_link_led_on(nxgep) != NXGE_OK) 109744961713Sgirish goto fail; 109844961713Sgirish } else { 109944961713Sgirish if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 110044961713Sgirish goto fail; 110144961713Sgirish } 110244961713Sgirish } else if ((portmode == PORT_1G_FIBER) || 11032e59129aSraghus (portmode == PORT_1G_COPPER) || 1104d81011f0Ssbehera (portmode == PORT_1G_SERDES) || 110500161856Syc (portmode == PORT_1G_TN1010) || 1106d81011f0Ssbehera (portmode == PORT_1G_RGMII_FIBER)) { 1107d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1108d81011f0Ssbehera "nxge_xif_init: Port[%d] Mode[%d] Speed[%d]", 1109d81011f0Ssbehera portn, portmode, statsp->mac_stats.link_speed)); 111044961713Sgirish if (statsp->mac_stats.link_speed == 1000) { 111144961713Sgirish SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE, 111244961713Sgirish MAC_GMII_MODE, rs); 111344961713Sgirish } else { 111444961713Sgirish SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE, 111544961713Sgirish MAC_MII_MODE, rs); 111644961713Sgirish } 111744961713Sgirish if (rs != NPI_SUCCESS) 111844961713Sgirish goto fail; 111944961713Sgirish } else { 112044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 112144961713Sgirish "nxge_xif_init: Unknown port mode (%d)" 112244961713Sgirish " for port<%d>", portmode, portn)); 112344961713Sgirish goto fail; 112444961713Sgirish } 112544961713Sgirish 1126d81011f0Ssbehera /* Enable ATCA mode */ 1127d81011f0Ssbehera 112844961713Sgirish } else if (portt == PORT_TYPE_BMAC) { 112944961713Sgirish 113044961713Sgirish /* Setup XIF Configuration for BMAC */ 113144961713Sgirish 1132d81011f0Ssbehera if ((portmode == PORT_1G_COPPER) || 1133d81011f0Ssbehera (portmode == PORT_1G_RGMII_FIBER)) { 113444961713Sgirish if (statsp->mac_stats.link_speed == 100) 113544961713Sgirish xif_cfg |= CFG_BMAC_XIF_SEL_CLK_25MHZ; 113644961713Sgirish } 113744961713Sgirish 113844961713Sgirish if (statsp->port_stats.lb_mode == nxge_lb_mac1000) 113944961713Sgirish xif_cfg |= CFG_BMAC_XIF_LOOPBACK; 114044961713Sgirish 114144961713Sgirish if (statsp->mac_stats.link_speed == 1000) 114244961713Sgirish xif_cfg |= CFG_BMAC_XIF_GMII_MODE; 114344961713Sgirish 114444961713Sgirish xif_cfg |= CFG_BMAC_XIF_TX_OUTPUT; 114544961713Sgirish 114644961713Sgirish rs = npi_bmac_xif_config(handle, INIT, portn, xif_cfg); 114744961713Sgirish if (rs != NPI_SUCCESS) 114844961713Sgirish goto fail; 114944961713Sgirish nxgep->mac.xif_config = xif_cfg; 115044961713Sgirish } 115144961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xif_init: port<%d>", portn)); 115244961713Sgirish return (NXGE_OK); 115344961713Sgirish fail: 115444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 115544961713Sgirish "nxge_xif_init: Failed to initialize XIF port<%d>", 115644961713Sgirish portn)); 115744961713Sgirish return (NXGE_ERROR | rs); 115844961713Sgirish } 115944961713Sgirish 116044961713Sgirish 116100161856Syc /* 116200161856Syc * Initialize the PCS sub-block in the MAC. Note that PCS does not 116300161856Syc * support loopback like XPCS. 116400161856Syc */ 116544961713Sgirish nxge_status_t 116644961713Sgirish nxge_pcs_init(p_nxge_t nxgep) 116744961713Sgirish { 116844961713Sgirish pcs_cfg_t pcs_cfg; 116944961713Sgirish uint32_t val; 117044961713Sgirish uint8_t portn; 117144961713Sgirish nxge_port_mode_t portmode; 117244961713Sgirish npi_handle_t handle; 117344961713Sgirish p_nxge_stats_t statsp; 117400161856Syc pcs_ctrl_t pcs_ctrl; 117544961713Sgirish npi_status_t rs = NPI_SUCCESS; 117600161856Syc uint8_t i; 117744961713Sgirish 117844961713Sgirish handle = nxgep->npi_handle; 117944961713Sgirish portmode = nxgep->mac.portmode; 118044961713Sgirish portn = nxgep->mac.portnum; 118144961713Sgirish statsp = nxgep->statsp; 118244961713Sgirish 118344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_init: port<%d>", portn)); 118444961713Sgirish 118500161856Syc if (portmode == PORT_1G_FIBER || 118600161856Syc portmode == PORT_1G_TN1010 || 118700161856Syc portmode == PORT_1G_SERDES) { 118800161856Syc if (portmode == PORT_1G_TN1010) { 118900161856Syc /* Reset PCS multiple time in PORT_1G_TN1010 mode */ 119000161856Syc for (i = 0; i < 6; i ++) { 119100161856Syc if ((rs = npi_mac_pcs_reset(handle, portn)) 119200161856Syc != NPI_SUCCESS) { 119300161856Syc goto fail; 119400161856Syc } 119500161856Syc } 119600161856Syc } else { 119700161856Syc if ((rs = npi_mac_pcs_reset(handle, portn)) 119800161856Syc != NPI_SUCCESS) 119900161856Syc goto fail; 12002e59129aSraghus } 12012e59129aSraghus 120244961713Sgirish /* Initialize port's PCS */ 120344961713Sgirish pcs_cfg.value = 0; 120444961713Sgirish pcs_cfg.bits.w0.enable = 1; 120544961713Sgirish pcs_cfg.bits.w0.mask = 1; 120644961713Sgirish PCS_REG_WR(handle, portn, PCS_CONFIG_REG, pcs_cfg.value); 120744961713Sgirish PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG, 0); 120844961713Sgirish 12092e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 12102e59129aSraghus "==> nxge_pcs_init: (1G) port<%d> write config 0x%llx", 12112e59129aSraghus portn, pcs_cfg.value)); 121200161856Syc 121300161856Syc if (portmode == PORT_1G_TN1010) { 121400161856Syc /* 121500161856Syc * Must disable PCS auto-negotiation when the the driver 121600161856Syc * is driving the TN1010 based XAUI card Otherwise the 121700161856Syc * autonegotiation between the PCS and the TN1010 PCS 121800161856Syc * will never complete and the Neptune/NIU will not work 121900161856Syc */ 122000161856Syc pcs_ctrl.value = 0; 122100161856Syc PCS_REG_WR(handle, portn, PCS_MII_CTRL_REG, 122200161856Syc pcs_ctrl.value); 122300161856Syc } 122400161856Syc } else if (portmode == PORT_10G_FIBER || 122500161856Syc portmode == PORT_10G_COPPER || 122600161856Syc portmode == PORT_10G_TN1010 || 122700161856Syc portmode == PORT_10G_SERDES) { 122844961713Sgirish /* Use internal XPCS, bypass 1G PCS */ 122944961713Sgirish XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val); 123044961713Sgirish val &= ~XMAC_XIF_XPCS_BYPASS; 123144961713Sgirish XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val); 123244961713Sgirish 123344961713Sgirish if ((rs = npi_xmac_xpcs_reset(handle, portn)) != NPI_SUCCESS) 123444961713Sgirish goto fail; 123544961713Sgirish 123644961713Sgirish /* Set XPCS Internal Loopback if necessary */ 123744961713Sgirish if ((rs = npi_xmac_xpcs_read(handle, portn, 123844961713Sgirish XPCS_REG_CONTROL1, &val)) 123944961713Sgirish != NPI_SUCCESS) 124044961713Sgirish goto fail; 124100161856Syc 124244961713Sgirish if ((statsp->port_stats.lb_mode == nxge_lb_mac10g) || 124344961713Sgirish (statsp->port_stats.lb_mode == nxge_lb_mac1000)) 124444961713Sgirish val |= XPCS_CTRL1_LOOPBK; 124544961713Sgirish else 124644961713Sgirish val &= ~XPCS_CTRL1_LOOPBK; 124744961713Sgirish if ((rs = npi_xmac_xpcs_write(handle, portn, 124844961713Sgirish XPCS_REG_CONTROL1, val)) 124944961713Sgirish != NPI_SUCCESS) 125044961713Sgirish goto fail; 125144961713Sgirish 125244961713Sgirish /* Clear descw errors */ 125344961713Sgirish if ((rs = npi_xmac_xpcs_write(handle, portn, 125444961713Sgirish XPCS_REG_DESCWERR_COUNTER, 0)) 125544961713Sgirish != NPI_SUCCESS) 125644961713Sgirish goto fail; 125744961713Sgirish /* Clear symbol errors */ 125844961713Sgirish if ((rs = npi_xmac_xpcs_read(handle, portn, 125944961713Sgirish XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val)) 126044961713Sgirish != NPI_SUCCESS) 126144961713Sgirish goto fail; 126244961713Sgirish if ((rs = npi_xmac_xpcs_read(handle, portn, 126344961713Sgirish XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val)) 126444961713Sgirish != NPI_SUCCESS) 126544961713Sgirish goto fail; 126644961713Sgirish 1267d81011f0Ssbehera } else if ((portmode == PORT_1G_COPPER) || 1268d81011f0Ssbehera (portmode == PORT_1G_RGMII_FIBER)) { 1269d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1270d81011f0Ssbehera "==> nxge_pcs_init: (1G) copper port<%d>", portn)); 127144961713Sgirish if (portn < 4) { 127244961713Sgirish PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG, 127344961713Sgirish PCS_DATAPATH_MODE_MII); 127444961713Sgirish } 127544961713Sgirish if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS) 127644961713Sgirish goto fail; 127744961713Sgirish 127844961713Sgirish } else { 127944961713Sgirish goto fail; 128044961713Sgirish } 128144961713Sgirish pass: 128244961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_init: port<%d>", portn)); 128344961713Sgirish return (NXGE_OK); 128444961713Sgirish fail: 128544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 128644961713Sgirish "nxge_pcs_init: Failed to initialize PCS port<%d>", 128744961713Sgirish portn)); 128844961713Sgirish return (NXGE_ERROR | rs); 128944961713Sgirish } 129044961713Sgirish 1291cb9d3ae6Smisaki /* 1292cb9d3ae6Smisaki * Initialize the MAC CTRL sub-block within the MAC 1293cb9d3ae6Smisaki * Only the receive-pause-cap is supported. 1294cb9d3ae6Smisaki */ 1295cb9d3ae6Smisaki nxge_status_t 1296cb9d3ae6Smisaki nxge_mac_ctrl_init(p_nxge_t nxgep) 1297cb9d3ae6Smisaki { 1298cb9d3ae6Smisaki uint8_t portn; 1299cb9d3ae6Smisaki nxge_port_t portt; 1300cb9d3ae6Smisaki p_nxge_stats_t statsp; 1301cb9d3ae6Smisaki npi_handle_t handle; 1302cb9d3ae6Smisaki uint32_t val; 1303cb9d3ae6Smisaki 1304cb9d3ae6Smisaki portn = NXGE_GET_PORT_NUM(nxgep->function_num); 1305cb9d3ae6Smisaki 1306cb9d3ae6Smisaki NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_ctrl_init: port<%d>", 1307cb9d3ae6Smisaki portn)); 1308cb9d3ae6Smisaki 1309cb9d3ae6Smisaki handle = nxgep->npi_handle; 1310cb9d3ae6Smisaki portt = nxgep->mac.porttype; 1311cb9d3ae6Smisaki statsp = nxgep->statsp; 1312cb9d3ae6Smisaki 1313cb9d3ae6Smisaki if (portt == PORT_TYPE_XMAC) { 131400161856Syc /* Reading the current XMAC Config Register for XMAC */ 1315cb9d3ae6Smisaki XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val); 1316cb9d3ae6Smisaki 1317cb9d3ae6Smisaki /* 1318cb9d3ae6Smisaki * Setup XMAC Configuration for XMAC 1319cb9d3ae6Smisaki * XMAC only supports receive-pause 1320cb9d3ae6Smisaki */ 1321cb9d3ae6Smisaki if (statsp->mac_stats.adv_cap_asmpause) { 1322cb9d3ae6Smisaki if (!statsp->mac_stats.adv_cap_pause) { 1323cb9d3ae6Smisaki /* 1324cb9d3ae6Smisaki * If adv_cap_asmpause is 1 and adv_cap_pause 1325cb9d3ae6Smisaki * is 0, enable receive pause. 1326cb9d3ae6Smisaki */ 1327cb9d3ae6Smisaki val |= XMAC_RX_CFG_RX_PAUSE_EN; 1328cb9d3ae6Smisaki } else { 1329cb9d3ae6Smisaki /* 1330cb9d3ae6Smisaki * If adv_cap_asmpause is 1 and adv_cap_pause 1331cb9d3ae6Smisaki * is 1, disable receive pause. Send pause is 1332cb9d3ae6Smisaki * not supported. 1333cb9d3ae6Smisaki */ 1334cb9d3ae6Smisaki val &= ~XMAC_RX_CFG_RX_PAUSE_EN; 1335cb9d3ae6Smisaki } 1336cb9d3ae6Smisaki } else { 13371bd6825cSml NXGE_DEBUG_MSG((nxgep, MAC_CTL, 13381bd6825cSml "==> nxge_mac_ctrl_init: port<%d>: pause", 13391bd6825cSml portn)); 1340cb9d3ae6Smisaki if (statsp->mac_stats.adv_cap_pause) { 13411bd6825cSml NXGE_DEBUG_MSG((nxgep, MAC_CTL, 13421bd6825cSml "==> nxge_mac_ctrl_init: port<%d>: " 13431bd6825cSml "enable pause", portn)); 1344cb9d3ae6Smisaki /* 1345cb9d3ae6Smisaki * If adv_cap_asmpause is 0 and adv_cap_pause 1346cb9d3ae6Smisaki * is 1, enable receive pause. 1347cb9d3ae6Smisaki */ 1348cb9d3ae6Smisaki val |= XMAC_RX_CFG_RX_PAUSE_EN; 1349cb9d3ae6Smisaki } else { 1350cb9d3ae6Smisaki /* 1351cb9d3ae6Smisaki * If adv_cap_asmpause is 0 and adv_cap_pause 1352cb9d3ae6Smisaki * is 0, disable receive pause. Send pause is 1353cb9d3ae6Smisaki * not supported 1354cb9d3ae6Smisaki */ 13551bd6825cSml NXGE_DEBUG_MSG((nxgep, MAC_CTL, 13561bd6825cSml "==> nxge_mac_ctrl_init: port<%d>: " 13571bd6825cSml "disable pause", portn)); 1358cb9d3ae6Smisaki val &= ~XMAC_RX_CFG_RX_PAUSE_EN; 1359cb9d3ae6Smisaki } 1360cb9d3ae6Smisaki } 1361cb9d3ae6Smisaki XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val); 1362cb9d3ae6Smisaki } else if (portt == PORT_TYPE_BMAC) { 136300161856Syc /* Reading the current MAC CTRL Config Register for BMAC */ 1364cb9d3ae6Smisaki BMAC_REG_RD(handle, portn, MAC_CTRL_CONFIG_REG, &val); 1365cb9d3ae6Smisaki 1366cb9d3ae6Smisaki /* Setup MAC CTRL Configuration for BMAC */ 1367cb9d3ae6Smisaki if (statsp->mac_stats.adv_cap_asmpause) { 1368cb9d3ae6Smisaki if (statsp->mac_stats.adv_cap_pause) { 1369cb9d3ae6Smisaki /* 1370cb9d3ae6Smisaki * If adv_cap_asmpause is 1 and adv_cap_pause 1371cb9d3ae6Smisaki * is 1, disable receive pause. Send pause 1372cb9d3ae6Smisaki * is not supported 1373cb9d3ae6Smisaki */ 1374cb9d3ae6Smisaki val &= ~MAC_CTRL_CFG_RECV_PAUSE_EN; 1375cb9d3ae6Smisaki } else { 1376cb9d3ae6Smisaki /* 1377cb9d3ae6Smisaki * If adv_cap_asmpause is 1 and adv_cap_pause 1378cb9d3ae6Smisaki * is 0, enable receive pause and disable 1379cb9d3ae6Smisaki * send pause. 1380cb9d3ae6Smisaki */ 1381cb9d3ae6Smisaki val |= MAC_CTRL_CFG_RECV_PAUSE_EN; 1382cb9d3ae6Smisaki val &= ~MAC_CTRL_CFG_SEND_PAUSE_EN; 1383cb9d3ae6Smisaki } 1384cb9d3ae6Smisaki } else { 1385cb9d3ae6Smisaki if (statsp->mac_stats.adv_cap_pause) { 1386cb9d3ae6Smisaki /* 1387cb9d3ae6Smisaki * If adv_cap_asmpause is 0 and adv_cap_pause 1388cb9d3ae6Smisaki * is 1, enable receive pause. Send pause is 1389cb9d3ae6Smisaki * not supported. 1390cb9d3ae6Smisaki */ 1391cb9d3ae6Smisaki val |= MAC_CTRL_CFG_RECV_PAUSE_EN; 1392cb9d3ae6Smisaki } else { 1393cb9d3ae6Smisaki /* 1394cb9d3ae6Smisaki * If adv_cap_asmpause is 0 and adv_cap_pause 1395cb9d3ae6Smisaki * is 0, pause capability is not available in 1396cb9d3ae6Smisaki * either direction. 1397cb9d3ae6Smisaki */ 1398cb9d3ae6Smisaki val &= (~MAC_CTRL_CFG_SEND_PAUSE_EN & 1399cb9d3ae6Smisaki ~MAC_CTRL_CFG_RECV_PAUSE_EN); 1400cb9d3ae6Smisaki } 1401cb9d3ae6Smisaki } 1402cb9d3ae6Smisaki BMAC_REG_WR(handle, portn, MAC_CTRL_CONFIG_REG, val); 1403cb9d3ae6Smisaki } 1404cb9d3ae6Smisaki 1405cb9d3ae6Smisaki NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_ctrl_init: port<%d>", 1406cb9d3ae6Smisaki portn)); 1407cb9d3ae6Smisaki 1408cb9d3ae6Smisaki return (NXGE_OK); 1409cb9d3ae6Smisaki } 1410cb9d3ae6Smisaki 141144961713Sgirish /* Initialize the Internal Serdes */ 141244961713Sgirish 141344961713Sgirish nxge_status_t 141444961713Sgirish nxge_serdes_init(p_nxge_t nxgep) 141544961713Sgirish { 141644961713Sgirish p_nxge_stats_t statsp; 141744961713Sgirish #ifdef NXGE_DEBUG 141844961713Sgirish uint8_t portn; 141944961713Sgirish #endif 142044961713Sgirish nxge_status_t status = NXGE_OK; 142144961713Sgirish 142244961713Sgirish #ifdef NXGE_DEBUG 142344961713Sgirish portn = nxgep->mac.portnum; 142444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 142559ac0c16Sdavemq "==> nxge_serdes_init port<%d>", portn)); 142644961713Sgirish #endif 142744961713Sgirish 142859ac0c16Sdavemq if (nxgep->xcvr.serdes_init) { 142959ac0c16Sdavemq statsp = nxgep->statsp; 143059ac0c16Sdavemq status = nxgep->xcvr.serdes_init(nxgep); 143159ac0c16Sdavemq if (status != NXGE_OK) 143244961713Sgirish goto fail; 143359ac0c16Sdavemq statsp->mac_stats.serdes_inits++; 143444961713Sgirish } 143544961713Sgirish 143644961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_serdes_init port<%d>", 143759ac0c16Sdavemq portn)); 143844961713Sgirish 143944961713Sgirish return (NXGE_OK); 144044961713Sgirish 144144961713Sgirish fail: 144244961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 144359ac0c16Sdavemq "nxge_serdes_init: Failed to initialize serdes for port<%d>", 144459ac0c16Sdavemq portn)); 144544961713Sgirish 144644961713Sgirish return (status); 144744961713Sgirish } 144844961713Sgirish 144944961713Sgirish /* Initialize the TI Hedwig Internal Serdes (N2-NIU only) */ 145044961713Sgirish 145159ac0c16Sdavemq static nxge_status_t 145244961713Sgirish nxge_n2_serdes_init(p_nxge_t nxgep) 145344961713Sgirish { 145444961713Sgirish uint8_t portn; 145544961713Sgirish int chan; 145644961713Sgirish esr_ti_cfgpll_l_t pll_cfg_l; 14572e59129aSraghus esr_ti_cfgpll_l_t pll_sts_l; 145844961713Sgirish esr_ti_cfgrx_l_t rx_cfg_l; 145944961713Sgirish esr_ti_cfgrx_h_t rx_cfg_h; 146044961713Sgirish esr_ti_cfgtx_l_t tx_cfg_l; 146144961713Sgirish esr_ti_cfgtx_h_t tx_cfg_h; 14622e59129aSraghus #ifdef NXGE_DEBUG 14632e59129aSraghus esr_ti_testcfg_t cfg; 14642e59129aSraghus #endif 146544961713Sgirish esr_ti_testcfg_t test_cfg; 146644961713Sgirish nxge_status_t status = NXGE_OK; 146744961713Sgirish 146844961713Sgirish portn = nxgep->mac.portnum; 146944961713Sgirish 147044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_n2_serdes_init port<%d>", 147144961713Sgirish portn)); 147244961713Sgirish 147344961713Sgirish tx_cfg_l.value = 0; 147444961713Sgirish tx_cfg_h.value = 0; 147544961713Sgirish rx_cfg_l.value = 0; 147644961713Sgirish rx_cfg_h.value = 0; 147744961713Sgirish pll_cfg_l.value = 0; 14782e59129aSraghus pll_sts_l.value = 0; 147944961713Sgirish test_cfg.value = 0; 148044961713Sgirish 148100161856Syc /* 148200161856Syc * If the nxge driver has been plumbed without a link, then it will 148300161856Syc * detect a link up when a cable connecting to an anto-negotiation 148400161856Syc * partner is plugged into the port. Because the TN1010 PHY supports 148500161856Syc * both 1G and 10G speeds, the driver must re-configure the 148600161856Syc * Neptune/NIU according to the negotiated speed. nxge_n2_serdes_init 148700161856Syc * is called at the post-link-up reconfiguration time. Here it calls 148800161856Syc * nxge_set_tn1010_param to set portmode before re-initializing 148900161856Syc * the serdes. 149000161856Syc */ 149100161856Syc if (nxgep->mac.portmode == PORT_1G_TN1010 || 149200161856Syc nxgep->mac.portmode == PORT_10G_TN1010) { 149300161856Syc if (nxge_set_tn1010_param(nxgep) != NXGE_OK) { 149400161856Syc goto fail; 149500161856Syc } 149600161856Syc } 149700161856Syc 149800161856Syc if (nxgep->mac.portmode == PORT_10G_FIBER || 149900161856Syc nxgep->mac.portmode == PORT_10G_TN1010 || 150000161856Syc nxgep->mac.portmode == PORT_10G_SERDES) { 150144961713Sgirish /* 0x0E01 */ 150244961713Sgirish tx_cfg_l.bits.entx = 1; 150344961713Sgirish tx_cfg_l.bits.swing = CFGTX_SWING_1375MV; 150444961713Sgirish 150544961713Sgirish /* 0x9101 */ 150644961713Sgirish rx_cfg_l.bits.enrx = 1; 150744961713Sgirish rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT; 150844961713Sgirish rx_cfg_l.bits.align = CFGRX_ALIGN_EN; 150944961713Sgirish rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES; 151044961713Sgirish 151144961713Sgirish /* 0x0008 */ 151244961713Sgirish rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF; 151344961713Sgirish 151444961713Sgirish /* Set loopback mode if necessary */ 151544961713Sgirish if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) { 151644961713Sgirish tx_cfg_l.bits.entest = 1; 151744961713Sgirish rx_cfg_l.bits.entest = 1; 151844961713Sgirish test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK; 151944961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, 152044961713Sgirish ESR_N2_DEV_ADDR, 152144961713Sgirish ESR_N2_TEST_CFG_REG, test_cfg.value)) 152244961713Sgirish != NXGE_OK) 152344961713Sgirish goto fail; 152444961713Sgirish } 152544961713Sgirish 152600161856Syc /* Initialize PLL for 10G */ 152700161856Syc pll_cfg_l.bits.mpy = CFGPLL_MPY_10X; 152800161856Syc pll_cfg_l.bits.enpll = 1; 152900161856Syc pll_sts_l.bits.enpll = 1; 153000161856Syc if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 153100161856Syc ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value)) != NXGE_OK) 153200161856Syc goto fail; 153300161856Syc 153400161856Syc if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 153500161856Syc ESR_N2_PLL_STS_L_REG, pll_sts_l.value)) != NXGE_OK) 153600161856Syc goto fail; 153744961713Sgirish 153800161856Syc #ifdef NXGE_DEBUG 153900161856Syc nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR, 154000161856Syc ESR_N2_PLL_CFG_L_REG, &cfg.value); 154100161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 154200161856Syc "==> nxge_n2_serdes_init port<%d>: PLL cfg.l 0x%x (0x%x)", 154300161856Syc portn, pll_cfg_l.value, cfg.value)); 154444961713Sgirish 154500161856Syc nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR, 154600161856Syc ESR_N2_PLL_STS_L_REG, &cfg.value); 154700161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 154800161856Syc "==> nxge_n2_serdes_init port<%d>: PLL sts.l 0x%x (0x%x)", 154900161856Syc portn, pll_sts_l.value, cfg.value)); 155000161856Syc #endif 155100161856Syc } else if (nxgep->mac.portmode == PORT_1G_FIBER || 155200161856Syc nxgep->mac.portmode == PORT_1G_TN1010 || 155300161856Syc nxgep->mac.portmode == PORT_1G_SERDES) { 155444961713Sgirish /* 0x0E21 */ 155544961713Sgirish tx_cfg_l.bits.entx = 1; 155644961713Sgirish tx_cfg_l.bits.rate = CFGTX_RATE_HALF; 155744961713Sgirish tx_cfg_l.bits.swing = CFGTX_SWING_1375MV; 155844961713Sgirish 155944961713Sgirish /* 0x9121 */ 156044961713Sgirish rx_cfg_l.bits.enrx = 1; 156144961713Sgirish rx_cfg_l.bits.rate = CFGRX_RATE_HALF; 156244961713Sgirish rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT; 156344961713Sgirish rx_cfg_l.bits.align = CFGRX_ALIGN_EN; 156444961713Sgirish rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES; 156544961713Sgirish 15662e59129aSraghus if (portn == 0) { 15672e59129aSraghus /* 0x8 */ 15682e59129aSraghus rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF; 15692e59129aSraghus } 157044961713Sgirish 157100161856Syc /* Initialize PLL for 1G */ 157244961713Sgirish pll_cfg_l.bits.mpy = CFGPLL_MPY_8X; 157344961713Sgirish pll_cfg_l.bits.enpll = 1; 15742e59129aSraghus pll_sts_l.bits.enpll = 1; 157544961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 157644961713Sgirish ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value)) 157744961713Sgirish != NXGE_OK) 157844961713Sgirish goto fail; 15792e59129aSraghus 15802e59129aSraghus if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 15812e59129aSraghus ESR_N2_PLL_STS_L_REG, pll_sts_l.value)) != NXGE_OK) 15822e59129aSraghus goto fail; 15832e59129aSraghus 15842e59129aSraghus #ifdef NXGE_DEBUG 15852e59129aSraghus nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR, 15862e59129aSraghus ESR_N2_PLL_CFG_L_REG, &cfg.value); 15872e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 15882e59129aSraghus "==> nxge_n2_serdes_init port<%d>: PLL cfg.l 0x%x (0x%x)", 15892e59129aSraghus portn, pll_cfg_l.value, cfg.value)); 15902e59129aSraghus 15912e59129aSraghus nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR, 15922e59129aSraghus ESR_N2_PLL_STS_L_REG, &cfg.value); 15932e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 15942e59129aSraghus "==> nxge_n2_serdes_init port<%d>: PLL sts.l 0x%x (0x%x)", 15952e59129aSraghus portn, pll_sts_l.value, cfg.value)); 15962e59129aSraghus #endif 15972e59129aSraghus 15982e59129aSraghus /* Set loopback mode if necessary */ 15992e59129aSraghus if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) { 16002e59129aSraghus tx_cfg_l.bits.entest = 1; 16012e59129aSraghus rx_cfg_l.bits.entest = 1; 16022e59129aSraghus test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK; 16032e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 16042e59129aSraghus "==> nxge_n2_serdes_init port<%d>: loopback 0x%x", 16052e59129aSraghus portn, test_cfg.value)); 16062e59129aSraghus if ((status = nxge_mdio_write(nxgep, portn, 16072e59129aSraghus ESR_N2_DEV_ADDR, 16082e59129aSraghus ESR_N2_TEST_CFG_REG, test_cfg.value)) != NXGE_OK) { 16092e59129aSraghus goto fail; 16102e59129aSraghus } 16112e59129aSraghus } 161244961713Sgirish } else { 161344961713Sgirish goto fail; 161444961713Sgirish } 161544961713Sgirish 161644961713Sgirish /* MIF_REG_WR(handle, MIF_MASK_REG, ~mask); */ 161744961713Sgirish 161844961713Sgirish NXGE_DELAY(20); 161944961713Sgirish 162044961713Sgirish /* init TX channels */ 162144961713Sgirish for (chan = 0; chan < 4; chan++) { 162244961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 162344961713Sgirish ESR_N2_TX_CFG_L_REG_ADDR(chan), tx_cfg_l.value)) 162444961713Sgirish != NXGE_OK) 162544961713Sgirish goto fail; 162644961713Sgirish 162744961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 162844961713Sgirish ESR_N2_TX_CFG_H_REG_ADDR(chan), tx_cfg_h.value)) 162944961713Sgirish != NXGE_OK) 163044961713Sgirish goto fail; 16312e59129aSraghus 16322e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 16332e59129aSraghus "==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_l 0x%x", 16342e59129aSraghus portn, chan, tx_cfg_l.value)); 16352e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 16362e59129aSraghus "==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_h 0x%x", 16372e59129aSraghus portn, chan, tx_cfg_h.value)); 163844961713Sgirish } 163944961713Sgirish 164044961713Sgirish /* init RX channels */ 164144961713Sgirish for (chan = 0; chan < 4; chan++) { 164244961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 164344961713Sgirish ESR_N2_RX_CFG_L_REG_ADDR(chan), rx_cfg_l.value)) 164444961713Sgirish != NXGE_OK) 164544961713Sgirish goto fail; 164644961713Sgirish 164744961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 164844961713Sgirish ESR_N2_RX_CFG_H_REG_ADDR(chan), rx_cfg_h.value)) 164944961713Sgirish != NXGE_OK) 165044961713Sgirish goto fail; 16512e59129aSraghus 16522e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 16532e59129aSraghus "==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_l 0x%x", 16542e59129aSraghus portn, chan, rx_cfg_l.value)); 165500161856Syc 16562e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 16572e59129aSraghus "==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_h 0x%x", 16582e59129aSraghus portn, chan, rx_cfg_h.value)); 165944961713Sgirish } 166044961713Sgirish 166144961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_n2_serdes_init port<%d>", 166244961713Sgirish portn)); 166344961713Sgirish 166444961713Sgirish return (NXGE_OK); 166544961713Sgirish fail: 16662d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 16672d17280bSsbehera "nxge_n2_serdes_init: Failed to initialize N2 serdes for port<%d>", 16682d17280bSsbehera portn)); 166944961713Sgirish 167044961713Sgirish return (status); 167144961713Sgirish } 167244961713Sgirish 167359ac0c16Sdavemq /* Initialize the Neptune Internal Serdes for 10G (Neptune only) */ 167444961713Sgirish 167559ac0c16Sdavemq static nxge_status_t 167659ac0c16Sdavemq nxge_neptune_10G_serdes_init(p_nxge_t nxgep) 167744961713Sgirish { 167844961713Sgirish npi_handle_t handle; 167944961713Sgirish uint8_t portn; 1680321febdeSsbehera int chan, i; 168144961713Sgirish sr_rx_tx_ctrl_l_t rx_tx_ctrl_l; 168244961713Sgirish sr_rx_tx_ctrl_h_t rx_tx_ctrl_h; 168344961713Sgirish sr_glue_ctrl0_l_t glue_ctrl0_l; 168444961713Sgirish sr_glue_ctrl0_h_t glue_ctrl0_h; 168544961713Sgirish uint64_t val; 168644961713Sgirish uint16_t val16l; 168744961713Sgirish uint16_t val16h; 168844961713Sgirish nxge_status_t status = NXGE_OK; 168944961713Sgirish 169044961713Sgirish portn = nxgep->mac.portnum; 169144961713Sgirish 169244961713Sgirish if ((portn != 0) && (portn != 1)) 169344961713Sgirish return (NXGE_OK); 169444961713Sgirish 169559ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 169659ac0c16Sdavemq "==> nxge_neptune_10G_serdes_init port<%d>", portn)); 169744961713Sgirish handle = nxgep->npi_handle; 169859ac0c16Sdavemq switch (portn) { 169959ac0c16Sdavemq case 0: 17004202ea4bSsbehera /* Reset Serdes */ 17014202ea4bSsbehera ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0); 17024202ea4bSsbehera NXGE_DELAY(20); 17034202ea4bSsbehera ESR_REG_WR(handle, ESR_RESET_REG, 0x0); 17044202ea4bSsbehera NXGE_DELAY(2000); 17054202ea4bSsbehera 17064202ea4bSsbehera /* Configure Serdes to 10G mode */ 17074202ea4bSsbehera ESR_REG_WR(handle, ESR_0_PLL_CONFIG_REG, 17084202ea4bSsbehera ESR_PLL_CFG_10G_SERDES); 17094202ea4bSsbehera 171059ac0c16Sdavemq ESR_REG_WR(handle, ESR_0_CONTROL_REG, 171159ac0c16Sdavemq ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 | 171259ac0c16Sdavemq ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 | 171359ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) | 171459ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) | 171559ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) | 171659ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 171759ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 171859ac0c16Sdavemq (0x1 << ESR_CTL_LOSADJ_0_SHIFT) | 171959ac0c16Sdavemq (0x1 << ESR_CTL_LOSADJ_1_SHIFT) | 172059ac0c16Sdavemq (0x1 << ESR_CTL_LOSADJ_2_SHIFT) | 172159ac0c16Sdavemq (0x1 << ESR_CTL_LOSADJ_3_SHIFT)); 172259ac0c16Sdavemq 172359ac0c16Sdavemq /* Set Serdes0 Internal Loopback if necessary */ 172459ac0c16Sdavemq if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) { 172559ac0c16Sdavemq ESR_REG_WR(handle, 172659ac0c16Sdavemq ESR_0_TEST_CONFIG_REG, 172759ac0c16Sdavemq ESR_PAD_LOOPBACK_CH3 | 172859ac0c16Sdavemq ESR_PAD_LOOPBACK_CH2 | 172959ac0c16Sdavemq ESR_PAD_LOOPBACK_CH1 | 173059ac0c16Sdavemq ESR_PAD_LOOPBACK_CH0); 173159ac0c16Sdavemq } else { 173259ac0c16Sdavemq ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0); 173344961713Sgirish } 173459ac0c16Sdavemq break; 173559ac0c16Sdavemq case 1: 17364202ea4bSsbehera /* Reset Serdes */ 17374202ea4bSsbehera ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_1); 17384202ea4bSsbehera NXGE_DELAY(20); 17394202ea4bSsbehera ESR_REG_WR(handle, ESR_RESET_REG, 0x0); 17404202ea4bSsbehera NXGE_DELAY(2000); 17414202ea4bSsbehera 17424202ea4bSsbehera /* Configure Serdes to 10G mode */ 17434202ea4bSsbehera ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG, 17444202ea4bSsbehera ESR_PLL_CFG_10G_SERDES); 17454202ea4bSsbehera 174659ac0c16Sdavemq ESR_REG_WR(handle, ESR_1_CONTROL_REG, 174759ac0c16Sdavemq ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 | 174859ac0c16Sdavemq ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 | 174959ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) | 175059ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) | 175159ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) | 175259ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 175359ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 175459ac0c16Sdavemq (0x1 << ESR_CTL_LOSADJ_0_SHIFT) | 175559ac0c16Sdavemq (0x1 << ESR_CTL_LOSADJ_1_SHIFT) | 175659ac0c16Sdavemq (0x1 << ESR_CTL_LOSADJ_2_SHIFT) | 175759ac0c16Sdavemq (0x1 << ESR_CTL_LOSADJ_3_SHIFT)); 175859ac0c16Sdavemq 175959ac0c16Sdavemq /* Set Serdes1 Internal Loopback if necessary */ 176059ac0c16Sdavemq if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) { 176159ac0c16Sdavemq ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 176259ac0c16Sdavemq ESR_PAD_LOOPBACK_CH3 | ESR_PAD_LOOPBACK_CH2 | 176359ac0c16Sdavemq ESR_PAD_LOOPBACK_CH1 | ESR_PAD_LOOPBACK_CH0); 176459ac0c16Sdavemq } else { 176559ac0c16Sdavemq ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0); 176644961713Sgirish } 176759ac0c16Sdavemq break; 176859ac0c16Sdavemq default: 176959ac0c16Sdavemq /* Nothing to do here */ 177059ac0c16Sdavemq goto done; 177159ac0c16Sdavemq } 177244961713Sgirish 177359ac0c16Sdavemq /* init TX RX channels */ 177459ac0c16Sdavemq for (chan = 0; chan < 4; chan++) { 177559ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, portn, 177659ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 177759ac0c16Sdavemq &rx_tx_ctrl_l.value)) != NXGE_OK) 177844961713Sgirish goto fail; 177959ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, portn, 178059ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 178159ac0c16Sdavemq &rx_tx_ctrl_h.value)) != NXGE_OK) 178244961713Sgirish goto fail; 178359ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, portn, 178459ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 178559ac0c16Sdavemq &glue_ctrl0_l.value)) != NXGE_OK) 178659ac0c16Sdavemq goto fail; 178759ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, portn, 178859ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 178959ac0c16Sdavemq &glue_ctrl0_h.value)) != NXGE_OK) 179059ac0c16Sdavemq goto fail; 179159ac0c16Sdavemq rx_tx_ctrl_l.bits.enstretch = 1; 179259ac0c16Sdavemq rx_tx_ctrl_h.bits.vmuxlo = 2; 179359ac0c16Sdavemq rx_tx_ctrl_h.bits.vpulselo = 2; 179459ac0c16Sdavemq glue_ctrl0_l.bits.rxlosenable = 1; 179559ac0c16Sdavemq glue_ctrl0_l.bits.samplerate = 0xF; 179659ac0c16Sdavemq glue_ctrl0_l.bits.thresholdcount = 0xFF; 179759ac0c16Sdavemq glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES; 179844961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, 179959ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 180059ac0c16Sdavemq rx_tx_ctrl_l.value)) != NXGE_OK) 180144961713Sgirish goto fail; 180244961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, 180359ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 180459ac0c16Sdavemq rx_tx_ctrl_h.value)) != NXGE_OK) 180544961713Sgirish goto fail; 180659ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, portn, 180759ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 180859ac0c16Sdavemq glue_ctrl0_l.value)) != NXGE_OK) 180944961713Sgirish goto fail; 181059ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, portn, 181159ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 181259ac0c16Sdavemq glue_ctrl0_h.value)) != NXGE_OK) 181344961713Sgirish goto fail; 181444961713Sgirish } 181544961713Sgirish 181659ac0c16Sdavemq /* Apply Tx core reset */ 181759ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, portn, 181859ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), 181959ac0c16Sdavemq (uint16_t)0)) != NXGE_OK) 182059ac0c16Sdavemq goto fail; 182159ac0c16Sdavemq 182259ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 182359ac0c16Sdavemq ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) != 182459ac0c16Sdavemq NXGE_OK) 182559ac0c16Sdavemq goto fail; 182659ac0c16Sdavemq 182759ac0c16Sdavemq NXGE_DELAY(200); 182859ac0c16Sdavemq 182959ac0c16Sdavemq /* Apply Rx core reset */ 183059ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 183159ac0c16Sdavemq ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) != 183259ac0c16Sdavemq NXGE_OK) 183359ac0c16Sdavemq goto fail; 183459ac0c16Sdavemq 183559ac0c16Sdavemq NXGE_DELAY(200); 183659ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 183759ac0c16Sdavemq ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK) 183859ac0c16Sdavemq goto fail; 183959ac0c16Sdavemq 184059ac0c16Sdavemq NXGE_DELAY(200); 184159ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, portn, 184259ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), 184359ac0c16Sdavemq &val16l)) != NXGE_OK) 184459ac0c16Sdavemq goto fail; 184559ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 184659ac0c16Sdavemq ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK) 184759ac0c16Sdavemq goto fail; 184859ac0c16Sdavemq if ((val16l != 0) || (val16h != 0)) { 184959ac0c16Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1850d81011f0Ssbehera "Failed to reset port<%d> XAUI Serdes " 1851d81011f0Ssbehera "(val16l 0x%x val16h 0x%x)", 1852d81011f0Ssbehera portn, val16l, val16h)); 185359ac0c16Sdavemq } 185459ac0c16Sdavemq 185559ac0c16Sdavemq if (portn == 0) { 1856321febdeSsbehera /* Wait for serdes to be ready */ 1857321febdeSsbehera for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) { 1858321febdeSsbehera ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val); 1859321febdeSsbehera if ((val & ESR_SIG_P0_BITS_MASK) != 1860321febdeSsbehera (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0 | 1861321febdeSsbehera ESR_SIG_XSERDES_RDY_P0 | 1862321febdeSsbehera ESR_SIG_XDETECT_P0_CH3 | 1863321febdeSsbehera ESR_SIG_XDETECT_P0_CH2 | 1864321febdeSsbehera ESR_SIG_XDETECT_P0_CH1 | 1865321febdeSsbehera ESR_SIG_XDETECT_P0_CH0)) 1866321febdeSsbehera 1867321febdeSsbehera NXGE_DELAY(SERDES_RDY_WT_INTERVAL); 1868321febdeSsbehera else 1869321febdeSsbehera break; 1870321febdeSsbehera } 1871321febdeSsbehera 1872321febdeSsbehera if (i == MAX_SERDES_RDY_RETRIES) { 1873ab6abb7aSjoycey /* 1874ab6abb7aSjoycey * RDY signal stays low may due to the absent of the 1875ab6abb7aSjoycey * external PHY, it is not an error condition. But still 1876ab6abb7aSjoycey * print the message for the debugging purpose when link 1877ab6abb7aSjoycey * stays down 1878ab6abb7aSjoycey */ 1879321febdeSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1880321febdeSsbehera "nxge_neptune_10G_serdes_init: " 1881321febdeSsbehera "Serdes/signal for port<%d> not ready", portn)); 188200161856Syc goto done; 188359ac0c16Sdavemq } 188459ac0c16Sdavemq } else if (portn == 1) { 1885321febdeSsbehera /* Wait for serdes to be ready */ 1886321febdeSsbehera for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) { 1887321febdeSsbehera ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val); 1888321febdeSsbehera if ((val & ESR_SIG_P1_BITS_MASK) != 1889321febdeSsbehera (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1 | 1890321febdeSsbehera ESR_SIG_XSERDES_RDY_P1 | 1891321febdeSsbehera ESR_SIG_XDETECT_P1_CH3 | 1892321febdeSsbehera ESR_SIG_XDETECT_P1_CH2 | 1893321febdeSsbehera ESR_SIG_XDETECT_P1_CH1 | 1894321febdeSsbehera ESR_SIG_XDETECT_P1_CH0)) 1895321febdeSsbehera 1896321febdeSsbehera NXGE_DELAY(SERDES_RDY_WT_INTERVAL); 1897321febdeSsbehera else 1898321febdeSsbehera break; 1899321febdeSsbehera } 1900321febdeSsbehera 1901321febdeSsbehera if (i == MAX_SERDES_RDY_RETRIES) { 1902ab6abb7aSjoycey /* 1903ab6abb7aSjoycey * RDY signal stays low may due to the absent of the 1904ab6abb7aSjoycey * external PHY, it is not an error condition. But still 1905ab6abb7aSjoycey * print the message for the debugging purpose when link 1906ab6abb7aSjoycey * stays down 1907ab6abb7aSjoycey */ 1908321febdeSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1909321febdeSsbehera "nxge_neptune_10G_serdes_init: " 1910321febdeSsbehera "Serdes/signal for port<%d> not ready", portn)); 191100161856Syc goto done; 191244961713Sgirish } 191344961713Sgirish } 191444961713Sgirish 191544961713Sgirish done: 191659ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 191759ac0c16Sdavemq "<== nxge_neptune_10G_serdes_init port<%d>", portn)); 191859ac0c16Sdavemq 191944961713Sgirish return (NXGE_OK); 192044961713Sgirish fail: 19212d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 192259ac0c16Sdavemq "nxge_neptune_10G_serdes_init: " 192359ac0c16Sdavemq "Failed to initialize Neptune serdes for port<%d>", portn)); 192444961713Sgirish 192544961713Sgirish return (status); 192644961713Sgirish } 192744961713Sgirish 192859ac0c16Sdavemq /* Initialize Neptune Internal Serdes for 1G (Neptune only) */ 192944961713Sgirish 193059ac0c16Sdavemq static nxge_status_t 193159ac0c16Sdavemq nxge_1G_serdes_init(p_nxge_t nxgep) 193244961713Sgirish { 193359ac0c16Sdavemq npi_handle_t handle; 193459ac0c16Sdavemq uint8_t portn; 1935d81011f0Ssbehera int chan; 1936d81011f0Ssbehera sr_rx_tx_ctrl_l_t rx_tx_ctrl_l; 1937d81011f0Ssbehera sr_rx_tx_ctrl_h_t rx_tx_ctrl_h; 1938d81011f0Ssbehera sr_glue_ctrl0_l_t glue_ctrl0_l; 1939d81011f0Ssbehera sr_glue_ctrl0_h_t glue_ctrl0_h; 194059ac0c16Sdavemq uint64_t val; 1941d81011f0Ssbehera uint16_t val16l; 1942d81011f0Ssbehera uint16_t val16h; 1943d81011f0Ssbehera nxge_status_t status = NXGE_OK; 194444961713Sgirish 194544961713Sgirish portn = nxgep->mac.portnum; 194644961713Sgirish 194759ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 194859ac0c16Sdavemq "==> nxge_1G_serdes_init port<%d>", portn)); 194944961713Sgirish 195059ac0c16Sdavemq handle = nxgep->npi_handle; 195144961713Sgirish 195259ac0c16Sdavemq switch (portn) { 195359ac0c16Sdavemq case 0: 1954d81011f0Ssbehera /* Assert the reset register */ 1955d81011f0Ssbehera ESR_REG_RD(handle, ESR_RESET_REG, &val); 1956d81011f0Ssbehera val |= ESR_RESET_0; 1957d81011f0Ssbehera ESR_REG_WR(handle, ESR_RESET_REG, val); 1958d81011f0Ssbehera 1959d81011f0Ssbehera /* Set the PLL register to 0x79 */ 1960d81011f0Ssbehera ESR_REG_WR(handle, ESR_0_PLL_CONFIG_REG, 1961d81011f0Ssbehera ESR_PLL_CFG_1G_SERDES); 1962d81011f0Ssbehera 1963d81011f0Ssbehera /* Set the control register to 0x249249f */ 1964d81011f0Ssbehera ESR_REG_WR(handle, ESR_0_CONTROL_REG, ESR_CTL_1G_SERDES); 1965d81011f0Ssbehera 1966d81011f0Ssbehera /* Set Serdes0 Internal Loopback if necessary */ 1967d81011f0Ssbehera if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) { 1968d81011f0Ssbehera /* Set pad loopback modes 0xaa */ 1969d81011f0Ssbehera ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 1970d81011f0Ssbehera ESR_TSTCFG_LBTEST_PAD); 1971d81011f0Ssbehera } else { 1972d81011f0Ssbehera ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0); 1973d81011f0Ssbehera } 1974d81011f0Ssbehera 1975d81011f0Ssbehera /* Deassert the reset register */ 1976d81011f0Ssbehera ESR_REG_RD(handle, ESR_RESET_REG, &val); 1977d81011f0Ssbehera val &= ~ESR_RESET_0; 1978d81011f0Ssbehera ESR_REG_WR(handle, ESR_RESET_REG, val); 197959ac0c16Sdavemq break; 1980d81011f0Ssbehera 198159ac0c16Sdavemq case 1: 1982d81011f0Ssbehera /* Assert the reset register */ 1983d81011f0Ssbehera ESR_REG_RD(handle, ESR_RESET_REG, &val); 1984d81011f0Ssbehera val |= ESR_RESET_1; 1985d81011f0Ssbehera ESR_REG_WR(handle, ESR_RESET_REG, val); 1986d81011f0Ssbehera 1987d81011f0Ssbehera /* Set PLL register to 0x79 */ 1988d81011f0Ssbehera ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG, 1989d81011f0Ssbehera ESR_PLL_CFG_1G_SERDES); 1990d81011f0Ssbehera 1991d81011f0Ssbehera /* Set the control register to 0x249249f */ 1992d81011f0Ssbehera ESR_REG_WR(handle, ESR_1_CONTROL_REG, ESR_CTL_1G_SERDES); 1993d81011f0Ssbehera 1994d81011f0Ssbehera /* Set Serdes1 Internal Loopback if necessary */ 1995d81011f0Ssbehera if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) { 1996d81011f0Ssbehera /* Set pad loopback mode 0xaa */ 1997d81011f0Ssbehera ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 1998d81011f0Ssbehera ESR_TSTCFG_LBTEST_PAD); 1999d81011f0Ssbehera } else { 2000d81011f0Ssbehera ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0); 2001d81011f0Ssbehera } 2002d81011f0Ssbehera 2003d81011f0Ssbehera /* Deassert the reset register */ 2004d81011f0Ssbehera ESR_REG_RD(handle, ESR_RESET_REG, &val); 2005d81011f0Ssbehera val &= ~ESR_RESET_1; 2006d81011f0Ssbehera ESR_REG_WR(handle, ESR_RESET_REG, val); 200759ac0c16Sdavemq break; 2008d81011f0Ssbehera 200959ac0c16Sdavemq default: 2010d81011f0Ssbehera /* Nothing to do here */ 2011d81011f0Ssbehera goto done; 2012d81011f0Ssbehera } 2013d81011f0Ssbehera 2014d81011f0Ssbehera /* init TX RX channels */ 2015d81011f0Ssbehera for (chan = 0; chan < 4; chan++) { 2016d81011f0Ssbehera if ((status = nxge_mdio_read(nxgep, portn, 2017d81011f0Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 2018d81011f0Ssbehera &rx_tx_ctrl_l.value)) != NXGE_OK) { 2019d81011f0Ssbehera goto fail; 2020d81011f0Ssbehera } 2021d81011f0Ssbehera if ((status = nxge_mdio_read(nxgep, portn, 2022d81011f0Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 2023d81011f0Ssbehera &rx_tx_ctrl_h.value)) != NXGE_OK) { 2024d81011f0Ssbehera goto fail; 2025d81011f0Ssbehera } 2026d81011f0Ssbehera if ((status = nxge_mdio_read(nxgep, portn, 2027d81011f0Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 2028d81011f0Ssbehera &glue_ctrl0_l.value)) != NXGE_OK) { 2029d81011f0Ssbehera goto fail; 2030d81011f0Ssbehera } 2031d81011f0Ssbehera if ((status = nxge_mdio_read(nxgep, portn, 2032d81011f0Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 2033d81011f0Ssbehera &glue_ctrl0_h.value)) != NXGE_OK) { 2034d81011f0Ssbehera goto fail; 2035d81011f0Ssbehera } 2036d81011f0Ssbehera 2037d81011f0Ssbehera rx_tx_ctrl_l.bits.enstretch = 1; 2038d81011f0Ssbehera rx_tx_ctrl_h.bits.vmuxlo = 2; 2039d81011f0Ssbehera rx_tx_ctrl_h.bits.vpulselo = 2; 2040d81011f0Ssbehera glue_ctrl0_l.bits.rxlosenable = 1; 2041d81011f0Ssbehera glue_ctrl0_l.bits.samplerate = 0xF; 2042d81011f0Ssbehera glue_ctrl0_l.bits.thresholdcount = 0xFF; 2043d81011f0Ssbehera glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES; 2044d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, 2045d81011f0Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 2046d81011f0Ssbehera rx_tx_ctrl_l.value)) != NXGE_OK) { 2047d81011f0Ssbehera goto fail; 2048d81011f0Ssbehera } 2049d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, 2050d81011f0Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 2051d81011f0Ssbehera rx_tx_ctrl_h.value)) != NXGE_OK) { 2052d81011f0Ssbehera goto fail; 2053d81011f0Ssbehera } 2054d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, 2055d81011f0Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 2056d81011f0Ssbehera glue_ctrl0_l.value)) != NXGE_OK) { 2057d81011f0Ssbehera goto fail; 2058d81011f0Ssbehera } 2059d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, 2060d81011f0Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 2061d81011f0Ssbehera glue_ctrl0_h.value)) != NXGE_OK) { 2062d81011f0Ssbehera goto fail; 2063d81011f0Ssbehera } 2064d81011f0Ssbehera } 2065d81011f0Ssbehera 2066d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2067d81011f0Ssbehera ESR_NEP_RX_POWER_CONTROL_L_ADDR(), 0xfff)) != NXGE_OK) { 2068d81011f0Ssbehera goto fail; 2069d81011f0Ssbehera } 2070d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2071d81011f0Ssbehera ESR_NEP_RX_POWER_CONTROL_H_ADDR(), 0xfff)) != NXGE_OK) { 2072d81011f0Ssbehera goto fail; 2073d81011f0Ssbehera } 2074d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2075d81011f0Ssbehera ESR_NEP_TX_POWER_CONTROL_L_ADDR(), 0x70)) != NXGE_OK) { 2076d81011f0Ssbehera goto fail; 2077d81011f0Ssbehera } 2078d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2079d81011f0Ssbehera ESR_NEP_TX_POWER_CONTROL_H_ADDR(), 0xfff)) != NXGE_OK) { 208059ac0c16Sdavemq goto fail; 208144961713Sgirish } 208244961713Sgirish 2083d81011f0Ssbehera /* Apply Tx core reset */ 2084d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2085d81011f0Ssbehera ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0)) != NXGE_OK) { 2086d81011f0Ssbehera goto fail; 2087d81011f0Ssbehera } 2088d81011f0Ssbehera 2089d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2090d81011f0Ssbehera ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) != 2091d81011f0Ssbehera NXGE_OK) { 2092d81011f0Ssbehera goto fail; 2093d81011f0Ssbehera } 2094d81011f0Ssbehera 2095d81011f0Ssbehera NXGE_DELAY(200); 2096d81011f0Ssbehera 2097d81011f0Ssbehera /* Apply Rx core reset */ 2098d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2099d81011f0Ssbehera ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) != 2100d81011f0Ssbehera NXGE_OK) { 2101d81011f0Ssbehera goto fail; 2102d81011f0Ssbehera } 2103d81011f0Ssbehera 2104d81011f0Ssbehera NXGE_DELAY(200); 2105d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2106d81011f0Ssbehera ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK) { 2107d81011f0Ssbehera goto fail; 2108d81011f0Ssbehera } 2109d81011f0Ssbehera 2110d81011f0Ssbehera NXGE_DELAY(200); 2111d81011f0Ssbehera if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2112d81011f0Ssbehera ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), &val16l)) != NXGE_OK) { 2113d81011f0Ssbehera goto fail; 2114d81011f0Ssbehera } 2115d81011f0Ssbehera if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2116d81011f0Ssbehera ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK) { 2117d81011f0Ssbehera goto fail; 2118d81011f0Ssbehera } 2119d81011f0Ssbehera if ((val16l != 0) || (val16h != 0)) { 2120d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2121d81011f0Ssbehera "Failed to reset port<%d> XAUI Serdes " 2122d81011f0Ssbehera "(val16l 0x%x val16h 0x%x)", portn, val16l, val16h)); 2123d81011f0Ssbehera status = NXGE_ERROR; 2124d81011f0Ssbehera goto fail; 2125d81011f0Ssbehera } 2126d81011f0Ssbehera 2127d81011f0Ssbehera NXGE_DELAY(200); 2128d81011f0Ssbehera ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val); 2129d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2130d81011f0Ssbehera "nxge_neptune_serdes_init: read internal signal reg port<%d> " 2131d81011f0Ssbehera "val 0x%x", portn, val)); 2132d81011f0Ssbehera if (portn == 0) { 2133d81011f0Ssbehera if ((val & ESR_SIG_P0_BITS_MASK_1G) != 2134d81011f0Ssbehera (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0)) { 2135ab6abb7aSjoycey /* 2136ab6abb7aSjoycey * RDY signal stays low may due to the absent of the 2137ab6abb7aSjoycey * external PHY, it is not an error condition. But still 2138ab6abb7aSjoycey * print the message for the debugging purpose when link 2139ab6abb7aSjoycey * stays down 2140ab6abb7aSjoycey */ 2141d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2142ab6abb7aSjoycey "nxge_neptune_1G_serdes_init: " 2143ab6abb7aSjoycey "Serdes/signal for port<%d> not ready", portn)); 214400161856Syc goto done; 2145d81011f0Ssbehera } 2146d81011f0Ssbehera } else if (portn == 1) { 2147d81011f0Ssbehera if ((val & ESR_SIG_P1_BITS_MASK_1G) != 2148d81011f0Ssbehera (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1)) { 2149ab6abb7aSjoycey /* 2150ab6abb7aSjoycey * RDY signal stays low may due to the absent of the 2151ab6abb7aSjoycey * external PHY, it is not an error condition. But still 2152ab6abb7aSjoycey * print the message for the debugging purpose when link 2153ab6abb7aSjoycey * stays down 2154ab6abb7aSjoycey */ 2155d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2156ab6abb7aSjoycey "nxge_neptune_1G_serdes_init: " 2157ab6abb7aSjoycey "Serdes/signal for port<%d> not ready", portn)); 215800161856Syc goto done; 215900161856Syc 2160d81011f0Ssbehera } 2161d81011f0Ssbehera } 2162d81011f0Ssbehera done: 216359ac0c16Sdavemq 216459ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 216559ac0c16Sdavemq "<== nxge_1G_serdes_init port<%d>", portn)); 216644961713Sgirish return (NXGE_OK); 216759ac0c16Sdavemq fail: 2168d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 216959ac0c16Sdavemq "nxge_1G_serdes_init: " 217059ac0c16Sdavemq "Failed to initialize Neptune serdes for port<%d>", 217159ac0c16Sdavemq portn)); 217259ac0c16Sdavemq 2173d81011f0Ssbehera return (status); 217444961713Sgirish } 217544961713Sgirish 21762d17280bSsbehera /* Initialize the BCM 8704 xcvr */ 217744961713Sgirish 217859ac0c16Sdavemq static nxge_status_t 21792d17280bSsbehera nxge_BCM8704_xcvr_init(p_nxge_t nxgep) 218044961713Sgirish { 218144961713Sgirish uint16_t val; 218244961713Sgirish #ifdef NXGE_DEBUG 218314ea4bb7Ssd uint8_t portn; 218444961713Sgirish uint16_t val1; 218544961713Sgirish #endif 218644961713Sgirish uint8_t phy_port_addr; 218744961713Sgirish pmd_tx_control_t tx_ctl; 218844961713Sgirish control_t ctl; 218944961713Sgirish phyxs_control_t phyxs_ctl; 219044961713Sgirish pcs_control_t pcs_ctl; 219144961713Sgirish uint32_t delay = 0; 219244961713Sgirish optics_dcntr_t op_ctr; 219344961713Sgirish nxge_status_t status = NXGE_OK; 219414ea4bb7Ssd #ifdef NXGE_DEBUG 219544961713Sgirish portn = nxgep->mac.portnum; 219614ea4bb7Ssd #endif 21972d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8704_xcvr_init: port<%d>", 219859ac0c16Sdavemq portn)); 219944961713Sgirish 220059ac0c16Sdavemq phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn; 220159ac0c16Sdavemq 220259ac0c16Sdavemq /* Reset the transceiver */ 220359ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 220459ac0c16Sdavemq BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK) 220559ac0c16Sdavemq goto fail; 220659ac0c16Sdavemq 220759ac0c16Sdavemq phyxs_ctl.bits.reset = 1; 220859ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 220959ac0c16Sdavemq BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK) 221059ac0c16Sdavemq goto fail; 221159ac0c16Sdavemq 221259ac0c16Sdavemq do { 221359ac0c16Sdavemq drv_usecwait(500); 221459ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 221559ac0c16Sdavemq BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG, 221659ac0c16Sdavemq &phyxs_ctl.value)) != NXGE_OK) 221759ac0c16Sdavemq goto fail; 221859ac0c16Sdavemq delay++; 221959ac0c16Sdavemq } while ((phyxs_ctl.bits.reset) && (delay < 100)); 222059ac0c16Sdavemq if (delay == 100) { 222159ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: " 222259ac0c16Sdavemq "failed to reset Transceiver on port<%d>", portn)); 222359ac0c16Sdavemq status = NXGE_ERROR; 222459ac0c16Sdavemq goto fail; 222559ac0c16Sdavemq } 222644961713Sgirish 222759ac0c16Sdavemq /* Set to 0x7FBF */ 222859ac0c16Sdavemq ctl.value = 0; 222959ac0c16Sdavemq ctl.bits.res1 = 0x3F; 223059ac0c16Sdavemq ctl.bits.optxon_lvl = 1; 223159ac0c16Sdavemq ctl.bits.oprxflt_lvl = 1; 223259ac0c16Sdavemq ctl.bits.optrxlos_lvl = 1; 223359ac0c16Sdavemq ctl.bits.optxflt_lvl = 1; 223459ac0c16Sdavemq ctl.bits.opprflt_lvl = 1; 223559ac0c16Sdavemq ctl.bits.obtmpflt_lvl = 1; 223659ac0c16Sdavemq ctl.bits.opbiasflt_lvl = 1; 223759ac0c16Sdavemq ctl.bits.optxrst_lvl = 1; 223859ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, 223959ac0c16Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, ctl.value)) 224059ac0c16Sdavemq != NXGE_OK) 224159ac0c16Sdavemq goto fail; 224259ac0c16Sdavemq 224359ac0c16Sdavemq /* Set to 0x164 */ 224459ac0c16Sdavemq tx_ctl.value = 0; 224559ac0c16Sdavemq tx_ctl.bits.tsck_lpwren = 1; 224659ac0c16Sdavemq tx_ctl.bits.tx_dac_txck = 0x2; 224759ac0c16Sdavemq tx_ctl.bits.tx_dac_txd = 0x1; 224859ac0c16Sdavemq tx_ctl.bits.xfp_clken = 1; 224959ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, 225059ac0c16Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, 225159ac0c16Sdavemq tx_ctl.value)) != NXGE_OK) 225259ac0c16Sdavemq goto fail; 225344961713Sgirish /* 225459ac0c16Sdavemq * According to Broadcom's instruction, SW needs to read 225559ac0c16Sdavemq * back these registers twice after written. 225644961713Sgirish */ 225759ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 225859ac0c16Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val)) 225959ac0c16Sdavemq != NXGE_OK) 226059ac0c16Sdavemq goto fail; 226144961713Sgirish 226259ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 226359ac0c16Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val)) 226459ac0c16Sdavemq != NXGE_OK) 226559ac0c16Sdavemq goto fail; 226644961713Sgirish 226759ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 226859ac0c16Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val)) 226959ac0c16Sdavemq != NXGE_OK) 227059ac0c16Sdavemq goto fail; 227144961713Sgirish 227259ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 227359ac0c16Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val)) 227459ac0c16Sdavemq != NXGE_OK) 227559ac0c16Sdavemq goto fail; 227644961713Sgirish 227759ac0c16Sdavemq /* Enable Tx and Rx LEDs to be driven by traffic */ 227859ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 227959ac0c16Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 228059ac0c16Sdavemq &op_ctr.value)) != NXGE_OK) 228159ac0c16Sdavemq goto fail; 2282cb9d3ae6Smisaki if (NXGE_IS_XAUI_PLATFORM(nxgep)) { 2283cb9d3ae6Smisaki op_ctr.bits.gpio_sel = 0x1; 2284cb9d3ae6Smisaki } else { 2285cb9d3ae6Smisaki op_ctr.bits.gpio_sel = 0x3; 2286cb9d3ae6Smisaki } 228759ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, 228859ac0c16Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 228959ac0c16Sdavemq op_ctr.value)) != NXGE_OK) 229059ac0c16Sdavemq goto fail; 229144961713Sgirish 229259ac0c16Sdavemq NXGE_DELAY(1000000); 229344961713Sgirish 229459ac0c16Sdavemq /* Set BCM8704 Internal Loopback mode if necessary */ 229559ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 229659ac0c16Sdavemq BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value)) 229759ac0c16Sdavemq != NXGE_OK) 229859ac0c16Sdavemq goto fail; 229959ac0c16Sdavemq if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g) 230059ac0c16Sdavemq pcs_ctl.bits.loopback = 1; 230159ac0c16Sdavemq else 230259ac0c16Sdavemq pcs_ctl.bits.loopback = 0; 230359ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, 230459ac0c16Sdavemq BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value)) 230559ac0c16Sdavemq != NXGE_OK) 230659ac0c16Sdavemq goto fail; 230744961713Sgirish 230859ac0c16Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 0x1, 0xA, &val); 230959ac0c16Sdavemq if (status != NXGE_OK) 231059ac0c16Sdavemq goto fail; 231159ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 231259ac0c16Sdavemq "BCM8704 port<%d> Dev 1 Reg 0xA = 0x%x\n", portn, val)); 231359ac0c16Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0x20, &val); 231459ac0c16Sdavemq if (status != NXGE_OK) 231559ac0c16Sdavemq goto fail; 231659ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 231759ac0c16Sdavemq "BCM8704 port<%d> Dev 3 Reg 0x20 = 0x%x\n", portn, val)); 231859ac0c16Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, &val); 231959ac0c16Sdavemq if (status != NXGE_OK) 232059ac0c16Sdavemq goto fail; 232159ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 232259ac0c16Sdavemq "BCM8704 port<%d> Dev 4 Reg 0x18 = 0x%x\n", portn, val)); 232344961713Sgirish 232459ac0c16Sdavemq #ifdef NXGE_DEBUG 232559ac0c16Sdavemq /* Diagnose link issue if link is not up */ 232659ac0c16Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_USER_DEV3_ADDR, 232759ac0c16Sdavemq BCM8704_USER_ANALOG_STATUS0_REG, 232859ac0c16Sdavemq &val); 232959ac0c16Sdavemq if (status != NXGE_OK) 233059ac0c16Sdavemq goto fail; 233144961713Sgirish 233259ac0c16Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 233344961713Sgirish BCM8704_USER_DEV3_ADDR, 233459ac0c16Sdavemq BCM8704_USER_ANALOG_STATUS0_REG, 233559ac0c16Sdavemq &val); 233659ac0c16Sdavemq if (status != NXGE_OK) 233759ac0c16Sdavemq goto fail; 233844961713Sgirish 233959ac0c16Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 234044961713Sgirish BCM8704_USER_DEV3_ADDR, 234159ac0c16Sdavemq BCM8704_USER_TX_ALARM_STATUS_REG, 234259ac0c16Sdavemq &val1); 234359ac0c16Sdavemq if (status != NXGE_OK) 234459ac0c16Sdavemq goto fail; 234544961713Sgirish 234659ac0c16Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 234744961713Sgirish BCM8704_USER_DEV3_ADDR, 234859ac0c16Sdavemq BCM8704_USER_TX_ALARM_STATUS_REG, 234959ac0c16Sdavemq &val1); 235059ac0c16Sdavemq if (status != NXGE_OK) 235159ac0c16Sdavemq goto fail; 235244961713Sgirish 235359ac0c16Sdavemq if (val != 0x3FC) { 235459ac0c16Sdavemq if ((val == 0x43BC) && (val1 != 0)) { 235559ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 235659ac0c16Sdavemq "Cable not connected to peer or bad" 235759ac0c16Sdavemq " cable on port<%d>\n", portn)); 235859ac0c16Sdavemq } else if (val == 0x639C) { 235959ac0c16Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 236059ac0c16Sdavemq "Optical module (XFP) is bad or absent" 236159ac0c16Sdavemq " on port<%d>\n", portn)); 236259ac0c16Sdavemq } 236359ac0c16Sdavemq } 236459ac0c16Sdavemq #endif 236544961713Sgirish 23662d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8704_xcvr_init: port<%d>", 23672d17280bSsbehera portn)); 23682d17280bSsbehera return (NXGE_OK); 23692d17280bSsbehera 23702d17280bSsbehera fail: 23712d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 23722d17280bSsbehera "nxge_BCM8704_xcvr_init: failed to initialize transceiver for " 23732d17280bSsbehera "port<%d>", nxgep->mac.portnum)); 23742d17280bSsbehera return (NXGE_ERROR); 23752d17280bSsbehera } 23762d17280bSsbehera 23772d17280bSsbehera /* Initialize the BCM 8706 Transceiver */ 23782d17280bSsbehera 23792d17280bSsbehera static nxge_status_t 23802d17280bSsbehera nxge_BCM8706_xcvr_init(p_nxge_t nxgep) 23812d17280bSsbehera { 23822d17280bSsbehera uint8_t phy_port_addr; 23832d17280bSsbehera phyxs_control_t phyxs_ctl; 23842d17280bSsbehera pcs_control_t pcs_ctl; 23852d17280bSsbehera uint32_t delay = 0; 23862d17280bSsbehera optics_dcntr_t op_ctr; 23872d17280bSsbehera nxge_status_t status = NXGE_OK; 23882d17280bSsbehera #ifdef NXGE_DEBUG 23892d17280bSsbehera uint8_t portn = nxgep->mac.portnum; 23902d17280bSsbehera #endif 23912d17280bSsbehera 23922d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8706_xcvr_init: port<%d>", 23932d17280bSsbehera portn)); 23942d17280bSsbehera 23952d17280bSsbehera phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn; 23962d17280bSsbehera 23972d17280bSsbehera /* Reset the transceiver */ 23982d17280bSsbehera if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 23992d17280bSsbehera BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK) 24002d17280bSsbehera goto fail; 24012d17280bSsbehera 24022d17280bSsbehera phyxs_ctl.bits.reset = 1; 24032d17280bSsbehera if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 24042d17280bSsbehera BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK) 24052d17280bSsbehera goto fail; 24062d17280bSsbehera do { 24072d17280bSsbehera drv_usecwait(500); 24082d17280bSsbehera if ((status = nxge_mdio_read(nxgep, phy_port_addr, 24092d17280bSsbehera BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG, 24102d17280bSsbehera &phyxs_ctl.value)) != NXGE_OK) 24112d17280bSsbehera goto fail; 24122d17280bSsbehera delay++; 24132d17280bSsbehera } while ((phyxs_ctl.bits.reset) && (delay < 100)); 24142d17280bSsbehera 24152d17280bSsbehera if (delay == 100) { 24162d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: " 24172d17280bSsbehera "failed to reset Transceiver on port<%d>", portn)); 24182d17280bSsbehera status = NXGE_ERROR; 24192d17280bSsbehera goto fail; 24202d17280bSsbehera } 24212d17280bSsbehera 24222d17280bSsbehera NXGE_DELAY(1000000); 24232d17280bSsbehera 24242d17280bSsbehera /* Set BCM8706 Internal Loopback mode if necessary */ 24252d17280bSsbehera if ((status = nxge_mdio_read(nxgep, phy_port_addr, 24262d17280bSsbehera BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value)) 24272d17280bSsbehera != NXGE_OK) 24282d17280bSsbehera goto fail; 24292d17280bSsbehera if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g) 24302d17280bSsbehera pcs_ctl.bits.loopback = 1; 24312d17280bSsbehera else 24322d17280bSsbehera pcs_ctl.bits.loopback = 0; 24332d17280bSsbehera if ((status = nxge_mdio_write(nxgep, phy_port_addr, 24342d17280bSsbehera BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value)) 24352d17280bSsbehera != NXGE_OK) 24362d17280bSsbehera goto fail; 24372d17280bSsbehera 24382d17280bSsbehera /* Enable Tx and Rx LEDs to be driven by traffic */ 24392d17280bSsbehera if ((status = nxge_mdio_read(nxgep, phy_port_addr, 24402d17280bSsbehera BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 24412d17280bSsbehera &op_ctr.value)) != NXGE_OK) 24422d17280bSsbehera goto fail; 24432d17280bSsbehera op_ctr.bits.gpio_sel = 0x3; 24442d17280bSsbehera op_ctr.bits.res2 = 0x1; 24452d17280bSsbehera 24462d17280bSsbehera if ((status = nxge_mdio_write(nxgep, phy_port_addr, 24472d17280bSsbehera BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 24482d17280bSsbehera op_ctr.value)) != NXGE_OK) 24492d17280bSsbehera goto fail; 24502d17280bSsbehera 24512d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8706_xcvr_init: port<%d>", 24522d17280bSsbehera portn)); 24532d17280bSsbehera return (NXGE_OK); 24542d17280bSsbehera 24552d17280bSsbehera fail: 24562d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 24572d17280bSsbehera "nxge_BCM8706_xcvr_init: failed to initialize transceiver for " 24582d17280bSsbehera "port<%d>", nxgep->mac.portnum)); 24592d17280bSsbehera return (status); 24602d17280bSsbehera } 24612d17280bSsbehera 246252cdd236Ssbehera #define CHK_STAT(x) status = (x); if (status != NXGE_OK) goto fail 246352cdd236Ssbehera 246452cdd236Ssbehera #define MRVL88X2011_RD(nxgep, port, d, r, p) \ 246552cdd236Ssbehera CHK_STAT(nxge_mdio_read(nxgep, port, d, r, p)) 246652cdd236Ssbehera 246752cdd236Ssbehera #define MRVL88X2011_WR(nxgep, port, d, r, p) \ 246852cdd236Ssbehera CHK_STAT(nxge_mdio_write(nxgep, port, d, r, p)) 246952cdd236Ssbehera 247052cdd236Ssbehera 247152cdd236Ssbehera static void 247252cdd236Ssbehera nxge_mrvl88x2011_led_blink_rate(p_nxge_t nxgep, uint16_t rate) 247352cdd236Ssbehera { 247452cdd236Ssbehera uint16_t value; 247552cdd236Ssbehera uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn; 247652cdd236Ssbehera 247752cdd236Ssbehera if (nxge_mdio_read(nxgep, phy, MRVL_88X2011_USER_DEV2_ADDR, 247852cdd236Ssbehera MRVL_88X2011_LED_BLINK_CTL, &value) == NXGE_OK) { 247952cdd236Ssbehera value &= ~MRVL_88X2011_LED_BLK_MASK; 248052cdd236Ssbehera value |= (rate << MRVL_88X2011_LED_BLK_SHIFT); 248152cdd236Ssbehera (void) nxge_mdio_write(nxgep, phy, 248252cdd236Ssbehera MRVL_88X2011_USER_DEV2_ADDR, MRVL_88X2011_LED_BLINK_CTL, 248352cdd236Ssbehera value); 248452cdd236Ssbehera } 248552cdd236Ssbehera } 248652cdd236Ssbehera 248752cdd236Ssbehera static nxge_status_t 248852cdd236Ssbehera nxge_mrvl88x2011_setup_lb(p_nxge_t nxgep) 248952cdd236Ssbehera { 249052cdd236Ssbehera nxge_status_t status; 249152cdd236Ssbehera pcs_control_t pcs_ctl; 249252cdd236Ssbehera uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn; 249352cdd236Ssbehera 249452cdd236Ssbehera MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR, 249552cdd236Ssbehera MRVL_88X2011_PMA_PMD_CTL_1, &pcs_ctl.value); 249652cdd236Ssbehera 249752cdd236Ssbehera if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g) 249852cdd236Ssbehera pcs_ctl.bits.loopback = 1; 249952cdd236Ssbehera else 250052cdd236Ssbehera pcs_ctl.bits.loopback = 0; 250152cdd236Ssbehera 250252cdd236Ssbehera MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR, 250352cdd236Ssbehera MRVL_88X2011_PMA_PMD_CTL_1, pcs_ctl.value); 250452cdd236Ssbehera 250552cdd236Ssbehera fail: 250652cdd236Ssbehera return (status); 250752cdd236Ssbehera } 250852cdd236Ssbehera 250952cdd236Ssbehera 251052cdd236Ssbehera static void 251152cdd236Ssbehera nxge_mrvl88x2011_led(p_nxge_t nxgep, uint16_t val) 251252cdd236Ssbehera { 251352cdd236Ssbehera uint16_t val2; 251452cdd236Ssbehera uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn; 251552cdd236Ssbehera 251652cdd236Ssbehera val2 = MRVL_88X2011_LED(MRVL_88X2011_LED_ACT, val); 251752cdd236Ssbehera val2 &= ~MRVL_88X2011_LED(MRVL_88X2011_LED_ACT, 251852cdd236Ssbehera MRVL_88X2011_LED_CTL_MASK); 251952cdd236Ssbehera val2 |= MRVL_88X2011_LED(MRVL_88X2011_LED_ACT, val); 252052cdd236Ssbehera 252152cdd236Ssbehera if (nxge_mdio_write(nxgep, phy, MRVL_88X2011_USER_DEV2_ADDR, 252252cdd236Ssbehera MRVL_88X2011_LED_8_TO_11_CTL, val2) != NXGE_OK) { 252352cdd236Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 252452cdd236Ssbehera "nxge_mrvl88x2011_led: nxge_mdio_write failed!!")); 252552cdd236Ssbehera } 252652cdd236Ssbehera } 252752cdd236Ssbehera 252852cdd236Ssbehera 252952cdd236Ssbehera static nxge_status_t 253052cdd236Ssbehera nxge_mrvl88x2011_xcvr_init(p_nxge_t nxgep) 253152cdd236Ssbehera { 253252cdd236Ssbehera uint8_t phy; 253352cdd236Ssbehera nxge_status_t status; 253452cdd236Ssbehera uint16_t clk; 253552cdd236Ssbehera 253652cdd236Ssbehera phy = nxgep->statsp->mac_stats.xcvr_portn; 253752cdd236Ssbehera 253852cdd236Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 253952cdd236Ssbehera "==> nxge_mrvl88x2011_xcvr_init: port<%d> addr<0x%x>", 254052cdd236Ssbehera nxgep->mac.portnum, phy)); 254152cdd236Ssbehera 254252cdd236Ssbehera /* Set LED functions */ 254352cdd236Ssbehera nxge_mrvl88x2011_led_blink_rate(nxgep, MRVL_88X2011_LED_BLK134MS); 254452cdd236Ssbehera /* PCS activity */ 254552cdd236Ssbehera nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_ACT); 254652cdd236Ssbehera 254752cdd236Ssbehera MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR, 254852cdd236Ssbehera MRVL_88X2011_GEN_CTL, &clk); 254952cdd236Ssbehera clk |= MRVL_88X2011_ENA_XFPREFCLK; 255052cdd236Ssbehera MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR, 255152cdd236Ssbehera MRVL_88X2011_GEN_CTL, clk); 255252cdd236Ssbehera 255352cdd236Ssbehera /* Set internal loopback mode if necessary */ 255452cdd236Ssbehera 255552cdd236Ssbehera CHK_STAT(nxge_mrvl88x2011_setup_lb(nxgep)); 255652cdd236Ssbehera 255752cdd236Ssbehera /* Enable PMD */ 255852cdd236Ssbehera MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR, 255952cdd236Ssbehera MRVL_88X2011_10G_PMD_TX_DIS, MRVL_88X2011_ENA_PMDTX); 256052cdd236Ssbehera 256152cdd236Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, " nxge_mrvl88x2011_reset: OK")); 256252cdd236Ssbehera 256352cdd236Ssbehera fail: 256452cdd236Ssbehera return (status); 256552cdd236Ssbehera } 256652cdd236Ssbehera 256752cdd236Ssbehera 256852cdd236Ssbehera 25692d17280bSsbehera /* Initialize the 10G Transceiver */ 25702d17280bSsbehera 25712d17280bSsbehera static nxge_status_t 25722d17280bSsbehera nxge_10G_xcvr_init(p_nxge_t nxgep) 25732d17280bSsbehera { 25742d17280bSsbehera p_nxge_stats_t statsp; 25751bd6825cSml p_nxge_param_t param_arr = nxgep->param_arr; 25762d17280bSsbehera nxge_status_t status = NXGE_OK; 25772d17280bSsbehera #ifdef NXGE_DEBUG 25782d17280bSsbehera uint8_t portn = nxgep->mac.portnum; 25792d17280bSsbehera #endif 25802d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>", 25812d17280bSsbehera portn)); 25822d17280bSsbehera 25832d17280bSsbehera statsp = nxgep->statsp; 25842d17280bSsbehera 25852d17280bSsbehera if (nxgep->mac.portmode == PORT_10G_SERDES) { 25862d17280bSsbehera goto done; 25872d17280bSsbehera } 25882d17280bSsbehera 25892d17280bSsbehera /* Disable Link LEDs */ 25902d17280bSsbehera if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 25912d17280bSsbehera goto fail; 25922d17280bSsbehera 25932d17280bSsbehera /* Set Clause 45 */ 25942d17280bSsbehera npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE); 25952d17280bSsbehera 25962d17280bSsbehera switch (nxgep->chip_id) { 25972d17280bSsbehera case BCM8704_CHIP_ID: 259800161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_10G_xcvr_init: " 25992d17280bSsbehera "Chip ID 8704 [0x%x] for 10G xcvr", nxgep->chip_id)); 26002d17280bSsbehera status = nxge_BCM8704_xcvr_init(nxgep); 26012d17280bSsbehera break; 26022d17280bSsbehera case BCM8706_CHIP_ID: 260300161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_10G_xcvr_init: " 26042d17280bSsbehera "Chip ID 8706 [0x%x] for 10G xcvr", nxgep->chip_id)); 26052d17280bSsbehera status = nxge_BCM8706_xcvr_init(nxgep); 26062d17280bSsbehera break; 260752cdd236Ssbehera case MRVL88X201X_CHIP_ID: 260800161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_10G_xcvr_init: " 260952cdd236Ssbehera "Chip ID 8706 [0x%x] for 10G xcvr", nxgep->chip_id)); 261052cdd236Ssbehera status = nxge_mrvl88x2011_xcvr_init(nxgep); 261152cdd236Ssbehera break; 26122d17280bSsbehera default: 26132d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_xcvr_init: " 26142d17280bSsbehera "Unknown chip ID 0x%x for 10G xcvr addr[%d]", 26152d17280bSsbehera nxgep->chip_id, nxgep->statsp->mac_stats.xcvr_portn)); 26162d17280bSsbehera goto fail; 26172d17280bSsbehera } 26182d17280bSsbehera 26192d17280bSsbehera if (status != NXGE_OK) { 26202d17280bSsbehera goto fail; 26212d17280bSsbehera } 26222e59129aSraghus done: 262359ac0c16Sdavemq statsp->mac_stats.cap_10gfdx = 1; 262459ac0c16Sdavemq statsp->mac_stats.lp_cap_10gfdx = 1; 26251bd6825cSml statsp->mac_stats.adv_cap_asmpause = 26261bd6825cSml param_arr[param_anar_asmpause].value; 26271bd6825cSml statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value; 262844961713Sgirish 262959ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>", 263059ac0c16Sdavemq portn)); 263159ac0c16Sdavemq return (NXGE_OK); 263244961713Sgirish 263359ac0c16Sdavemq fail: 26342d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 263559ac0c16Sdavemq "nxge_10G_xcvr_init: failed to initialize transceiver for " 26362d17280bSsbehera "port<%d>", nxgep->mac.portnum)); 26372d17280bSsbehera return (NXGE_ERROR); 263859ac0c16Sdavemq } 263944961713Sgirish 264059ac0c16Sdavemq /* Initialize the 1G copper (BCM 5464) Transceiver */ 264144961713Sgirish 264259ac0c16Sdavemq static nxge_status_t 264359ac0c16Sdavemq nxge_1G_xcvr_init(p_nxge_t nxgep) 264459ac0c16Sdavemq { 264559ac0c16Sdavemq p_nxge_param_t param_arr = nxgep->param_arr; 264659ac0c16Sdavemq p_nxge_stats_t statsp = nxgep->statsp; 264759ac0c16Sdavemq nxge_status_t status = NXGE_OK; 264844961713Sgirish 26492e59129aSraghus if (nxgep->mac.portmode == PORT_1G_SERDES) { 26502e59129aSraghus statsp->mac_stats.cap_1000fdx = 26512e59129aSraghus param_arr[param_anar_1000fdx].value; 26522e59129aSraghus goto done; 26532e59129aSraghus } 26542e59129aSraghus 265559ac0c16Sdavemq /* Set Clause 22 */ 265659ac0c16Sdavemq npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_FALSE); 265744961713Sgirish 265859ac0c16Sdavemq /* Set capability flags */ 265959ac0c16Sdavemq statsp->mac_stats.cap_1000fdx = param_arr[param_anar_1000fdx].value; 26602e59129aSraghus if ((nxgep->mac.portmode == PORT_1G_COPPER) || 26612e59129aSraghus (nxgep->mac.portmode == PORT_1G_FIBER)) { 26622e59129aSraghus statsp->mac_stats.cap_100fdx = 26632e59129aSraghus param_arr[param_anar_100fdx].value; 26642e59129aSraghus statsp->mac_stats.cap_10fdx = 26652e59129aSraghus param_arr[param_anar_10fdx].value; 26662e59129aSraghus } 266744961713Sgirish 266859ac0c16Sdavemq status = nxge_mii_xcvr_init(nxgep); 26692e59129aSraghus done: 267059ac0c16Sdavemq return (status); 267159ac0c16Sdavemq } 267259ac0c16Sdavemq 267300161856Syc /* 267400161856Syc * Although the Teranetics copper transceiver (TN1010) does not need 267500161856Syc * to be initialized by the driver for passing packets, this funtion 267600161856Syc * initializes the members of nxgep->statsp->mac_stats struct for 267700161856Syc * kstat based on the value of nxgep->statsp->ports_stats.lb_mode. 267800161856Syc * It also configures the TN1010 for PHY loopback to support SunVTS. 267900161856Syc * 268000161856Syc * TN1010 only has the option to disable advertisement for the 10G 268100161856Syc * mode. So we can set it to either Dual Mode or 1G Only mode but 268200161856Syc * can't set it to 10G Only mode. 268300161856Syc * 268400161856Syc * ndd -set command can set the following 6 speed/duplex related parameters. 268500161856Syc * 268600161856Syc * ---------------------------------------------------------------- 268700161856Syc * ndd -set /dev/nxgeX param n kstat nxge:X | grep param 268800161856Syc * ---------------------------------------------------------------- 268900161856Syc * adv_autoneg_cap kstat nxge:1 | grep adv_cap_autoneg 269000161856Syc * adv_10gfdx_cap 269100161856Syc * adv_1000fdx_cap kstat nxge:1 | grep adv_cap_1000fdx 269200161856Syc * adv_100fdx_cap kstat nxge:1 | grep adv_cap_100fdx 269300161856Syc * adv_10fdx_cap kstat nxge:1 | grep adv_cap_10fdx 269400161856Syc * adv_pause_cap kstat nxge:1 | grep adv_cap_pause 269500161856Syc * ---------------------------------------------------------------- 269600161856Syc */ 269700161856Syc static nxge_status_t 269800161856Syc nxge_tn1010_xcvr_init(p_nxge_t nxgep) 269900161856Syc { 270000161856Syc p_nxge_param_t param_arr; 270100161856Syc p_nxge_stats_t statsp; 270200161856Syc tn1010_pcs_ctrl_t tn1010_pcs_ctrl; 270300161856Syc uint16_t speed; 270400161856Syc uint8_t phy_port_addr; 270500161856Syc uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 270600161856Syc int status = NXGE_OK; 270700161856Syc 270800161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_1G_tn1010_xcvr_init")); 270900161856Syc 271000161856Syc param_arr = nxgep->param_arr; 271100161856Syc statsp = nxgep->statsp; 271200161856Syc 271300161856Syc /* 271400161856Syc * Initialize the xcvr statistics which are NOT controlled by ndd 271500161856Syc */ 271600161856Syc statsp->mac_stats.cap_autoneg = 1; /* TN1010 autoneg is always on */ 271700161856Syc statsp->mac_stats.cap_100T4 = 0; 271800161856Syc 271900161856Syc /* 272000161856Syc * Read the TN1010 link speed and initialize capabilities kstat. Note 272100161856Syc * that function nxge_check_tn1010_link repeatedly invoked by the 272200161856Syc * timer will update link_speed real time. 272300161856Syc */ 272400161856Syc if (nxge_get_tn1010_speed(nxgep, &speed) != NXGE_OK) { 272500161856Syc goto fail; 272600161856Syc } 272700161856Syc if (speed == TN1010_SPEED_1G) { 272800161856Syc statsp->mac_stats.cap_10gfdx = 0; 272900161856Syc } else { 273000161856Syc statsp->mac_stats.cap_10gfdx = 1; 273100161856Syc } 273200161856Syc 273300161856Syc /* Whether we are in 1G or 10G mode, we always have the 1G capability */ 273400161856Syc statsp->mac_stats.cap_1000fdx = 1; 273500161856Syc 273600161856Syc /* TN1010 is not able to operate in the following states */ 273700161856Syc statsp->mac_stats.cap_1000hdx = 0; 273800161856Syc statsp->mac_stats.cap_100fdx = 0; 273900161856Syc statsp->mac_stats.cap_100hdx = 0; 274000161856Syc statsp->mac_stats.cap_10fdx = 0; 274100161856Syc statsp->mac_stats.cap_10hdx = 0; 274200161856Syc 274300161856Syc /* param_anar_pause can be modified by ndd -set */ 274400161856Syc statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value; 274500161856Syc 274600161856Syc /* 274700161856Syc * The following 4 lines actually overwrites what ever the ndd command 274800161856Syc * has set. For example, by command 274900161856Syc * ndd -set /dev/nxge1 adv_autoneg_cap n (n = 0 or 1) 275000161856Syc * we could set param_arr[param_autoneg].value to n. However, because 275100161856Syc * here we assign constants to these parameters, whatever we set with 275200161856Syc * the "ndd -set" command will be replaced. So command 275300161856Syc * kstat nxge:X | grep param 275400161856Syc * will always show those constant values. In other words, the 275500161856Syc * "ndd -set" command can NOT change the values of these 4 parameters 275600161856Syc * even though the command appears to be successful. 275700161856Syc * 275800161856Syc * Note: TN1010 auto negotiation is always enabled. 275900161856Syc */ 276000161856Syc statsp->mac_stats.adv_cap_autoneg 276100161856Syc = param_arr[param_autoneg].value = 1; 276200161856Syc statsp->mac_stats.adv_cap_1000fdx 276300161856Syc = param_arr[param_anar_1000fdx].value = 1; 276400161856Syc statsp->mac_stats.adv_cap_100fdx 276500161856Syc = param_arr[param_anar_100fdx].value = 0; 276600161856Syc statsp->mac_stats.adv_cap_10fdx 276700161856Syc = param_arr[param_anar_10fdx].value = 0; 276800161856Syc 276900161856Syc /* 277000161856Syc * The following 4 ndd params have type NXGE_PARAM_MAC_DONT_SHOW as 277100161856Syc * defined in nxge_param_arr[], therefore they are not seen by the 277200161856Syc * "ndd -get" command and can not be changed by ndd. We just set 277300161856Syc * them (both ndd param and kstat values) to constant 0 because TN1010 277400161856Syc * does not support those speeds. 277500161856Syc */ 277600161856Syc statsp->mac_stats.adv_cap_100T4 277700161856Syc = param_arr[param_anar_100T4].value = 0; 277800161856Syc statsp->mac_stats.adv_cap_1000hdx 277900161856Syc = param_arr[param_anar_1000hdx].value = 0; 278000161856Syc statsp->mac_stats.adv_cap_100hdx 278100161856Syc = param_arr[param_anar_100hdx].value = 0; 278200161856Syc statsp->mac_stats.adv_cap_10hdx 278300161856Syc = param_arr[param_anar_10hdx].value = 0; 278400161856Syc 278500161856Syc /* 278600161856Syc * adv_cap_pause has type NXGE_PARAM_MAC_RW, so it can be modified 278700161856Syc * by ndd 278800161856Syc */ 278900161856Syc statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value; 279000161856Syc 279100161856Syc /* 279200161856Syc * nxge_param_arr[] defines the adv_cap_asmpause with type 279300161856Syc * NXGE_PARAM_DONT_SHOW, therefore they are NOT seen by the 279400161856Syc * "ndd -get" command and can not be changed by ndd. Here we do not 279500161856Syc * assign a constant to it so the default value defined in 279600161856Syc * nxge_param_arr[] will be used to set the parameter and 279700161856Syc * will be shown by the kstat. 279800161856Syc */ 279900161856Syc statsp->mac_stats.adv_cap_asmpause 280000161856Syc = param_arr[param_anar_asmpause].value; 280100161856Syc 280200161856Syc /* 280300161856Syc * Initialize the link statistics. 280400161856Syc */ 280500161856Syc statsp->mac_stats.link_T4 = 0; 280600161856Syc statsp->mac_stats.link_asmpause = 0; 280700161856Syc statsp->mac_stats.link_pause = 0; 280800161856Syc if (speed == TN1010_SPEED_1G) { 280900161856Syc statsp->mac_stats.link_speed = 1000; 281000161856Syc statsp->mac_stats.link_duplex = 2; /* Full duplex */ 281100161856Syc statsp->mac_stats.link_up = 1; 281200161856Syc } else { 281300161856Syc statsp->mac_stats.link_speed = 10000; 281400161856Syc statsp->mac_stats.link_duplex = 2; 281500161856Syc statsp->mac_stats.link_up = 1; 281600161856Syc } 281700161856Syc 281800161856Syc /* 281900161856Syc * Because TN1010 does not have a link partner register, to 282000161856Syc * figure out the link partner's capabilities is tricky. Here we 282100161856Syc * just set the kstat based on our knowledge about the partner 282200161856Syc * (The partner must support auto-neg because auto-negotiation 282300161856Syc * has completed, it must support 1G or 10G because that is the 282400161856Syc * negotiated speed we are using.) 282500161856Syc * 282600161856Syc * Note: Current kstat does not show lp_cap_10gfdx and 282700161856Syc * lp_cap_10ghdx. 282800161856Syc */ 282900161856Syc if (speed == TN1010_SPEED_1G) { 283000161856Syc statsp->mac_stats.lp_cap_1000fdx = 1; 283100161856Syc statsp->mac_stats.lp_cap_10gfdx = 0; 283200161856Syc } else { 283300161856Syc statsp->mac_stats.lp_cap_1000fdx = 0; 283400161856Syc statsp->mac_stats.lp_cap_10gfdx = 1; 283500161856Syc } 283600161856Syc statsp->mac_stats.lp_cap_10ghdx = 0; 283700161856Syc statsp->mac_stats.lp_cap_1000hdx = 0; 283800161856Syc statsp->mac_stats.lp_cap_100fdx = 0; 283900161856Syc statsp->mac_stats.lp_cap_100hdx = 0; 284000161856Syc statsp->mac_stats.lp_cap_10fdx = 0; 284100161856Syc statsp->mac_stats.lp_cap_10hdx = 0; 284200161856Syc statsp->mac_stats.lp_cap_10gfdx = 0; 284300161856Syc statsp->mac_stats.lp_cap_10ghdx = 0; 284400161856Syc statsp->mac_stats.lp_cap_100T4 = 0; 284500161856Syc statsp->mac_stats.lp_cap_autoneg = 1; 284600161856Syc statsp->mac_stats.lp_cap_asmpause = 0; 284700161856Syc statsp->mac_stats.lp_cap_pause = 0; 284800161856Syc 284900161856Syc /* Handle PHY loopback for SunVTS loopback test */ 285000161856Syc npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE); 285100161856Syc phy_port_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 285200161856Syc 285300161856Syc if ((status = nxge_mdio_read(nxgep, phy_port_addr, 285400161856Syc TN1010_PCS_DEV_ADDR, TN1010_PCS_CONTROL_REG, 285500161856Syc &tn1010_pcs_ctrl.value)) != NXGE_OK) { 285600161856Syc goto fail; 285700161856Syc } 285800161856Syc if ((statsp->port_stats.lb_mode == nxge_lb_phy1000) || 285900161856Syc (statsp->port_stats.lb_mode == nxge_lb_phy10g)) { 286000161856Syc tn1010_pcs_ctrl.bits.loopback = 1; 286100161856Syc } else { 286200161856Syc tn1010_pcs_ctrl.bits.loopback = 0; 286300161856Syc } 286400161856Syc if ((status = nxge_mdio_write(nxgep, phy_port_addr, 286500161856Syc TN1010_PCS_DEV_ADDR, TN1010_PCS_CONTROL_REG, 286600161856Syc tn1010_pcs_ctrl.value)) != NXGE_OK) { 286700161856Syc goto fail; 286800161856Syc } 286900161856Syc 287000161856Syc statsp->mac_stats.xcvr_inits++; 287100161856Syc 287200161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 287300161856Syc "<== nxge_1G_tn1010_xcvr_init status 0x%x", status)); 287400161856Syc return (status); 287500161856Syc fail: 287600161856Syc NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 287700161856Syc "<== nxge_1G_tn1010_xcvr_init status 0x%x", status)); 287800161856Syc return (status); 287900161856Syc } 288000161856Syc 288159ac0c16Sdavemq /* Initialize transceiver */ 288259ac0c16Sdavemq 288359ac0c16Sdavemq nxge_status_t 288459ac0c16Sdavemq nxge_xcvr_init(p_nxge_t nxgep) 288559ac0c16Sdavemq { 288659ac0c16Sdavemq p_nxge_stats_t statsp; 288759ac0c16Sdavemq #ifdef NXGE_DEBUG 288859ac0c16Sdavemq uint8_t portn; 288944961713Sgirish #endif 289044961713Sgirish 289159ac0c16Sdavemq nxge_status_t status = NXGE_OK; 289259ac0c16Sdavemq #ifdef NXGE_DEBUG 289359ac0c16Sdavemq portn = nxgep->mac.portnum; 289459ac0c16Sdavemq #endif 289559ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", portn)); 289659ac0c16Sdavemq statsp = nxgep->statsp; 289744961713Sgirish 289859ac0c16Sdavemq /* 289900161856Syc * Initialize the xcvr statistics. nxgep->xcvr.xcvr_init will 290000161856Syc * modify mac_stats. 290159ac0c16Sdavemq */ 290259ac0c16Sdavemq statsp->mac_stats.cap_autoneg = 0; 290359ac0c16Sdavemq statsp->mac_stats.cap_100T4 = 0; 290459ac0c16Sdavemq statsp->mac_stats.cap_100fdx = 0; 290559ac0c16Sdavemq statsp->mac_stats.cap_100hdx = 0; 290659ac0c16Sdavemq statsp->mac_stats.cap_10fdx = 0; 290759ac0c16Sdavemq statsp->mac_stats.cap_10hdx = 0; 290859ac0c16Sdavemq statsp->mac_stats.cap_asmpause = 0; 290959ac0c16Sdavemq statsp->mac_stats.cap_pause = 0; 291059ac0c16Sdavemq statsp->mac_stats.cap_1000fdx = 0; 291159ac0c16Sdavemq statsp->mac_stats.cap_1000hdx = 0; 291259ac0c16Sdavemq statsp->mac_stats.cap_10gfdx = 0; 291359ac0c16Sdavemq statsp->mac_stats.cap_10ghdx = 0; 291459ac0c16Sdavemq 291559ac0c16Sdavemq /* 291659ac0c16Sdavemq * Initialize the link statistics. 291759ac0c16Sdavemq */ 291859ac0c16Sdavemq statsp->mac_stats.link_T4 = 0; 291959ac0c16Sdavemq statsp->mac_stats.link_asmpause = 0; 292059ac0c16Sdavemq statsp->mac_stats.link_pause = 0; 292144961713Sgirish 292259ac0c16Sdavemq if (nxgep->xcvr.xcvr_init) { 292359ac0c16Sdavemq status = nxgep->xcvr.xcvr_init(nxgep); 292459ac0c16Sdavemq if (status != NXGE_OK) 292544961713Sgirish goto fail; 292659ac0c16Sdavemq statsp->mac_stats.xcvr_inits++; 292744961713Sgirish } 292844961713Sgirish 292959ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", 293059ac0c16Sdavemq portn)); 293144961713Sgirish return (NXGE_OK); 293244961713Sgirish 293344961713Sgirish fail: 293444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 293559ac0c16Sdavemq "nxge_xcvr_init: failed to initialize transceiver for port<%d>", 293659ac0c16Sdavemq portn)); 293744961713Sgirish return (status); 293844961713Sgirish } 293944961713Sgirish 29402e59129aSraghus /* Look for transceiver type */ 29412e59129aSraghus 29422e59129aSraghus nxge_status_t 29432e59129aSraghus nxge_xcvr_find(p_nxge_t nxgep) 29442e59129aSraghus { 2945d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_find: port<%d>", 2946d81011f0Ssbehera nxgep->mac.portnum)); 29472e59129aSraghus 29482e59129aSraghus if (nxge_get_xcvr_type(nxgep) != NXGE_OK) 29492e59129aSraghus return (NXGE_ERROR); 29502e59129aSraghus 29512e59129aSraghus if (nxge_setup_xcvr_table(nxgep) != NXGE_OK) 29522e59129aSraghus return (NXGE_ERROR); 29532e59129aSraghus 29542e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xcvr_find: xcvr_inuse = %d", 29552e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse)); 29562e59129aSraghus return (NXGE_OK); 29572e59129aSraghus } 295844961713Sgirish 295944961713Sgirish /* Initialize the TxMAC sub-block */ 296044961713Sgirish 296144961713Sgirish nxge_status_t 296244961713Sgirish nxge_tx_mac_init(p_nxge_t nxgep) 296344961713Sgirish { 296444961713Sgirish npi_attr_t ap; 296544961713Sgirish uint8_t portn; 296644961713Sgirish nxge_port_mode_t portmode; 296744961713Sgirish nxge_port_t portt; 296844961713Sgirish npi_handle_t handle; 296944961713Sgirish npi_status_t rs = NPI_SUCCESS; 297044961713Sgirish 297144961713Sgirish portn = NXGE_GET_PORT_NUM(nxgep->function_num); 297244961713Sgirish portt = nxgep->mac.porttype; 297344961713Sgirish handle = nxgep->npi_handle; 297444961713Sgirish portmode = nxgep->mac.portmode; 297544961713Sgirish 297644961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_init: port<%d>", 297744961713Sgirish portn)); 297844961713Sgirish /* Set Max and Min Frame Size */ 29791bd6825cSml /* 29801bd6825cSml * Use maxframesize to configure the hardware maxframe size 298100161856Syc * and minframesize to configure the hardware minframe size. 29821bd6825cSml */ 29831bd6825cSml NXGE_DEBUG_MSG((nxgep, MAC_CTL, 29841bd6825cSml "==> nxge_tx_mac_init: port<%d> " 29851bd6825cSml "min framesize %d max framesize %d ", 29861bd6825cSml nxgep->mac.minframesize, 29871bd6825cSml nxgep->mac.maxframesize, 29881bd6825cSml portn)); 298944961713Sgirish 29901bd6825cSml SET_MAC_ATTR2(handle, ap, portn, 29911bd6825cSml MAC_PORT_FRAME_SIZE, 29921bd6825cSml nxgep->mac.minframesize, 29931bd6825cSml nxgep->mac.maxframesize, 29941bd6825cSml rs); 299544961713Sgirish if (rs != NPI_SUCCESS) 299644961713Sgirish goto fail; 299744961713Sgirish 299844961713Sgirish if (portt == PORT_TYPE_XMAC) { 299944961713Sgirish if ((rs = npi_xmac_tx_iconfig(handle, INIT, portn, 300044961713Sgirish 0)) != NPI_SUCCESS) 300144961713Sgirish goto fail; 300244961713Sgirish nxgep->mac.tx_iconfig = NXGE_XMAC_TX_INTRS; 300344961713Sgirish if ((portmode == PORT_10G_FIBER) || 30042e59129aSraghus (portmode == PORT_10G_COPPER) || 300500161856Syc (portmode == PORT_10G_TN1010) || 30062e59129aSraghus (portmode == PORT_10G_SERDES)) { 300744961713Sgirish SET_MAC_ATTR1(handle, ap, portn, XMAC_10G_PORT_IPG, 300844961713Sgirish XGMII_IPG_12_15, rs); 300944961713Sgirish if (rs != NPI_SUCCESS) 301044961713Sgirish goto fail; 301144961713Sgirish nxgep->mac.ipg[0] = XGMII_IPG_12_15; 301244961713Sgirish } else { 301344961713Sgirish SET_MAC_ATTR1(handle, ap, portn, XMAC_PORT_IPG, 301444961713Sgirish MII_GMII_IPG_12, rs); 301544961713Sgirish if (rs != NPI_SUCCESS) 301644961713Sgirish goto fail; 301744961713Sgirish nxgep->mac.ipg[0] = MII_GMII_IPG_12; 301844961713Sgirish } 301944961713Sgirish if ((rs = npi_xmac_tx_config(handle, INIT, portn, 302044961713Sgirish CFG_XMAC_TX_CRC | CFG_XMAC_TX)) != NPI_SUCCESS) 302144961713Sgirish goto fail; 302244961713Sgirish nxgep->mac.tx_config = CFG_XMAC_TX_CRC | CFG_XMAC_TX; 302344961713Sgirish nxgep->mac.maxburstsize = 0; /* not programmable */ 302444961713Sgirish nxgep->mac.ctrltype = 0; /* not programmable */ 302544961713Sgirish nxgep->mac.pa_size = 0; /* not programmable */ 302644961713Sgirish 302744961713Sgirish if ((rs = npi_xmac_zap_tx_counters(handle, portn)) 302844961713Sgirish != NPI_SUCCESS) 302944961713Sgirish goto fail; 303044961713Sgirish 303144961713Sgirish } else { 303244961713Sgirish if ((rs = npi_bmac_tx_iconfig(handle, INIT, portn, 303344961713Sgirish 0)) != NPI_SUCCESS) 303444961713Sgirish goto fail; 303544961713Sgirish nxgep->mac.tx_iconfig = NXGE_BMAC_TX_INTRS; 303644961713Sgirish 303744961713Sgirish SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_CTRL_TYPE, 0x8808, 303844961713Sgirish rs); 303944961713Sgirish if (rs != NPI_SUCCESS) 304044961713Sgirish goto fail; 304144961713Sgirish nxgep->mac.ctrltype = 0x8808; 304244961713Sgirish 304344961713Sgirish SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_PA_SIZE, 0x7, rs); 304444961713Sgirish if (rs != NPI_SUCCESS) 304544961713Sgirish goto fail; 304644961713Sgirish nxgep->mac.pa_size = 0x7; 304744961713Sgirish 304844961713Sgirish if ((rs = npi_bmac_tx_config(handle, INIT, portn, 304944961713Sgirish CFG_BMAC_TX_CRC | CFG_BMAC_TX)) != NPI_SUCCESS) 305044961713Sgirish goto fail; 305144961713Sgirish nxgep->mac.tx_config = CFG_BMAC_TX_CRC | CFG_BMAC_TX; 305244961713Sgirish } 305344961713Sgirish 305444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_init: port<%d>", 305544961713Sgirish portn)); 305644961713Sgirish 305744961713Sgirish return (NXGE_OK); 305844961713Sgirish fail: 305944961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 306044961713Sgirish "nxge_tx_mac_init: failed to initialize port<%d> TXMAC", 306144961713Sgirish portn)); 306244961713Sgirish 306344961713Sgirish return (NXGE_ERROR | rs); 306444961713Sgirish } 306544961713Sgirish 3066678453a8Sspeer int 3067678453a8Sspeer nxge_hio_hostinfo_get_rdc_table(p_nxge_t nxgep) 3068678453a8Sspeer { 3069678453a8Sspeer int rdc_tbl; 3070678453a8Sspeer 3071678453a8Sspeer /* 3072678453a8Sspeer * Get an RDC table (version 0). 3073678453a8Sspeer */ 3074678453a8Sspeer if ((rdc_tbl = nxge_fzc_rdc_tbl_bind(nxgep, -1, B_FALSE)) < 0) { 3075678453a8Sspeer NXGE_ERROR_MSG((nxgep, OBP_CTL, 3076678453a8Sspeer "nxge_hio_hostinfo_get_rdc_table: " 3077678453a8Sspeer "there are no free RDC tables!")); 3078678453a8Sspeer return (EBUSY); 3079678453a8Sspeer } 3080678453a8Sspeer 3081678453a8Sspeer return (rdc_tbl); 3082678453a8Sspeer } 3083678453a8Sspeer 3084678453a8Sspeer /* 3085678453a8Sspeer * nxge_hio_hostinfo_init 3086678453a8Sspeer * 3087678453a8Sspeer * Initialize an alternate MAC address, and bind a macrdctbln to it. 3088678453a8Sspeer * 3089678453a8Sspeer * Arguments: 3090678453a8Sspeer * nxge 3091678453a8Sspeer * vr The Virtualization Region 3092678453a8Sspeer * macaddr The alternate MAC address 3093678453a8Sspeer * 3094678453a8Sspeer * Notes: 3095678453a8Sspeer * 1. Find & bind an RDC table to <nxge>. 3096678453a8Sspeer * 2. Program an alternate MAC address (<macaddr>). 3097678453a8Sspeer * 3. Bind the RDC table to <macaddr>. 3098678453a8Sspeer * 3099678453a8Sspeer * Context: 3100678453a8Sspeer * Service domain 3101678453a8Sspeer * 3102678453a8Sspeer * Side Effects: 3103678453a8Sspeer * nxge->class_config.mac_host_info[slot].rdctbl 3104678453a8Sspeer * vr->slot & vr->altmac 3105678453a8Sspeer * 3106678453a8Sspeer */ 3107678453a8Sspeer int 3108678453a8Sspeer nxge_hio_hostinfo_init( 3109678453a8Sspeer nxge_t *nxge, 3110678453a8Sspeer nxge_hio_vr_t *vr, /* Virtualization Region */ 3111678453a8Sspeer ether_addr_t *macaddr) /* The alternate MAC address */ 3112678453a8Sspeer { 3113678453a8Sspeer int rdc_tbl, slot; 3114678453a8Sspeer 3115678453a8Sspeer nxge_class_pt_cfg_t *class; 3116678453a8Sspeer hostinfo_t mac_rdc; 3117678453a8Sspeer npi_mac_addr_t altmac; 3118678453a8Sspeer nxge_mmac_t *mmac_info; 3119678453a8Sspeer nxge_rdc_grp_t *group; 3120678453a8Sspeer uint8_t *addr = (uint8_t *)macaddr; 3121678453a8Sspeer 3122678453a8Sspeer mutex_enter(nxge->genlock); 3123678453a8Sspeer 3124678453a8Sspeer rdc_tbl = vr->rdc_tbl; 3125678453a8Sspeer 3126678453a8Sspeer /* Initialize the NXGE RDC table data structure. */ 3127678453a8Sspeer group = &nxge->pt_config.rdc_grps[rdc_tbl]; 3128678453a8Sspeer group->port = NXGE_GET_PORT_NUM(nxge->function_num); 3129678453a8Sspeer group->config_method = RDC_TABLE_ENTRY_METHOD_REP; 3130678453a8Sspeer group->flag = 1; /* This group has been configured. */ 3131678453a8Sspeer 3132678453a8Sspeer mmac_info = &nxge->nxge_mmac_info; 3133678453a8Sspeer 3134678453a8Sspeer /* 3135678453a8Sspeer * Are there free slots. 3136678453a8Sspeer */ 3137678453a8Sspeer if (mmac_info->naddrfree == 0) { 3138678453a8Sspeer mutex_exit(nxge->genlock); 3139678453a8Sspeer return (ENOSPC); 3140678453a8Sspeer } 3141678453a8Sspeer 3142678453a8Sspeer /* 3143678453a8Sspeer * The vswitch has already added this MAC address. 3144678453a8Sspeer * Find its assigned slot. 3145678453a8Sspeer */ 3146678453a8Sspeer if (mmac_info->num_factory_mmac < mmac_info->num_mmac) { 3147678453a8Sspeer for (slot = mmac_info->num_factory_mmac + 1; 3148678453a8Sspeer slot <= mmac_info->num_mmac; slot++) { 3149678453a8Sspeer if (!(mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED)) 3150678453a8Sspeer break; 3151678453a8Sspeer } 3152678453a8Sspeer if (slot > mmac_info->num_mmac) { 3153678453a8Sspeer for (slot = 1; slot <= mmac_info->num_factory_mmac; 3154678453a8Sspeer slot++) { 3155678453a8Sspeer if (!(mmac_info->mac_pool[slot].flags 3156678453a8Sspeer & MMAC_SLOT_USED)) 3157678453a8Sspeer break; 3158678453a8Sspeer } 3159678453a8Sspeer } 3160678453a8Sspeer } else { 3161678453a8Sspeer for (slot = 1; slot <= mmac_info->num_mmac; slot++) { 3162678453a8Sspeer if (!(mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED)) 3163678453a8Sspeer break; 3164678453a8Sspeer } 3165678453a8Sspeer } 3166678453a8Sspeer 3167678453a8Sspeer ASSERT(slot <= mmac_info->num_mmac); 3168678453a8Sspeer vr->slot = slot; 3169678453a8Sspeer slot = vr->slot - 1; 3170678453a8Sspeer 3171678453a8Sspeer /* 317200161856Syc * Program the mac address. 3173678453a8Sspeer */ 3174678453a8Sspeer altmac.w2 = (((uint16_t)addr[0]) << 8) | 3175678453a8Sspeer (((uint16_t)addr[1]) & 0x0ff); 3176678453a8Sspeer altmac.w1 = (((uint16_t)addr[2]) << 8) | 3177678453a8Sspeer (((uint16_t)addr[3]) & 0x0ff); 3178678453a8Sspeer altmac.w0 = (((uint16_t)addr[4]) << 8) | 3179678453a8Sspeer (((uint16_t)addr[5]) & 0x0ff); 3180678453a8Sspeer 3181678453a8Sspeer if (npi_mac_altaddr_entry(nxge->npi_handle, OP_SET, 3182678453a8Sspeer nxge->function_num, slot, &altmac) != NPI_SUCCESS) { 3183678453a8Sspeer mutex_exit(nxge->genlock); 3184678453a8Sspeer return (EIO); 3185678453a8Sspeer } 3186678453a8Sspeer 3187678453a8Sspeer /* 3188678453a8Sspeer * Associate <rdc_tbl> with this MAC address slot. 3189678453a8Sspeer */ 3190678453a8Sspeer class = (p_nxge_class_pt_cfg_t)&nxge->class_config; 3191678453a8Sspeer 3192678453a8Sspeer /* Update this variable. */ 3193678453a8Sspeer class = (p_nxge_class_pt_cfg_t)&nxge->class_config; 3194678453a8Sspeer class->mac_host_info[slot].rdctbl = (uint8_t)rdc_tbl; 3195678453a8Sspeer 3196678453a8Sspeer mac_rdc.value = 0; 3197678453a8Sspeer mac_rdc.bits.w0.rdc_tbl_num = rdc_tbl; 3198678453a8Sspeer mac_rdc.bits.w0.mac_pref = class->mac_host_info[slot].mpr_npr; 3199678453a8Sspeer /* <mpr_npr> had better be 1! */ 3200678453a8Sspeer 3201678453a8Sspeer /* Program the RDC table. */ 3202678453a8Sspeer if ((npi_mac_hostinfo_entry(nxge->npi_handle, OP_SET, 3203678453a8Sspeer nxge->function_num, slot, &mac_rdc)) != NPI_SUCCESS) { 3204678453a8Sspeer mutex_exit(nxge->genlock); 3205678453a8Sspeer (void) nxge_m_mmac_remove(nxge, vr->slot); 3206678453a8Sspeer return (EIO); 3207678453a8Sspeer } 3208678453a8Sspeer 3209678453a8Sspeer if (nxge->mac.portnum != XMAC_PORT_0 && 3210678453a8Sspeer nxge->mac.portnum != XMAC_PORT_1) 3211678453a8Sspeer slot++; 3212678453a8Sspeer 3213678453a8Sspeer /* (Re-)enable the MAC address. */ 3214678453a8Sspeer (void) npi_mac_altaddr_enable( 3215678453a8Sspeer nxge->npi_handle, nxge->mac.portnum, slot); 3216678453a8Sspeer 3217678453a8Sspeer bcopy(macaddr, vr->altmac, sizeof (vr->altmac)); 3218678453a8Sspeer 3219678453a8Sspeer /* 3220678453a8Sspeer * Update mmac 3221678453a8Sspeer */ 3222678453a8Sspeer bcopy(addr, mmac_info->mac_pool[vr->slot].addr, ETHERADDRL); 3223678453a8Sspeer mmac_info->mac_pool[vr->slot].flags |= MMAC_SLOT_USED; 3224678453a8Sspeer mmac_info->mac_pool[vr->slot].flags &= ~MMAC_VENDOR_ADDR; 3225678453a8Sspeer mmac_info->naddrfree--; 3226678453a8Sspeer nxge_mmac_kstat_update(nxge, vr->slot, B_FALSE); 3227678453a8Sspeer 3228678453a8Sspeer mutex_exit(nxge->genlock); 3229678453a8Sspeer return (0); 3230678453a8Sspeer } 3231678453a8Sspeer 3232678453a8Sspeer /* 3233678453a8Sspeer * nxge_hio_hostinfo_uninit 3234678453a8Sspeer * 3235678453a8Sspeer * Uninitialize an alternate MAC address. 3236678453a8Sspeer * 3237678453a8Sspeer * Arguments: 3238678453a8Sspeer * nxge 3239678453a8Sspeer * vr The Virtualization Region 3240678453a8Sspeer * 3241678453a8Sspeer * Notes: 3242678453a8Sspeer * 1. Remove the VR's alternate MAC address. 3243678453a8Sspeer * 1. Free (unbind) the RDC table allocated to this VR. 3244678453a8Sspeer * 3245678453a8Sspeer * Context: 3246678453a8Sspeer * Service domain 3247678453a8Sspeer * 3248678453a8Sspeer * Side Effects: 3249678453a8Sspeer * nxge->class_config.mac_host_info[slot].rdctbl 3250678453a8Sspeer * 3251678453a8Sspeer */ 3252678453a8Sspeer void 3253678453a8Sspeer nxge_hio_hostinfo_uninit( 3254678453a8Sspeer nxge_t *nxge, 3255678453a8Sspeer nxge_hio_vr_t *vr) 3256678453a8Sspeer { 3257678453a8Sspeer nxge_class_pt_cfg_t *class; 3258678453a8Sspeer 3259678453a8Sspeer (void) npi_mac_altaddr_disable( 3260678453a8Sspeer nxge->npi_handle, nxge->mac.portnum, vr->slot); 3261678453a8Sspeer 3262678453a8Sspeer /* Set this variable to its default. */ 3263678453a8Sspeer class = (p_nxge_class_pt_cfg_t)&nxge->class_config; 3264678453a8Sspeer class->mac_host_info[vr->slot].rdctbl = 3265678453a8Sspeer nxge->pt_config.hw_config.def_mac_rxdma_grpid; 3266678453a8Sspeer 3267678453a8Sspeer (void) nxge_m_mmac_remove(nxge, vr->slot); 3268678453a8Sspeer vr->slot = -1; 3269678453a8Sspeer 3270678453a8Sspeer (void) nxge_fzc_rdc_tbl_unbind(nxge, vr->rdc_tbl); 3271678453a8Sspeer vr->rdc_tbl = -1; 3272678453a8Sspeer } 3273678453a8Sspeer 327444961713Sgirish /* Initialize the RxMAC sub-block */ 327544961713Sgirish 327644961713Sgirish nxge_status_t 327744961713Sgirish nxge_rx_mac_init(p_nxge_t nxgep) 327844961713Sgirish { 327944961713Sgirish npi_attr_t ap; 328044961713Sgirish uint32_t i; 328144961713Sgirish uint16_t hashtab_e; 328244961713Sgirish p_hash_filter_t hash_filter; 328344961713Sgirish nxge_port_t portt; 328444961713Sgirish uint8_t portn; 328544961713Sgirish npi_handle_t handle; 328644961713Sgirish npi_status_t rs = NPI_SUCCESS; 328744961713Sgirish uint16_t *addr16p; 328844961713Sgirish uint16_t addr0, addr1, addr2; 328944961713Sgirish xmac_rx_config_t xconfig; 329044961713Sgirish bmac_rx_config_t bconfig; 329144961713Sgirish 329244961713Sgirish portn = NXGE_GET_PORT_NUM(nxgep->function_num); 329344961713Sgirish 329444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_init: port<%d>\n", 329544961713Sgirish portn)); 329644961713Sgirish handle = nxgep->npi_handle; 329744961713Sgirish portt = nxgep->mac.porttype; 329844961713Sgirish 329944961713Sgirish addr16p = (uint16_t *)nxgep->ouraddr.ether_addr_octet; 330044961713Sgirish addr0 = ntohs(addr16p[2]); 330144961713Sgirish addr1 = ntohs(addr16p[1]); 330244961713Sgirish addr2 = ntohs(addr16p[0]); 330344961713Sgirish SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR, addr0, addr1, addr2, 330444961713Sgirish rs); 330544961713Sgirish 330644961713Sgirish if (rs != NPI_SUCCESS) 330744961713Sgirish goto fail; 330844961713Sgirish SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR_FILTER, 0, 0, 0, rs); 330944961713Sgirish if (rs != NPI_SUCCESS) 331044961713Sgirish goto fail; 331144961713Sgirish SET_MAC_ATTR2(handle, ap, portn, MAC_PORT_ADDR_FILTER_MASK, 0, 0, rs); 331244961713Sgirish if (rs != NPI_SUCCESS) 331344961713Sgirish goto fail; 331444961713Sgirish 331544961713Sgirish /* 331644961713Sgirish * Load the multicast hash filter bits. 331744961713Sgirish */ 331844961713Sgirish hash_filter = nxgep->hash_filter; 331944961713Sgirish for (i = 0; i < MAC_MAX_HASH_ENTRY; i++) { 332044961713Sgirish if (hash_filter != NULL) { 332144961713Sgirish hashtab_e = (uint16_t)hash_filter->hash_filter_regs[ 332244961713Sgirish (NMCFILTER_REGS - 1) - i]; 332344961713Sgirish } else { 332444961713Sgirish hashtab_e = 0; 332544961713Sgirish } 332644961713Sgirish 332744961713Sgirish if ((rs = npi_mac_hashtab_entry(handle, OP_SET, portn, i, 332844961713Sgirish (uint16_t *)&hashtab_e)) != NPI_SUCCESS) 332944961713Sgirish goto fail; 333044961713Sgirish } 333144961713Sgirish 333244961713Sgirish if (portt == PORT_TYPE_XMAC) { 333344961713Sgirish if ((rs = npi_xmac_rx_iconfig(handle, INIT, portn, 333444961713Sgirish 0)) != NPI_SUCCESS) 333544961713Sgirish goto fail; 333644961713Sgirish nxgep->mac.rx_iconfig = NXGE_XMAC_RX_INTRS; 333744961713Sgirish 333844961713Sgirish (void) nxge_fflp_init_hostinfo(nxgep); 333944961713Sgirish 334044961713Sgirish xconfig = CFG_XMAC_RX_ERRCHK | CFG_XMAC_RX_CRC_CHK | 3341a3c5bd6dSspeer CFG_XMAC_RX | CFG_XMAC_RX_CODE_VIO_CHK & 3342a3c5bd6dSspeer ~CFG_XMAC_RX_STRIP_CRC; 334344961713Sgirish 334444961713Sgirish if (nxgep->filter.all_phys_cnt != 0) 334544961713Sgirish xconfig |= CFG_XMAC_RX_PROMISCUOUS; 334644961713Sgirish 334744961713Sgirish if (nxgep->filter.all_multicast_cnt != 0) 334844961713Sgirish xconfig |= CFG_XMAC_RX_PROMISCUOUSGROUP; 334944961713Sgirish 335044961713Sgirish xconfig |= CFG_XMAC_RX_HASH_FILTER; 335144961713Sgirish 335244961713Sgirish if ((rs = npi_xmac_rx_config(handle, INIT, portn, 335344961713Sgirish xconfig)) != NPI_SUCCESS) 335444961713Sgirish goto fail; 335544961713Sgirish nxgep->mac.rx_config = xconfig; 335644961713Sgirish 335744961713Sgirish /* Comparison of mac unique address is always enabled on XMAC */ 335844961713Sgirish 335944961713Sgirish if ((rs = npi_xmac_zap_rx_counters(handle, portn)) 336044961713Sgirish != NPI_SUCCESS) 336144961713Sgirish goto fail; 336244961713Sgirish } else { 336344961713Sgirish (void) nxge_fflp_init_hostinfo(nxgep); 336444961713Sgirish 336544961713Sgirish if (npi_bmac_rx_iconfig(nxgep->npi_handle, INIT, portn, 336644961713Sgirish 0) != NPI_SUCCESS) 336744961713Sgirish goto fail; 336844961713Sgirish nxgep->mac.rx_iconfig = NXGE_BMAC_RX_INTRS; 336944961713Sgirish 3370a3c5bd6dSspeer bconfig = CFG_BMAC_RX_DISCARD_ON_ERR | CFG_BMAC_RX & 3371a3c5bd6dSspeer ~CFG_BMAC_RX_STRIP_CRC; 337244961713Sgirish 337344961713Sgirish if (nxgep->filter.all_phys_cnt != 0) 337444961713Sgirish bconfig |= CFG_BMAC_RX_PROMISCUOUS; 337544961713Sgirish 337644961713Sgirish if (nxgep->filter.all_multicast_cnt != 0) 337744961713Sgirish bconfig |= CFG_BMAC_RX_PROMISCUOUSGROUP; 337844961713Sgirish 337944961713Sgirish bconfig |= CFG_BMAC_RX_HASH_FILTER; 338044961713Sgirish if ((rs = npi_bmac_rx_config(handle, INIT, portn, 338144961713Sgirish bconfig)) != NPI_SUCCESS) 338244961713Sgirish goto fail; 338344961713Sgirish nxgep->mac.rx_config = bconfig; 338444961713Sgirish 338544961713Sgirish /* Always enable comparison of mac unique address */ 338644961713Sgirish if ((rs = npi_mac_altaddr_enable(handle, portn, 0)) 338744961713Sgirish != NPI_SUCCESS) 338844961713Sgirish goto fail; 338944961713Sgirish } 339044961713Sgirish 339144961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_init: port<%d>\n", 339244961713Sgirish portn)); 339344961713Sgirish 339444961713Sgirish return (NXGE_OK); 339544961713Sgirish 339644961713Sgirish fail: 339744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 339844961713Sgirish "nxge_rx_mac_init: Failed to Initialize port<%d> RxMAC", 339944961713Sgirish portn)); 340044961713Sgirish 340144961713Sgirish return (NXGE_ERROR | rs); 340244961713Sgirish } 340344961713Sgirish 340444961713Sgirish /* Enable TXMAC */ 340544961713Sgirish 340644961713Sgirish nxge_status_t 340744961713Sgirish nxge_tx_mac_enable(p_nxge_t nxgep) 340844961713Sgirish { 340944961713Sgirish npi_handle_t handle; 341044961713Sgirish npi_status_t rs = NPI_SUCCESS; 341144961713Sgirish nxge_status_t status = NXGE_OK; 341244961713Sgirish 341344961713Sgirish handle = nxgep->npi_handle; 341444961713Sgirish 341544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_enable: port<%d>", 341644961713Sgirish nxgep->mac.portnum)); 341744961713Sgirish 341844961713Sgirish if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK) 341944961713Sgirish goto fail; 342044961713Sgirish 342144961713Sgirish /* based on speed */ 342244961713Sgirish nxgep->msg_min = ETHERMIN; 342344961713Sgirish 342444961713Sgirish if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 342544961713Sgirish if ((rs = npi_xmac_tx_config(handle, ENABLE, nxgep->mac.portnum, 342644961713Sgirish CFG_XMAC_TX)) != NPI_SUCCESS) 342744961713Sgirish goto fail; 342844961713Sgirish } else { 342944961713Sgirish if ((rs = npi_bmac_tx_config(handle, ENABLE, nxgep->mac.portnum, 343044961713Sgirish CFG_BMAC_TX)) != NPI_SUCCESS) 343144961713Sgirish goto fail; 343244961713Sgirish } 343344961713Sgirish 343444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_enable: port<%d>", 343544961713Sgirish nxgep->mac.portnum)); 343644961713Sgirish 343744961713Sgirish return (NXGE_OK); 343844961713Sgirish fail: 343944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 344044961713Sgirish "nxgep_tx_mac_enable: Failed to enable port<%d> TxMAC", 344144961713Sgirish nxgep->mac.portnum)); 344244961713Sgirish if (rs != NPI_SUCCESS) 344344961713Sgirish return (NXGE_ERROR | rs); 344444961713Sgirish else 344544961713Sgirish return (status); 344644961713Sgirish } 344744961713Sgirish 344844961713Sgirish /* Disable TXMAC */ 344944961713Sgirish 345044961713Sgirish nxge_status_t 345144961713Sgirish nxge_tx_mac_disable(p_nxge_t nxgep) 345244961713Sgirish { 345344961713Sgirish npi_handle_t handle; 345444961713Sgirish npi_status_t rs = NPI_SUCCESS; 345544961713Sgirish 3456678453a8Sspeer if (isLDOMguest(nxgep)) 3457678453a8Sspeer return (NXGE_OK); 3458678453a8Sspeer 345944961713Sgirish handle = nxgep->npi_handle; 346044961713Sgirish 346144961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_disable: port<%d>", 346244961713Sgirish nxgep->mac.portnum)); 346344961713Sgirish 346444961713Sgirish if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 346544961713Sgirish if ((rs = npi_xmac_tx_config(handle, DISABLE, 346644961713Sgirish nxgep->mac.portnum, CFG_XMAC_TX)) != NPI_SUCCESS) 346744961713Sgirish goto fail; 346844961713Sgirish } else { 346944961713Sgirish if ((rs = npi_bmac_tx_config(handle, DISABLE, 347044961713Sgirish nxgep->mac.portnum, CFG_BMAC_TX)) != NPI_SUCCESS) 347144961713Sgirish goto fail; 347244961713Sgirish } 347344961713Sgirish 347444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_disable: port<%d>", 347544961713Sgirish nxgep->mac.portnum)); 347644961713Sgirish return (NXGE_OK); 347744961713Sgirish fail: 347844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 347944961713Sgirish "nxge_tx_mac_disable: Failed to disable port<%d> TxMAC", 348044961713Sgirish nxgep->mac.portnum)); 348144961713Sgirish return (NXGE_ERROR | rs); 348244961713Sgirish } 348344961713Sgirish 348444961713Sgirish /* Enable RXMAC */ 348544961713Sgirish 348644961713Sgirish nxge_status_t 348744961713Sgirish nxge_rx_mac_enable(p_nxge_t nxgep) 348844961713Sgirish { 348944961713Sgirish npi_handle_t handle; 349044961713Sgirish uint8_t portn; 349144961713Sgirish npi_status_t rs = NPI_SUCCESS; 349244961713Sgirish nxge_status_t status = NXGE_OK; 349344961713Sgirish 3494678453a8Sspeer /* This is a service-domain-only activity. */ 3495678453a8Sspeer if (isLDOMguest(nxgep)) 3496678453a8Sspeer return (status); 3497678453a8Sspeer 349844961713Sgirish handle = nxgep->npi_handle; 349944961713Sgirish portn = nxgep->mac.portnum; 350044961713Sgirish 350144961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_enable: port<%d>", 350244961713Sgirish portn)); 350344961713Sgirish 350444961713Sgirish if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK) 350544961713Sgirish goto fail; 350644961713Sgirish 350744961713Sgirish if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 350844961713Sgirish if ((rs = npi_xmac_rx_config(handle, ENABLE, portn, 3509678453a8Sspeer CFG_XMAC_RX)) != NPI_SUCCESS) 351044961713Sgirish goto fail; 351144961713Sgirish } else { 351244961713Sgirish if ((rs = npi_bmac_rx_config(handle, ENABLE, portn, 3513678453a8Sspeer CFG_BMAC_RX)) != NPI_SUCCESS) 351444961713Sgirish goto fail; 351544961713Sgirish } 351644961713Sgirish 3517678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3518678453a8Sspeer "<== nxge_rx_mac_enable: port<%d>", portn)); 351944961713Sgirish 352044961713Sgirish return (NXGE_OK); 352144961713Sgirish fail: 352244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3523678453a8Sspeer "nxgep_rx_mac_enable: Failed to enable port<%d> RxMAC", portn)); 352444961713Sgirish 352544961713Sgirish if (rs != NPI_SUCCESS) 352644961713Sgirish return (NXGE_ERROR | rs); 352744961713Sgirish else 352844961713Sgirish return (status); 352944961713Sgirish } 353044961713Sgirish 353144961713Sgirish /* Disable RXMAC */ 353244961713Sgirish 353344961713Sgirish nxge_status_t 353444961713Sgirish nxge_rx_mac_disable(p_nxge_t nxgep) 353544961713Sgirish { 353644961713Sgirish npi_handle_t handle; 353744961713Sgirish uint8_t portn; 353844961713Sgirish npi_status_t rs = NPI_SUCCESS; 353944961713Sgirish 3540678453a8Sspeer /* If we are a guest domain driver, don't bother. */ 3541678453a8Sspeer if (isLDOMguest(nxgep)) 3542678453a8Sspeer return (NXGE_OK); 3543678453a8Sspeer 354444961713Sgirish handle = nxgep->npi_handle; 354544961713Sgirish portn = nxgep->mac.portnum; 354644961713Sgirish 354744961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_disable: port<%d>", 354844961713Sgirish portn)); 354944961713Sgirish 355044961713Sgirish if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 355144961713Sgirish if ((rs = npi_xmac_rx_config(handle, DISABLE, portn, 355244961713Sgirish CFG_XMAC_RX)) != NPI_SUCCESS) 355344961713Sgirish goto fail; 355444961713Sgirish } else { 355544961713Sgirish if ((rs = npi_bmac_rx_config(handle, DISABLE, portn, 355644961713Sgirish CFG_BMAC_RX)) != NPI_SUCCESS) 355744961713Sgirish goto fail; 355844961713Sgirish } 355944961713Sgirish 356044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_disable: port<%d>", 356144961713Sgirish portn)); 356244961713Sgirish return (NXGE_OK); 356344961713Sgirish fail: 356444961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 356544961713Sgirish "nxgep_rx_mac_disable: ", 356644961713Sgirish "Failed to disable port<%d> RxMAC", 356744961713Sgirish portn)); 356844961713Sgirish 356944961713Sgirish return (NXGE_ERROR | rs); 357044961713Sgirish } 357144961713Sgirish 357244961713Sgirish /* Reset TXMAC */ 357344961713Sgirish 357444961713Sgirish nxge_status_t 357544961713Sgirish nxge_tx_mac_reset(p_nxge_t nxgep) 357644961713Sgirish { 357744961713Sgirish npi_handle_t handle; 357844961713Sgirish uint8_t portn; 357944961713Sgirish npi_status_t rs = NPI_SUCCESS; 358044961713Sgirish 358144961713Sgirish handle = nxgep->npi_handle; 358244961713Sgirish portn = nxgep->mac.portnum; 358344961713Sgirish 358444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_reset: port<%d>", 358544961713Sgirish portn)); 358644961713Sgirish 358744961713Sgirish if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 358844961713Sgirish if ((rs = npi_xmac_reset(handle, portn, XTX_MAC_RESET_ALL)) 358944961713Sgirish != NPI_SUCCESS) 359044961713Sgirish goto fail; 359144961713Sgirish } else { 359244961713Sgirish if ((rs = npi_bmac_reset(handle, portn, TX_MAC_RESET)) 359344961713Sgirish != NPI_SUCCESS) 359444961713Sgirish goto fail; 359544961713Sgirish } 359644961713Sgirish 359744961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_reset: port<%d>", 359844961713Sgirish portn)); 359944961713Sgirish 360044961713Sgirish return (NXGE_OK); 360144961713Sgirish fail: 360244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 360344961713Sgirish "nxge_tx_mac_reset: Failed to Reset TxMAC port<%d>", 360444961713Sgirish portn)); 360544961713Sgirish 360644961713Sgirish return (NXGE_ERROR | rs); 360744961713Sgirish } 360844961713Sgirish 360944961713Sgirish /* Reset RXMAC */ 361044961713Sgirish 361144961713Sgirish nxge_status_t 361244961713Sgirish nxge_rx_mac_reset(p_nxge_t nxgep) 361344961713Sgirish { 361444961713Sgirish npi_handle_t handle; 361544961713Sgirish uint8_t portn; 361644961713Sgirish npi_status_t rs = NPI_SUCCESS; 361744961713Sgirish 361844961713Sgirish handle = nxgep->npi_handle; 361944961713Sgirish portn = nxgep->mac.portnum; 362044961713Sgirish 362144961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_reset: port<%d>", 362244961713Sgirish portn)); 362344961713Sgirish 362444961713Sgirish if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 362544961713Sgirish if ((rs = npi_xmac_reset(handle, portn, XRX_MAC_RESET_ALL)) 362644961713Sgirish != NPI_SUCCESS) 362744961713Sgirish goto fail; 362844961713Sgirish } else { 362944961713Sgirish if ((rs = npi_bmac_reset(handle, portn, RX_MAC_RESET)) 363044961713Sgirish != NPI_SUCCESS) 363144961713Sgirish goto fail; 363244961713Sgirish } 363344961713Sgirish 363444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_reset: port<%d>", 363544961713Sgirish portn)); 363644961713Sgirish 363759ac0c16Sdavemq return (NXGE_OK); 363859ac0c16Sdavemq fail: 363959ac0c16Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 364059ac0c16Sdavemq "nxge_rx_mac_reset: Failed to Reset RxMAC port<%d>", 364159ac0c16Sdavemq portn)); 364259ac0c16Sdavemq return (NXGE_ERROR | rs); 364359ac0c16Sdavemq } 364459ac0c16Sdavemq 364559ac0c16Sdavemq /* 10G fiber link interrupt start routine */ 364659ac0c16Sdavemq 364759ac0c16Sdavemq static nxge_status_t 364859ac0c16Sdavemq nxge_10G_link_intr_start(p_nxge_t nxgep) 364959ac0c16Sdavemq { 365059ac0c16Sdavemq npi_status_t rs = NPI_SUCCESS; 365159ac0c16Sdavemq uint8_t portn = nxgep->mac.portnum; 365259ac0c16Sdavemq 365359ac0c16Sdavemq rs = npi_xmac_xpcs_link_intr_enable(nxgep->npi_handle, portn); 365459ac0c16Sdavemq 365559ac0c16Sdavemq if (rs != NPI_SUCCESS) 365659ac0c16Sdavemq return (NXGE_ERROR | rs); 365759ac0c16Sdavemq else 365859ac0c16Sdavemq return (NXGE_OK); 365959ac0c16Sdavemq } 366059ac0c16Sdavemq 366159ac0c16Sdavemq /* 10G fiber link interrupt stop routine */ 366259ac0c16Sdavemq 366359ac0c16Sdavemq static nxge_status_t 366459ac0c16Sdavemq nxge_10G_link_intr_stop(p_nxge_t nxgep) 366559ac0c16Sdavemq { 366659ac0c16Sdavemq npi_status_t rs = NPI_SUCCESS; 366759ac0c16Sdavemq uint8_t portn = nxgep->mac.portnum; 366859ac0c16Sdavemq 366959ac0c16Sdavemq rs = npi_xmac_xpcs_link_intr_disable(nxgep->npi_handle, portn); 367059ac0c16Sdavemq 367159ac0c16Sdavemq if (rs != NPI_SUCCESS) 367259ac0c16Sdavemq return (NXGE_ERROR | rs); 367359ac0c16Sdavemq else 367459ac0c16Sdavemq return (NXGE_OK); 367559ac0c16Sdavemq } 367659ac0c16Sdavemq 367759ac0c16Sdavemq /* 1G fiber link interrupt start routine */ 367859ac0c16Sdavemq 367959ac0c16Sdavemq static nxge_status_t 368059ac0c16Sdavemq nxge_1G_fiber_link_intr_start(p_nxge_t nxgep) 368159ac0c16Sdavemq { 368259ac0c16Sdavemq npi_status_t rs = NPI_SUCCESS; 368359ac0c16Sdavemq uint8_t portn = nxgep->mac.portnum; 368459ac0c16Sdavemq 368559ac0c16Sdavemq rs = npi_mac_pcs_link_intr_enable(nxgep->npi_handle, portn); 368659ac0c16Sdavemq if (rs != NPI_SUCCESS) 368759ac0c16Sdavemq return (NXGE_ERROR | rs); 368859ac0c16Sdavemq else 368959ac0c16Sdavemq return (NXGE_OK); 369059ac0c16Sdavemq } 369159ac0c16Sdavemq 369259ac0c16Sdavemq /* 1G fiber link interrupt stop routine */ 369359ac0c16Sdavemq 369459ac0c16Sdavemq static nxge_status_t 369559ac0c16Sdavemq nxge_1G_fiber_link_intr_stop(p_nxge_t nxgep) 369659ac0c16Sdavemq { 369759ac0c16Sdavemq npi_status_t rs = NPI_SUCCESS; 369859ac0c16Sdavemq uint8_t portn = nxgep->mac.portnum; 369959ac0c16Sdavemq 370059ac0c16Sdavemq rs = npi_mac_pcs_link_intr_disable(nxgep->npi_handle, portn); 370159ac0c16Sdavemq 370259ac0c16Sdavemq if (rs != NPI_SUCCESS) 370359ac0c16Sdavemq return (NXGE_ERROR | rs); 370459ac0c16Sdavemq else 370559ac0c16Sdavemq return (NXGE_OK); 370659ac0c16Sdavemq } 370759ac0c16Sdavemq 370859ac0c16Sdavemq /* 1G copper link interrupt start routine */ 370959ac0c16Sdavemq 371059ac0c16Sdavemq static nxge_status_t 371159ac0c16Sdavemq nxge_1G_copper_link_intr_start(p_nxge_t nxgep) 371259ac0c16Sdavemq { 371359ac0c16Sdavemq npi_status_t rs = NPI_SUCCESS; 371459ac0c16Sdavemq uint8_t portn = nxgep->mac.portnum; 371559ac0c16Sdavemq 371659ac0c16Sdavemq rs = npi_mac_mif_link_intr_enable(nxgep->npi_handle, portn, 37176b438925Ssbehera MII_STATUS, MII_STATUS_LINKUP); 371859ac0c16Sdavemq 371959ac0c16Sdavemq if (rs != NPI_SUCCESS) 372059ac0c16Sdavemq return (NXGE_ERROR | rs); 372159ac0c16Sdavemq else 372259ac0c16Sdavemq return (NXGE_OK); 372344961713Sgirish } 372444961713Sgirish 372559ac0c16Sdavemq /* 1G copper link interrupt stop routine */ 372659ac0c16Sdavemq 372759ac0c16Sdavemq static nxge_status_t 372859ac0c16Sdavemq nxge_1G_copper_link_intr_stop(p_nxge_t nxgep) 372959ac0c16Sdavemq { 373059ac0c16Sdavemq npi_status_t rs = NPI_SUCCESS; 373159ac0c16Sdavemq uint8_t portn = nxgep->mac.portnum; 373259ac0c16Sdavemq 373359ac0c16Sdavemq rs = npi_mac_mif_link_intr_disable(nxgep->npi_handle, portn); 373459ac0c16Sdavemq 373559ac0c16Sdavemq if (rs != NPI_SUCCESS) 373659ac0c16Sdavemq return (NXGE_ERROR | rs); 373759ac0c16Sdavemq else 373859ac0c16Sdavemq return (NXGE_OK); 373959ac0c16Sdavemq } 374044961713Sgirish 374159ac0c16Sdavemq /* Enable/Disable Link Status change interrupt */ 374244961713Sgirish 374344961713Sgirish nxge_status_t 374444961713Sgirish nxge_link_intr(p_nxge_t nxgep, link_intr_enable_t enable) 374544961713Sgirish { 374659ac0c16Sdavemq uint8_t portn; 374759ac0c16Sdavemq nxge_status_t status = NXGE_OK; 374844961713Sgirish 374944961713Sgirish portn = nxgep->mac.portnum; 375044961713Sgirish 375144961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_intr: port<%d>", portn)); 375259ac0c16Sdavemq if (!nxgep->xcvr.link_intr_stop || !nxgep->xcvr.link_intr_start) 375359ac0c16Sdavemq return (NXGE_OK); 375444961713Sgirish 375559ac0c16Sdavemq if (enable == LINK_INTR_START) 375659ac0c16Sdavemq status = nxgep->xcvr.link_intr_start(nxgep); 375759ac0c16Sdavemq else if (enable == LINK_INTR_STOP) 375859ac0c16Sdavemq status = nxgep->xcvr.link_intr_stop(nxgep); 375959ac0c16Sdavemq if (status != NXGE_OK) 376059ac0c16Sdavemq goto fail; 376144961713Sgirish 376244961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_intr: port<%d>", portn)); 376344961713Sgirish 376444961713Sgirish return (NXGE_OK); 376544961713Sgirish fail: 376644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 376744961713Sgirish "nxge_link_intr: Failed to set port<%d> mif intr mode", 376844961713Sgirish portn)); 376944961713Sgirish 377059ac0c16Sdavemq return (status); 377144961713Sgirish } 377244961713Sgirish 377344961713Sgirish /* Initialize 1G Fiber / Copper transceiver using Clause 22 */ 377444961713Sgirish 377544961713Sgirish nxge_status_t 377644961713Sgirish nxge_mii_xcvr_init(p_nxge_t nxgep) 377744961713Sgirish { 377844961713Sgirish p_nxge_param_t param_arr; 377944961713Sgirish p_nxge_stats_t statsp; 378044961713Sgirish uint8_t xcvr_portn; 378144961713Sgirish p_mii_regs_t mii_regs; 378244961713Sgirish mii_bmcr_t bmcr; 378344961713Sgirish mii_bmsr_t bmsr; 378444961713Sgirish mii_anar_t anar; 378544961713Sgirish mii_gcr_t gcr; 378644961713Sgirish mii_esr_t esr; 378744961713Sgirish mii_aux_ctl_t bcm5464r_aux; 378844961713Sgirish int status = NXGE_OK; 378944961713Sgirish 379044961713Sgirish uint_t delay; 379144961713Sgirish 379244961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_init")); 379344961713Sgirish 379444961713Sgirish param_arr = nxgep->param_arr; 379544961713Sgirish statsp = nxgep->statsp; 379644961713Sgirish xcvr_portn = statsp->mac_stats.xcvr_portn; 379744961713Sgirish 379844961713Sgirish mii_regs = NULL; 379944961713Sgirish 380044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 380144961713Sgirish "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value)); 380244961713Sgirish 3803d81011f0Ssbehera /* 3804d81011f0Ssbehera * The mif phy mode may be connected to either a copper link 3805d81011f0Ssbehera * or fiber link. Read the mode control register to get the fiber 3806d81011f0Ssbehera * configuration if it is hard-wired to fiber link. 3807d81011f0Ssbehera */ 3808d81011f0Ssbehera (void) nxge_mii_get_link_mode(nxgep); 3809d81011f0Ssbehera if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) { 3810d81011f0Ssbehera return (nxge_mii_xcvr_fiber_init(nxgep)); 3811d81011f0Ssbehera } 3812d81011f0Ssbehera 381344961713Sgirish /* 381444961713Sgirish * Reset the transceiver. 381544961713Sgirish */ 381644961713Sgirish delay = 0; 381744961713Sgirish bmcr.value = 0; 381844961713Sgirish bmcr.bits.reset = 1; 381944961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 3820adfcba55Sjoycey #if defined(__i386) 3821adfcba55Sjoycey (uint8_t)(uint32_t)&mii_regs->bmcr, bmcr.value)) != NXGE_OK) 3822adfcba55Sjoycey #else 382344961713Sgirish (uint8_t)(uint64_t)&mii_regs->bmcr, bmcr.value)) != NXGE_OK) 3824adfcba55Sjoycey #endif 382544961713Sgirish goto fail; 382644961713Sgirish do { 382744961713Sgirish drv_usecwait(500); 382844961713Sgirish if ((status = nxge_mii_read(nxgep, xcvr_portn, 3829adfcba55Sjoycey #if defined(__i386) 3830adfcba55Sjoycey (uint8_t)(uint32_t)&mii_regs->bmcr, &bmcr.value)) 3831adfcba55Sjoycey #else 383244961713Sgirish (uint8_t)(uint64_t)&mii_regs->bmcr, &bmcr.value)) 3833adfcba55Sjoycey #endif 383444961713Sgirish != NXGE_OK) 383544961713Sgirish goto fail; 383644961713Sgirish delay++; 383744961713Sgirish } while ((bmcr.bits.reset) && (delay < 1000)); 383844961713Sgirish if (delay == 1000) { 383944961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed.")); 384044961713Sgirish goto fail; 384144961713Sgirish } 384244961713Sgirish 384344961713Sgirish if ((status = nxge_mii_read(nxgep, xcvr_portn, 3844adfcba55Sjoycey #if defined(__i386) 3845adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->bmsr), 3846adfcba55Sjoycey #else 384744961713Sgirish (uint8_t)(uint64_t)(&mii_regs->bmsr), 3848adfcba55Sjoycey #endif 384944961713Sgirish &bmsr.value)) != NXGE_OK) 385044961713Sgirish goto fail; 385144961713Sgirish 385244961713Sgirish param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able; 385344961713Sgirish param_arr[param_anar_100T4].value &= bmsr.bits.link_100T4; 385444961713Sgirish param_arr[param_anar_100fdx].value &= bmsr.bits.link_100fdx; 385544961713Sgirish param_arr[param_anar_100hdx].value = 0; 385644961713Sgirish param_arr[param_anar_10fdx].value &= bmsr.bits.link_10fdx; 385744961713Sgirish param_arr[param_anar_10hdx].value = 0; 385844961713Sgirish 385944961713Sgirish /* 386058324dfcSspeer * Initialize the xcvr statistics. 386144961713Sgirish */ 386244961713Sgirish statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able; 386344961713Sgirish statsp->mac_stats.cap_100T4 = bmsr.bits.link_100T4; 386444961713Sgirish statsp->mac_stats.cap_100fdx = bmsr.bits.link_100fdx; 386544961713Sgirish statsp->mac_stats.cap_100hdx = 0; 386644961713Sgirish statsp->mac_stats.cap_10fdx = bmsr.bits.link_10fdx; 386744961713Sgirish statsp->mac_stats.cap_10hdx = 0; 386844961713Sgirish statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value; 386944961713Sgirish statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value; 387044961713Sgirish 387144961713Sgirish /* 387200161856Syc * Initialize the xcvr advertised capability statistics. 387344961713Sgirish */ 387444961713Sgirish statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value; 387544961713Sgirish statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 387644961713Sgirish statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 387744961713Sgirish statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value; 387844961713Sgirish statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value; 387944961713Sgirish statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value; 388044961713Sgirish statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value; 388144961713Sgirish statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value; 388244961713Sgirish statsp->mac_stats.adv_cap_asmpause = 388344961713Sgirish param_arr[param_anar_asmpause].value; 388444961713Sgirish statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value; 388544961713Sgirish 388644961713Sgirish 388744961713Sgirish /* 388844961713Sgirish * Check for extended status just in case we're 388944961713Sgirish * running a Gigibit phy. 389044961713Sgirish */ 389144961713Sgirish if (bmsr.bits.extend_status) { 389244961713Sgirish if ((status = nxge_mii_read(nxgep, xcvr_portn, 3893adfcba55Sjoycey #if defined(__i386) 3894adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->esr), &esr.value)) 3895adfcba55Sjoycey #else 389644961713Sgirish (uint8_t)(uint64_t)(&mii_regs->esr), &esr.value)) 3897adfcba55Sjoycey #endif 389844961713Sgirish != NXGE_OK) 389944961713Sgirish goto fail; 390044961713Sgirish param_arr[param_anar_1000fdx].value &= 390144961713Sgirish esr.bits.link_1000fdx; 390244961713Sgirish param_arr[param_anar_1000hdx].value = 0; 390344961713Sgirish 390444961713Sgirish statsp->mac_stats.cap_1000fdx = 390544961713Sgirish (esr.bits.link_1000Xfdx || 390644961713Sgirish esr.bits.link_1000fdx); 390744961713Sgirish statsp->mac_stats.cap_1000hdx = 0; 390844961713Sgirish } else { 390944961713Sgirish param_arr[param_anar_1000fdx].value = 0; 391044961713Sgirish param_arr[param_anar_1000hdx].value = 0; 391144961713Sgirish } 391244961713Sgirish 391344961713Sgirish /* 391444961713Sgirish * Initialize 1G Statistics once the capability is established. 391544961713Sgirish */ 391644961713Sgirish statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 391744961713Sgirish statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 391844961713Sgirish 391944961713Sgirish /* 392000161856Syc * Initialize the link statistics. 392144961713Sgirish */ 392244961713Sgirish statsp->mac_stats.link_T4 = 0; 392344961713Sgirish statsp->mac_stats.link_asmpause = 0; 392444961713Sgirish statsp->mac_stats.link_pause = 0; 392544961713Sgirish statsp->mac_stats.link_speed = 0; 392644961713Sgirish statsp->mac_stats.link_duplex = 0; 392744961713Sgirish statsp->mac_stats.link_up = 0; 392844961713Sgirish 392944961713Sgirish /* 393044961713Sgirish * Switch off Auto-negotiation, 100M and full duplex. 393144961713Sgirish */ 393244961713Sgirish bmcr.value = 0; 393344961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 3934adfcba55Sjoycey #if defined(__i386) 3935adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 3936adfcba55Sjoycey #else 393744961713Sgirish (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 3938adfcba55Sjoycey #endif 393944961713Sgirish goto fail; 394044961713Sgirish 394144961713Sgirish if ((statsp->port_stats.lb_mode == nxge_lb_phy) || 394244961713Sgirish (statsp->port_stats.lb_mode == nxge_lb_phy1000)) { 394344961713Sgirish bmcr.bits.loopback = 1; 394444961713Sgirish bmcr.bits.enable_autoneg = 0; 394544961713Sgirish if (statsp->port_stats.lb_mode == nxge_lb_phy1000) 394644961713Sgirish bmcr.bits.speed_1000_sel = 1; 394744961713Sgirish bmcr.bits.duplex_mode = 1; 394844961713Sgirish param_arr[param_autoneg].value = 0; 394944961713Sgirish } else { 395044961713Sgirish bmcr.bits.loopback = 0; 395144961713Sgirish } 395244961713Sgirish 395344961713Sgirish if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) || 395444961713Sgirish (statsp->port_stats.lb_mode == nxge_lb_ext100) || 395544961713Sgirish (statsp->port_stats.lb_mode == nxge_lb_ext10)) { 395644961713Sgirish param_arr[param_autoneg].value = 0; 395744961713Sgirish bcm5464r_aux.value = 0; 395844961713Sgirish bcm5464r_aux.bits.ext_lb = 1; 395944961713Sgirish bcm5464r_aux.bits.write_1 = 1; 396044961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 396144961713Sgirish BCM5464R_AUX_CTL, bcm5464r_aux.value)) 396244961713Sgirish != NXGE_OK) 396344961713Sgirish goto fail; 396444961713Sgirish } 396544961713Sgirish 396600161856Syc /* If auto-negotiation is desired */ 396744961713Sgirish if (param_arr[param_autoneg].value) { 396844961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 396944961713Sgirish "Restarting Auto-negotiation.")); 397044961713Sgirish /* 397144961713Sgirish * Setup our Auto-negotiation advertisement register. 397244961713Sgirish */ 397344961713Sgirish anar.value = 0; 397444961713Sgirish anar.bits.selector = 1; 397544961713Sgirish anar.bits.cap_100T4 = param_arr[param_anar_100T4].value; 397644961713Sgirish anar.bits.cap_100fdx = param_arr[param_anar_100fdx].value; 397744961713Sgirish anar.bits.cap_100hdx = param_arr[param_anar_100hdx].value; 397844961713Sgirish anar.bits.cap_10fdx = param_arr[param_anar_10fdx].value; 397944961713Sgirish anar.bits.cap_10hdx = param_arr[param_anar_10hdx].value; 398044961713Sgirish anar.bits.cap_asmpause = 0; 398144961713Sgirish anar.bits.cap_pause = 0; 398244961713Sgirish if (param_arr[param_anar_1000fdx].value || 398344961713Sgirish param_arr[param_anar_100fdx].value || 398444961713Sgirish param_arr[param_anar_10fdx].value) { 398544961713Sgirish anar.bits.cap_asmpause = statsp->mac_stats.cap_asmpause; 398644961713Sgirish anar.bits.cap_pause = statsp->mac_stats.cap_pause; 398744961713Sgirish } 398844961713Sgirish 398900161856Syc /* Write to the auto-negotiation advertisement register */ 399044961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 3991adfcba55Sjoycey #if defined(__i386) 3992adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->anar), anar.value)) 3993adfcba55Sjoycey #else 399444961713Sgirish (uint8_t)(uint64_t)(&mii_regs->anar), anar.value)) 3995adfcba55Sjoycey #endif 399644961713Sgirish != NXGE_OK) 399744961713Sgirish goto fail; 399844961713Sgirish if (bmsr.bits.extend_status) { 399944961713Sgirish gcr.value = 0; 400044961713Sgirish gcr.bits.ms_mode_en = 400144961713Sgirish param_arr[param_master_cfg_enable].value; 400244961713Sgirish gcr.bits.master = 400344961713Sgirish param_arr[param_master_cfg_value].value; 400444961713Sgirish gcr.bits.link_1000fdx = 400544961713Sgirish param_arr[param_anar_1000fdx].value; 400644961713Sgirish gcr.bits.link_1000hdx = 400744961713Sgirish param_arr[param_anar_1000hdx].value; 400844961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 4009adfcba55Sjoycey #if defined(__i386) 4010adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->gcr), gcr.value)) 4011adfcba55Sjoycey #else 401244961713Sgirish (uint8_t)(uint64_t)(&mii_regs->gcr), gcr.value)) 4013adfcba55Sjoycey #endif 401444961713Sgirish != NXGE_OK) 401544961713Sgirish goto fail; 401644961713Sgirish } 401744961713Sgirish 401844961713Sgirish bmcr.bits.enable_autoneg = 1; 401944961713Sgirish bmcr.bits.restart_autoneg = 1; 402044961713Sgirish 402144961713Sgirish } else { 402244961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode.")); 402344961713Sgirish bmcr.bits.speed_1000_sel = 402444961713Sgirish param_arr[param_anar_1000fdx].value | 402544961713Sgirish param_arr[param_anar_1000hdx].value; 402644961713Sgirish bmcr.bits.speed_sel = (~bmcr.bits.speed_1000_sel) & 402744961713Sgirish (param_arr[param_anar_100fdx].value | 402844961713Sgirish param_arr[param_anar_100hdx].value); 402900161856Syc 403000161856Syc /* Force to 1G */ 403144961713Sgirish if (bmcr.bits.speed_1000_sel) { 403244961713Sgirish statsp->mac_stats.link_speed = 1000; 403344961713Sgirish gcr.value = 0; 403444961713Sgirish gcr.bits.ms_mode_en = 403544961713Sgirish param_arr[param_master_cfg_enable].value; 403644961713Sgirish gcr.bits.master = 403744961713Sgirish param_arr[param_master_cfg_value].value; 403844961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 4039adfcba55Sjoycey #if defined(__i386) 4040adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->gcr), 4041adfcba55Sjoycey #else 404244961713Sgirish (uint8_t)(uint64_t)(&mii_regs->gcr), 4043adfcba55Sjoycey #endif 404444961713Sgirish gcr.value)) 404544961713Sgirish != NXGE_OK) 404644961713Sgirish goto fail; 404744961713Sgirish if (param_arr[param_anar_1000fdx].value) { 404844961713Sgirish bmcr.bits.duplex_mode = 1; 404944961713Sgirish statsp->mac_stats.link_duplex = 2; 405044961713Sgirish } else 405144961713Sgirish statsp->mac_stats.link_duplex = 1; 405200161856Syc 405300161856Syc /* Force to 100M */ 405444961713Sgirish } else if (bmcr.bits.speed_sel) { 405544961713Sgirish statsp->mac_stats.link_speed = 100; 405644961713Sgirish if (param_arr[param_anar_100fdx].value) { 405744961713Sgirish bmcr.bits.duplex_mode = 1; 405844961713Sgirish statsp->mac_stats.link_duplex = 2; 405944961713Sgirish } else 406044961713Sgirish statsp->mac_stats.link_duplex = 1; 406100161856Syc 406200161856Syc /* Force to 10M */ 406344961713Sgirish } else { 406444961713Sgirish statsp->mac_stats.link_speed = 10; 406544961713Sgirish if (param_arr[param_anar_10fdx].value) { 406644961713Sgirish bmcr.bits.duplex_mode = 1; 406744961713Sgirish statsp->mac_stats.link_duplex = 2; 406844961713Sgirish } else 406944961713Sgirish statsp->mac_stats.link_duplex = 1; 407044961713Sgirish } 407144961713Sgirish if (statsp->mac_stats.link_duplex != 1) { 407244961713Sgirish statsp->mac_stats.link_asmpause = 407344961713Sgirish statsp->mac_stats.cap_asmpause; 407444961713Sgirish statsp->mac_stats.link_pause = 407544961713Sgirish statsp->mac_stats.cap_pause; 407644961713Sgirish } 407744961713Sgirish 407844961713Sgirish if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) || 407944961713Sgirish (statsp->port_stats.lb_mode == nxge_lb_ext100) || 408044961713Sgirish (statsp->port_stats.lb_mode == nxge_lb_ext10)) { 408144961713Sgirish if (statsp->port_stats.lb_mode == nxge_lb_ext1000) { 408244961713Sgirish /* BCM5464R 1000mbps external loopback mode */ 408344961713Sgirish gcr.value = 0; 408444961713Sgirish gcr.bits.ms_mode_en = 1; 408544961713Sgirish gcr.bits.master = 1; 408644961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 4087adfcba55Sjoycey #if defined(__i386) 4088adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->gcr), 4089adfcba55Sjoycey #else 409044961713Sgirish (uint8_t)(uint64_t)(&mii_regs->gcr), 4091adfcba55Sjoycey #endif 409244961713Sgirish gcr.value)) 409344961713Sgirish != NXGE_OK) 409444961713Sgirish goto fail; 409544961713Sgirish bmcr.value = 0; 409644961713Sgirish bmcr.bits.speed_1000_sel = 1; 409744961713Sgirish statsp->mac_stats.link_speed = 1000; 409844961713Sgirish } else if (statsp->port_stats.lb_mode 409944961713Sgirish == nxge_lb_ext100) { 410044961713Sgirish /* BCM5464R 100mbps external loopback mode */ 410144961713Sgirish bmcr.value = 0; 410244961713Sgirish bmcr.bits.speed_sel = 1; 410344961713Sgirish bmcr.bits.duplex_mode = 1; 410444961713Sgirish statsp->mac_stats.link_speed = 100; 410544961713Sgirish } else if (statsp->port_stats.lb_mode 410644961713Sgirish == nxge_lb_ext10) { 410744961713Sgirish /* BCM5464R 10mbps external loopback mode */ 410844961713Sgirish bmcr.value = 0; 410944961713Sgirish bmcr.bits.duplex_mode = 1; 411044961713Sgirish statsp->mac_stats.link_speed = 10; 411144961713Sgirish } 411244961713Sgirish } 411344961713Sgirish } 411444961713Sgirish 411544961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 4116adfcba55Sjoycey #if defined(__i386) 4117adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->bmcr), 4118adfcba55Sjoycey #else 411944961713Sgirish (uint8_t)(uint64_t)(&mii_regs->bmcr), 4120adfcba55Sjoycey #endif 412144961713Sgirish bmcr.value)) != NXGE_OK) 412244961713Sgirish goto fail; 412344961713Sgirish 412444961713Sgirish if ((status = nxge_mii_read(nxgep, xcvr_portn, 4125adfcba55Sjoycey #if defined(__i386) 4126adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK) 4127adfcba55Sjoycey #else 412844961713Sgirish (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK) 4129adfcba55Sjoycey #endif 413044961713Sgirish goto fail; 413144961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "bmcr = 0x%04X", bmcr.value)); 413244961713Sgirish 413344961713Sgirish /* 413444961713Sgirish * Initialize the xcvr status kept in the context structure. 413544961713Sgirish */ 413644961713Sgirish nxgep->soft_bmsr.value = 0; 413744961713Sgirish 413844961713Sgirish if ((status = nxge_mii_read(nxgep, xcvr_portn, 4139adfcba55Sjoycey #if defined(__i386) 4140adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->bmsr), 4141adfcba55Sjoycey #else 414244961713Sgirish (uint8_t)(uint64_t)(&mii_regs->bmsr), 4143adfcba55Sjoycey #endif 414444961713Sgirish &nxgep->bmsr.value)) != NXGE_OK) 414544961713Sgirish goto fail; 414644961713Sgirish 414744961713Sgirish statsp->mac_stats.xcvr_inits++; 414844961713Sgirish nxgep->bmsr.value = 0; 414944961713Sgirish 415044961713Sgirish fail: 415144961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 415244961713Sgirish "<== nxge_mii_xcvr_init status 0x%x", status)); 415344961713Sgirish return (status); 415444961713Sgirish } 415544961713Sgirish 4156d81011f0Ssbehera nxge_status_t 4157d81011f0Ssbehera nxge_mii_xcvr_fiber_init(p_nxge_t nxgep) 4158d81011f0Ssbehera { 4159d81011f0Ssbehera p_nxge_param_t param_arr; 4160d81011f0Ssbehera p_nxge_stats_t statsp; 4161d81011f0Ssbehera uint8_t xcvr_portn; 4162d81011f0Ssbehera p_mii_regs_t mii_regs; 4163d81011f0Ssbehera mii_bmcr_t bmcr; 4164d81011f0Ssbehera mii_bmsr_t bmsr; 4165d81011f0Ssbehera mii_gcr_t gcr; 4166d81011f0Ssbehera mii_esr_t esr; 4167d81011f0Ssbehera mii_aux_ctl_t bcm5464r_aux; 4168d81011f0Ssbehera int status = NXGE_OK; 4169d81011f0Ssbehera 4170d81011f0Ssbehera uint_t delay; 4171d81011f0Ssbehera 4172d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_fiber_init")); 4173d81011f0Ssbehera 4174d81011f0Ssbehera param_arr = nxgep->param_arr; 4175d81011f0Ssbehera statsp = nxgep->statsp; 4176d81011f0Ssbehera xcvr_portn = statsp->mac_stats.xcvr_portn; 4177d81011f0Ssbehera 4178d81011f0Ssbehera mii_regs = NULL; 4179d81011f0Ssbehera 4180d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4181d81011f0Ssbehera "nxge_mii_xcvr_fiber_init: " 4182d81011f0Ssbehera "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value)); 4183d81011f0Ssbehera 4184d81011f0Ssbehera /* 4185d81011f0Ssbehera * Reset the transceiver. 4186d81011f0Ssbehera */ 4187d81011f0Ssbehera delay = 0; 4188d81011f0Ssbehera bmcr.value = 0; 4189d81011f0Ssbehera bmcr.bits.reset = 1; 4190d81011f0Ssbehera 4191d81011f0Ssbehera #if defined(__i386) 4192d81011f0Ssbehera 4193d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 4194d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 4195d81011f0Ssbehera goto fail; 4196d81011f0Ssbehera #else 4197d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 4198d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 4199d81011f0Ssbehera goto fail; 4200d81011f0Ssbehera #endif 4201d81011f0Ssbehera do { 4202d81011f0Ssbehera drv_usecwait(500); 4203d81011f0Ssbehera #if defined(__i386) 4204d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 4205d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) 4206d81011f0Ssbehera != NXGE_OK) 4207d81011f0Ssbehera goto fail; 4208d81011f0Ssbehera #else 4209d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 4210d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) 4211d81011f0Ssbehera != NXGE_OK) 4212d81011f0Ssbehera goto fail; 4213d81011f0Ssbehera #endif 4214d81011f0Ssbehera delay++; 4215d81011f0Ssbehera } while ((bmcr.bits.reset) && (delay < 1000)); 4216d81011f0Ssbehera if (delay == 1000) { 4217d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed.")); 4218d81011f0Ssbehera goto fail; 4219d81011f0Ssbehera } 4220d81011f0Ssbehera 4221d81011f0Ssbehera #if defined(__i386) 4222d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 4223d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK) 4224d81011f0Ssbehera goto fail; 4225d81011f0Ssbehera #else 4226d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 4227d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK) 4228d81011f0Ssbehera goto fail; 4229d81011f0Ssbehera #endif 4230d81011f0Ssbehera 4231d81011f0Ssbehera param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able; 4232d81011f0Ssbehera param_arr[param_anar_100T4].value = 0; 4233d81011f0Ssbehera param_arr[param_anar_100fdx].value = 0; 4234d81011f0Ssbehera param_arr[param_anar_100hdx].value = 0; 4235d81011f0Ssbehera param_arr[param_anar_10fdx].value = 0; 4236d81011f0Ssbehera param_arr[param_anar_10hdx].value = 0; 4237d81011f0Ssbehera 4238d81011f0Ssbehera /* 4239d81011f0Ssbehera * Initialize the xcvr statistics. 4240d81011f0Ssbehera */ 4241d81011f0Ssbehera statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able; 4242d81011f0Ssbehera statsp->mac_stats.cap_100T4 = 0; 4243d81011f0Ssbehera statsp->mac_stats.cap_100fdx = 0; 4244d81011f0Ssbehera statsp->mac_stats.cap_100hdx = 0; 4245d81011f0Ssbehera statsp->mac_stats.cap_10fdx = 0; 4246d81011f0Ssbehera statsp->mac_stats.cap_10hdx = 0; 4247d81011f0Ssbehera statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value; 4248d81011f0Ssbehera statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value; 4249d81011f0Ssbehera 4250d81011f0Ssbehera /* 4251d81011f0Ssbehera * Initialize the xcvr advertised capability statistics. 4252d81011f0Ssbehera */ 4253d81011f0Ssbehera statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value; 4254d81011f0Ssbehera statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 4255d81011f0Ssbehera statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 4256d81011f0Ssbehera statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value; 4257d81011f0Ssbehera statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value; 4258d81011f0Ssbehera statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value; 4259d81011f0Ssbehera statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value; 4260d81011f0Ssbehera statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value; 4261d81011f0Ssbehera statsp->mac_stats.adv_cap_asmpause = 4262d81011f0Ssbehera param_arr[param_anar_asmpause].value; 4263d81011f0Ssbehera statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value; 4264d81011f0Ssbehera 4265d81011f0Ssbehera /* 4266d81011f0Ssbehera * Check for extended status just in case we're 4267d81011f0Ssbehera * running a Gigibit phy. 4268d81011f0Ssbehera */ 4269d81011f0Ssbehera if (bmsr.bits.extend_status) { 4270d81011f0Ssbehera #if defined(__i386) 4271d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 4272d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->esr), &esr.value)) != 4273d81011f0Ssbehera NXGE_OK) 4274d81011f0Ssbehera goto fail; 4275d81011f0Ssbehera #else 4276d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 4277d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->esr), &esr.value)) != 4278d81011f0Ssbehera NXGE_OK) 4279d81011f0Ssbehera goto fail; 4280d81011f0Ssbehera #endif 4281d81011f0Ssbehera param_arr[param_anar_1000fdx].value &= 4282d81011f0Ssbehera esr.bits.link_1000fdx; 4283d81011f0Ssbehera param_arr[param_anar_1000hdx].value = 0; 4284d81011f0Ssbehera 4285d81011f0Ssbehera statsp->mac_stats.cap_1000fdx = 4286d81011f0Ssbehera (esr.bits.link_1000Xfdx || esr.bits.link_1000fdx); 4287d81011f0Ssbehera statsp->mac_stats.cap_1000hdx = 0; 4288d81011f0Ssbehera } else { 4289d81011f0Ssbehera param_arr[param_anar_1000fdx].value = 0; 4290d81011f0Ssbehera param_arr[param_anar_1000hdx].value = 0; 4291d81011f0Ssbehera } 4292d81011f0Ssbehera 4293d81011f0Ssbehera /* 4294d81011f0Ssbehera * Initialize 1G Statistics once the capability is established. 4295d81011f0Ssbehera */ 4296d81011f0Ssbehera statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 4297d81011f0Ssbehera statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 4298d81011f0Ssbehera 4299d81011f0Ssbehera /* 4300d81011f0Ssbehera * Initialize the link statistics. 4301d81011f0Ssbehera */ 4302d81011f0Ssbehera statsp->mac_stats.link_T4 = 0; 4303d81011f0Ssbehera statsp->mac_stats.link_asmpause = 0; 4304d81011f0Ssbehera statsp->mac_stats.link_pause = 0; 4305d81011f0Ssbehera statsp->mac_stats.link_speed = 0; 4306d81011f0Ssbehera statsp->mac_stats.link_duplex = 0; 4307d81011f0Ssbehera statsp->mac_stats.link_up = 0; 4308d81011f0Ssbehera 4309d81011f0Ssbehera /* 4310d81011f0Ssbehera * Switch off Auto-negotiation, 100M and full duplex. 4311d81011f0Ssbehera */ 4312d81011f0Ssbehera bmcr.value = 0; 4313d81011f0Ssbehera #if defined(__i386) 4314d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 4315d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 4316d81011f0Ssbehera goto fail; 4317d81011f0Ssbehera #else 4318d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 4319d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 4320d81011f0Ssbehera goto fail; 4321d81011f0Ssbehera #endif 4322d81011f0Ssbehera 4323d81011f0Ssbehera if ((statsp->port_stats.lb_mode == nxge_lb_phy) || 4324d81011f0Ssbehera (statsp->port_stats.lb_mode == nxge_lb_phy1000)) { 4325d81011f0Ssbehera bmcr.bits.loopback = 1; 4326d81011f0Ssbehera bmcr.bits.enable_autoneg = 0; 4327d81011f0Ssbehera if (statsp->port_stats.lb_mode == nxge_lb_phy1000) 4328d81011f0Ssbehera bmcr.bits.speed_1000_sel = 1; 4329d81011f0Ssbehera bmcr.bits.duplex_mode = 1; 4330d81011f0Ssbehera param_arr[param_autoneg].value = 0; 4331d81011f0Ssbehera } else { 4332d81011f0Ssbehera bmcr.bits.loopback = 0; 4333d81011f0Ssbehera } 4334d81011f0Ssbehera 4335d81011f0Ssbehera if (statsp->port_stats.lb_mode == nxge_lb_ext1000) { 4336d81011f0Ssbehera param_arr[param_autoneg].value = 0; 4337d81011f0Ssbehera bcm5464r_aux.value = 0; 4338d81011f0Ssbehera bcm5464r_aux.bits.ext_lb = 1; 4339d81011f0Ssbehera bcm5464r_aux.bits.write_1 = 1; 4340d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 4341d81011f0Ssbehera BCM5464R_AUX_CTL, bcm5464r_aux.value)) != NXGE_OK) 4342d81011f0Ssbehera goto fail; 4343d81011f0Ssbehera } 4344d81011f0Ssbehera 4345d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode.")); 4346d81011f0Ssbehera bmcr.bits.speed_1000_sel = 1; 4347d81011f0Ssbehera bmcr.bits.speed_sel = 0; 4348d81011f0Ssbehera bmcr.bits.duplex_mode = 1; 4349d81011f0Ssbehera statsp->mac_stats.link_speed = 1000; 4350d81011f0Ssbehera statsp->mac_stats.link_duplex = 2; 4351d81011f0Ssbehera 4352d81011f0Ssbehera if ((statsp->port_stats.lb_mode == nxge_lb_ext1000)) { 4353d81011f0Ssbehera /* BCM5464R 1000mbps external loopback mode */ 4354d81011f0Ssbehera gcr.value = 0; 4355d81011f0Ssbehera gcr.bits.ms_mode_en = 1; 4356d81011f0Ssbehera gcr.bits.master = 1; 4357d81011f0Ssbehera #if defined(__i386) 4358d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 4359d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->gcr), 4360d81011f0Ssbehera gcr.value)) != NXGE_OK) 4361d81011f0Ssbehera goto fail; 4362d81011f0Ssbehera #else 4363d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 4364d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->gcr), 4365d81011f0Ssbehera gcr.value)) != NXGE_OK) 4366d81011f0Ssbehera goto fail; 4367d81011f0Ssbehera #endif 4368d81011f0Ssbehera bmcr.value = 0; 4369d81011f0Ssbehera bmcr.bits.speed_1000_sel = 1; 4370d81011f0Ssbehera statsp->mac_stats.link_speed = 1000; 4371d81011f0Ssbehera } 4372d81011f0Ssbehera 4373d81011f0Ssbehera #if defined(__i386) 4374d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 4375d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmcr), 4376d81011f0Ssbehera bmcr.value)) != NXGE_OK) 4377d81011f0Ssbehera goto fail; 4378d81011f0Ssbehera #else 4379d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 4380d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmcr), 4381d81011f0Ssbehera bmcr.value)) != NXGE_OK) 4382d81011f0Ssbehera goto fail; 4383d81011f0Ssbehera #endif 4384d81011f0Ssbehera 4385d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4386d81011f0Ssbehera "nxge_mii_xcvr_fiber_init: value wrote bmcr = 0x%x", 4387d81011f0Ssbehera bmcr.value)); 4388d81011f0Ssbehera 4389d81011f0Ssbehera #if defined(__i386) 4390d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 4391d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK) 4392d81011f0Ssbehera goto fail; 4393d81011f0Ssbehera #else 4394d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 4395d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK) 4396d81011f0Ssbehera goto fail; 4397d81011f0Ssbehera #endif 4398d81011f0Ssbehera 4399d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4400d81011f0Ssbehera "nxge_mii_xcvr_fiber_init: read bmcr = 0x%04X", bmcr.value)); 4401d81011f0Ssbehera 4402d81011f0Ssbehera /* 4403d81011f0Ssbehera * Initialize the xcvr status kept in the context structure. 4404d81011f0Ssbehera */ 4405d81011f0Ssbehera nxgep->soft_bmsr.value = 0; 4406d81011f0Ssbehera #if defined(__i386) 4407d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 4408d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmsr), 4409d81011f0Ssbehera &nxgep->bmsr.value)) != NXGE_OK) 4410d81011f0Ssbehera goto fail; 4411d81011f0Ssbehera #else 4412d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 4413d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmsr), 4414d81011f0Ssbehera &nxgep->bmsr.value)) != NXGE_OK) 4415d81011f0Ssbehera goto fail; 4416d81011f0Ssbehera #endif 4417d81011f0Ssbehera 4418d81011f0Ssbehera statsp->mac_stats.xcvr_inits++; 4419d81011f0Ssbehera nxgep->bmsr.value = 0; 4420d81011f0Ssbehera 4421d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4422d81011f0Ssbehera "<== nxge_mii_xcvr_fiber_init status 0x%x", status)); 4423d81011f0Ssbehera return (status); 4424d81011f0Ssbehera 4425d81011f0Ssbehera fail: 4426d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4427d81011f0Ssbehera "<== nxge_mii_xcvr_fiber_init status 0x%x", status)); 4428d81011f0Ssbehera return (status); 4429d81011f0Ssbehera } 4430d81011f0Ssbehera 443144961713Sgirish /* Read from a MII compliant register */ 443244961713Sgirish 443344961713Sgirish nxge_status_t 443444961713Sgirish nxge_mii_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg, 443544961713Sgirish uint16_t *value) 443644961713Sgirish { 443744961713Sgirish npi_status_t rs = NPI_SUCCESS; 443844961713Sgirish 443944961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_read: xcvr_port<%d>" 444044961713Sgirish "xcvr_reg<%d>", xcvr_portn, xcvr_reg)); 444144961713Sgirish 4442321febdeSsbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 444344961713Sgirish 4444d81011f0Ssbehera if ((nxgep->mac.portmode == PORT_1G_COPPER) || 4445d81011f0Ssbehera (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) { 444644961713Sgirish if ((rs = npi_mac_mif_mii_read(nxgep->npi_handle, 444744961713Sgirish xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 444844961713Sgirish goto fail; 44492e59129aSraghus } else if ((nxgep->mac.portmode == PORT_1G_FIBER) || 44502e59129aSraghus (nxgep->mac.portmode == PORT_1G_SERDES)) { 445144961713Sgirish if ((rs = npi_mac_pcs_mii_read(nxgep->npi_handle, 445244961713Sgirish xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 445344961713Sgirish goto fail; 445444961713Sgirish } else 445544961713Sgirish goto fail; 445644961713Sgirish 4457321febdeSsbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 445844961713Sgirish 445944961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_read: xcvr_port<%d>" 446044961713Sgirish "xcvr_reg<%d> value=0x%x", 446144961713Sgirish xcvr_portn, xcvr_reg, *value)); 446244961713Sgirish return (NXGE_OK); 446344961713Sgirish fail: 4464321febdeSsbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 446544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 446644961713Sgirish "nxge_mii_read: Failed to read mii on xcvr %d", 446744961713Sgirish xcvr_portn)); 446844961713Sgirish 446944961713Sgirish return (NXGE_ERROR | rs); 447044961713Sgirish } 447144961713Sgirish 447244961713Sgirish /* Write to a MII compliant Register */ 447344961713Sgirish 447444961713Sgirish nxge_status_t 447544961713Sgirish nxge_mii_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg, 447644961713Sgirish uint16_t value) 447744961713Sgirish { 447844961713Sgirish npi_status_t rs = NPI_SUCCESS; 447944961713Sgirish 448044961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_write: xcvr_port<%d>" 448144961713Sgirish "xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg, 448244961713Sgirish value)); 448344961713Sgirish 4484321febdeSsbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 448544961713Sgirish 4486d81011f0Ssbehera if ((nxgep->mac.portmode == PORT_1G_COPPER) || 4487d81011f0Ssbehera (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) { 448844961713Sgirish if ((rs = npi_mac_mif_mii_write(nxgep->npi_handle, 448944961713Sgirish xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 449044961713Sgirish goto fail; 44912e59129aSraghus } else if ((nxgep->mac.portmode == PORT_1G_FIBER) || 44922e59129aSraghus (nxgep->mac.portmode == PORT_1G_SERDES)) { 449344961713Sgirish if ((rs = npi_mac_pcs_mii_write(nxgep->npi_handle, 449444961713Sgirish xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 449544961713Sgirish goto fail; 449644961713Sgirish } else 449744961713Sgirish goto fail; 449844961713Sgirish 4499321febdeSsbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 450044961713Sgirish 450144961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_write: xcvr_port<%d>" 450244961713Sgirish "xcvr_reg<%d>", xcvr_portn, xcvr_reg)); 450344961713Sgirish return (NXGE_OK); 450444961713Sgirish fail: 4505321febdeSsbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 450644961713Sgirish 450744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 450844961713Sgirish "nxge_mii_write: Failed to write mii on xcvr %d", 450944961713Sgirish xcvr_portn)); 451044961713Sgirish 451144961713Sgirish return (NXGE_ERROR | rs); 451244961713Sgirish } 451344961713Sgirish 451400161856Syc /* 451500161856Syc * Perform write to Clause45 serdes / transceiver device 451600161856Syc * Arguments: 451700161856Syc * xcvr_portn: The IEEE 802.3 Clause45 PHYAD, it is the same as port 451800161856Syc * number if nxge_mdio_write is used for accessing the 451900161856Syc * internal LSIL serdes. Otherwise PHYAD is different 452000161856Syc * for different platforms. 452100161856Syc * device: With each PHYAD, the driver can use MDIO to control 452200161856Syc * multiple devices inside the PHY, here "device" is an 452300161856Syc * MMD (MDIO managable device). 452400161856Syc * xcvr_reg: Each device has multiple registers. xcvr_reg specifies 452500161856Syc * the register which the driver will write value to. 452600161856Syc * value: The register value will be filled in. 452700161856Syc */ 452844961713Sgirish nxge_status_t 452944961713Sgirish nxge_mdio_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device, 453044961713Sgirish uint16_t xcvr_reg, uint16_t *value) 453144961713Sgirish { 453244961713Sgirish npi_status_t rs = NPI_SUCCESS; 453344961713Sgirish 453444961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_read: xcvr_port<%d>", 453544961713Sgirish xcvr_portn)); 453644961713Sgirish 453753560810Ssbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 453844961713Sgirish 453944961713Sgirish if ((rs = npi_mac_mif_mdio_read(nxgep->npi_handle, 454044961713Sgirish xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS) 454144961713Sgirish goto fail; 454244961713Sgirish 454353560810Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 454444961713Sgirish 454544961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_read: xcvr_port<%d>", 454644961713Sgirish xcvr_portn)); 454744961713Sgirish return (NXGE_OK); 454844961713Sgirish fail: 454953560810Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 455044961713Sgirish 455144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 455244961713Sgirish "nxge_mdio_read: Failed to read mdio on xcvr %d", 455344961713Sgirish xcvr_portn)); 455444961713Sgirish 455544961713Sgirish return (NXGE_ERROR | rs); 455644961713Sgirish } 455744961713Sgirish 455844961713Sgirish /* Perform write to Clause45 serdes / transceiver device */ 455944961713Sgirish 456044961713Sgirish nxge_status_t 456144961713Sgirish nxge_mdio_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device, 456244961713Sgirish uint16_t xcvr_reg, uint16_t value) 456344961713Sgirish { 456444961713Sgirish npi_status_t rs = NPI_SUCCESS; 456544961713Sgirish 456644961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_write: xcvr_port<%d>", 456744961713Sgirish xcvr_portn)); 456844961713Sgirish 456953560810Ssbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 457044961713Sgirish 457144961713Sgirish if ((rs = npi_mac_mif_mdio_write(nxgep->npi_handle, 457244961713Sgirish xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS) 457344961713Sgirish goto fail; 457444961713Sgirish 457553560810Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 457644961713Sgirish 457744961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_write: xcvr_port<%d>", 457844961713Sgirish xcvr_portn)); 457944961713Sgirish return (NXGE_OK); 458044961713Sgirish fail: 458153560810Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 458244961713Sgirish 458344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 458444961713Sgirish "nxge_mdio_write: Failed to write mdio on xcvr %d", 458544961713Sgirish xcvr_portn)); 458644961713Sgirish 458744961713Sgirish return (NXGE_ERROR | rs); 458844961713Sgirish } 458944961713Sgirish 459044961713Sgirish 459144961713Sgirish /* Check MII to see if there is any link status change */ 459244961713Sgirish 459344961713Sgirish nxge_status_t 4594a3c5bd6dSspeer nxge_mii_check(p_nxge_t nxgep, mii_bmsr_t bmsr, mii_bmsr_t bmsr_ints, 4595a3c5bd6dSspeer nxge_link_state_t *link_up) 459644961713Sgirish { 459744961713Sgirish p_nxge_param_t param_arr; 459844961713Sgirish p_nxge_stats_t statsp; 459944961713Sgirish p_mii_regs_t mii_regs; 460044961713Sgirish p_mii_bmsr_t soft_bmsr; 460144961713Sgirish mii_anar_t anar; 460244961713Sgirish mii_anlpar_t anlpar; 460344961713Sgirish mii_anar_t an_common; 460444961713Sgirish mii_aner_t aner; 460544961713Sgirish mii_gsr_t gsr; 460644961713Sgirish nxge_status_t status = NXGE_OK; 460744961713Sgirish 460844961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_check")); 460944961713Sgirish 461044961713Sgirish mii_regs = NULL; 461144961713Sgirish param_arr = nxgep->param_arr; 461244961713Sgirish statsp = nxgep->statsp; 461344961713Sgirish soft_bmsr = &nxgep->soft_bmsr; 4614a3c5bd6dSspeer *link_up = LINK_NO_CHANGE; 461544961713Sgirish 4616d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4617d81011f0Ssbehera "==> nxge_mii_check bmsr 0x%x bmsr_int 0x%x", 4618d81011f0Ssbehera bmsr.value, bmsr_ints.value)); 4619d81011f0Ssbehera 462044961713Sgirish if (bmsr_ints.bits.link_status) { 4621d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4622d81011f0Ssbehera "==> nxge_mii_check (link up) bmsr 0x%x bmsr_int 0x%x", 4623d81011f0Ssbehera bmsr.value, bmsr_ints.value)); 462444961713Sgirish if (bmsr.bits.link_status) { 462544961713Sgirish soft_bmsr->bits.link_status = 1; 4626d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4627d81011f0Ssbehera "==> nxge_mii_check (link up) soft bmsr 0x%x bmsr_int " 4628d81011f0Ssbehera "0x%x", bmsr.value, bmsr_ints.value)); 462944961713Sgirish } else { 463044961713Sgirish statsp->mac_stats.link_up = 0; 463144961713Sgirish soft_bmsr->bits.link_status = 0; 463244961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 463344961713Sgirish "Link down cable problem")); 4634a3c5bd6dSspeer *link_up = LINK_IS_DOWN; 463544961713Sgirish } 463644961713Sgirish } 463744961713Sgirish 4638d81011f0Ssbehera if (nxgep->mac.portmode == PORT_1G_COPPER && 4639d81011f0Ssbehera param_arr[param_autoneg].value) { 464044961713Sgirish if (bmsr_ints.bits.auto_neg_complete) { 464144961713Sgirish if (bmsr.bits.auto_neg_complete) 464244961713Sgirish soft_bmsr->bits.auto_neg_complete = 1; 464344961713Sgirish else 464444961713Sgirish soft_bmsr->bits.auto_neg_complete = 0; 464544961713Sgirish } 464644961713Sgirish if (soft_bmsr->bits.link_status == 0) { 464744961713Sgirish statsp->mac_stats.link_T4 = 0; 464844961713Sgirish statsp->mac_stats.link_speed = 0; 464944961713Sgirish statsp->mac_stats.link_duplex = 0; 465044961713Sgirish statsp->mac_stats.link_asmpause = 0; 465144961713Sgirish statsp->mac_stats.link_pause = 0; 465244961713Sgirish statsp->mac_stats.lp_cap_autoneg = 0; 465344961713Sgirish statsp->mac_stats.lp_cap_100T4 = 0; 465444961713Sgirish statsp->mac_stats.lp_cap_1000fdx = 0; 465544961713Sgirish statsp->mac_stats.lp_cap_1000hdx = 0; 465644961713Sgirish statsp->mac_stats.lp_cap_100fdx = 0; 465744961713Sgirish statsp->mac_stats.lp_cap_100hdx = 0; 465844961713Sgirish statsp->mac_stats.lp_cap_10fdx = 0; 465944961713Sgirish statsp->mac_stats.lp_cap_10hdx = 0; 466044961713Sgirish statsp->mac_stats.lp_cap_10gfdx = 0; 466144961713Sgirish statsp->mac_stats.lp_cap_10ghdx = 0; 466244961713Sgirish statsp->mac_stats.lp_cap_asmpause = 0; 466344961713Sgirish statsp->mac_stats.lp_cap_pause = 0; 466444961713Sgirish } 466544961713Sgirish } else 466644961713Sgirish soft_bmsr->bits.auto_neg_complete = 1; 466744961713Sgirish 466844961713Sgirish if ((bmsr_ints.bits.link_status || 466944961713Sgirish bmsr_ints.bits.auto_neg_complete) && 467044961713Sgirish soft_bmsr->bits.link_status && 467144961713Sgirish soft_bmsr->bits.auto_neg_complete) { 467244961713Sgirish statsp->mac_stats.link_up = 1; 4673d81011f0Ssbehera 4674d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4675d81011f0Ssbehera "==> nxge_mii_check " 4676d81011f0Ssbehera "(auto negotiation complete or link up) " 4677d81011f0Ssbehera "soft bmsr 0x%x bmsr_int 0x%x", 4678d81011f0Ssbehera bmsr.value, bmsr_ints.value)); 4679d81011f0Ssbehera 4680d81011f0Ssbehera if (nxgep->mac.portmode == PORT_1G_COPPER && 4681d81011f0Ssbehera param_arr[param_autoneg].value) { 468244961713Sgirish if ((status = nxge_mii_read(nxgep, 468344961713Sgirish statsp->mac_stats.xcvr_portn, 4684adfcba55Sjoycey #if defined(__i386) 4685adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->anar), 4686adfcba55Sjoycey #else 468744961713Sgirish (uint8_t)(uint64_t)(&mii_regs->anar), 4688adfcba55Sjoycey #endif 468944961713Sgirish &anar.value)) != NXGE_OK) 469044961713Sgirish goto fail; 469144961713Sgirish if ((status = nxge_mii_read(nxgep, 469244961713Sgirish statsp->mac_stats.xcvr_portn, 4693adfcba55Sjoycey #if defined(__i386) 4694adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->anlpar), 4695adfcba55Sjoycey #else 469644961713Sgirish (uint8_t)(uint64_t)(&mii_regs->anlpar), 4697adfcba55Sjoycey #endif 469844961713Sgirish &anlpar.value)) != NXGE_OK) 469944961713Sgirish goto fail; 470044961713Sgirish if ((status = nxge_mii_read(nxgep, 470144961713Sgirish statsp->mac_stats.xcvr_portn, 4702adfcba55Sjoycey #if defined(__i386) 4703adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->aner), 4704adfcba55Sjoycey #else 470544961713Sgirish (uint8_t)(uint64_t)(&mii_regs->aner), 4706adfcba55Sjoycey #endif 470744961713Sgirish &aner.value)) != NXGE_OK) 470844961713Sgirish goto fail; 470944961713Sgirish statsp->mac_stats.lp_cap_autoneg = aner.bits.lp_an_able; 471044961713Sgirish statsp->mac_stats.lp_cap_100T4 = anlpar.bits.cap_100T4; 471144961713Sgirish statsp->mac_stats.lp_cap_100fdx = 471244961713Sgirish anlpar.bits.cap_100fdx; 471344961713Sgirish statsp->mac_stats.lp_cap_100hdx = 471444961713Sgirish anlpar.bits.cap_100hdx; 471544961713Sgirish statsp->mac_stats.lp_cap_10fdx = anlpar.bits.cap_10fdx; 471644961713Sgirish statsp->mac_stats.lp_cap_10hdx = anlpar.bits.cap_10hdx; 471744961713Sgirish statsp->mac_stats.lp_cap_asmpause = 471844961713Sgirish anlpar.bits.cap_asmpause; 471944961713Sgirish statsp->mac_stats.lp_cap_pause = anlpar.bits.cap_pause; 472044961713Sgirish an_common.value = anar.value & anlpar.value; 472144961713Sgirish if (param_arr[param_anar_1000fdx].value || 472244961713Sgirish param_arr[param_anar_1000hdx].value) { 472344961713Sgirish if ((status = nxge_mii_read(nxgep, 472444961713Sgirish statsp->mac_stats.xcvr_portn, 4725adfcba55Sjoycey #if defined(__i386) 4726adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->gsr), 4727adfcba55Sjoycey #else 472844961713Sgirish (uint8_t)(uint64_t)(&mii_regs->gsr), 4729adfcba55Sjoycey #endif 473044961713Sgirish &gsr.value)) 473144961713Sgirish != NXGE_OK) 473244961713Sgirish goto fail; 473344961713Sgirish statsp->mac_stats.lp_cap_1000fdx = 473444961713Sgirish gsr.bits.link_1000fdx; 473544961713Sgirish statsp->mac_stats.lp_cap_1000hdx = 473644961713Sgirish gsr.bits.link_1000hdx; 473744961713Sgirish if (param_arr[param_anar_1000fdx].value && 473844961713Sgirish gsr.bits.link_1000fdx) { 473944961713Sgirish statsp->mac_stats.link_speed = 1000; 474044961713Sgirish statsp->mac_stats.link_duplex = 2; 474144961713Sgirish } else if ( 474244961713Sgirish param_arr[param_anar_1000hdx].value && 474344961713Sgirish gsr.bits.link_1000hdx) { 474444961713Sgirish statsp->mac_stats.link_speed = 1000; 474544961713Sgirish statsp->mac_stats.link_duplex = 1; 474644961713Sgirish } 474744961713Sgirish } 474844961713Sgirish if ((an_common.value != 0) && 474944961713Sgirish !(statsp->mac_stats.link_speed)) { 475044961713Sgirish if (an_common.bits.cap_100T4) { 475144961713Sgirish statsp->mac_stats.link_T4 = 1; 475244961713Sgirish statsp->mac_stats.link_speed = 100; 475344961713Sgirish statsp->mac_stats.link_duplex = 1; 475444961713Sgirish } else if (an_common.bits.cap_100fdx) { 475544961713Sgirish statsp->mac_stats.link_speed = 100; 475644961713Sgirish statsp->mac_stats.link_duplex = 2; 475744961713Sgirish } else if (an_common.bits.cap_100hdx) { 475844961713Sgirish statsp->mac_stats.link_speed = 100; 475944961713Sgirish statsp->mac_stats.link_duplex = 1; 476044961713Sgirish } else if (an_common.bits.cap_10fdx) { 476144961713Sgirish statsp->mac_stats.link_speed = 10; 476244961713Sgirish statsp->mac_stats.link_duplex = 2; 476344961713Sgirish } else if (an_common.bits.cap_10hdx) { 476444961713Sgirish statsp->mac_stats.link_speed = 10; 476544961713Sgirish statsp->mac_stats.link_duplex = 1; 476644961713Sgirish } else { 476744961713Sgirish goto fail; 476844961713Sgirish } 476944961713Sgirish } 477044961713Sgirish if (statsp->mac_stats.link_duplex != 1) { 477144961713Sgirish statsp->mac_stats.link_asmpause = 477244961713Sgirish an_common.bits.cap_asmpause; 477344961713Sgirish if (statsp->mac_stats.link_asmpause) 477444961713Sgirish if ((statsp->mac_stats.cap_pause == 0) && 477544961713Sgirish (statsp->mac_stats.lp_cap_pause 477644961713Sgirish == 1)) 477744961713Sgirish statsp->mac_stats.link_pause 477844961713Sgirish = 0; 477944961713Sgirish else 478044961713Sgirish statsp->mac_stats.link_pause 478144961713Sgirish = 1; 478244961713Sgirish else 478344961713Sgirish statsp->mac_stats.link_pause = 478444961713Sgirish an_common.bits.cap_pause; 478544961713Sgirish } 4786d81011f0Ssbehera } else if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) { 4787d81011f0Ssbehera statsp->mac_stats.link_speed = 1000; 4788d81011f0Ssbehera statsp->mac_stats.link_duplex = 2; 478944961713Sgirish } 4790a3c5bd6dSspeer *link_up = LINK_IS_UP; 4791a3c5bd6dSspeer } 4792a3c5bd6dSspeer 4793a3c5bd6dSspeer if (nxgep->link_notify) { 4794a3c5bd6dSspeer *link_up = ((statsp->mac_stats.link_up) ? LINK_IS_UP : 4795a3c5bd6dSspeer LINK_IS_DOWN); 4796a3c5bd6dSspeer nxgep->link_notify = B_FALSE; 479744961713Sgirish } 479844961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mii_check")); 479944961713Sgirish return (NXGE_OK); 480044961713Sgirish fail: 480144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 480244961713Sgirish "nxge_mii_check: Unable to check MII")); 480344961713Sgirish return (status); 480444961713Sgirish } 480544961713Sgirish 480600161856Syc /* 480700161856Syc * Check PCS to see if there is any link status change. 480800161856Syc * This function is called by PORT_1G_SERDES only. 480900161856Syc */ 481000161856Syc void 48112e59129aSraghus nxge_pcs_check(p_nxge_t nxgep, uint8_t portn, nxge_link_state_t *link_up) 48122e59129aSraghus { 48132e59129aSraghus p_nxge_stats_t statsp; 48142e59129aSraghus boolean_t linkup; 48152e59129aSraghus 48162e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_check")); 48172e59129aSraghus 48182e59129aSraghus statsp = nxgep->statsp; 48192e59129aSraghus *link_up = LINK_NO_CHANGE; 48202e59129aSraghus 48212e59129aSraghus (void) npi_mac_get_link_status(nxgep->npi_handle, portn, &linkup); 48222e59129aSraghus if (linkup) { 48232e59129aSraghus if (nxgep->link_notify || 48242e59129aSraghus nxgep->statsp->mac_stats.link_up == 0) { 48252e59129aSraghus statsp->mac_stats.link_up = 1; 48262e59129aSraghus statsp->mac_stats.link_speed = 1000; 48272e59129aSraghus statsp->mac_stats.link_duplex = 2; 48282e59129aSraghus *link_up = LINK_IS_UP; 48292e59129aSraghus nxgep->link_notify = B_FALSE; 48302e59129aSraghus } 48312e59129aSraghus } else { 48322e59129aSraghus if (nxgep->link_notify || 48332e59129aSraghus nxgep->statsp->mac_stats.link_up == 1) { 48342e59129aSraghus statsp->mac_stats.link_up = 0; 48352e59129aSraghus statsp->mac_stats.link_speed = 0; 48362e59129aSraghus statsp->mac_stats.link_duplex = 0; 48372e59129aSraghus *link_up = LINK_IS_DOWN; 48382e59129aSraghus nxgep->link_notify = B_FALSE; 48392e59129aSraghus } 48402e59129aSraghus } 48412e59129aSraghus 48422e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_check")); 48432e59129aSraghus } 48442e59129aSraghus 484544961713Sgirish /* Add a multicast address entry into the HW hash table */ 484644961713Sgirish 484744961713Sgirish nxge_status_t 484844961713Sgirish nxge_add_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp) 484944961713Sgirish { 485044961713Sgirish uint32_t mchash; 485144961713Sgirish p_hash_filter_t hash_filter; 485244961713Sgirish uint16_t hash_bit; 485344961713Sgirish boolean_t rx_init = B_FALSE; 485444961713Sgirish uint_t j; 485544961713Sgirish nxge_status_t status = NXGE_OK; 485644961713Sgirish 485744961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_add_mcast_addr")); 485844961713Sgirish 485944961713Sgirish RW_ENTER_WRITER(&nxgep->filter_lock); 486044961713Sgirish mchash = crc32_mchash(addrp); 486144961713Sgirish if (nxgep->hash_filter == NULL) { 486244961713Sgirish NXGE_DEBUG_MSG((NULL, STR_CTL, 486344961713Sgirish "Allocating hash filter storage.")); 486444961713Sgirish nxgep->hash_filter = KMEM_ZALLOC(sizeof (hash_filter_t), 486544961713Sgirish KM_SLEEP); 486644961713Sgirish } 486744961713Sgirish hash_filter = nxgep->hash_filter; 486844961713Sgirish j = mchash / HASH_REG_WIDTH; 486944961713Sgirish hash_bit = (1 << (mchash % HASH_REG_WIDTH)); 487044961713Sgirish hash_filter->hash_filter_regs[j] |= hash_bit; 487144961713Sgirish hash_filter->hash_bit_ref_cnt[mchash]++; 487244961713Sgirish if (hash_filter->hash_bit_ref_cnt[mchash] == 1) { 487344961713Sgirish hash_filter->hash_ref_cnt++; 487444961713Sgirish rx_init = B_TRUE; 487544961713Sgirish } 487644961713Sgirish if (rx_init) { 487744961713Sgirish if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 487844961713Sgirish goto fail; 487944961713Sgirish if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 488044961713Sgirish goto fail; 488144961713Sgirish } 488244961713Sgirish 488344961713Sgirish RW_EXIT(&nxgep->filter_lock); 488444961713Sgirish 488544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_add_mcast_addr")); 488644961713Sgirish 488744961713Sgirish return (NXGE_OK); 488844961713Sgirish fail: 488944961713Sgirish RW_EXIT(&nxgep->filter_lock); 489044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_add_mcast_addr: " 489144961713Sgirish "Unable to add multicast address")); 489244961713Sgirish return (status); 489344961713Sgirish } 489444961713Sgirish 489544961713Sgirish /* Remove a multicast address entry from the HW hash table */ 489644961713Sgirish 489744961713Sgirish nxge_status_t 489844961713Sgirish nxge_del_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp) 489944961713Sgirish { 490044961713Sgirish uint32_t mchash; 490144961713Sgirish p_hash_filter_t hash_filter; 490244961713Sgirish uint16_t hash_bit; 490344961713Sgirish boolean_t rx_init = B_FALSE; 490444961713Sgirish uint_t j; 490544961713Sgirish nxge_status_t status = NXGE_OK; 490644961713Sgirish 490744961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_del_mcast_addr")); 490844961713Sgirish RW_ENTER_WRITER(&nxgep->filter_lock); 490944961713Sgirish mchash = crc32_mchash(addrp); 491044961713Sgirish if (nxgep->hash_filter == NULL) { 491144961713Sgirish NXGE_DEBUG_MSG((NULL, STR_CTL, 491244961713Sgirish "Hash filter already de_allocated.")); 491344961713Sgirish RW_EXIT(&nxgep->filter_lock); 491444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr")); 491544961713Sgirish return (NXGE_OK); 491644961713Sgirish } 491744961713Sgirish hash_filter = nxgep->hash_filter; 491844961713Sgirish hash_filter->hash_bit_ref_cnt[mchash]--; 491944961713Sgirish if (hash_filter->hash_bit_ref_cnt[mchash] == 0) { 492044961713Sgirish j = mchash / HASH_REG_WIDTH; 492144961713Sgirish hash_bit = (1 << (mchash % HASH_REG_WIDTH)); 492244961713Sgirish hash_filter->hash_filter_regs[j] &= ~hash_bit; 492344961713Sgirish hash_filter->hash_ref_cnt--; 492444961713Sgirish rx_init = B_TRUE; 492544961713Sgirish } 492644961713Sgirish if (hash_filter->hash_ref_cnt == 0) { 492744961713Sgirish NXGE_DEBUG_MSG((NULL, STR_CTL, 492844961713Sgirish "De-allocating hash filter storage.")); 492944961713Sgirish KMEM_FREE(hash_filter, sizeof (hash_filter_t)); 493044961713Sgirish nxgep->hash_filter = NULL; 493144961713Sgirish } 493244961713Sgirish 493344961713Sgirish if (rx_init) { 493444961713Sgirish if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 493544961713Sgirish goto fail; 493644961713Sgirish if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 493744961713Sgirish goto fail; 493844961713Sgirish } 493944961713Sgirish RW_EXIT(&nxgep->filter_lock); 494044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr")); 494144961713Sgirish 494244961713Sgirish return (NXGE_OK); 494344961713Sgirish fail: 494444961713Sgirish RW_EXIT(&nxgep->filter_lock); 494544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_del_mcast_addr: " 494644961713Sgirish "Unable to remove multicast address")); 494744961713Sgirish 494844961713Sgirish return (status); 494944961713Sgirish } 495044961713Sgirish 495144961713Sgirish /* Set MAC address into MAC address HW registers */ 495244961713Sgirish 495344961713Sgirish nxge_status_t 495444961713Sgirish nxge_set_mac_addr(p_nxge_t nxgep, struct ether_addr *addrp) 495544961713Sgirish { 495644961713Sgirish nxge_status_t status = NXGE_OK; 495744961713Sgirish 495844961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_mac_addr")); 495944961713Sgirish 496044961713Sgirish MUTEX_ENTER(&nxgep->ouraddr_lock); 496144961713Sgirish /* 496244961713Sgirish * Exit if the address is same as ouraddr or multicast or broadcast 496344961713Sgirish */ 496444961713Sgirish if (((addrp->ether_addr_octet[0] & 01) == 1) || 496544961713Sgirish (ether_cmp(addrp, ðerbroadcastaddr) == 0) || 496644961713Sgirish (ether_cmp(addrp, &nxgep->ouraddr) == 0)) { 496744961713Sgirish goto nxge_set_mac_addr_exit; 496844961713Sgirish } 496944961713Sgirish nxgep->ouraddr = *addrp; 497044961713Sgirish /* 497144961713Sgirish * Set new interface local address and re-init device. 497244961713Sgirish * This is destructive to any other streams attached 497344961713Sgirish * to this device. 497444961713Sgirish */ 497544961713Sgirish RW_ENTER_WRITER(&nxgep->filter_lock); 497644961713Sgirish if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 497744961713Sgirish goto fail; 497844961713Sgirish if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 497944961713Sgirish goto fail; 498044961713Sgirish 498144961713Sgirish RW_EXIT(&nxgep->filter_lock); 498244961713Sgirish MUTEX_EXIT(&nxgep->ouraddr_lock); 498344961713Sgirish goto nxge_set_mac_addr_end; 498444961713Sgirish nxge_set_mac_addr_exit: 498544961713Sgirish MUTEX_EXIT(&nxgep->ouraddr_lock); 498644961713Sgirish nxge_set_mac_addr_end: 498744961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_mac_addr")); 498844961713Sgirish 498944961713Sgirish return (NXGE_OK); 499044961713Sgirish fail: 499144961713Sgirish MUTEX_EXIT(&nxgep->ouraddr_lock); 499244961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_mac_addr: " 499344961713Sgirish "Unable to set mac address")); 499444961713Sgirish return (status); 499544961713Sgirish } 499644961713Sgirish 499798ecde52Stm static 499898ecde52Stm check_link_state_t 499900161856Syc nxge_check_link_stop(nxge_t *nxge) 500098ecde52Stm { 500198ecde52Stm /* If the poll has been cancelled, return STOP. */ 500298ecde52Stm MUTEX_ENTER(&nxge->poll_lock); 500398ecde52Stm if (nxge->suspended || nxge->poll_state == LINK_MONITOR_STOPPING) { 500498ecde52Stm nxge->poll_state = LINK_MONITOR_STOP; 500598ecde52Stm nxge->nxge_link_poll_timerid = 0; 500698ecde52Stm cv_broadcast(&nxge->poll_cv); 500798ecde52Stm MUTEX_EXIT(&nxge->poll_lock); 500898ecde52Stm 500998ecde52Stm NXGE_DEBUG_MSG((nxge, MAC_CTL, 501098ecde52Stm "nxge_check_%s_link(port<%d>) stopped.", 501198ecde52Stm nxge->mac.portmode == PORT_10G_FIBER ? "10g" : "mii", 501298ecde52Stm nxge->mac.portnum)); 501398ecde52Stm return (CHECK_LINK_STOP); 501498ecde52Stm } 501598ecde52Stm MUTEX_EXIT(&nxge->poll_lock); 501698ecde52Stm 501798ecde52Stm return (CHECK_LINK_RESCHEDULE); 501898ecde52Stm } 501998ecde52Stm 502000161856Syc /* 502100161856Syc * Check status of MII (MIF or PCS) link. 502200161856Syc * This function is called once per second, that is because this function 502300161856Syc * calls nxge_link_monitor with LINK_MONITOR_START, which starts a timer to 502400161856Syc * call this function recursively. 502500161856Syc */ 502659ac0c16Sdavemq static nxge_status_t 502744961713Sgirish nxge_check_mii_link(p_nxge_t nxgep) 502844961713Sgirish { 502944961713Sgirish mii_bmsr_t bmsr_ints, bmsr_data; 503044961713Sgirish mii_anlpar_t anlpar; 503144961713Sgirish mii_gsr_t gsr; 503244961713Sgirish p_mii_regs_t mii_regs; 503344961713Sgirish nxge_status_t status = NXGE_OK; 503444961713Sgirish uint8_t portn; 5035a3c5bd6dSspeer nxge_link_state_t link_up; 503644961713Sgirish 503798ecde52Stm if (nxgep->nxge_magic != NXGE_MAGIC) 503898ecde52Stm return (NXGE_ERROR); 503998ecde52Stm 504098ecde52Stm if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 504198ecde52Stm return (NXGE_OK); 504298ecde52Stm 504344961713Sgirish portn = nxgep->mac.portnum; 504444961713Sgirish 504544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_mii_link port<%d>", 504698ecde52Stm portn)); 504744961713Sgirish 504844961713Sgirish mii_regs = NULL; 504944961713Sgirish 505044961713Sgirish RW_ENTER_WRITER(&nxgep->filter_lock); 505144961713Sgirish 505244961713Sgirish if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10) 505344961713Sgirish goto nxge_check_mii_link_exit; 505444961713Sgirish 50552e59129aSraghus switch (nxgep->mac.portmode) { 50562e59129aSraghus default: 5057d81011f0Ssbehera bmsr_data.value = 0; 505844961713Sgirish if ((status = nxge_mii_read(nxgep, 50592e59129aSraghus nxgep->statsp->mac_stats.xcvr_portn, 5060adfcba55Sjoycey #if defined(__i386) 5061adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->bmsr), 5062adfcba55Sjoycey #else 50632e59129aSraghus (uint8_t)(uint64_t)(&mii_regs->bmsr), 5064adfcba55Sjoycey #endif 50652e59129aSraghus &bmsr_data.value)) != NXGE_OK) { 506644961713Sgirish goto fail; 506744961713Sgirish } 506844961713Sgirish 5069d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5070d81011f0Ssbehera "==> nxge_check_mii_link port<0x%x> " 5071d81011f0Ssbehera "RIGHT AFTER READ bmsr_data 0x%x (nxgep->bmsr 0x%x ", 50722d17280bSsbehera portn, bmsr_data.value, nxgep->bmsr.value)); 5073d81011f0Ssbehera 50742e59129aSraghus if (nxgep->param_arr[param_autoneg].value) { 50752e59129aSraghus if ((status = nxge_mii_read(nxgep, 50762e59129aSraghus nxgep->statsp->mac_stats.xcvr_portn, 5077adfcba55Sjoycey #if defined(__i386) 5078adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->gsr), 5079adfcba55Sjoycey #else 50802e59129aSraghus (uint8_t)(uint64_t)(&mii_regs->gsr), 5081adfcba55Sjoycey #endif 50822e59129aSraghus &gsr.value)) != NXGE_OK) 50832e59129aSraghus goto fail; 50842e59129aSraghus if ((status = nxge_mii_read(nxgep, 50852e59129aSraghus nxgep->statsp->mac_stats.xcvr_portn, 5086adfcba55Sjoycey #if defined(__i386) 5087adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->anlpar), 5088adfcba55Sjoycey #else 50892e59129aSraghus (uint8_t)(uint64_t)(&mii_regs->anlpar), 5090adfcba55Sjoycey #endif 50912e59129aSraghus &anlpar.value)) != NXGE_OK) 50922e59129aSraghus goto fail; 5093d81011f0Ssbehera if (nxgep->mac.portmode != PORT_1G_RGMII_FIBER) { 5094d81011f0Ssbehera 5095d81011f0Ssbehera if (nxgep->statsp->mac_stats.link_up && 5096d81011f0Ssbehera ((nxgep->statsp->mac_stats.lp_cap_1000fdx ^ 5097d81011f0Ssbehera gsr.bits.link_1000fdx) || 5098d81011f0Ssbehera (nxgep->statsp->mac_stats.lp_cap_1000hdx ^ 5099d81011f0Ssbehera gsr.bits.link_1000hdx) || 5100d81011f0Ssbehera (nxgep->statsp->mac_stats.lp_cap_100T4 ^ 5101d81011f0Ssbehera anlpar.bits.cap_100T4) || 5102d81011f0Ssbehera (nxgep->statsp->mac_stats.lp_cap_100fdx ^ 5103d81011f0Ssbehera anlpar.bits.cap_100fdx) || 5104d81011f0Ssbehera (nxgep->statsp->mac_stats.lp_cap_100hdx ^ 5105d81011f0Ssbehera anlpar.bits.cap_100hdx) || 5106d81011f0Ssbehera (nxgep->statsp->mac_stats.lp_cap_10fdx ^ 5107d81011f0Ssbehera anlpar.bits.cap_10fdx) || 5108d81011f0Ssbehera (nxgep->statsp->mac_stats.lp_cap_10hdx ^ 5109d81011f0Ssbehera anlpar.bits.cap_10hdx))) { 5110d81011f0Ssbehera bmsr_data.bits.link_status = 0; 5111d81011f0Ssbehera } 51122e59129aSraghus } 51132e59129aSraghus } 511444961713Sgirish 51152e59129aSraghus /* Workaround for link down issue */ 51162e59129aSraghus if (bmsr_data.value == 0) { 51172e59129aSraghus cmn_err(CE_NOTE, "!LINK DEBUG: Read zero bmsr\n"); 51182e59129aSraghus goto nxge_check_mii_link_exit; 51192e59129aSraghus } 51202e59129aSraghus 5121d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5122d81011f0Ssbehera "==> nxge_check_mii_link port<0x%x> :" 5123d81011f0Ssbehera "BEFORE BMSR ^ nxgep->bmsr 0x%x bmsr_data 0x%x", 51242d17280bSsbehera portn, nxgep->bmsr.value, bmsr_data.value)); 5125d81011f0Ssbehera 51262e59129aSraghus bmsr_ints.value = nxgep->bmsr.value ^ bmsr_data.value; 51272e59129aSraghus nxgep->bmsr.value = bmsr_data.value; 5128d81011f0Ssbehera 5129d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5130d81011f0Ssbehera "==> nxge_check_mii_link port<0x%x> CALLING " 5131d81011f0Ssbehera "bmsr_data 0x%x bmsr_ints.value 0x%x", 51322d17280bSsbehera portn, bmsr_data.value, bmsr_ints.value)); 5133d81011f0Ssbehera 51342e59129aSraghus if ((status = nxge_mii_check(nxgep, bmsr_data, bmsr_ints, 51352e59129aSraghus &link_up)) != NXGE_OK) { 51362e59129aSraghus goto fail; 51372e59129aSraghus } 51382e59129aSraghus break; 51392e59129aSraghus 51402e59129aSraghus case PORT_1G_SERDES: 514100161856Syc /* 514200161856Syc * Above default is for all cases except PORT_1G_SERDES. 514300161856Syc * The default case gets information from the PHY, but a 514400161856Syc * nxge whose portmode equals PORT_1G_SERDES does not 514500161856Syc * have a PHY. 514600161856Syc */ 51472e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 51482e59129aSraghus "==> nxge_check_mii_link port<%d> (SERDES)", portn)); 514900161856Syc nxge_pcs_check(nxgep, portn, &link_up); 51502e59129aSraghus break; 51512e59129aSraghus } 515244961713Sgirish 515344961713Sgirish nxge_check_mii_link_exit: 515444961713Sgirish RW_EXIT(&nxgep->filter_lock); 5155a3c5bd6dSspeer if (link_up == LINK_IS_UP) { 5156a3c5bd6dSspeer nxge_link_is_up(nxgep); 5157a3c5bd6dSspeer } else if (link_up == LINK_IS_DOWN) { 5158a3c5bd6dSspeer nxge_link_is_down(nxgep); 5159a3c5bd6dSspeer } 516044961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 516144961713Sgirish 516244961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_mii_link port<%d>", 51632e59129aSraghus portn)); 516444961713Sgirish return (NXGE_OK); 516544961713Sgirish 516644961713Sgirish fail: 516744961713Sgirish RW_EXIT(&nxgep->filter_lock); 516844961713Sgirish 516944961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 517044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 51712e59129aSraghus "nxge_check_mii_link: Failed to check link port<%d>", 51722e59129aSraghus portn)); 517344961713Sgirish return (status); 517444961713Sgirish } 517544961713Sgirish 517644961713Sgirish /*ARGSUSED*/ 517759ac0c16Sdavemq static nxge_status_t 517844961713Sgirish nxge_check_10g_link(p_nxge_t nxgep) 517944961713Sgirish { 518044961713Sgirish uint8_t portn; 518144961713Sgirish nxge_status_t status = NXGE_OK; 5182763fcc44Ssbehera boolean_t link_up; 51832e59129aSraghus uint32_t val; 51842e59129aSraghus npi_status_t rs; 518544961713Sgirish 518698ecde52Stm if (nxgep->nxge_magic != NXGE_MAGIC) 518798ecde52Stm return (NXGE_ERROR); 518898ecde52Stm 518998ecde52Stm if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 519098ecde52Stm return (NXGE_OK); 519198ecde52Stm 519244961713Sgirish portn = nxgep->mac.portnum; 5193d81011f0Ssbehera val = 0; 5194d81011f0Ssbehera rs = NPI_SUCCESS; 519544961713Sgirish 519644961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_10g_link port<%d>", 519798ecde52Stm portn)); 519844961713Sgirish 51992e59129aSraghus switch (nxgep->mac.portmode) { 52002e59129aSraghus default: 52012d17280bSsbehera /* 52022d17280bSsbehera * Check if the phy is present in case of hot swappable phy 52032d17280bSsbehera */ 52042d17280bSsbehera if (nxgep->hot_swappable_phy) { 52052d17280bSsbehera boolean_t phy_present_now = B_FALSE; 52062d17280bSsbehera 52072d17280bSsbehera /* 52082d17280bSsbehera * If this is the 2nd Goa port, then check 2 addresses 52092d17280bSsbehera * to take care of the Goa NEM card requirements. 52102d17280bSsbehera */ 52112d17280bSsbehera if (portn == 1) { 52122d17280bSsbehera if (nxge_is_phy_present(nxgep, 521300161856Syc ALT_GOA_CLAUSE45_PORT1_ADDR, 52142d17280bSsbehera BCM8706_DEV_ID, BCM_PHY_ID_MASK)) { 52152d17280bSsbehera phy_present_now = B_TRUE; 52162d17280bSsbehera nxgep->xcvr_addr = 521700161856Syc ALT_GOA_CLAUSE45_PORT1_ADDR; 52182d17280bSsbehera goto phy_check_done; 52192d17280bSsbehera } 52202d17280bSsbehera } 52212d17280bSsbehera if (nxge_is_phy_present(nxgep, 522200161856Syc (GOA_CLAUSE45_PORT_ADDR_BASE) + portn, 52232d17280bSsbehera BCM8706_DEV_ID, BCM_PHY_ID_MASK)) { 52242d17280bSsbehera nxgep->xcvr_addr = 522500161856Syc (GOA_CLAUSE45_PORT_ADDR_BASE) + portn; 52262d17280bSsbehera phy_present_now = B_TRUE; 52272d17280bSsbehera } 52282d17280bSsbehera 52292d17280bSsbehera phy_check_done: 52302d17280bSsbehera if (nxgep->phy_absent) { 52312d17280bSsbehera if (phy_present_now) { 52322d17280bSsbehera /* 52332d17280bSsbehera * Detect, Initialize phy and do link up 52342d17280bSsbehera * set xcvr vals, link_init, nxge_init 52352d17280bSsbehera */ 52362d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 52372d17280bSsbehera "Hot swappable phy DETECTED!!")); 52382d17280bSsbehera nxgep->phy_absent = B_FALSE; 52392d17280bSsbehera (void) nxge_xcvr_find(nxgep); 52402d17280bSsbehera (void) nxge_link_init(nxgep); 52412d17280bSsbehera if (!(nxgep->drv_state & 52422d17280bSsbehera STATE_HW_INITIALIZED)) { 52432d17280bSsbehera status = nxge_init(nxgep); 52442d17280bSsbehera if (status != NXGE_OK) { 52452d17280bSsbehera NXGE_ERROR_MSG((nxgep, 52462d17280bSsbehera NXGE_ERR_CTL, 52472d17280bSsbehera "Hot swappable " 52482d17280bSsbehera "phy present, but" 52492d17280bSsbehera " driver init" 52502d17280bSsbehera " failed...")); 52512d17280bSsbehera goto fail; 52522d17280bSsbehera } 52532d17280bSsbehera } 52542d17280bSsbehera } 52552d17280bSsbehera 52562d17280bSsbehera goto start_link_check; 52572d17280bSsbehera 52582d17280bSsbehera } else if (!phy_present_now) { 52592d17280bSsbehera /* 52602d17280bSsbehera * Phy gone, bring link down reset xcvr vals 52612d17280bSsbehera */ 52622d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 52632d17280bSsbehera "Hot swappable phy REMOVED!!")); 52642d17280bSsbehera nxgep->phy_absent = B_TRUE; 52652d17280bSsbehera nxgep->statsp->mac_stats.link_up = 0; 52662d17280bSsbehera nxgep->statsp->mac_stats.link_speed = 0; 52672d17280bSsbehera nxgep->statsp->mac_stats.link_duplex = 0; 52682d17280bSsbehera nxge_link_is_down(nxgep); 52692d17280bSsbehera nxgep->link_notify = B_FALSE; 52702d17280bSsbehera 52712d17280bSsbehera (void) nxge_xcvr_find(nxgep); 52722d17280bSsbehera 52732d17280bSsbehera goto start_link_check; 52742d17280bSsbehera 52752d17280bSsbehera } 52762d17280bSsbehera } 527752cdd236Ssbehera if (nxgep->chip_id == MRVL88X201X_CHIP_ID) { 527800161856Syc status = nxge_check_mrvl88x2011_link(nxgep, &link_up); 527952cdd236Ssbehera } else { 528052cdd236Ssbehera status = nxge_check_bcm8704_link(nxgep, &link_up); 528152cdd236Ssbehera } 52822e59129aSraghus if (status != NXGE_OK) 52832e59129aSraghus goto fail; 52842e59129aSraghus break; 52852e59129aSraghus case PORT_10G_SERDES: 52862e59129aSraghus rs = npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 5287763fcc44Ssbehera XPCS_REG_STATUS, &val); 52882e59129aSraghus if (rs != 0) 52892e59129aSraghus goto fail; 52902e59129aSraghus 52912e59129aSraghus link_up = B_FALSE; 5292763fcc44Ssbehera if (val & XPCS_STATUS_LANE_ALIGN) { 5293763fcc44Ssbehera link_up = B_TRUE; 52942e59129aSraghus } 52952e59129aSraghus 52962e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 52972e59129aSraghus "==> nxge_check_10g_link port<%d> " 5298763fcc44Ssbehera "XPCS_REG_STATUS2 0x%x link_up %d", 5299763fcc44Ssbehera portn, val, link_up)); 53002e59129aSraghus 53012e59129aSraghus break; 53022e59129aSraghus } 530344961713Sgirish 530444961713Sgirish if (link_up) { 5305a3c5bd6dSspeer if (nxgep->link_notify || 5306a3c5bd6dSspeer nxgep->statsp->mac_stats.link_up == 0) { 530744961713Sgirish if (nxge_10g_link_led_on(nxgep) != NXGE_OK) 530844961713Sgirish goto fail; 530944961713Sgirish nxgep->statsp->mac_stats.link_up = 1; 531044961713Sgirish nxgep->statsp->mac_stats.link_speed = 10000; 531144961713Sgirish nxgep->statsp->mac_stats.link_duplex = 2; 531244961713Sgirish 531344961713Sgirish nxge_link_is_up(nxgep); 5314a3c5bd6dSspeer nxgep->link_notify = B_FALSE; 531544961713Sgirish } 531644961713Sgirish } else { 5317a3c5bd6dSspeer if (nxgep->link_notify || 5318a3c5bd6dSspeer nxgep->statsp->mac_stats.link_up == 1) { 531944961713Sgirish if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 532044961713Sgirish goto fail; 532144961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 53222e59129aSraghus "Link down cable problem")); 532344961713Sgirish nxgep->statsp->mac_stats.link_up = 0; 532444961713Sgirish nxgep->statsp->mac_stats.link_speed = 0; 532544961713Sgirish nxgep->statsp->mac_stats.link_duplex = 0; 532644961713Sgirish 532744961713Sgirish nxge_link_is_down(nxgep); 5328a3c5bd6dSspeer nxgep->link_notify = B_FALSE; 532944961713Sgirish } 533044961713Sgirish } 533144961713Sgirish 53322d17280bSsbehera start_link_check: 533344961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 533444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_10g_link port<%d>", 533598ecde52Stm portn)); 533644961713Sgirish return (NXGE_OK); 533744961713Sgirish 533844961713Sgirish fail: 533998ecde52Stm (void) nxge_check_link_stop(nxgep); 534098ecde52Stm 534144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 534298ecde52Stm "nxge_check_10g_link: Failed to check link port<%d>", 534398ecde52Stm portn)); 534444961713Sgirish return (status); 534544961713Sgirish } 534644961713Sgirish 534744961713Sgirish 534844961713Sgirish /* Declare link down */ 534944961713Sgirish 535044961713Sgirish void 535144961713Sgirish nxge_link_is_down(p_nxge_t nxgep) 535244961713Sgirish { 535359ac0c16Sdavemq p_nxge_stats_t statsp; 535459ac0c16Sdavemq char link_stat_msg[64]; 535559ac0c16Sdavemq 535644961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_down")); 535744961713Sgirish 535859ac0c16Sdavemq statsp = nxgep->statsp; 535959ac0c16Sdavemq (void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is down", 536059ac0c16Sdavemq statsp->mac_stats.xcvr_portn); 536159ac0c16Sdavemq 536259ac0c16Sdavemq if (nxge_no_msg == B_FALSE) { 536359ac0c16Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg)); 536459ac0c16Sdavemq } 536559ac0c16Sdavemq 536644961713Sgirish mac_link_update(nxgep->mach, LINK_STATE_DOWN); 536744961713Sgirish 536844961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_down")); 536944961713Sgirish } 537044961713Sgirish 537144961713Sgirish /* Declare link up */ 537244961713Sgirish 537344961713Sgirish void 537444961713Sgirish nxge_link_is_up(p_nxge_t nxgep) 537544961713Sgirish { 537659ac0c16Sdavemq p_nxge_stats_t statsp; 537759ac0c16Sdavemq char link_stat_msg[64]; 537844961713Sgirish uint32_t val; 537944961713Sgirish 538044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_up")); 538144961713Sgirish 538259ac0c16Sdavemq statsp = nxgep->statsp; 538359ac0c16Sdavemq (void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is up %d Mbps ", 538459ac0c16Sdavemq statsp->mac_stats.xcvr_portn, 538559ac0c16Sdavemq statsp->mac_stats.link_speed); 538659ac0c16Sdavemq 538759ac0c16Sdavemq if (statsp->mac_stats.link_T4) 538859ac0c16Sdavemq (void) strcat(link_stat_msg, "T4"); 538959ac0c16Sdavemq else if (statsp->mac_stats.link_duplex == 2) 539059ac0c16Sdavemq (void) strcat(link_stat_msg, "full duplex"); 539159ac0c16Sdavemq else 539259ac0c16Sdavemq (void) strcat(link_stat_msg, "half duplex"); 539359ac0c16Sdavemq 539444961713Sgirish 539544961713Sgirish /* Clean up symbol errors incurred during link transition */ 53962e59129aSraghus if ((nxgep->mac.portmode == PORT_10G_FIBER) || 53972e59129aSraghus (nxgep->mac.portmode == PORT_10G_SERDES)) { 539844961713Sgirish (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 539944961713Sgirish XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val); 540044961713Sgirish (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 540144961713Sgirish XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val); 540244961713Sgirish } 540344961713Sgirish 540400161856Syc /* 540500161856Syc * If the driver was plumbed without a link (therefore auto-negotiation 540600161856Syc * could not complete), the driver will detect a link up when a cable 540700161856Syc * conneting to a link partner is plugged into the port. By the time 540800161856Syc * link-up is detected, auto-negotiation should have completed (The 540900161856Syc * TN1010 tries to contact a link partner every 8~24ms). Here we re- 541000161856Syc * configure the Neptune/NIU according to the newly negotiated speed. 541100161856Syc * This is necessary only for the TN1010 basad device because only the 541200161856Syc * TN1010 supports dual speeds. 541300161856Syc */ 541400161856Syc if (nxgep->mac.portmode == PORT_1G_TN1010 || 541500161856Syc nxgep->mac.portmode == PORT_10G_TN1010) { 541600161856Syc 541700161856Syc (void) nxge_set_tn1010_param(nxgep); 541800161856Syc 541900161856Syc /* 542000161856Syc * nxge_xcvr_find calls nxge_get_xcvr_type (which sets 542100161856Syc * nxgep->portmode) and nxge_setup_xcvr_table (which sets 542200161856Syc * the nxgep->xcvr to the proper nxge_xcvr_table_t struct). 542300161856Syc */ 542400161856Syc if (nxge_xcvr_find(nxgep) != NXGE_OK) { 542500161856Syc NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 542600161856Syc "nxge_link_is_up: nxge_xcvr_find failed")); 542700161856Syc } 542800161856Syc 542900161856Syc /* nxge_link_init calls nxge_xcvr_init and nxge_serdes_init */ 543000161856Syc if (nxge_link_init(nxgep) != NXGE_OK) { 543100161856Syc NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 543200161856Syc "nxge_link_is_up: nxge_link_init failed")); 543300161856Syc } 543400161856Syc 543500161856Syc /* 543600161856Syc * nxge_mac_init calls many subroutines including 543700161856Syc * nxge_xif_init which sets XGMII or GMII mode 543800161856Syc */ 543900161856Syc if (nxge_mac_init(nxgep) != NXGE_OK) { 544000161856Syc NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 544100161856Syc "nxge_link_is_up: nxge_mac_init failed")); 544200161856Syc } 544300161856Syc } else { 544400161856Syc (void) nxge_xif_init(nxgep); 544500161856Syc } 544600161856Syc 544759ac0c16Sdavemq if (nxge_no_msg == B_FALSE) { 544859ac0c16Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg)); 544959ac0c16Sdavemq } 545059ac0c16Sdavemq 545144961713Sgirish mac_link_update(nxgep->mach, LINK_STATE_UP); 545244961713Sgirish 545344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_up")); 545444961713Sgirish } 545544961713Sgirish 545600161856Syc #ifdef NXGE_DEBUG 545700161856Syc /* Dump all TN1010 Status registers */ 545800161856Syc static void 545900161856Syc nxge_dump_tn1010_status_regs(p_nxge_t nxgep) 546000161856Syc { 546100161856Syc uint16_t val; 546200161856Syc 546300161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 546400161856Syc TN1010_PMA_PMD_DEV_ADDR, 1, &val); 546500161856Syc cmn_err(CE_NOTE, "PMA status1 = 0x%x", val); 546600161856Syc 546700161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 546800161856Syc TN1010_PMA_PMD_DEV_ADDR, 8, &val); 546900161856Syc cmn_err(CE_NOTE, "PMA status2 = 0x%x", val); 547000161856Syc 547100161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 547200161856Syc TN1010_PMA_PMD_DEV_ADDR, 129, &val); 547300161856Syc cmn_err(CE_NOTE, "10BASET-T status = 0x%x", val); 547400161856Syc 547500161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 547600161856Syc TN1010_PCS_DEV_ADDR, 1, &val); 547700161856Syc cmn_err(CE_NOTE, "PCS status1 = 0x%x", val); 547800161856Syc 547900161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 548000161856Syc TN1010_PCS_DEV_ADDR, 8, &val); 548100161856Syc cmn_err(CE_NOTE, "PCS status2 = 0x%x", val); 548200161856Syc 548300161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 548400161856Syc TN1010_PCS_DEV_ADDR, 32, &val); 548500161856Syc cmn_err(CE_NOTE, "10GBASE-R status1 = 0x%x", val); 548600161856Syc 548700161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 548800161856Syc TN1010_PCS_DEV_ADDR, 33, &val); 548900161856Syc cmn_err(CE_NOTE, "10GBASE-R Status2 = 0x%x", val); 549000161856Syc 549100161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 549200161856Syc TN1010_PHYXS_DEV_ADDR, 1, &val); 549300161856Syc cmn_err(CE_NOTE, "PHYXS status1 = 0x%x", val); 549400161856Syc 549500161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 549600161856Syc TN1010_PHYXS_DEV_ADDR, 8, &val); 549700161856Syc cmn_err(CE_NOTE, "PHYXS status2 = 0x%x", val); 549800161856Syc 549900161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 550000161856Syc TN1010_PHYXS_DEV_ADDR, 24, &val); 550100161856Syc cmn_err(CE_NOTE, "XGXS Lane status = 0x%x", val); 550200161856Syc 550300161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 550400161856Syc TN1010_AUTONEG_DEV_ADDR, 1, &val); 550500161856Syc cmn_err(CE_NOTE, "Autoneg status = 0x%x", val); 550600161856Syc 550700161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 550800161856Syc TN1010_AUTONEG_DEV_ADDR, 33, &val); 550900161856Syc cmn_err(CE_NOTE, "10Gbase-T An status = 0x%x", val); 551000161856Syc 551100161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 551200161856Syc TN1010_VENDOR_MMD1_DEV_ADDR, 1, &val); 551300161856Syc cmn_err(CE_NOTE, "TN1010 status = 0x%x", val); 551400161856Syc 551500161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 551600161856Syc TN1010_VENDOR_MMD1_DEV_ADDR, 8, &val); 551700161856Syc cmn_err(CE_NOTE, "Device status = 0x%x", val); 551800161856Syc 551900161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 552000161856Syc TN1010_VENDOR_MMD1_DEV_ADDR, 16, &val); 552100161856Syc cmn_err(CE_NOTE, "DDR status = 0x%x", val); 552200161856Syc 552300161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 552400161856Syc TN1010_VENDOR_MMD1_DEV_ADDR, 17, &val); 552500161856Syc cmn_err(CE_NOTE, "DDR fault status = 0x%x", val); 552600161856Syc 552700161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 552800161856Syc TN1010_VENDOR_MMD1_DEV_ADDR, 11, &val); 552900161856Syc cmn_err(CE_NOTE, "Firmware Revision = 0x%x Major = 0x%x Minor = 0x%x", 553000161856Syc val, (val & 0xFF00) >> 8, val & 0x00FF); 553100161856Syc } 553200161856Syc #endif 553300161856Syc 553444961713Sgirish /* 553544961713Sgirish * Calculate the bit in the multicast address filter 553644961713Sgirish * that selects the given * address. 553744961713Sgirish * Note: For GEM, the last 8-bits are used. 553844961713Sgirish */ 553944961713Sgirish uint32_t 554044961713Sgirish crc32_mchash(p_ether_addr_t addr) 554144961713Sgirish { 554244961713Sgirish uint8_t *cp; 554344961713Sgirish uint32_t crc; 554444961713Sgirish uint32_t c; 554544961713Sgirish int byte; 554644961713Sgirish int bit; 554744961713Sgirish 554844961713Sgirish cp = (uint8_t *)addr; 554944961713Sgirish crc = (uint32_t)0xffffffff; 555044961713Sgirish for (byte = 0; byte < 6; byte++) { 555144961713Sgirish c = (uint32_t)cp[byte]; 555244961713Sgirish for (bit = 0; bit < 8; bit++) { 555344961713Sgirish if ((c & 0x1) ^ (crc & 0x1)) 555444961713Sgirish crc = (crc >> 1)^0xedb88320; 555544961713Sgirish else 555644961713Sgirish crc = (crc >> 1); 555744961713Sgirish c >>= 1; 555844961713Sgirish } 555944961713Sgirish } 556044961713Sgirish return ((~crc) >> (32 - HASH_BITS)); 556144961713Sgirish } 556244961713Sgirish 556344961713Sgirish /* Reset serdes */ 556444961713Sgirish 556544961713Sgirish nxge_status_t 556644961713Sgirish nxge_serdes_reset(p_nxge_t nxgep) 556744961713Sgirish { 556844961713Sgirish npi_handle_t handle; 556944961713Sgirish 557044961713Sgirish handle = nxgep->npi_handle; 557144961713Sgirish 557244961713Sgirish ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0 | ESR_RESET_1); 557344961713Sgirish drv_usecwait(500); 557444961713Sgirish ESR_REG_WR(handle, ESR_CONFIG_REG, 0); 557544961713Sgirish 557644961713Sgirish return (NXGE_OK); 557744961713Sgirish } 557844961713Sgirish 557900161856Syc /* 558000161856Syc * This function monitors link status using interrupt or polling. 558100161856Syc * It calls nxgep->xcvr.check_link, a member function of 558200161856Syc * nxge_xcvr_table_t. But nxgep->xcvr.check_link calls this 558300161856Syc * function back, that is why the check_link routine is 558400161856Syc * executed periodically. 558500161856Syc */ 558644961713Sgirish nxge_status_t 558744961713Sgirish nxge_link_monitor(p_nxge_t nxgep, link_mon_enable_t enable) 558844961713Sgirish { 558944961713Sgirish nxge_status_t status = NXGE_OK; 559044961713Sgirish 5591678453a8Sspeer /* If we are a guest domain driver, don't bother. */ 5592678453a8Sspeer if (isLDOMguest(nxgep)) 5593678453a8Sspeer return (status); 5594678453a8Sspeer 559544961713Sgirish /* 559698ecde52Stm * Return immediately if this is an imaginary XMAC port. 559798ecde52Stm * (At least, we don't have 4-port XMAC cards yet.) 559844961713Sgirish */ 55992e59129aSraghus if ((nxgep->mac.portmode == PORT_10G_FIBER || 56002e59129aSraghus nxgep->mac.portmode == PORT_10G_SERDES) && 56012e59129aSraghus (nxgep->mac.portnum > 1)) 560244961713Sgirish return (NXGE_OK); 560344961713Sgirish 560444961713Sgirish if (nxgep->statsp == NULL) { 560544961713Sgirish /* stats has not been allocated. */ 560644961713Sgirish return (NXGE_OK); 560744961713Sgirish } 5608321febdeSsbehera /* Don't check link if we're in internal loopback mode */ 5609321febdeSsbehera if (nxgep->statsp->port_stats.lb_mode >= nxge_lb_serdes10g) 561044961713Sgirish return (NXGE_OK); 561144961713Sgirish 561244961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 561398ecde52Stm "==> nxge_link_monitor port<%d> enable=%d", 561498ecde52Stm nxgep->mac.portnum, enable)); 561544961713Sgirish if (enable == LINK_MONITOR_START) { 561644961713Sgirish if (nxgep->mac.linkchkmode == LINKCHK_INTR) { 561744961713Sgirish if ((status = nxge_link_intr(nxgep, LINK_INTR_START)) 561898ecde52Stm != NXGE_OK) 561944961713Sgirish goto fail; 562044961713Sgirish } else { 562198ecde52Stm timeout_id_t timerid; 562200161856Syc /* 562300161856Syc * check_link_stop means "Stop the link check", so 562400161856Syc * we return without starting the timer. 562500161856Syc */ 562698ecde52Stm if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 562798ecde52Stm return (NXGE_OK); 562898ecde52Stm 562900161856Syc /* 563000161856Syc * Otherwise fire the timer for the nxge to check 563100161856Syc * the link using the check_link function 563200161856Syc * of the nxge_xcvr_table and pass "nxgep" as the 563300161856Syc * argument to the check_link function. 563400161856Syc */ 563559ac0c16Sdavemq if (nxgep->xcvr.check_link) { 563659ac0c16Sdavemq timerid = timeout( 563759ac0c16Sdavemq (fptrv_t)(nxgep->xcvr.check_link), 563898ecde52Stm nxgep, 563998ecde52Stm drv_usectohz(LINK_MONITOR_PERIOD)); 564059ac0c16Sdavemq MUTEX_ENTER(&nxgep->poll_lock); 564159ac0c16Sdavemq nxgep->nxge_link_poll_timerid = timerid; 564259ac0c16Sdavemq MUTEX_EXIT(&nxgep->poll_lock); 564359ac0c16Sdavemq } else { 564498ecde52Stm return (NXGE_ERROR); 564544961713Sgirish } 564644961713Sgirish } 564744961713Sgirish } else { 564844961713Sgirish if (nxgep->mac.linkchkmode == LINKCHK_INTR) { 564944961713Sgirish if ((status = nxge_link_intr(nxgep, LINK_INTR_STOP)) 565098ecde52Stm != NXGE_OK) 565144961713Sgirish goto fail; 565244961713Sgirish } else { 565398ecde52Stm clock_t rv; 565498ecde52Stm 565598ecde52Stm MUTEX_ENTER(&nxgep->poll_lock); 565698ecde52Stm 565798ecde52Stm /* If <timerid> == 0, the link monitor has */ 565898ecde52Stm /* never been started, or just now stopped. */ 565998ecde52Stm if (nxgep->nxge_link_poll_timerid == 0) { 566098ecde52Stm MUTEX_EXIT(&nxgep->poll_lock); 566198ecde52Stm return (NXGE_OK); 566298ecde52Stm } 566398ecde52Stm 566498ecde52Stm nxgep->poll_state = LINK_MONITOR_STOPPING; 566598ecde52Stm rv = cv_timedwait(&nxgep->poll_cv, 566698ecde52Stm &nxgep->poll_lock, 566798ecde52Stm ddi_get_lbolt() + 566898ecde52Stm drv_usectohz(LM_WAIT_MULTIPLIER * 566998ecde52Stm LINK_MONITOR_PERIOD)); 567098ecde52Stm if (rv == -1) { 567198ecde52Stm NXGE_DEBUG_MSG((nxgep, MAC_CTL, 567298ecde52Stm "==> stopping port %d: " 567398ecde52Stm "cv_timedwait(%d) timed out", 567498ecde52Stm nxgep->mac.portnum, nxgep->poll_state)); 567598ecde52Stm nxgep->poll_state = LINK_MONITOR_STOP; 567644961713Sgirish nxgep->nxge_link_poll_timerid = 0; 567744961713Sgirish } 567898ecde52Stm 567998ecde52Stm MUTEX_EXIT(&nxgep->poll_lock); 568044961713Sgirish } 568144961713Sgirish } 568244961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 568398ecde52Stm "<== nxge_link_monitor port<%d> enable=%d", 568498ecde52Stm nxgep->mac.portnum, enable)); 5685678453a8Sspeer 568644961713Sgirish return (NXGE_OK); 568744961713Sgirish fail: 568844961713Sgirish return (status); 568900161856Syc 569000161856Syc } 569100161856Syc 569200161856Syc nxge_status_t 569300161856Syc nxge_check_tn1010_link(p_nxge_t nxgep) 569400161856Syc { 569500161856Syc nxge_status_t status = NXGE_OK; 569600161856Syc nxge_link_state_t link_up; 569700161856Syc 569800161856Syc if (nxgep->nxge_magic != NXGE_MAGIC) { 569900161856Syc /* magic is 0 if driver is not attached */ 570000161856Syc return (NXGE_ERROR); 570100161856Syc } 570200161856Syc 570300161856Syc /* Link has been stopped, no need to continue */ 570400161856Syc if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) { 570500161856Syc return (NXGE_OK); 570600161856Syc } 570700161856Syc 570800161856Syc if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10) 570900161856Syc goto nxge_check_tn1010_link_exit; 571000161856Syc 571100161856Syc if ((status = nxge_tn1010_check(nxgep, &link_up)) != NXGE_OK) 571200161856Syc goto fail; 571300161856Syc 571400161856Syc nxge_check_tn1010_link_exit: 571500161856Syc if (link_up == LINK_IS_UP) 571600161856Syc nxge_link_is_up(nxgep); 571700161856Syc else if (link_up == LINK_IS_DOWN) 571800161856Syc nxge_link_is_down(nxgep); 571900161856Syc 572000161856Syc /* 572100161856Syc * nxge_link_monitor will call (nxgep->xcvr.check_link) 572200161856Syc * which could be THIS function. 572300161856Syc */ 572400161856Syc (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 572500161856Syc 572600161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_tn1010_link port<%d>", 572700161856Syc portn)); 572800161856Syc return (NXGE_OK); 572900161856Syc 573000161856Syc fail: 573100161856Syc (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 573200161856Syc 573300161856Syc NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 573400161856Syc "nxge_check_tn1010_link: Failed to check link")); 573500161856Syc return (status); 573600161856Syc } 573700161856Syc 573800161856Syc 573900161856Syc /* 574000161856Syc * Fill variable "link_up" with either LINK_IS_UP or LINK_IS_DOWN. 574100161856Syc */ 574200161856Syc static nxge_status_t 574300161856Syc nxge_tn1010_check(p_nxge_t nxgep, nxge_link_state_t *link_up) 574400161856Syc { 574500161856Syc nxge_status_t status = NXGE_OK; 574600161856Syc p_nxge_stats_t statsp; 574700161856Syc uint8_t phy_port_addr, portn; 574800161856Syc uint16_t val; 574900161856Syc 575000161856Syc *link_up = LINK_NO_CHANGE; 575100161856Syc 575200161856Syc portn = NXGE_GET_PORT_NUM(nxgep->function_num); 575300161856Syc phy_port_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 575400161856Syc statsp = nxgep->statsp; 575500161856Syc 575600161856Syc /* Check if link is up */ 575700161856Syc if ((status = nxge_mdio_read(nxgep, phy_port_addr, 575800161856Syc TN1010_AUTONEG_DEV_ADDR, TN1010_AUTONEG_STATUS_REG, &val)) 575900161856Syc != NXGE_OK) { 576000161856Syc goto fail; 576100161856Syc } 576200161856Syc /* 576300161856Syc * nxge_link_is_up has called nxge_set_tn1010_param and set 576400161856Syc * portmode and link_speed 576500161856Syc */ 576600161856Syc if (val & TN1010_AN_LINK_STAT_BIT) { 576700161856Syc if (nxgep->link_notify || 576800161856Syc nxgep->statsp->mac_stats.link_up == 0) { 576900161856Syc statsp->mac_stats.link_up = 1; 577000161856Syc statsp->mac_stats.link_duplex = 2; 577100161856Syc *link_up = LINK_IS_UP; 577200161856Syc nxgep->link_notify = B_FALSE; 577300161856Syc } 577400161856Syc } else { 577500161856Syc if (nxgep->link_notify || 577600161856Syc nxgep->statsp->mac_stats.link_up == 1) { 577700161856Syc statsp->mac_stats.link_up = 0; 577800161856Syc statsp->mac_stats.link_speed = 0; 577900161856Syc statsp->mac_stats.link_duplex = 0; 578000161856Syc *link_up = LINK_IS_DOWN; 578100161856Syc nxgep->link_notify = B_FALSE; 578200161856Syc } 578300161856Syc } 578400161856Syc return (NXGE_OK); 578500161856Syc 578600161856Syc fail: 578700161856Syc NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 578800161856Syc "nxge_tn1010_check: Unable to check TN1010")); 578900161856Syc return (status); 579044961713Sgirish } 579144961713Sgirish 579200161856Syc 579344961713Sgirish /* Set promiscous mode */ 579444961713Sgirish 579544961713Sgirish nxge_status_t 579644961713Sgirish nxge_set_promisc(p_nxge_t nxgep, boolean_t on) 579744961713Sgirish { 579844961713Sgirish nxge_status_t status = NXGE_OK; 579944961713Sgirish 580059ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_promisc: on %d", on)); 580144961713Sgirish 580244961713Sgirish nxgep->filter.all_phys_cnt = ((on) ? 1 : 0); 580344961713Sgirish 580444961713Sgirish RW_ENTER_WRITER(&nxgep->filter_lock); 580544961713Sgirish 580644961713Sgirish if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) { 580744961713Sgirish goto fail; 580844961713Sgirish } 580944961713Sgirish if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) { 581044961713Sgirish goto fail; 581144961713Sgirish } 581244961713Sgirish 581344961713Sgirish RW_EXIT(&nxgep->filter_lock); 581444961713Sgirish 581544961713Sgirish if (on) 581644961713Sgirish nxgep->statsp->mac_stats.promisc = B_TRUE; 581744961713Sgirish else 581844961713Sgirish nxgep->statsp->mac_stats.promisc = B_FALSE; 581944961713Sgirish 582044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_promisc")); 582144961713Sgirish 582244961713Sgirish return (NXGE_OK); 582344961713Sgirish fail: 582444961713Sgirish RW_EXIT(&nxgep->filter_lock); 582544961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_promisc: " 582659ac0c16Sdavemq "Unable to set promisc (%d)", on)); 582744961713Sgirish 582844961713Sgirish return (status); 582944961713Sgirish } 583044961713Sgirish 583144961713Sgirish /*ARGSUSED*/ 583244961713Sgirish uint_t 583344961713Sgirish nxge_mif_intr(void *arg1, void *arg2) 583444961713Sgirish { 583544961713Sgirish #ifdef NXGE_DEBUG 583644961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg2; 583744961713Sgirish #endif 583844961713Sgirish #if NXGE_MIF 583944961713Sgirish p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1; 584044961713Sgirish uint32_t status; 584144961713Sgirish npi_handle_t handle; 584244961713Sgirish uint8_t portn; 584344961713Sgirish p_nxge_stats_t statsp; 584444961713Sgirish #endif 584544961713Sgirish 584644961713Sgirish #ifdef NXGE_MIF 584744961713Sgirish if (arg2 == NULL || (void *)ldvp->nxgep != arg2) { 584844961713Sgirish nxgep = ldvp->nxgep; 584944961713Sgirish } 585044961713Sgirish nxgep = ldvp->nxgep; 585144961713Sgirish #endif 585244961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mif_intr")); 585344961713Sgirish 585444961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr")); 585544961713Sgirish return (DDI_INTR_CLAIMED); 585644961713Sgirish 585744961713Sgirish mif_intr_fail: 585844961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr")); 585944961713Sgirish return (DDI_INTR_UNCLAIMED); 586044961713Sgirish } 586144961713Sgirish 586244961713Sgirish /*ARGSUSED*/ 586344961713Sgirish uint_t 586444961713Sgirish nxge_mac_intr(void *arg1, void *arg2) 586544961713Sgirish { 586644961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg2; 586744961713Sgirish p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1; 586844961713Sgirish p_nxge_ldg_t ldgp; 586944961713Sgirish uint32_t status; 587044961713Sgirish npi_handle_t handle; 587144961713Sgirish uint8_t portn; 587244961713Sgirish p_nxge_stats_t statsp; 587344961713Sgirish npi_status_t rs = NPI_SUCCESS; 587444961713Sgirish 587544961713Sgirish if (arg2 == NULL || (void *)ldvp->nxgep != arg2) { 587644961713Sgirish nxgep = ldvp->nxgep; 587744961713Sgirish } 587844961713Sgirish 587944961713Sgirish ldgp = ldvp->ldgp; 588044961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mac_intr: " 588159ac0c16Sdavemq "group %d", ldgp->ldg)); 588244961713Sgirish 588344961713Sgirish handle = NXGE_DEV_NPI_HANDLE(nxgep); 588444961713Sgirish /* 588544961713Sgirish * This interrupt handler is for a specific 588644961713Sgirish * mac port. 588744961713Sgirish */ 588844961713Sgirish statsp = (p_nxge_stats_t)nxgep->statsp; 588944961713Sgirish portn = nxgep->mac.portnum; 589044961713Sgirish 589144961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 589259ac0c16Sdavemq "==> nxge_mac_intr: reading mac stats: port<%d>", portn)); 589344961713Sgirish 589444961713Sgirish if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 589544961713Sgirish rs = npi_xmac_tx_get_istatus(handle, portn, 589644961713Sgirish (xmac_tx_iconfig_t *)&status); 589744961713Sgirish if (rs != NPI_SUCCESS) 589844961713Sgirish goto npi_fail; 589944961713Sgirish if (status & ICFG_XMAC_TX_ALL) { 590044961713Sgirish if (status & ICFG_XMAC_TX_UNDERRUN) { 590144961713Sgirish statsp->xmac_stats.tx_underflow_err++; 590244961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 590344961713Sgirish NXGE_FM_EREPORT_TXMAC_UNDERFLOW); 590444961713Sgirish } 590544961713Sgirish if (status & ICFG_XMAC_TX_MAX_PACKET_ERR) { 590644961713Sgirish statsp->xmac_stats.tx_maxpktsize_err++; 5907f6485eecSyc /* 5908f6485eecSyc * Do not send FMA ereport because this 5909f6485eecSyc * error does not indicate HW failure. 5910f6485eecSyc */ 591144961713Sgirish } 591244961713Sgirish if (status & ICFG_XMAC_TX_OVERFLOW) { 591344961713Sgirish statsp->xmac_stats.tx_overflow_err++; 591444961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 591544961713Sgirish NXGE_FM_EREPORT_TXMAC_OVERFLOW); 591644961713Sgirish } 591744961713Sgirish if (status & ICFG_XMAC_TX_FIFO_XFR_ERR) { 591844961713Sgirish statsp->xmac_stats.tx_fifo_xfr_err++; 591944961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 592044961713Sgirish NXGE_FM_EREPORT_TXMAC_TXFIFO_XFR_ERR); 592144961713Sgirish } 592244961713Sgirish if (status & ICFG_XMAC_TX_BYTE_CNT_EXP) { 592344961713Sgirish statsp->xmac_stats.tx_byte_cnt += 592444961713Sgirish XTXMAC_BYTE_CNT_MASK; 592544961713Sgirish } 592644961713Sgirish if (status & ICFG_XMAC_TX_FRAME_CNT_EXP) { 592744961713Sgirish statsp->xmac_stats.tx_frame_cnt += 592844961713Sgirish XTXMAC_FRM_CNT_MASK; 592944961713Sgirish } 593044961713Sgirish } 593144961713Sgirish 593244961713Sgirish rs = npi_xmac_rx_get_istatus(handle, portn, 593344961713Sgirish (xmac_rx_iconfig_t *)&status); 593444961713Sgirish if (rs != NPI_SUCCESS) 593544961713Sgirish goto npi_fail; 593644961713Sgirish if (status & ICFG_XMAC_RX_ALL) { 593744961713Sgirish if (status & ICFG_XMAC_RX_OVERFLOW) 593844961713Sgirish statsp->xmac_stats.rx_overflow_err++; 593944961713Sgirish if (status & ICFG_XMAC_RX_UNDERFLOW) { 594044961713Sgirish statsp->xmac_stats.rx_underflow_err++; 594144961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 594244961713Sgirish NXGE_FM_EREPORT_RXMAC_UNDERFLOW); 594344961713Sgirish } 5944f6485eecSyc /* 5945f6485eecSyc * Do not send FMA ereport for the following 3 errors 5946f6485eecSyc * because they do not indicate HW failures. 5947f6485eecSyc */ 594844961713Sgirish if (status & ICFG_XMAC_RX_CRC_ERR_CNT_EXP) { 594944961713Sgirish statsp->xmac_stats.rx_crc_err_cnt += 595044961713Sgirish XRXMAC_CRC_ER_CNT_MASK; 595144961713Sgirish } 595244961713Sgirish if (status & ICFG_XMAC_RX_LEN_ERR_CNT_EXP) { 595344961713Sgirish statsp->xmac_stats.rx_len_err_cnt += 595444961713Sgirish MAC_LEN_ER_CNT_MASK; 595544961713Sgirish } 595644961713Sgirish if (status & ICFG_XMAC_RX_VIOL_ERR_CNT_EXP) { 595744961713Sgirish statsp->xmac_stats.rx_viol_err_cnt += 595844961713Sgirish XRXMAC_CD_VIO_CNT_MASK; 595944961713Sgirish } 596044961713Sgirish if (status & ICFG_XMAC_RX_OCT_CNT_EXP) { 596144961713Sgirish statsp->xmac_stats.rx_byte_cnt += 596244961713Sgirish XRXMAC_BT_CNT_MASK; 596344961713Sgirish } 596444961713Sgirish if (status & ICFG_XMAC_RX_HST_CNT1_EXP) { 596544961713Sgirish statsp->xmac_stats.rx_hist1_cnt += 596644961713Sgirish XRXMAC_HIST_CNT1_MASK; 596744961713Sgirish } 596844961713Sgirish if (status & ICFG_XMAC_RX_HST_CNT2_EXP) { 596944961713Sgirish statsp->xmac_stats.rx_hist2_cnt += 597044961713Sgirish XRXMAC_HIST_CNT2_MASK; 597144961713Sgirish } 597244961713Sgirish if (status & ICFG_XMAC_RX_HST_CNT3_EXP) { 597344961713Sgirish statsp->xmac_stats.rx_hist3_cnt += 597444961713Sgirish XRXMAC_HIST_CNT3_MASK; 597544961713Sgirish } 597644961713Sgirish if (status & ICFG_XMAC_RX_HST_CNT4_EXP) { 597744961713Sgirish statsp->xmac_stats.rx_hist4_cnt += 597844961713Sgirish XRXMAC_HIST_CNT4_MASK; 597944961713Sgirish } 598044961713Sgirish if (status & ICFG_XMAC_RX_HST_CNT5_EXP) { 598144961713Sgirish statsp->xmac_stats.rx_hist5_cnt += 598244961713Sgirish XRXMAC_HIST_CNT5_MASK; 598344961713Sgirish } 598444961713Sgirish if (status & ICFG_XMAC_RX_HST_CNT6_EXP) { 598544961713Sgirish statsp->xmac_stats.rx_hist6_cnt += 598644961713Sgirish XRXMAC_HIST_CNT6_MASK; 598744961713Sgirish } 598844961713Sgirish if (status & ICFG_XMAC_RX_BCAST_CNT_EXP) { 598944961713Sgirish statsp->xmac_stats.rx_broadcast_cnt += 599044961713Sgirish XRXMAC_BC_FRM_CNT_MASK; 599144961713Sgirish } 599244961713Sgirish if (status & ICFG_XMAC_RX_MCAST_CNT_EXP) { 599344961713Sgirish statsp->xmac_stats.rx_mult_cnt += 599444961713Sgirish XRXMAC_MC_FRM_CNT_MASK; 599544961713Sgirish } 5996f6485eecSyc /* 5997f6485eecSyc * Do not send FMA ereport for the following 3 errors 5998f6485eecSyc * because they do not indicate HW failures. 5999f6485eecSyc */ 600044961713Sgirish if (status & ICFG_XMAC_RX_FRAG_CNT_EXP) { 600144961713Sgirish statsp->xmac_stats.rx_frag_cnt += 600244961713Sgirish XRXMAC_FRAG_CNT_MASK; 600344961713Sgirish } 600444961713Sgirish if (status & ICFG_XMAC_RX_ALIGNERR_CNT_EXP) { 600544961713Sgirish statsp->xmac_stats.rx_frame_align_err_cnt += 600644961713Sgirish XRXMAC_AL_ER_CNT_MASK; 600744961713Sgirish } 600844961713Sgirish if (status & ICFG_XMAC_RX_LINK_FLT_CNT_EXP) { 600944961713Sgirish statsp->xmac_stats.rx_linkfault_err_cnt += 601044961713Sgirish XMAC_LINK_FLT_CNT_MASK; 601144961713Sgirish } 601244961713Sgirish if (status & ICFG_XMAC_RX_REMOTE_FLT_DET) { 601344961713Sgirish statsp->xmac_stats.rx_remotefault_err++; 601444961713Sgirish } 601544961713Sgirish if (status & ICFG_XMAC_RX_LOCAL_FLT_DET) { 601644961713Sgirish statsp->xmac_stats.rx_localfault_err++; 601744961713Sgirish } 601844961713Sgirish } 601944961713Sgirish 602044961713Sgirish rs = npi_xmac_ctl_get_istatus(handle, portn, 602144961713Sgirish (xmac_ctl_iconfig_t *)&status); 602244961713Sgirish if (rs != NPI_SUCCESS) 602344961713Sgirish goto npi_fail; 602444961713Sgirish if (status & ICFG_XMAC_CTRL_ALL) { 602544961713Sgirish if (status & ICFG_XMAC_CTRL_PAUSE_RCVD) 602644961713Sgirish statsp->xmac_stats.rx_pause_cnt++; 602744961713Sgirish if (status & ICFG_XMAC_CTRL_PAUSE_STATE) 602844961713Sgirish statsp->xmac_stats.tx_pause_state++; 602944961713Sgirish if (status & ICFG_XMAC_CTRL_NOPAUSE_STATE) 603044961713Sgirish statsp->xmac_stats.tx_nopause_state++; 603144961713Sgirish } 603244961713Sgirish } else if (nxgep->mac.porttype == PORT_TYPE_BMAC) { 603344961713Sgirish rs = npi_bmac_tx_get_istatus(handle, portn, 603444961713Sgirish (bmac_tx_iconfig_t *)&status); 603544961713Sgirish if (rs != NPI_SUCCESS) 603644961713Sgirish goto npi_fail; 603744961713Sgirish if (status & ICFG_BMAC_TX_ALL) { 603844961713Sgirish if (status & ICFG_BMAC_TX_UNDERFLOW) { 603944961713Sgirish statsp->bmac_stats.tx_underrun_err++; 604044961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 604144961713Sgirish NXGE_FM_EREPORT_TXMAC_UNDERFLOW); 604244961713Sgirish } 604344961713Sgirish if (status & ICFG_BMAC_TX_MAXPKTSZ_ERR) { 604444961713Sgirish statsp->bmac_stats.tx_max_pkt_err++; 604544961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 604644961713Sgirish NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR); 604744961713Sgirish } 604844961713Sgirish if (status & ICFG_BMAC_TX_BYTE_CNT_EXP) { 604944961713Sgirish statsp->bmac_stats.tx_byte_cnt += 605044961713Sgirish BTXMAC_BYTE_CNT_MASK; 605144961713Sgirish } 605244961713Sgirish if (status & ICFG_BMAC_TX_FRAME_CNT_EXP) { 605344961713Sgirish statsp->bmac_stats.tx_frame_cnt += 605444961713Sgirish BTXMAC_FRM_CNT_MASK; 605544961713Sgirish } 605644961713Sgirish } 605744961713Sgirish 605844961713Sgirish rs = npi_bmac_rx_get_istatus(handle, portn, 605944961713Sgirish (bmac_rx_iconfig_t *)&status); 606044961713Sgirish if (rs != NPI_SUCCESS) 606144961713Sgirish goto npi_fail; 606244961713Sgirish if (status & ICFG_BMAC_RX_ALL) { 606344961713Sgirish if (status & ICFG_BMAC_RX_OVERFLOW) { 606444961713Sgirish statsp->bmac_stats.rx_overflow_err++; 606544961713Sgirish } 606644961713Sgirish if (status & ICFG_BMAC_RX_FRAME_CNT_EXP) { 606744961713Sgirish statsp->bmac_stats.rx_frame_cnt += 606844961713Sgirish RXMAC_FRM_CNT_MASK; 606944961713Sgirish } 607044961713Sgirish if (status & ICFG_BMAC_RX_CRC_ERR_CNT_EXP) { 607144961713Sgirish statsp->bmac_stats.rx_crc_err_cnt += 607244961713Sgirish BMAC_CRC_ER_CNT_MASK; 607344961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 607444961713Sgirish NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP); 607544961713Sgirish } 607644961713Sgirish if (status & ICFG_BMAC_RX_LEN_ERR_CNT_EXP) { 607744961713Sgirish statsp->bmac_stats.rx_len_err_cnt += 607844961713Sgirish MAC_LEN_ER_CNT_MASK; 607944961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 608044961713Sgirish NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP); 608144961713Sgirish } 608244961713Sgirish if (status & ICFG_BMAC_RX_VIOL_ERR_CNT_EXP) 608344961713Sgirish statsp->bmac_stats.rx_viol_err_cnt += 608444961713Sgirish BMAC_CD_VIO_CNT_MASK; 608544961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 608644961713Sgirish NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP); 608744961713Sgirish } 608844961713Sgirish if (status & ICFG_BMAC_RX_BYTE_CNT_EXP) { 608944961713Sgirish statsp->bmac_stats.rx_byte_cnt += 609044961713Sgirish BRXMAC_BYTE_CNT_MASK; 609144961713Sgirish } 609244961713Sgirish if (status & ICFG_BMAC_RX_ALIGNERR_CNT_EXP) { 609344961713Sgirish statsp->bmac_stats.rx_align_err_cnt += 609444961713Sgirish BMAC_AL_ER_CNT_MASK; 609544961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 609644961713Sgirish NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP); 609744961713Sgirish } 609844961713Sgirish 609944961713Sgirish rs = npi_bmac_ctl_get_istatus(handle, portn, 610044961713Sgirish (bmac_ctl_iconfig_t *)&status); 610144961713Sgirish if (rs != NPI_SUCCESS) 610244961713Sgirish goto npi_fail; 610344961713Sgirish 610444961713Sgirish if (status & ICFG_BMAC_CTL_ALL) { 610544961713Sgirish if (status & ICFG_BMAC_CTL_RCVPAUSE) 610644961713Sgirish statsp->bmac_stats.rx_pause_cnt++; 610744961713Sgirish if (status & ICFG_BMAC_CTL_INPAUSE_ST) 610844961713Sgirish statsp->bmac_stats.tx_pause_state++; 610944961713Sgirish if (status & ICFG_BMAC_CTL_INNOTPAUSE_ST) 611044961713Sgirish statsp->bmac_stats.tx_nopause_state++; 611144961713Sgirish } 611244961713Sgirish } 611344961713Sgirish 611444961713Sgirish if (ldgp->nldvs == 1) { 611544961713Sgirish (void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg, 611644961713Sgirish B_TRUE, ldgp->ldg_timer); 611744961713Sgirish } 611844961713Sgirish 611944961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mac_intr")); 612044961713Sgirish return (DDI_INTR_CLAIMED); 612144961713Sgirish 612244961713Sgirish npi_fail: 612344961713Sgirish NXGE_ERROR_MSG((nxgep, INT_CTL, "<== nxge_mac_intr")); 612444961713Sgirish return (DDI_INTR_UNCLAIMED); 612544961713Sgirish } 612644961713Sgirish 612744961713Sgirish nxge_status_t 612844961713Sgirish nxge_check_bcm8704_link(p_nxge_t nxgep, boolean_t *link_up) 612944961713Sgirish { 613044961713Sgirish uint8_t phy_port_addr; 613144961713Sgirish nxge_status_t status = NXGE_OK; 613244961713Sgirish boolean_t rx_sig_ok; 613344961713Sgirish boolean_t pcs_blk_lock; 613444961713Sgirish boolean_t link_align; 613544961713Sgirish uint16_t val1, val2, val3; 613644961713Sgirish #ifdef NXGE_DEBUG_SYMBOL_ERR 613744961713Sgirish uint16_t val_debug; 613844961713Sgirish uint16_t val; 613944961713Sgirish #endif 614044961713Sgirish 614144961713Sgirish phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn; 614244961713Sgirish 614344961713Sgirish #ifdef NXGE_DEBUG_SYMBOL_ERR 614444961713Sgirish /* Check Device 3 Register Device 3 0xC809 */ 614544961713Sgirish (void) nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0xC809, &val_debug); 614644961713Sgirish if ((val_debug & ~0x200) != 0) { 614744961713Sgirish cmn_err(CE_NOTE, "!Port%d BCM8704 Dev3 Reg 0xc809 = 0x%x\n", 614844961713Sgirish nxgep->mac.portnum, val_debug); 614944961713Sgirish (void) nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, 615044961713Sgirish &val_debug); 615144961713Sgirish cmn_err(CE_NOTE, "!Port%d BCM8704 Dev4 Reg 0x18 = 0x%x\n", 615244961713Sgirish nxgep->mac.portnum, val_debug); 615344961713Sgirish } 615444961713Sgirish 615544961713Sgirish (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 615644961713Sgirish XPCS_REG_DESCWERR_COUNTER, &val); 615744961713Sgirish if (val != 0) 615844961713Sgirish cmn_err(CE_NOTE, "!XPCS DESCWERR = 0x%x\n", val); 615944961713Sgirish 616044961713Sgirish (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 616144961713Sgirish XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val); 616244961713Sgirish if (val != 0) 616344961713Sgirish cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L0_1 = 0x%x\n", val); 616444961713Sgirish 616544961713Sgirish (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 616644961713Sgirish XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val); 616744961713Sgirish if (val != 0) 616844961713Sgirish cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L2_3 = 0x%x\n", val); 616944961713Sgirish #endif 617044961713Sgirish 617144961713Sgirish /* Check from BCM8704 if 10G link is up or down */ 617244961713Sgirish 617344961713Sgirish /* Check Device 1 Register 0xA bit0 */ 617444961713Sgirish status = nxge_mdio_read(nxgep, phy_port_addr, 617544961713Sgirish BCM8704_PMA_PMD_DEV_ADDR, 617644961713Sgirish BCM8704_PMD_RECEIVE_SIG_DETECT, 617744961713Sgirish &val1); 617844961713Sgirish if (status != NXGE_OK) 617944961713Sgirish goto fail; 618044961713Sgirish rx_sig_ok = ((val1 & GLOB_PMD_RX_SIG_OK) ? B_TRUE : B_FALSE); 618144961713Sgirish 618244961713Sgirish /* Check Device 3 Register 0x20 bit0 */ 618344961713Sgirish if ((status = nxge_mdio_read(nxgep, phy_port_addr, 618444961713Sgirish BCM8704_PCS_DEV_ADDR, 618544961713Sgirish BCM8704_10GBASE_R_PCS_STATUS_REG, 618644961713Sgirish &val2)) != NPI_SUCCESS) 618744961713Sgirish goto fail; 618844961713Sgirish pcs_blk_lock = ((val2 & PCS_10GBASE_R_PCS_BLK_LOCK) ? B_TRUE : B_FALSE); 618944961713Sgirish 619044961713Sgirish /* Check Device 4 Register 0x18 bit12 */ 619144961713Sgirish status = nxge_mdio_read(nxgep, phy_port_addr, 619244961713Sgirish BCM8704_PHYXS_ADDR, 619344961713Sgirish BCM8704_PHYXS_XGXS_LANE_STATUS_REG, 619444961713Sgirish &val3); 619544961713Sgirish if (status != NXGE_OK) 619644961713Sgirish goto fail; 61972d17280bSsbehera 61982d17280bSsbehera switch (nxgep->chip_id) { 61992d17280bSsbehera case BCM8704_CHIP_ID: 62002d17280bSsbehera link_align = (val3 == (XGXS_LANE_ALIGN_STATUS | 62012d17280bSsbehera XGXS_LANE3_SYNC | XGXS_LANE2_SYNC | XGXS_LANE1_SYNC | 62022d17280bSsbehera XGXS_LANE0_SYNC | 0x400)) ? B_TRUE : B_FALSE; 62032d17280bSsbehera break; 62042d17280bSsbehera case BCM8706_CHIP_ID: 62052d17280bSsbehera link_align = ((val3 & XGXS_LANE_ALIGN_STATUS) && 62062d17280bSsbehera (val3 & XGXS_LANE3_SYNC) && (val3 & XGXS_LANE2_SYNC) && 62072d17280bSsbehera (val3 & XGXS_LANE1_SYNC) && (val3 & XGXS_LANE0_SYNC)) ? 62082d17280bSsbehera B_TRUE : B_FALSE; 62092d17280bSsbehera break; 62102d17280bSsbehera default: 62112d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_check_bcm8704_link:" 62122d17280bSsbehera "Unknown chip ID [0x%x]", nxgep->chip_id)); 62132d17280bSsbehera goto fail; 62142d17280bSsbehera } 62152d17280bSsbehera 621644961713Sgirish 621744961713Sgirish #ifdef NXGE_DEBUG_ALIGN_ERR 621844961713Sgirish /* Temp workaround for link down issue */ 621944961713Sgirish if (pcs_blk_lock == B_FALSE) { 622044961713Sgirish if (val2 != 0x4) { 622144961713Sgirish pcs_blk_lock = B_TRUE; 622244961713Sgirish cmn_err(CE_NOTE, 622344961713Sgirish "!LINK DEBUG: port%d PHY Dev3 " 622444961713Sgirish "Reg 0x20 = 0x%x\n", 622544961713Sgirish nxgep->mac.portnum, val2); 622644961713Sgirish } 622744961713Sgirish } 622844961713Sgirish 622944961713Sgirish if (link_align == B_FALSE) { 623044961713Sgirish if (val3 != 0x140f) { 623144961713Sgirish link_align = B_TRUE; 623244961713Sgirish cmn_err(CE_NOTE, 623344961713Sgirish "!LINK DEBUG: port%d PHY Dev4 " 623444961713Sgirish "Reg 0x18 = 0x%x\n", 623544961713Sgirish nxgep->mac.portnum, val3); 623644961713Sgirish } 623744961713Sgirish } 623844961713Sgirish 623944961713Sgirish if (rx_sig_ok == B_FALSE) { 624044961713Sgirish if ((val2 == 0) || (val3 == 0)) { 624144961713Sgirish rx_sig_ok = B_TRUE; 624244961713Sgirish cmn_err(CE_NOTE, 624344961713Sgirish "!LINK DEBUG: port %d Dev3 or Dev4 read zero\n", 624444961713Sgirish nxgep->mac.portnum); 624544961713Sgirish } 624644961713Sgirish } 624744961713Sgirish #endif 624844961713Sgirish 624944961713Sgirish *link_up = ((rx_sig_ok == B_TRUE) && (pcs_blk_lock == B_TRUE) && 625044961713Sgirish (link_align == B_TRUE)) ? B_TRUE : B_FALSE; 625144961713Sgirish 625244961713Sgirish return (NXGE_OK); 625344961713Sgirish fail: 625444961713Sgirish return (status); 625544961713Sgirish } 625644961713Sgirish 625752cdd236Ssbehera static nxge_status_t 625800161856Syc nxge_check_mrvl88x2011_link(p_nxge_t nxgep, boolean_t *link_up) 625952cdd236Ssbehera { 626052cdd236Ssbehera uint8_t phy; 626152cdd236Ssbehera nxge_status_t status = NXGE_OK; 626252cdd236Ssbehera boolean_t pma_status; 626352cdd236Ssbehera boolean_t pcs_status; 626452cdd236Ssbehera boolean_t xgxs_status; 626552cdd236Ssbehera uint16_t val; 626652cdd236Ssbehera 626752cdd236Ssbehera phy = nxgep->statsp->mac_stats.xcvr_portn; 626852cdd236Ssbehera 626952cdd236Ssbehera MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR, 627052cdd236Ssbehera MRVL_88X2011_10G_PMD_STAT_2, &val); 627152cdd236Ssbehera 627252cdd236Ssbehera *link_up = B_FALSE; 627352cdd236Ssbehera 627452cdd236Ssbehera /* Check from Marvell 88X2011 if 10G link is up or down */ 627552cdd236Ssbehera 627652cdd236Ssbehera /* Check PMA/PMD Register: 1.0001.2 == 1 */ 627752cdd236Ssbehera MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR, 627852cdd236Ssbehera MRVL_88X2011_PMA_PMD_STAT_1, &val); 627952cdd236Ssbehera 628052cdd236Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 628152cdd236Ssbehera "nxge_check_mrvl88x2011_link: pmd=0x%x", val)); 628252cdd236Ssbehera 628352cdd236Ssbehera pma_status = ((val & MRVL_88X2011_LNK_STATUS_OK) ? B_TRUE : B_FALSE); 628452cdd236Ssbehera 628552cdd236Ssbehera /* Check PMC Register : 3.0001.2 == 1: read twice */ 628652cdd236Ssbehera MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR, 628752cdd236Ssbehera MRVL_88X2011_PMA_PMD_STAT_1, &val); 628852cdd236Ssbehera MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR, 628952cdd236Ssbehera MRVL_88X2011_PMA_PMD_STAT_1, &val); 629052cdd236Ssbehera 629152cdd236Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 629252cdd236Ssbehera "nxge_check_mrvl88x2011_link: pcs=0x%x", val)); 629352cdd236Ssbehera 629452cdd236Ssbehera pcs_status = ((val & MRVL_88X2011_LNK_STATUS_OK) ? B_TRUE : B_FALSE); 629552cdd236Ssbehera 629652cdd236Ssbehera /* Check XGXS Register : 4.0018.[0-3,12] */ 629752cdd236Ssbehera MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV4_ADDR, 629852cdd236Ssbehera MRVL_88X2011_10G_XGXS_LANE_STAT, &val); 629952cdd236Ssbehera 630052cdd236Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 630152cdd236Ssbehera "nxge_check_mrvl88x2011_link: xgxs=0x%x", val)); 630252cdd236Ssbehera 630352cdd236Ssbehera xgxs_status = (val == (XGXS_LANE_ALIGN_STATUS | XGXS_LANE3_SYNC | 630452cdd236Ssbehera XGXS_LANE2_SYNC | XGXS_LANE1_SYNC | 630552cdd236Ssbehera XGXS_LANE0_SYNC | XGXS_PATTERN_TEST_ABILITY | 630652cdd236Ssbehera XGXS_LANE_STAT_MAGIC)) ? B_TRUE : B_FALSE; 630752cdd236Ssbehera 630852cdd236Ssbehera *link_up = (pma_status && pcs_status && xgxs_status) ? 630952cdd236Ssbehera B_TRUE : B_FALSE; 631052cdd236Ssbehera 631152cdd236Ssbehera fail: 631252cdd236Ssbehera 631352cdd236Ssbehera if (*link_up == B_FALSE) { 631452cdd236Ssbehera /* PCS OFF */ 631552cdd236Ssbehera nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_CTL_OFF); 631652cdd236Ssbehera } else { 631752cdd236Ssbehera /* PCS Activity */ 631852cdd236Ssbehera nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_CTL_PCS_ACT); 631952cdd236Ssbehera } 632052cdd236Ssbehera 632152cdd236Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 632252cdd236Ssbehera " <== nxge_check_mrvl88x2011_link: up=%d", *link_up)); 632352cdd236Ssbehera 632452cdd236Ssbehera return (status); 632552cdd236Ssbehera } 632652cdd236Ssbehera 632759ac0c16Sdavemq nxge_status_t 632859ac0c16Sdavemq nxge_10g_link_led_on(p_nxge_t nxgep) 632959ac0c16Sdavemq { 633059ac0c16Sdavemq if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_TRUE) 633159ac0c16Sdavemq != NPI_SUCCESS) 633259ac0c16Sdavemq return (NXGE_ERROR); 633359ac0c16Sdavemq else 633459ac0c16Sdavemq return (NXGE_OK); 633559ac0c16Sdavemq } 633644961713Sgirish 633744961713Sgirish nxge_status_t 633859ac0c16Sdavemq nxge_10g_link_led_off(p_nxge_t nxgep) 633944961713Sgirish { 634059ac0c16Sdavemq if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_FALSE) 634159ac0c16Sdavemq != NPI_SUCCESS) 634259ac0c16Sdavemq return (NXGE_ERROR); 634359ac0c16Sdavemq else 634459ac0c16Sdavemq return (NXGE_OK); 634559ac0c16Sdavemq } 634644961713Sgirish 63472d17280bSsbehera static boolean_t 63482d17280bSsbehera nxge_is_phy_present(p_nxge_t nxgep, int addr, uint32_t id, uint32_t mask) 63492d17280bSsbehera { 63502d17280bSsbehera uint32_t pma_pmd_id = 0; 63512d17280bSsbehera uint32_t pcs_id = 0; 63522d17280bSsbehera uint32_t phy_id = 0; 63532d17280bSsbehera 63542d17280bSsbehera pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, addr); 63552d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 63562d17280bSsbehera "nxge_is_phy_present: pma_pmd_id[0x%x]", pma_pmd_id)); 63572d17280bSsbehera if ((pma_pmd_id & mask) == (id & mask)) 63582d17280bSsbehera goto found_phy; 63592d17280bSsbehera pcs_id = nxge_get_cl45_pcs_id(nxgep, addr); 63602d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 63612d17280bSsbehera "nxge_is_phy_present: pcs_id[0x%x]", pcs_id)); 63622d17280bSsbehera if ((pcs_id & mask) == (id & mask)) 63632d17280bSsbehera goto found_phy; 63642d17280bSsbehera phy_id = nxge_get_cl22_phy_id(nxgep, addr); 63652d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 63662d17280bSsbehera "nxge_is_phy_present: phy_id[0x%x]", phy_id)); 63672d17280bSsbehera if ((phy_id & mask) == (id & mask)) 63682d17280bSsbehera goto found_phy; 63692d17280bSsbehera 63702d17280bSsbehera return (B_FALSE); 63712d17280bSsbehera 63722d17280bSsbehera found_phy: 63732d17280bSsbehera return (B_TRUE); 63742d17280bSsbehera } 63752d17280bSsbehera 637659ac0c16Sdavemq /* Check if the given id read using the given MDIO Clause is supported */ 637759ac0c16Sdavemq 637859ac0c16Sdavemq static boolean_t 637959ac0c16Sdavemq nxge_is_supported_phy(uint32_t id, uint8_t type) 638059ac0c16Sdavemq { 638159ac0c16Sdavemq int i; 638259ac0c16Sdavemq boolean_t found = B_FALSE; 638359ac0c16Sdavemq 638459ac0c16Sdavemq switch (type) { 638559ac0c16Sdavemq case CLAUSE_45_TYPE: 638600161856Syc for (i = 0; i < NUM_CLAUSE_45_IDS; i++) { 638700161856Syc if (((nxge_supported_cl45_ids[i] & BCM_PHY_ID_MASK) == 638800161856Syc (id & BCM_PHY_ID_MASK)) || 638900161856Syc (TN1010_DEV_ID == (id & TN1010_DEV_ID_MASK))) { 639059ac0c16Sdavemq found = B_TRUE; 639159ac0c16Sdavemq break; 639259ac0c16Sdavemq } 639359ac0c16Sdavemq } 639459ac0c16Sdavemq break; 639559ac0c16Sdavemq case CLAUSE_22_TYPE: 639600161856Syc for (i = 0; i < NUM_CLAUSE_22_IDS; i++) { 639730505775Ssbehera if ((nxge_supported_cl22_ids[i] & BCM_PHY_ID_MASK) == 639830505775Ssbehera (id & BCM_PHY_ID_MASK)) { 639959ac0c16Sdavemq found = B_TRUE; 640059ac0c16Sdavemq break; 640156d930aeSspeer } 640244961713Sgirish } 640359ac0c16Sdavemq break; 640459ac0c16Sdavemq default: 640559ac0c16Sdavemq break; 640656d930aeSspeer } 640756d930aeSspeer 640859ac0c16Sdavemq return (found); 640959ac0c16Sdavemq } 641059ac0c16Sdavemq 64112e59129aSraghus static uint32_t 64122e59129aSraghus nxge_get_cl45_pma_pmd_id(p_nxge_t nxgep, int phy_port) 64132e59129aSraghus { 64142e59129aSraghus uint16_t val1 = 0; 64152e59129aSraghus uint16_t val2 = 0; 64162e59129aSraghus uint32_t pma_pmd_dev_id = 0; 64172e59129aSraghus npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep); 64182e59129aSraghus 641953560810Ssbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 64202e59129aSraghus (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR, 64212e59129aSraghus NXGE_DEV_ID_REG_1, &val1); 64222e59129aSraghus (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR, 64232e59129aSraghus NXGE_DEV_ID_REG_2, &val2); 642453560810Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 64252e59129aSraghus 642600161856Syc /* Concatenate the Device ID stored in two registers. */ 64272e59129aSraghus pma_pmd_dev_id = val1; 64282e59129aSraghus pma_pmd_dev_id = (pma_pmd_dev_id << 16); 64292e59129aSraghus pma_pmd_dev_id |= val2; 64302e59129aSraghus 64312e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PMA/PMD " 64322e59129aSraghus "devid[0x%llx]", phy_port, pma_pmd_dev_id)); 64332e59129aSraghus 64342e59129aSraghus return (pma_pmd_dev_id); 64352e59129aSraghus } 64362e59129aSraghus 64372e59129aSraghus static uint32_t 64382e59129aSraghus nxge_get_cl45_pcs_id(p_nxge_t nxgep, int phy_port) 64392e59129aSraghus { 64402e59129aSraghus uint16_t val1 = 0; 64412e59129aSraghus uint16_t val2 = 0; 64422e59129aSraghus uint32_t pcs_dev_id = 0; 64432e59129aSraghus npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep); 64442e59129aSraghus 644553560810Ssbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 64462e59129aSraghus (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR, 64472e59129aSraghus NXGE_DEV_ID_REG_1, &val1); 64482e59129aSraghus (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR, 64492e59129aSraghus NXGE_DEV_ID_REG_2, &val2); 645053560810Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 64512e59129aSraghus 64522e59129aSraghus pcs_dev_id = val1; 64532e59129aSraghus pcs_dev_id = (pcs_dev_id << 16); 64542e59129aSraghus pcs_dev_id |= val2; 64552e59129aSraghus 64562e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS " 64572e59129aSraghus "devid[0x%llx]", phy_port, pcs_dev_id)); 64582e59129aSraghus 64592e59129aSraghus return (pcs_dev_id); 64602e59129aSraghus } 64612e59129aSraghus 64622e59129aSraghus static uint32_t 64632e59129aSraghus nxge_get_cl22_phy_id(p_nxge_t nxgep, int phy_port) 64642e59129aSraghus { 64652e59129aSraghus uint16_t val1 = 0; 64662e59129aSraghus uint16_t val2 = 0; 64672e59129aSraghus uint32_t phy_id = 0; 64682e59129aSraghus npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep); 64692e59129aSraghus npi_status_t npi_status = NPI_SUCCESS; 64702e59129aSraghus 6471321febdeSsbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 64722e59129aSraghus npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_1, 64732e59129aSraghus &val1); 64742e59129aSraghus if (npi_status != NPI_SUCCESS) { 64752e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] " 64762e59129aSraghus "clause 22 read to reg 2 failed!!!")); 64772e59129aSraghus goto exit; 64782e59129aSraghus } 64792e59129aSraghus npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_2, 64802e59129aSraghus &val2); 64812e59129aSraghus if (npi_status != 0) { 64822e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] " 64832e59129aSraghus "clause 22 read to reg 3 failed!!!")); 64842e59129aSraghus goto exit; 64852e59129aSraghus } 64862e59129aSraghus phy_id = val1; 64872e59129aSraghus phy_id = (phy_id << 16); 64882e59129aSraghus phy_id |= val2; 64892e59129aSraghus 64902e59129aSraghus exit: 6491321febdeSsbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 64922e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID [0x%llx]", 64932e59129aSraghus phy_port, phy_id)); 64942e59129aSraghus 64952e59129aSraghus return (phy_id); 64962e59129aSraghus } 64972e59129aSraghus 649859ac0c16Sdavemq /* 649959ac0c16Sdavemq * Scan the PHY ports 0 through 31 to get the PHY ID using Clause 22 MDIO 650059ac0c16Sdavemq * read and the PMA/PMD device ID and the PCS device ID using Clause 45 MDIO 650159ac0c16Sdavemq * read. Then use the values obtained to determine the phy type of each port 650259ac0c16Sdavemq * and the Neptune type. 650300161856Syc * 650400161856Syc * This function sets hw_p->xcvr_addr[i] for future MDIO access and set 650500161856Syc * hw_p->niu_type for each nxge instance to figure out nxgep->mac.portmode 650600161856Syc * in case the portmode information is not available via OBP, nxge.conf, 650700161856Syc * VPD or SEEPROM. 650859ac0c16Sdavemq */ 650959ac0c16Sdavemq nxge_status_t 651059ac0c16Sdavemq nxge_scan_ports_phy(p_nxge_t nxgep, p_nxge_hw_list_t hw_p) 651159ac0c16Sdavemq { 651259a835ddSjoycey int i, j, l; 651359ac0c16Sdavemq uint32_t pma_pmd_dev_id = 0; 651459ac0c16Sdavemq uint32_t pcs_dev_id = 0; 651559ac0c16Sdavemq uint32_t phy_id = 0; 651630505775Ssbehera uint32_t port_pma_pmd_dev_id[NXGE_PORTS_NEPTUNE]; 651730505775Ssbehera uint32_t port_pcs_dev_id[NXGE_PORTS_NEPTUNE]; 651830505775Ssbehera uint32_t port_phy_id[NXGE_PORTS_NEPTUNE]; 651959ac0c16Sdavemq uint8_t pma_pmd_dev_fd[NXGE_MAX_PHY_PORTS]; 652059ac0c16Sdavemq uint8_t pcs_dev_fd[NXGE_MAX_PHY_PORTS]; 65212d17280bSsbehera uint8_t phy_fd_arr[NXGE_MAX_PHY_PORTS]; 65222d17280bSsbehera uint8_t port_fd_arr[NXGE_MAX_PHY_PORTS]; 652359ac0c16Sdavemq uint8_t total_port_fd, total_phy_fd; 652400161856Syc uint8_t num_xaui; 652559ac0c16Sdavemq nxge_status_t status = NXGE_OK; 652656d930aeSspeer 652759ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_scan_ports_phy: ")); 652856d930aeSspeer NXGE_DEBUG_MSG((nxgep, MAC_CTL, 652959ac0c16Sdavemq "==> nxge_scan_ports_phy: nxge niu_type[0x%x]", 653059ac0c16Sdavemq nxgep->niu_type)); 653159ac0c16Sdavemq 6532678453a8Sspeer if (isLDOMguest(nxgep)) { 6533678453a8Sspeer hw_p->niu_type = NIU_TYPE_NONE; 6534678453a8Sspeer hw_p->platform_type = P_NEPTUNE_NONE; 6535678453a8Sspeer return (NXGE_OK); 6536678453a8Sspeer } 6537678453a8Sspeer 653859a835ddSjoycey j = l = 0; 653959ac0c16Sdavemq total_port_fd = total_phy_fd = 0; 654056d930aeSspeer /* 654159ac0c16Sdavemq * Clause 45 and Clause 22 port/phy addresses 0 through 7 are reserved 654200161856Syc * for on chip serdes usages. "i" in the following for loop starts at 8. 654356d930aeSspeer */ 654459ac0c16Sdavemq for (i = NXGE_EXT_PHY_PORT_ST; i < NXGE_MAX_PHY_PORTS; i++) { 65452e59129aSraghus 65462e59129aSraghus pma_pmd_dev_id = nxge_get_cl45_pma_pmd_id(nxgep, i); 654759ac0c16Sdavemq 654859ac0c16Sdavemq if (nxge_is_supported_phy(pma_pmd_dev_id, CLAUSE_45_TYPE)) { 654959ac0c16Sdavemq pma_pmd_dev_fd[i] = 1; 655059ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] " 655152cdd236Ssbehera "PMA/PMD dev %x found", i, pma_pmd_dev_id)); 655230505775Ssbehera if (j < NXGE_PORTS_NEPTUNE) { 655300161856Syc if ((pma_pmd_dev_id & TN1010_DEV_ID_MASK) 655400161856Syc == TN1010_DEV_ID) { 655500161856Syc port_pma_pmd_dev_id[j] = TN1010_DEV_ID; 655600161856Syc } else { 655700161856Syc port_pma_pmd_dev_id[j] = 655800161856Syc pma_pmd_dev_id & BCM_PHY_ID_MASK; 655900161856Syc } 65602d17280bSsbehera port_fd_arr[j] = (uint8_t)i; 656159ac0c16Sdavemq j++; 656259ac0c16Sdavemq } 656359ac0c16Sdavemq } else { 656459ac0c16Sdavemq pma_pmd_dev_fd[i] = 0; 656559ac0c16Sdavemq } 656659ac0c16Sdavemq 65672e59129aSraghus pcs_dev_id = nxge_get_cl45_pcs_id(nxgep, i); 656859ac0c16Sdavemq 656959ac0c16Sdavemq if (nxge_is_supported_phy(pcs_dev_id, CLAUSE_45_TYPE)) { 657059ac0c16Sdavemq pcs_dev_fd[i] = 1; 657159ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS " 657252cdd236Ssbehera "dev %x found", i, pcs_dev_id)); 657359a835ddSjoycey if (pma_pmd_dev_fd[i] == 1) { 657400161856Syc if ((pcs_dev_id & TN1010_DEV_ID_MASK) 657500161856Syc == TN1010_DEV_ID) { 657600161856Syc port_pcs_dev_id[j - 1] = 657700161856Syc TN1010_DEV_ID; 657800161856Syc } else { 657900161856Syc port_pcs_dev_id[j - 1] = 658000161856Syc pcs_dev_id & 658100161856Syc BCM_PHY_ID_MASK; 658200161856Syc } 658359a835ddSjoycey } else { 658459a835ddSjoycey if (j < NXGE_PORTS_NEPTUNE) { 658500161856Syc if ((pcs_dev_id & TN1010_DEV_ID_MASK) 658600161856Syc == TN1010_DEV_ID) { 658700161856Syc port_pcs_dev_id[j] = 658800161856Syc TN1010_DEV_ID; 658900161856Syc } else { 659000161856Syc port_pcs_dev_id[j] = 659100161856Syc pcs_dev_id & 659200161856Syc BCM_PHY_ID_MASK; 659300161856Syc } 659459a835ddSjoycey port_fd_arr[j] = (uint8_t)i; 659559a835ddSjoycey j++; 659659a835ddSjoycey } 659759ac0c16Sdavemq } 659859ac0c16Sdavemq } else { 659959ac0c16Sdavemq pcs_dev_fd[i] = 0; 660059ac0c16Sdavemq } 660159ac0c16Sdavemq 66022d17280bSsbehera if (pcs_dev_fd[i] || pma_pmd_dev_fd[i]) { 66032d17280bSsbehera total_port_fd ++; 66042d17280bSsbehera } 660559ac0c16Sdavemq 66062e59129aSraghus phy_id = nxge_get_cl22_phy_id(nxgep, i); 660759ac0c16Sdavemq if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) { 66082d17280bSsbehera total_phy_fd ++; 660959ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID" 661052cdd236Ssbehera "%x found", i, phy_id)); 661130505775Ssbehera if (l < NXGE_PORTS_NEPTUNE) { 661200161856Syc if ((phy_id & TN1010_DEV_ID_MASK) 661300161856Syc == TN1010_DEV_ID) { 661400161856Syc port_phy_id[l] = TN1010_DEV_ID; 661500161856Syc } else { 661600161856Syc port_phy_id[l] 661700161856Syc = phy_id & BCM_PHY_ID_MASK; 661800161856Syc } 66192d17280bSsbehera phy_fd_arr[l] = (uint8_t)i; 662059ac0c16Sdavemq l++; 662159ac0c16Sdavemq } 662259ac0c16Sdavemq } 662359ac0c16Sdavemq } 662459ac0c16Sdavemq 662559ac0c16Sdavemq switch (total_port_fd) { 662659ac0c16Sdavemq case 2: 662759ac0c16Sdavemq switch (total_phy_fd) { 662859ac0c16Sdavemq case 2: 662959a835ddSjoycey /* 2 10G, 2 1G RGMII Fiber */ 663059a835ddSjoycey if ((((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) && 663159a835ddSjoycey (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) || 663259a835ddSjoycey ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) && 663359a835ddSjoycey (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) && 663459a835ddSjoycey ((port_phy_id[0] == PHY_BCM5482_FAMILY) && 663559a835ddSjoycey (port_phy_id[1] == PHY_BCM5482_FAMILY))) { 663659a835ddSjoycey 663759a835ddSjoycey hw_p->platform_type = 663859a835ddSjoycey P_NEPTUNE_GENERIC; 663959a835ddSjoycey 664059a835ddSjoycey hw_p->niu_type = NEPTUNE_2_10GF_2_1GRF; 664159a835ddSjoycey 664259a835ddSjoycey hw_p->xcvr_addr[0] = port_fd_arr[0]; 664359a835ddSjoycey hw_p->xcvr_addr[1] = port_fd_arr[1]; 664459a835ddSjoycey hw_p->xcvr_addr[2] = phy_fd_arr[0]; 664559a835ddSjoycey hw_p->xcvr_addr[3] = phy_fd_arr[1]; 664659a835ddSjoycey 664759a835ddSjoycey NXGE_DEBUG_MSG((nxgep, MAC_CTL, 664859a835ddSjoycey "ARTM card with 2 10G, 2 1G")); 664959a835ddSjoycey } else { 665059a835ddSjoycey NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 665159a835ddSjoycey "Unsupported neptune type 1")); 665259a835ddSjoycey goto error_exit; 665359a835ddSjoycey } 665459a835ddSjoycey break; 665559a835ddSjoycey 665659ac0c16Sdavemq case 1: 665759ac0c16Sdavemq /* TODO - 2 10G, 1 1G */ 665859ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 665959ac0c16Sdavemq "Unsupported neptune type 2 10G, 1 1G")); 666059ac0c16Sdavemq goto error_exit; 666159ac0c16Sdavemq case 0: 666200161856Syc /* 666300161856Syc * 2 10G: 2XGF NIC, Marvell, Goa, Huron with 2 XAUI 666400161856Syc * cards, etc. 666500161856Syc */ 666630505775Ssbehera if (((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) && 666730505775Ssbehera (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) || 666830505775Ssbehera ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) && 666952cdd236Ssbehera (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY)) || 667052cdd236Ssbehera ((port_pcs_dev_id[0] == MARVELL_88X201X_PHY_ID) && 667152cdd236Ssbehera (port_pcs_dev_id[1] == MARVELL_88X201X_PHY_ID)) || 667252cdd236Ssbehera ((port_pma_pmd_dev_id[0] == 667352cdd236Ssbehera MARVELL_88X201X_PHY_ID) && 667452cdd236Ssbehera (port_pma_pmd_dev_id[1] == 667552cdd236Ssbehera MARVELL_88X201X_PHY_ID))) { 66762e59129aSraghus 66772e59129aSraghus /* 66782e59129aSraghus * Check the first phy port address against 66792e59129aSraghus * the known phy start addresses to determine 66802e59129aSraghus * the platform type. 66812e59129aSraghus */ 66822d17280bSsbehera 66832d17280bSsbehera switch (port_fd_arr[0]) { 668400161856Syc case NEPTUNE_CLAUSE45_PORT_ADDR_BASE: 668552cdd236Ssbehera /* 668652cdd236Ssbehera * The Marvell case also falls into 668752cdd236Ssbehera * this case as 668852cdd236Ssbehera * MRVL88X2011_NEPTUNE_PORT_ADDR_BASE 668900161856Syc * == NEPTUNE_CLAUSE45_PORT_ADDR_BASE. 669052cdd236Ssbehera * This is OK for the 2 10G case. 669152cdd236Ssbehera */ 66922e59129aSraghus hw_p->niu_type = NEPTUNE_2_10GF; 66932e59129aSraghus hw_p->platform_type = 66942e59129aSraghus P_NEPTUNE_ATLAS_2PORT; 66952d17280bSsbehera break; 669600161856Syc case GOA_CLAUSE45_PORT_ADDR_BASE: 66972d17280bSsbehera if (hw_p->platform_type != 66982d17280bSsbehera P_NEPTUNE_NIU) { 66992d17280bSsbehera hw_p->platform_type = 67002d17280bSsbehera P_NEPTUNE_GENERIC; 67012d17280bSsbehera hw_p->niu_type = 67022d17280bSsbehera NEPTUNE_2_10GF; 67032d17280bSsbehera } 67042d17280bSsbehera break; 67052d17280bSsbehera default: 67062d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 67072e59129aSraghus "Unsupported neptune type 2 - 1")); 67082e59129aSraghus goto error_exit; 67092e59129aSraghus } 67102d17280bSsbehera 67112d17280bSsbehera for (i = 0; i < 2; i++) { 67122d17280bSsbehera hw_p->xcvr_addr[i] = port_fd_arr[i]; 67132d17280bSsbehera } 671400161856Syc 671500161856Syc /* Both XAUI slots have copper XAUI cards */ 671600161856Syc } else if ((((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 671700161856Syc == TN1010_DEV_ID) && 671800161856Syc ((port_pcs_dev_id[1] & TN1010_DEV_ID_MASK) 671900161856Syc == TN1010_DEV_ID)) || 672000161856Syc (((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK) 672100161856Syc == TN1010_DEV_ID) && 672200161856Syc ((port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK) 672300161856Syc == TN1010_DEV_ID))) { 672400161856Syc hw_p->niu_type = NEPTUNE_2_TN1010; 672500161856Syc hw_p->xcvr_addr[0] = port_fd_arr[0]; 672600161856Syc hw_p->xcvr_addr[1] = port_fd_arr[1]; 672700161856Syc 672800161856Syc /* Slot0 has fiber XAUI, slot1 has copper XAUI */ 672900161856Syc } else if ((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY && 673000161856Syc (port_pcs_dev_id[1] & TN1010_DEV_ID_MASK) 673100161856Syc == TN1010_DEV_ID) || 673200161856Syc (port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY && 673300161856Syc (port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK) == 673400161856Syc TN1010_DEV_ID)) { 673500161856Syc hw_p->niu_type = NEPTUNE_1_10GF_1_TN1010; 673600161856Syc hw_p->xcvr_addr[0] = port_fd_arr[0]; 673700161856Syc hw_p->xcvr_addr[1] = port_fd_arr[1]; 673800161856Syc 673900161856Syc /* Slot0 has copper XAUI, slot1 has fiber XAUI */ 674000161856Syc } else if ((port_pcs_dev_id[1] == PHY_BCM8704_FAMILY && 674100161856Syc (port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 674200161856Syc == TN1010_DEV_ID) || 674300161856Syc (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY && 674400161856Syc (port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK) 674500161856Syc == TN1010_DEV_ID)) { 674600161856Syc hw_p->niu_type = NEPTUNE_1_TN1010_1_10GF; 674700161856Syc hw_p->xcvr_addr[0] = port_fd_arr[0]; 674800161856Syc hw_p->xcvr_addr[1] = port_fd_arr[1]; 674900161856Syc 675059ac0c16Sdavemq } else { 675159ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 675259ac0c16Sdavemq "Unsupported neptune type 2")); 675359ac0c16Sdavemq goto error_exit; 675459ac0c16Sdavemq } 675559ac0c16Sdavemq break; 675600161856Syc 675759ac0c16Sdavemq case 4: 675800161856Syc if (nxge_get_num_of_xaui( 675900161856Syc port_pma_pmd_dev_id, port_pcs_dev_id, 676000161856Syc port_phy_id, &num_xaui) == NXGE_ERROR) { 676100161856Syc goto error_exit; 676200161856Syc } 676300161856Syc if (num_xaui != 2) 676400161856Syc goto error_exit; 676559ac0c16Sdavemq 676600161856Syc /* 676700161856Syc * Maramba with 2 XAUIs (either fiber or copper) 676800161856Syc * 676900161856Syc * Check the first phy port address against 677000161856Syc * the known phy start addresses to determine 677100161856Syc * the platform type. 677200161856Syc */ 677300161856Syc switch (phy_fd_arr[0]) { 677400161856Syc case MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE: 677500161856Syc hw_p->platform_type = 677600161856Syc P_NEPTUNE_MARAMBA_P0; 677700161856Syc break; 677800161856Syc case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE: 677900161856Syc hw_p->platform_type = 678000161856Syc P_NEPTUNE_MARAMBA_P1; 678100161856Syc break; 678200161856Syc default: 678300161856Syc NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 678400161856Syc "Unknown port %d...Cannot " 678500161856Syc "determine platform type", i)); 678600161856Syc goto error_exit; 678700161856Syc } 67882d17280bSsbehera 678900161856Syc hw_p->xcvr_addr[0] = port_fd_arr[0]; 679000161856Syc hw_p->xcvr_addr[1] = port_fd_arr[1]; 679100161856Syc hw_p->xcvr_addr[2] = phy_fd_arr[2]; 679200161856Syc hw_p->xcvr_addr[3] = phy_fd_arr[3]; 679300161856Syc 679400161856Syc /* slot0 has fiber XAUI, slot1 has Cu XAUI */ 679500161856Syc if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY && 679600161856Syc (port_pcs_dev_id[1] & TN1010_DEV_ID_MASK) 679700161856Syc == TN1010_DEV_ID) { 679800161856Syc hw_p->niu_type = NEPTUNE_1_10GF_1_TN1010_2_1GC; 679900161856Syc 680000161856Syc /* slot0 has Cu XAUI, slot1 has fiber XAUI */ 680100161856Syc } else if (((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 680200161856Syc == TN1010_DEV_ID) && 680300161856Syc port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) { 680400161856Syc hw_p->niu_type = NEPTUNE_1_TN1010_1_10GF_2_1GC; 680500161856Syc 680600161856Syc /* Both slots have fiber XAUI */ 680700161856Syc } else if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY && 680800161856Syc port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) { 68092e59129aSraghus hw_p->niu_type = NEPTUNE_2_10GF_2_1GC; 68102e59129aSraghus 681100161856Syc /* Both slots have copper XAUI */ 681200161856Syc } else if (((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 681300161856Syc == TN1010_DEV_ID) && 681400161856Syc (port_pcs_dev_id[1] & TN1010_DEV_ID_MASK) 681500161856Syc == TN1010_DEV_ID) { 681600161856Syc hw_p->niu_type = NEPTUNE_2_TN1010_2_1GC; 68172d17280bSsbehera 681859ac0c16Sdavemq } else { 681959ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 682059ac0c16Sdavemq "Unsupported neptune type 3")); 682159ac0c16Sdavemq goto error_exit; 682259ac0c16Sdavemq } 682359ac0c16Sdavemq break; 682459ac0c16Sdavemq default: 682559ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 682659ac0c16Sdavemq "Unsupported neptune type 5")); 682759ac0c16Sdavemq goto error_exit; 682859ac0c16Sdavemq } 682930505775Ssbehera break; 683000161856Syc case 1: /* Only one clause45 port */ 683100161856Syc switch (total_phy_fd) { /* Number of clause22 ports */ 683259ac0c16Sdavemq case 3: 68332e59129aSraghus /* 68342e59129aSraghus * TODO 3 1G, 1 10G mode. 68352e59129aSraghus * Differentiate between 1_1G_1_10G_2_1G and 68362e59129aSraghus * 1_10G_3_1G 68372e59129aSraghus */ 68382e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 68392e59129aSraghus "Unsupported neptune type 7")); 68402e59129aSraghus goto error_exit; 684159ac0c16Sdavemq case 2: 684259ac0c16Sdavemq /* 684359ac0c16Sdavemq * TODO 2 1G, 1 10G mode. 684459ac0c16Sdavemq * Differentiate between 1_1G_1_10G_1_1G and 684559ac0c16Sdavemq * 1_10G_2_1G 684659ac0c16Sdavemq */ 684759ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 684859ac0c16Sdavemq "Unsupported neptune type 8")); 684959ac0c16Sdavemq goto error_exit; 685059ac0c16Sdavemq case 1: 685159ac0c16Sdavemq /* 685259ac0c16Sdavemq * TODO 1 1G, 1 10G mode. 685359ac0c16Sdavemq * Differentiate between 1_1G_1_10G and 685459ac0c16Sdavemq * 1_10G_1_1G 685559ac0c16Sdavemq */ 685659ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 685759ac0c16Sdavemq "Unsupported neptune type 9")); 685859ac0c16Sdavemq goto error_exit; 685900161856Syc case 0: /* N2 with 1 XAUI (fiber or copper) */ 686000161856Syc /* Fiber XAUI */ 68612d17280bSsbehera if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY || 68622d17280bSsbehera port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) { 68632d17280bSsbehera 68642d17280bSsbehera /* 68652d17280bSsbehera * Check the first phy port address against 68662d17280bSsbehera * the known phy start addresses to determine 68672d17280bSsbehera * the platform type. 68682d17280bSsbehera */ 68692d17280bSsbehera 68702d17280bSsbehera switch (port_fd_arr[0]) { 687100161856Syc case N2_CLAUSE45_PORT_ADDR_BASE: 687200161856Syc case (N2_CLAUSE45_PORT_ADDR_BASE + 1): 687300161856Syc case ALT_GOA_CLAUSE45_PORT1_ADDR: 687400161856Syc /* 687500161856Syc * If hw_p->platform_type == 687600161856Syc * P_NEPTUNE_NIU, then portmode 687700161856Syc * is already known, so there is 687800161856Syc * no need to figure out hw_p-> 687900161856Syc * platform_type because 688000161856Syc * platform_type is only for 688100161856Syc * figuring out portmode. 688200161856Syc */ 68832d17280bSsbehera if (hw_p->platform_type != 68842d17280bSsbehera P_NEPTUNE_NIU) { 68852d17280bSsbehera hw_p->platform_type = 68862d17280bSsbehera P_NEPTUNE_GENERIC; 68872d17280bSsbehera hw_p->niu_type = 68882d17280bSsbehera NEPTUNE_2_10GF; 68892d17280bSsbehera } 68902d17280bSsbehera break; 68912d17280bSsbehera default: 68922d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 68932d17280bSsbehera "Unsupported neptune type 10")); 68942d17280bSsbehera goto error_exit; 68952d17280bSsbehera } 6896321febdeSsbehera /* 6897321febdeSsbehera * For GOA, which is a hot swappable PHY, the 6898321febdeSsbehera * phy address to function number mapping 6899321febdeSsbehera * should be preserved, i.e., addr 16 is 6900321febdeSsbehera * assigned to function 0 and 20 to function 1 6901321febdeSsbehera * But for Huron XAUI, the assignment should 6902321febdeSsbehera * be by function number, i.e., whichever 6903321febdeSsbehera * function number attaches should be 6904321febdeSsbehera * assigned the available PHY (this is required 6905321febdeSsbehera * primarily to support pre-production Huron 6906321febdeSsbehera * boards where function 0 is mapped to addr 17 6907321febdeSsbehera */ 6908321febdeSsbehera if (port_fd_arr[0] == 690900161856Syc ALT_GOA_CLAUSE45_PORT1_ADDR) { 6910321febdeSsbehera hw_p->xcvr_addr[1] = port_fd_arr[0]; 6911321febdeSsbehera } else { 6912321febdeSsbehera hw_p->xcvr_addr[nxgep->function_num] = 6913321febdeSsbehera port_fd_arr[0]; 6914321febdeSsbehera } 691500161856Syc 691600161856Syc /* A 10G copper XAUI in either slot0 or slot1 */ 691700161856Syc } else if ((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 691800161856Syc == TN1010_DEV_ID || 691900161856Syc (port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK) 692000161856Syc == TN1010_DEV_ID) { 692100161856Syc switch (port_fd_arr[0]) { 692200161856Syc /* The XAUI is in slot0 */ 692300161856Syc case N2_CLAUSE45_PORT_ADDR_BASE: 692400161856Syc hw_p->niu_type = NEPTUNE_1_TN1010; 692500161856Syc break; 692600161856Syc 692700161856Syc /* The XAUI is in slot1 */ 692800161856Syc case (N2_CLAUSE45_PORT_ADDR_BASE + 1): 692900161856Syc hw_p->niu_type 693000161856Syc = NEPTUNE_1_NONE_1_TN1010; 693100161856Syc break; 693200161856Syc default: 693300161856Syc NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 693400161856Syc "Unsupported XAUI port address")); 693500161856Syc goto error_exit; 693600161856Syc } 693700161856Syc hw_p->xcvr_addr[nxgep->function_num] 693800161856Syc = port_fd_arr[0]; 693900161856Syc 69402d17280bSsbehera } else { 69412d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 694200161856Syc "Unsupported PHY type")); 69432d17280bSsbehera goto error_exit; 69442d17280bSsbehera } 69452d17280bSsbehera break; 694600161856Syc case 4: /* Maramba always have 4 clause 45 ports */ 694759ac0c16Sdavemq 694800161856Syc /* Maramba with 1 XAUI */ 694900161856Syc if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY || 695000161856Syc port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY || 695100161856Syc ((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 695200161856Syc == TN1010_DEV_ID) || 695300161856Syc ((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK) 695400161856Syc == TN1010_DEV_ID)) { 695559ac0c16Sdavemq /* 695659ac0c16Sdavemq * Check the first phy port address against 695759ac0c16Sdavemq * the known phy start addresses to determine 695859ac0c16Sdavemq * the platform type. 695959ac0c16Sdavemq */ 69602d17280bSsbehera switch (phy_fd_arr[0]) { 696100161856Syc case MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE: 696259ac0c16Sdavemq hw_p->platform_type = 696359ac0c16Sdavemq P_NEPTUNE_MARAMBA_P0; 69642d17280bSsbehera break; 696500161856Syc case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE: 696659ac0c16Sdavemq hw_p->platform_type = 696759ac0c16Sdavemq P_NEPTUNE_MARAMBA_P1; 69682d17280bSsbehera break; 69692d17280bSsbehera default: 697059ac0c16Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 697159ac0c16Sdavemq "Unknown port %d...Cannot " 69722d17280bSsbehera "determine platform type 10 - 2", 69732d17280bSsbehera i)); 69742e59129aSraghus goto error_exit; 69752e59129aSraghus } 69762e59129aSraghus 69772d17280bSsbehera /* 697800161856Syc * Check the clause45 address to determine 69792d17280bSsbehera * if XAUI is in port 0 or port 1. 69802d17280bSsbehera */ 69812d17280bSsbehera switch (port_fd_arr[0]) { 698200161856Syc case MARAMBA_CLAUSE45_PORT_ADDR_BASE: 698300161856Syc if (port_pcs_dev_id[0] 698400161856Syc == PHY_BCM8704_FAMILY || 698500161856Syc port_pma_pmd_dev_id[0] 698600161856Syc == PHY_BCM8704_FAMILY) { 698700161856Syc hw_p->niu_type 698800161856Syc = NEPTUNE_1_10GF_3_1GC; 698900161856Syc } else { 699000161856Syc hw_p->niu_type 699100161856Syc = NEPTUNE_1_TN1010_3_1GC; 699200161856Syc } 69932d17280bSsbehera hw_p->xcvr_addr[0] = port_fd_arr[0]; 69942d17280bSsbehera for (i = 1; i < NXGE_MAX_PORTS; i++) { 69952d17280bSsbehera hw_p->xcvr_addr[i] = 69962d17280bSsbehera phy_fd_arr[i]; 69972d17280bSsbehera } 69982d17280bSsbehera break; 699900161856Syc case (MARAMBA_CLAUSE45_PORT_ADDR_BASE + 1): 700000161856Syc if (port_pcs_dev_id[0] 700100161856Syc == PHY_BCM8704_FAMILY || 700200161856Syc port_pma_pmd_dev_id[0] 700300161856Syc == PHY_BCM8704_FAMILY) { 700400161856Syc hw_p->niu_type = 700500161856Syc NEPTUNE_1_1GC_1_10GF_2_1GC; 700600161856Syc } else { 700700161856Syc hw_p->niu_type = 700800161856Syc NEPTUNE_1_1GC_1_TN1010_2_1GC; 700900161856Syc } 70102d17280bSsbehera hw_p->xcvr_addr[0] = phy_fd_arr[0]; 70112d17280bSsbehera hw_p->xcvr_addr[1] = port_fd_arr[0]; 70122d17280bSsbehera hw_p->xcvr_addr[2] = phy_fd_arr[2]; 70132d17280bSsbehera hw_p->xcvr_addr[3] = phy_fd_arr[3]; 70142d17280bSsbehera break; 70152d17280bSsbehera default: 70162e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 70172e59129aSraghus "Unsupported neptune type 11")); 70182e59129aSraghus goto error_exit; 701959ac0c16Sdavemq } 702059ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 702100161856Syc "Maramba with 1 XAUI (fiber or copper)")); 702259ac0c16Sdavemq } else { 702359ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 702459ac0c16Sdavemq "Unsupported neptune type 12")); 702559ac0c16Sdavemq goto error_exit; 702659ac0c16Sdavemq } 702759ac0c16Sdavemq break; 702859ac0c16Sdavemq default: 702959ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 703059ac0c16Sdavemq "Unsupported neptune type 13")); 703159ac0c16Sdavemq goto error_exit; 703259ac0c16Sdavemq } 703359ac0c16Sdavemq break; 703400161856Syc case 0: /* 4 ports Neptune based NIC */ 703559ac0c16Sdavemq switch (total_phy_fd) { 703659ac0c16Sdavemq case 4: 703730505775Ssbehera if ((port_phy_id[0] == PHY_BCM5464R_FAMILY) && 703830505775Ssbehera (port_phy_id[1] == PHY_BCM5464R_FAMILY) && 703930505775Ssbehera (port_phy_id[2] == PHY_BCM5464R_FAMILY) && 704030505775Ssbehera (port_phy_id[3] == PHY_BCM5464R_FAMILY)) { 704159ac0c16Sdavemq 704259ac0c16Sdavemq /* 704359ac0c16Sdavemq * Check the first phy port address against 704459ac0c16Sdavemq * the known phy start addresses to determine 704559ac0c16Sdavemq * the platform type. 704659ac0c16Sdavemq */ 70472d17280bSsbehera switch (phy_fd_arr[0]) { 704800161856Syc case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE: 704959ac0c16Sdavemq hw_p->platform_type = 705059ac0c16Sdavemq P_NEPTUNE_MARAMBA_P1; 70512d17280bSsbehera break; 705200161856Syc case NEPTUNE_CLAUSE22_PORT_ADDR_BASE: 70532e59129aSraghus hw_p->platform_type = 70542e59129aSraghus P_NEPTUNE_ATLAS_4PORT; 70552d17280bSsbehera break; 70562d17280bSsbehera default: 70572e59129aSraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 70582e59129aSraghus "Unknown port %d...Cannot " 70592e59129aSraghus "determine platform type", i)); 70602e59129aSraghus goto error_exit; 706159ac0c16Sdavemq } 70622e59129aSraghus hw_p->niu_type = NEPTUNE_4_1GC; 70632d17280bSsbehera for (i = 0; i < NXGE_MAX_PORTS; i++) { 70642d17280bSsbehera hw_p->xcvr_addr[i] = phy_fd_arr[i]; 70652d17280bSsbehera } 706659ac0c16Sdavemq } else { 706759ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 706859ac0c16Sdavemq "Unsupported neptune type 14")); 706959ac0c16Sdavemq goto error_exit; 707059ac0c16Sdavemq } 707159ac0c16Sdavemq break; 707259ac0c16Sdavemq case 3: 707359ac0c16Sdavemq /* TODO 3 1G mode */ 707459ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 707559ac0c16Sdavemq "Unsupported neptune type 15")); 707659ac0c16Sdavemq goto error_exit; 707759ac0c16Sdavemq case 2: 707859ac0c16Sdavemq /* TODO 2 1G mode */ 707959a835ddSjoycey if ((port_phy_id[0] == PHY_BCM5482_FAMILY) && 708059a835ddSjoycey (port_phy_id[1] == PHY_BCM5482_FAMILY)) { 708159a835ddSjoycey hw_p->platform_type = P_NEPTUNE_GENERIC; 708259a835ddSjoycey hw_p->niu_type = NEPTUNE_2_1GRF; 708359a835ddSjoycey hw_p->xcvr_addr[2] = phy_fd_arr[0]; 708459a835ddSjoycey hw_p->xcvr_addr[3] = phy_fd_arr[1]; 708559a835ddSjoycey } else { 708659a835ddSjoycey NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 708759a835ddSjoycey "Unsupported neptune type 16")); 708859a835ddSjoycey goto error_exit; 708959a835ddSjoycey } 709059ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 709159a835ddSjoycey "2 RGMII Fiber ports - RTM")); 709259a835ddSjoycey break; 709359a835ddSjoycey 709459ac0c16Sdavemq case 1: 709559ac0c16Sdavemq /* TODO 1 1G mode */ 709659ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 709759ac0c16Sdavemq "Unsupported neptune type 17")); 709859ac0c16Sdavemq goto error_exit; 709959ac0c16Sdavemq default: 710059ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 710159ac0c16Sdavemq "Unsupported neptune type 18, total phy fd %d", 710259ac0c16Sdavemq total_phy_fd)); 710359ac0c16Sdavemq goto error_exit; 710459ac0c16Sdavemq } 710559ac0c16Sdavemq break; 710659ac0c16Sdavemq default: 710756d930aeSspeer NXGE_DEBUG_MSG((nxgep, MAC_CTL, 710859ac0c16Sdavemq "Unsupported neptune type 19")); 710959ac0c16Sdavemq goto error_exit; 711044961713Sgirish } 711144961713Sgirish 711259ac0c16Sdavemq scan_exit: 711344961713Sgirish 711459ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_scan_ports_phy, " 711559ac0c16Sdavemq "niu type [0x%x]\n", hw_p->niu_type)); 711659ac0c16Sdavemq return (status); 711744961713Sgirish 711859ac0c16Sdavemq error_exit: 711959ac0c16Sdavemq return (NXGE_ERROR); 712044961713Sgirish } 712156d930aeSspeer 712256d930aeSspeer boolean_t 712356d930aeSspeer nxge_is_valid_local_mac(ether_addr_st mac_addr) 712456d930aeSspeer { 712556d930aeSspeer if ((mac_addr.ether_addr_octet[0] & 0x01) || 712656d930aeSspeer (ether_cmp(&mac_addr, ðerbroadcastaddr) == 0) || 712756d930aeSspeer (ether_cmp(&mac_addr, ðerzeroaddr) == 0)) 712856d930aeSspeer return (B_FALSE); 712956d930aeSspeer else 713056d930aeSspeer return (B_TRUE); 713156d930aeSspeer } 713259ac0c16Sdavemq 713359ac0c16Sdavemq static void 713459ac0c16Sdavemq nxge_bcm5464_link_led_off(p_nxge_t nxgep) { 713559ac0c16Sdavemq 713659ac0c16Sdavemq npi_status_t rs = NPI_SUCCESS; 713759ac0c16Sdavemq uint8_t xcvr_portn; 713859ac0c16Sdavemq uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 713959ac0c16Sdavemq 714059ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_bcm5464_link_led_off")); 714159ac0c16Sdavemq 714259ac0c16Sdavemq if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P1) { 714300161856Syc xcvr_portn = MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE; 714459ac0c16Sdavemq } else if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P0) { 714500161856Syc xcvr_portn = MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE; 714659ac0c16Sdavemq } 714759ac0c16Sdavemq /* 714859ac0c16Sdavemq * For Altas 4-1G copper, Xcvr port numbers are 714959ac0c16Sdavemq * swapped with ethernet port number. This is 715059ac0c16Sdavemq * designed for better signal integrity in routing. 715159ac0c16Sdavemq */ 715259ac0c16Sdavemq switch (portn) { 715359ac0c16Sdavemq case 0: 715459ac0c16Sdavemq xcvr_portn += 3; 715559ac0c16Sdavemq break; 715659ac0c16Sdavemq case 1: 715759ac0c16Sdavemq xcvr_portn += 2; 715859ac0c16Sdavemq break; 715959ac0c16Sdavemq case 2: 716059ac0c16Sdavemq xcvr_portn += 1; 716159ac0c16Sdavemq break; 716259ac0c16Sdavemq case 3: 716359ac0c16Sdavemq default: 716459ac0c16Sdavemq break; 716559ac0c16Sdavemq } 716659ac0c16Sdavemq 7167321febdeSsbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 716859ac0c16Sdavemq rs = npi_mac_mif_mii_write(nxgep->npi_handle, 716959ac0c16Sdavemq xcvr_portn, BCM5464R_MISC, 0xb4ee); 717059ac0c16Sdavemq if (rs != NPI_SUCCESS) { 717159ac0c16Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 717259ac0c16Sdavemq "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write " 717359ac0c16Sdavemq "returned error 0x[%x]", rs)); 7174321febdeSsbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 717559ac0c16Sdavemq return; 717659ac0c16Sdavemq } 717759ac0c16Sdavemq 717859ac0c16Sdavemq rs = npi_mac_mif_mii_write(nxgep->npi_handle, 717959ac0c16Sdavemq xcvr_portn, BCM5464R_MISC, 0xb8ee); 718059ac0c16Sdavemq if (rs != NPI_SUCCESS) { 718159ac0c16Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 718259ac0c16Sdavemq "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write " 718359ac0c16Sdavemq "returned error 0x[%x]", rs)); 718459ac0c16Sdavemq } 718559ac0c16Sdavemq 7186321febdeSsbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 718759ac0c16Sdavemq } 7188d81011f0Ssbehera 7189d81011f0Ssbehera static nxge_status_t 7190d81011f0Ssbehera nxge_mii_get_link_mode(p_nxge_t nxgep) 7191d81011f0Ssbehera { 7192d81011f0Ssbehera p_nxge_stats_t statsp; 7193d81011f0Ssbehera uint8_t xcvr_portn; 7194d81011f0Ssbehera p_mii_regs_t mii_regs; 7195d81011f0Ssbehera mii_mode_control_stat_t mode; 7196d81011f0Ssbehera int status = NXGE_OK; 7197d81011f0Ssbehera 7198d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_get_link_mode")); 7199d81011f0Ssbehera 7200d81011f0Ssbehera statsp = nxgep->statsp; 7201d81011f0Ssbehera xcvr_portn = statsp->mac_stats.xcvr_portn; 7202d81011f0Ssbehera mii_regs = NULL; 7203d81011f0Ssbehera mode.value = 0; 72046b438925Ssbehera mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG; 7205d81011f0Ssbehera #if defined(__i386) 7206d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 7207d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->shadow), 7208d81011f0Ssbehera mode.value)) != NXGE_OK) { 7209d81011f0Ssbehera goto fail; 7210d81011f0Ssbehera #else 7211d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 7212d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->shadow), 7213d81011f0Ssbehera mode.value)) != NXGE_OK) { 7214d81011f0Ssbehera goto fail; 7215d81011f0Ssbehera #endif 7216d81011f0Ssbehera } 7217d81011f0Ssbehera #if defined(__i386) 7218d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 7219d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->shadow), 7220d81011f0Ssbehera &mode.value)) != NXGE_OK) { 7221d81011f0Ssbehera goto fail; 7222d81011f0Ssbehera } 7223d81011f0Ssbehera #else 7224d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 7225d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->shadow), 7226d81011f0Ssbehera &mode.value)) != NXGE_OK) { 7227d81011f0Ssbehera goto fail; 7228d81011f0Ssbehera } 7229d81011f0Ssbehera #endif 7230d81011f0Ssbehera 7231d81011f0Ssbehera if (mode.bits.mode == NXGE_MODE_SELECT_FIBER) { 7232d81011f0Ssbehera nxgep->mac.portmode = PORT_1G_RGMII_FIBER; 7233d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7234d81011f0Ssbehera "nxge_mii_get_link_mode: fiber mode")); 7235d81011f0Ssbehera } 7236d81011f0Ssbehera 7237d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7238d81011f0Ssbehera "nxge_mii_get_link_mode: " 7239d81011f0Ssbehera "(address 0x%x) port 0x%x mode value 0x%x link mode 0x%x", 72406b438925Ssbehera NXGE_MII_MODE_CONTROL_REG, xcvr_portn, 7241d81011f0Ssbehera mode.value, nxgep->mac.portmode)); 7242d81011f0Ssbehera 7243d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7244d81011f0Ssbehera "<== nxge_mii_get_link_mode")); 7245d81011f0Ssbehera return (status); 7246d81011f0Ssbehera fail: 7247d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7248d81011f0Ssbehera "<== nxge_mii_get_link_mode (failed)")); 7249d81011f0Ssbehera return (NXGE_ERROR); 7250d81011f0Ssbehera } 7251d81011f0Ssbehera 72521bd6825cSml nxge_status_t 72531bd6825cSml nxge_mac_set_framesize(p_nxge_t nxgep) 72541bd6825cSml { 72551bd6825cSml npi_attr_t ap; 72561bd6825cSml uint8_t portn; 72571bd6825cSml npi_handle_t handle; 72581bd6825cSml npi_status_t rs = NPI_SUCCESS; 72591bd6825cSml 72601bd6825cSml NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_set_framesize")); 72611bd6825cSml 72621bd6825cSml portn = NXGE_GET_PORT_NUM(nxgep->function_num); 72631bd6825cSml handle = nxgep->npi_handle; 72641bd6825cSml 72651bd6825cSml NXGE_DEBUG_MSG((nxgep, MAC_CTL, 72661bd6825cSml "==> nxge_mac_sec_framesize: port<%d> " 72671bd6825cSml "min framesize %d max framesize %d ", 72681bd6825cSml portn, 72691bd6825cSml nxgep->mac.minframesize, 72701bd6825cSml nxgep->mac.maxframesize)); 72711bd6825cSml 72721bd6825cSml SET_MAC_ATTR2(handle, ap, portn, 72731bd6825cSml MAC_PORT_FRAME_SIZE, 72741bd6825cSml nxgep->mac.minframesize, 72751bd6825cSml nxgep->mac.maxframesize, 72761bd6825cSml rs); 72771bd6825cSml if (rs != NPI_SUCCESS) { 72781bd6825cSml NXGE_DEBUG_MSG((nxgep, MAC_CTL, 72791bd6825cSml "<== nxge_mac_set_framesize: failed to configure " 72801bd6825cSml "max/min frame size port %d", portn)); 72811bd6825cSml 72821bd6825cSml return (NXGE_ERROR | rs); 72831bd6825cSml } 72841bd6825cSml 72851bd6825cSml NXGE_DEBUG_MSG((nxgep, MAC_CTL, 72861bd6825cSml "<== nxge_mac_set_framesize: port<%d>", portn)); 72871bd6825cSml 72881bd6825cSml return (NXGE_OK); 72891bd6825cSml } 72901bd6825cSml 729100161856Syc static nxge_status_t 729200161856Syc nxge_get_num_of_xaui(uint32_t *port_pma_pmd_dev_id, 729300161856Syc uint32_t *port_pcs_dev_id, uint32_t *port_phy_id, uint8_t *num_xaui) 729400161856Syc { 729500161856Syc uint8_t i; 729600161856Syc 729700161856Syc for (i = 0; i < 4; i++) { 729800161856Syc if (port_phy_id[i] != PHY_BCM5464R_FAMILY) 729900161856Syc return (NXGE_ERROR); 730000161856Syc } 730100161856Syc 730200161856Syc *num_xaui = 0; 730300161856Syc if ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY && 730400161856Syc port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) || 730500161856Syc (((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK) 730600161856Syc == TN1010_DEV_ID) && 730700161856Syc ((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 730800161856Syc == TN1010_DEV_ID))) { 730900161856Syc (*num_xaui) ++; 731000161856Syc } 731100161856Syc if ((port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY && 731200161856Syc port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) || 731300161856Syc (((port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK) 731400161856Syc == TN1010_DEV_ID) && 731500161856Syc ((port_pcs_dev_id[1] & TN1010_DEV_ID_MASK) 731600161856Syc == TN1010_DEV_ID))) { 731700161856Syc (*num_xaui) ++; 731800161856Syc } 731900161856Syc return (NXGE_OK); 732000161856Syc } 732100161856Syc 732200161856Syc /* 732300161856Syc * Instruction from Teranetics: Once you detect link is up, go 732400161856Syc * read Reg 30.1.4 for link speed: '1' for 1G and '0' for 10G. You 732500161856Syc * may want to qualify it by first checking Register 30.1.7:6 and 732600161856Syc * making sure it reads "01" (Auto-Neg Complete). 732700161856Syc * 732800161856Syc * If this function is called when the link is down or before auto- 732900161856Syc * negotiation has completed, then the speed of the PHY is not certain. 733000161856Syc * In such cases, this function returns 1G as the default speed with 733100161856Syc * NXGE_OK status instead of NXGE_ERROR. It is OK to initialize the 733200161856Syc * driver based on a default speed because this function will be called 733300161856Syc * again when the link comes up. Returning NXGE_ERROR, which may 733400161856Syc * cause brutal chain reaction in caller functions, is not necessary. 733500161856Syc */ 733600161856Syc static nxge_status_t 733700161856Syc nxge_get_tn1010_speed(p_nxge_t nxgep, uint16_t *speed) 733800161856Syc { 733900161856Syc uint8_t phy_port_addr, autoneg_stat, link_up; 734000161856Syc nxge_status_t status = NXGE_OK; 734100161856Syc uint16_t val; 734200161856Syc uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 734300161856Syc 734400161856Syc /* Set default speed to 10G */ 734500161856Syc *speed = TN1010_SPEED_10G; 734600161856Syc 734700161856Syc /* Set Clause 45 */ 734800161856Syc npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE); 734900161856Syc 735000161856Syc phy_port_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 735100161856Syc 735200161856Syc /* Check Device 1 Register 0xA bit0 for link up status */ 735300161856Syc status = nxge_mdio_read(nxgep, phy_port_addr, 735400161856Syc TN1010_AUTONEG_DEV_ADDR, TN1010_AUTONEG_STATUS_REG, &val); 735500161856Syc if (status != NXGE_OK) 735600161856Syc goto fail; 735700161856Syc 735800161856Syc link_up = ((val & TN1010_AN_LINK_STAT_BIT) 735900161856Syc ? B_TRUE : B_FALSE); 736000161856Syc if (link_up == B_FALSE) { 736100161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 736200161856Syc "nxge_get_tn1010_speed: link is down")); 736300161856Syc goto nxge_get_tn1010_speed_exit; 736400161856Syc } 736500161856Syc 736600161856Syc if ((status = nxge_mdio_read(nxgep, phy_port_addr, 736700161856Syc TN1010_VENDOR_MMD1_DEV_ADDR, TN1010_VENDOR_MMD1_STATUS_REG, 736800161856Syc &val)) != NXGE_OK) { 736900161856Syc goto fail; 737000161856Syc } 737100161856Syc autoneg_stat = (val & TN1010_VENDOR_MMD1_AN_STAT_BITS) >> 737200161856Syc TN1010_VENDOR_MMD1_AN_STAT_SHIFT; 737300161856Syc 737400161856Syc /* 737500161856Syc * Return NXGE_OK even when we can not get a settled speed. In 737600161856Syc * such case, the speed reported should not be trusted but that 737700161856Syc * is OK, we will call this function periodically and will get 737800161856Syc * the correct speed after the link is up. 737900161856Syc */ 738000161856Syc switch (autoneg_stat) { 738100161856Syc case TN1010_AN_IN_PROG: 738200161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 738300161856Syc "nxge_get_tn1010_speed: Auto-negotiation in progress")); 738400161856Syc break; 738500161856Syc case TN1010_AN_COMPLETE: 738600161856Syc if ((status = nxge_mdio_read(nxgep, phy_port_addr, 738700161856Syc TN1010_VENDOR_MMD1_DEV_ADDR, 738800161856Syc TN1010_VENDOR_MMD1_STATUS_REG, 738900161856Syc &val)) != NXGE_OK) { 739000161856Syc goto fail; 739100161856Syc } 739200161856Syc *speed = (val & TN1010_VENDOR_MMD1_AN_SPEED_BIT) >> 739300161856Syc TN1010_VENDOR_MMD1_AN_SPEED_SHIFT; 739400161856Syc break; 739500161856Syc case TN1010_AN_RSVD: 739600161856Syc NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 739700161856Syc "nxge_get_tn1010_speed: Autoneg status undefined")); 739800161856Syc break; 739900161856Syc case TN1010_AN_FAILED: 740000161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 740100161856Syc "nxge_get_tn1010_speed: Auto-negotiation failed")); 740200161856Syc break; 740300161856Syc default: 740400161856Syc break; 740500161856Syc } 740600161856Syc nxge_get_tn1010_speed_exit: 740700161856Syc return (NXGE_OK); 740800161856Syc fail: 740900161856Syc return (status); 741000161856Syc } 741100161856Syc 741200161856Syc 741300161856Syc /* 741400161856Syc * Teranetics TN1010 PHY chip supports both 1G and 10G modes, this function 741500161856Syc * figures out the speed of the PHY determined by the autonegotiation 741600161856Syc * process and sets the following 3 parameters, 741700161856Syc * nxgep->mac.portmode 741800161856Syc * nxgep->statsp->mac_stats.link_speed 741900161856Syc * nxgep->statsp->mac_stats.xcvr_inuse 742000161856Syc */ 742100161856Syc static nxge_status_t 742200161856Syc nxge_set_tn1010_param(p_nxge_t nxgep) 742300161856Syc { 742400161856Syc uint16_t speed; 742500161856Syc 742600161856Syc if (nxge_get_tn1010_speed(nxgep, &speed) != NXGE_OK) { 742700161856Syc NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 742800161856Syc "nxge_set_tn1010_param: " 742900161856Syc "Failed to get TN1010 speed")); 743000161856Syc return (NXGE_ERROR); 743100161856Syc } 743200161856Syc if (speed == TN1010_SPEED_1G) { 743300161856Syc nxgep->mac.portmode = PORT_1G_TN1010; 743400161856Syc nxgep->statsp->mac_stats.link_speed = 1000; 743500161856Syc nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 743600161856Syc } else { 743700161856Syc nxgep->mac.portmode = PORT_10G_TN1010; 743800161856Syc nxgep->statsp->mac_stats.link_speed = 10000; 743900161856Syc nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 744000161856Syc } 744100161856Syc return (NXGE_OK); 744200161856Syc } 744300161856Syc 7444d81011f0Ssbehera #ifdef NXGE_DEBUG 7445d81011f0Ssbehera static void 7446d81011f0Ssbehera nxge_mii_dump(p_nxge_t nxgep) 7447d81011f0Ssbehera { 7448d81011f0Ssbehera p_nxge_stats_t statsp; 7449d81011f0Ssbehera uint8_t xcvr_portn; 7450d81011f0Ssbehera p_mii_regs_t mii_regs; 7451d81011f0Ssbehera mii_bmcr_t bmcr; 7452d81011f0Ssbehera mii_bmsr_t bmsr; 7453d81011f0Ssbehera mii_idr1_t idr1; 7454d81011f0Ssbehera mii_idr2_t idr2; 7455d81011f0Ssbehera mii_mode_control_stat_t mode; 7456678453a8Sspeer p_nxge_param_t param_arr; 7457d81011f0Ssbehera 7458d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "==> nxge_mii_dump")); 7459d81011f0Ssbehera 7460d81011f0Ssbehera statsp = nxgep->statsp; 7461d81011f0Ssbehera xcvr_portn = statsp->mac_stats.xcvr_portn; 7462d81011f0Ssbehera 7463d81011f0Ssbehera mii_regs = NULL; 7464d81011f0Ssbehera 7465d81011f0Ssbehera #if defined(__i386) 7466d81011f0Ssbehera (void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn, 7467d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value); 7468d81011f0Ssbehera #else 7469d81011f0Ssbehera (void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn, 7470d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value); 7471d81011f0Ssbehera #endif 7472d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7473d81011f0Ssbehera "nxge_mii_dump: bmcr (0) xcvr 0x%x value 0x%x", 7474d81011f0Ssbehera xcvr_portn, bmcr.value)); 7475d81011f0Ssbehera 7476d81011f0Ssbehera #if defined(__i386) 7477d81011f0Ssbehera (void) nxge_mii_read(nxgep, 7478d81011f0Ssbehera nxgep->statsp->mac_stats.xcvr_portn, 7479d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmsr), &bmsr.value); 7480d81011f0Ssbehera #else 7481d81011f0Ssbehera (void) nxge_mii_read(nxgep, 7482d81011f0Ssbehera nxgep->statsp->mac_stats.xcvr_portn, 7483d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value); 7484d81011f0Ssbehera #endif 7485d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7486d81011f0Ssbehera "nxge_mii_dump: bmsr (1) xcvr 0x%x value 0x%x", 7487d81011f0Ssbehera xcvr_portn, bmsr.value)); 7488d81011f0Ssbehera 7489d81011f0Ssbehera #if defined(__i386) 7490d81011f0Ssbehera (void) nxge_mii_read(nxgep, 7491d81011f0Ssbehera nxgep->statsp->mac_stats.xcvr_portn, 7492d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->idr1), &idr1.value); 7493d81011f0Ssbehera #else 7494d81011f0Ssbehera (void) nxge_mii_read(nxgep, 7495d81011f0Ssbehera nxgep->statsp->mac_stats.xcvr_portn, 7496d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->idr1), &idr1.value); 7497d81011f0Ssbehera #endif 7498d81011f0Ssbehera 7499d81011f0Ssbehera 7500d81011f0Ssbehera #if defined(__i386) 7501d81011f0Ssbehera (void) nxge_mii_read(nxgep, 7502d81011f0Ssbehera nxgep->statsp->mac_stats.xcvr_portn, 7503d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->idr2), &idr2.value); 7504d81011f0Ssbehera #else 7505d81011f0Ssbehera (void) nxge_mii_read(nxgep, 7506d81011f0Ssbehera nxgep->statsp->mac_stats.xcvr_portn, 7507d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->idr2), &idr2.value); 7508d81011f0Ssbehera #endif 7509d81011f0Ssbehera 7510d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7511d81011f0Ssbehera "nxge_mii_dump: idr1 (2) xcvr 0x%x value 0x%x", 7512d81011f0Ssbehera xcvr_portn, idr1.value)); 7513d81011f0Ssbehera 7514d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7515d81011f0Ssbehera "nxge_mii_dump: idr2 (3) xcvr 0x%x value 0x%x", 7516d81011f0Ssbehera xcvr_portn, idr2.value)); 7517d81011f0Ssbehera 7518d81011f0Ssbehera mode.value = 0; 75196b438925Ssbehera mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG; 7520d81011f0Ssbehera 7521d81011f0Ssbehera #if defined(__i386) 7522d81011f0Ssbehera (void) nxge_mii_write(nxgep, xcvr_portn, 7523d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->shadow), mode.value); 7524d81011f0Ssbehera 7525d81011f0Ssbehera (void) nxge_mii_read(nxgep, xcvr_portn, 7526d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->shadow), &mode.value); 7527d81011f0Ssbehera #else 7528d81011f0Ssbehera (void) nxge_mii_write(nxgep, xcvr_portn, 7529d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->shadow), mode.value); 7530d81011f0Ssbehera 7531d81011f0Ssbehera (void) nxge_mii_read(nxgep, xcvr_portn, 7532d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->shadow), &mode.value); 7533d81011f0Ssbehera #endif 7534d81011f0Ssbehera 7535d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7536d81011f0Ssbehera "nxge_mii_dump: mode control xcvr 0x%x value 0x%x", 7537d81011f0Ssbehera xcvr_portn, mode.value)); 7538d81011f0Ssbehera } 7539d81011f0Ssbehera #endif 7540