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 /* 22e759c33aSMichael Speer * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 2344961713Sgirish * Use is subject to license terms. 2444961713Sgirish */ 2544961713Sgirish 2644961713Sgirish #include <sys/nxge/nxge_impl.h> 2744961713Sgirish #include <sys/nxge/nxge_mac.h> 28678453a8Sspeer #include <sys/nxge/nxge_hio.h> 2944961713Sgirish 3098ecde52Stm #define LINK_MONITOR_PERIOD (1000 * 1000) 3198ecde52Stm #define LM_WAIT_MULTIPLIER 8 3298ecde52Stm 33321febdeSsbehera #define SERDES_RDY_WT_INTERVAL 50 34321febdeSsbehera #define MAX_SERDES_RDY_RETRIES 10 35321febdeSsbehera 3600161856Syc #define TN1010_SPEED_1G 1 3700161856Syc #define TN1010_SPEED_10G 0 3800161856Syc #define TN1010_AN_IN_PROG 0 /* Auto negotiation in progress */ 3900161856Syc #define TN1010_AN_COMPLETE 1 4000161856Syc #define TN1010_AN_RSVD 2 4100161856Syc #define TN1010_AN_FAILED 3 4200161856Syc 4344961713Sgirish extern uint32_t nxge_no_link_notify; 4459ac0c16Sdavemq extern boolean_t nxge_no_msg; 4544961713Sgirish extern uint32_t nxge_lb_dbg; 464202ea4bSsbehera extern uint32_t nxge_jumbo_mtu; 4744961713Sgirish 4898ecde52Stm typedef enum { 4998ecde52Stm CHECK_LINK_RESCHEDULE, 5098ecde52Stm CHECK_LINK_STOP 5198ecde52Stm } check_link_state_t; 5298ecde52Stm 5398ecde52Stm static check_link_state_t nxge_check_link_stop(nxge_t *); 5498ecde52Stm 5544961713Sgirish /* 5644961713Sgirish * Ethernet broadcast address definition. 5744961713Sgirish */ 5844961713Sgirish static ether_addr_st etherbroadcastaddr = 5944961713Sgirish {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}; 6059ac0c16Sdavemq /* 6159ac0c16Sdavemq * Ethernet zero address definition. 6259ac0c16Sdavemq */ 6356d930aeSspeer static ether_addr_st etherzeroaddr = 6456d930aeSspeer {{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; 6559ac0c16Sdavemq /* 6659ac0c16Sdavemq * Supported chip types 6759ac0c16Sdavemq */ 6852cdd236Ssbehera static uint32_t nxge_supported_cl45_ids[] = { 6952cdd236Ssbehera BCM8704_DEV_ID, 7052cdd236Ssbehera MARVELL_88X_201X_DEV_ID, 7100161856Syc BCM8706_DEV_ID, 7200161856Syc TN1010_DEV_ID 7352cdd236Ssbehera }; 7452cdd236Ssbehera 75b1000363Sml static uint32_t nxge_supported_cl22_ids[] = { 76b1000363Sml BCM5464R_PHY_ID, 77b1000363Sml BCM5482_PHY_ID 78b1000363Sml }; 7959ac0c16Sdavemq 8059ac0c16Sdavemq #define NUM_CLAUSE_45_IDS (sizeof (nxge_supported_cl45_ids) / \ 8159ac0c16Sdavemq sizeof (uint32_t)) 8259ac0c16Sdavemq #define NUM_CLAUSE_22_IDS (sizeof (nxge_supported_cl22_ids) / \ 8359ac0c16Sdavemq sizeof (uint32_t)) 8459ac0c16Sdavemq /* 8559ac0c16Sdavemq * static functions 8659ac0c16Sdavemq */ 872e59129aSraghus static uint32_t nxge_get_cl45_pma_pmd_id(p_nxge_t, int); 882e59129aSraghus static uint32_t nxge_get_cl45_pcs_id(p_nxge_t, int); 892e59129aSraghus static uint32_t nxge_get_cl22_phy_id(p_nxge_t, int); 9059ac0c16Sdavemq static boolean_t nxge_is_supported_phy(uint32_t, uint8_t); 912d17280bSsbehera static boolean_t nxge_is_phy_present(p_nxge_t, int, uint32_t, uint32_t); 9259ac0c16Sdavemq static nxge_status_t nxge_n2_serdes_init(p_nxge_t); 9359ac0c16Sdavemq static nxge_status_t nxge_neptune_10G_serdes_init(p_nxge_t); 9459ac0c16Sdavemq static nxge_status_t nxge_1G_serdes_init(p_nxge_t); 9559ac0c16Sdavemq static nxge_status_t nxge_10G_link_intr_stop(p_nxge_t); 9659ac0c16Sdavemq static nxge_status_t nxge_10G_link_intr_start(p_nxge_t); 9759ac0c16Sdavemq static nxge_status_t nxge_1G_copper_link_intr_stop(p_nxge_t); 9859ac0c16Sdavemq static nxge_status_t nxge_1G_copper_link_intr_start(p_nxge_t); 9959ac0c16Sdavemq static nxge_status_t nxge_1G_fiber_link_intr_stop(p_nxge_t); 10059ac0c16Sdavemq static nxge_status_t nxge_1G_fiber_link_intr_start(p_nxge_t); 10159ac0c16Sdavemq static nxge_status_t nxge_check_mii_link(p_nxge_t); 10259ac0c16Sdavemq static nxge_status_t nxge_check_10g_link(p_nxge_t); 10359ac0c16Sdavemq static nxge_status_t nxge_10G_xcvr_init(p_nxge_t); 1042d17280bSsbehera static nxge_status_t nxge_BCM8704_xcvr_init(p_nxge_t); 1052d17280bSsbehera static nxge_status_t nxge_BCM8706_xcvr_init(p_nxge_t); 10659ac0c16Sdavemq static nxge_status_t nxge_1G_xcvr_init(p_nxge_t); 10759ac0c16Sdavemq static void nxge_bcm5464_link_led_off(p_nxge_t); 10800161856Syc static nxge_status_t nxge_check_mrvl88x2011_link(p_nxge_t, boolean_t *); 10952cdd236Ssbehera static nxge_status_t nxge_mrvl88x2011_xcvr_init(p_nxge_t); 11000161856Syc static nxge_status_t nxge_get_num_of_xaui(uint32_t *port_pma_pmd_dev_id, 11100161856Syc uint32_t *port_pcs_dev_id, uint32_t *port_phy_id, uint8_t *num_xaui); 11200161856Syc static nxge_status_t nxge_get_tn1010_speed(p_nxge_t nxgep, uint16_t *speed); 11300161856Syc static nxge_status_t nxge_set_tn1010_param(p_nxge_t nxgep); 11400161856Syc static nxge_status_t nxge_tn1010_check(p_nxge_t nxgep, 11500161856Syc nxge_link_state_t *link_up); 11600161856Syc static boolean_t nxge_is_tn1010_phy(p_nxge_t nxgep); 11700161856Syc static nxge_status_t nxge_tn1010_xcvr_init(p_nxge_t nxgep); 11800161856Syc 11900161856Syc nxge_status_t nxge_mac_init(p_nxge_t); 12000161856Syc static nxge_status_t nxge_mii_get_link_mode(p_nxge_t); 12100161856Syc 12200161856Syc #ifdef NXGE_DEBUG 12300161856Syc static void nxge_mii_dump(p_nxge_t); 12400161856Syc static nxge_status_t nxge_tn1010_reset(p_nxge_t nxgep); 12500161856Syc static void nxge_dump_tn1010_status_regs(p_nxge_t nxgep); 12600161856Syc #endif 12759ac0c16Sdavemq 12859ac0c16Sdavemq /* 12959ac0c16Sdavemq * xcvr tables for supported transceivers 13059ac0c16Sdavemq */ 13159ac0c16Sdavemq 13200161856Syc /* 13300161856Syc * nxge_n2_10G_table is for 10G fiber or serdes on N2-NIU systems. 13400161856Syc * The Teranetics TN1010 based copper XAUI card can also be used 13500161856Syc * on N2-NIU systems in 10G mode, but it uses its own table 13600161856Syc * nxge_n2_10G_tn1010_table below. 13700161856Syc */ 1382e59129aSraghus static nxge_xcvr_table_t nxge_n2_10G_table = { 13959ac0c16Sdavemq nxge_n2_serdes_init, 14059ac0c16Sdavemq nxge_10G_xcvr_init, 14159ac0c16Sdavemq nxge_10G_link_intr_stop, 14259ac0c16Sdavemq nxge_10G_link_intr_start, 14359ac0c16Sdavemq nxge_check_10g_link, 1442d17280bSsbehera PCS_XCVR 14559ac0c16Sdavemq }; 14659ac0c16Sdavemq 14700161856Syc /* 14800161856Syc * For the Teranetics TN1010 based copper XAUI card 14900161856Syc */ 15000161856Syc static nxge_xcvr_table_t nxge_n2_10G_tn1010_table = { 15100161856Syc nxge_n2_serdes_init, /* Handle both 1G and 10G */ 15200161856Syc nxge_tn1010_xcvr_init, /* Handle both 1G and 10G */ 15300161856Syc nxge_10G_link_intr_stop, 15400161856Syc nxge_10G_link_intr_start, 15500161856Syc nxge_check_tn1010_link, /* Will figure out speed */ 15600161856Syc XPCS_XCVR 15700161856Syc }; 15800161856Syc 1592e59129aSraghus static nxge_xcvr_table_t nxge_n2_1G_table = { 1602e59129aSraghus nxge_n2_serdes_init, 1612e59129aSraghus nxge_1G_xcvr_init, 1622e59129aSraghus nxge_1G_fiber_link_intr_stop, 1632e59129aSraghus nxge_1G_fiber_link_intr_start, 1642e59129aSraghus nxge_check_mii_link, 1652d17280bSsbehera PCS_XCVR 1662e59129aSraghus }; 1672e59129aSraghus 16800161856Syc static nxge_xcvr_table_t nxge_n2_1G_tn1010_table = { 16900161856Syc nxge_n2_serdes_init, 17000161856Syc nxge_tn1010_xcvr_init, 17100161856Syc nxge_1G_fiber_link_intr_stop, /* TN1010 is a Cu PHY, but it uses */ 17200161856Syc nxge_1G_fiber_link_intr_start, /* PCS for 1G, so call fiber func */ 17300161856Syc nxge_check_tn1010_link, 17400161856Syc PCS_XCVR 17500161856Syc }; 17600161856Syc 17700161856Syc static nxge_xcvr_table_t nxge_10G_tn1010_table = { 17800161856Syc nxge_neptune_10G_serdes_init, 17900161856Syc nxge_tn1010_xcvr_init, 18000161856Syc nxge_10G_link_intr_stop, 18100161856Syc nxge_10G_link_intr_start, 18200161856Syc nxge_check_tn1010_link, 18300161856Syc XPCS_XCVR 18400161856Syc }; 18500161856Syc 18600161856Syc static nxge_xcvr_table_t nxge_1G_tn1010_table = { 18700161856Syc nxge_1G_serdes_init, 18800161856Syc nxge_tn1010_xcvr_init, 18900161856Syc nxge_1G_fiber_link_intr_stop, 19000161856Syc nxge_1G_fiber_link_intr_start, 19100161856Syc nxge_check_tn1010_link, 19200161856Syc PCS_XCVR 19300161856Syc }; 19400161856Syc 19559ac0c16Sdavemq static nxge_xcvr_table_t nxge_10G_fiber_table = { 19659ac0c16Sdavemq nxge_neptune_10G_serdes_init, 19759ac0c16Sdavemq nxge_10G_xcvr_init, 19859ac0c16Sdavemq nxge_10G_link_intr_stop, 19959ac0c16Sdavemq nxge_10G_link_intr_start, 20059ac0c16Sdavemq nxge_check_10g_link, 2012d17280bSsbehera PCS_XCVR 20259ac0c16Sdavemq }; 20359ac0c16Sdavemq 20459ac0c16Sdavemq static nxge_xcvr_table_t nxge_1G_copper_table = { 20559ac0c16Sdavemq NULL, 20659ac0c16Sdavemq nxge_1G_xcvr_init, 20759ac0c16Sdavemq nxge_1G_copper_link_intr_stop, 20859ac0c16Sdavemq nxge_1G_copper_link_intr_start, 20959ac0c16Sdavemq nxge_check_mii_link, 2102d17280bSsbehera INT_MII_XCVR 21159ac0c16Sdavemq }; 21259ac0c16Sdavemq 21300161856Syc /* This table is for Neptune portmode == PORT_1G_SERDES cases */ 21459ac0c16Sdavemq static nxge_xcvr_table_t nxge_1G_fiber_table = { 21559ac0c16Sdavemq nxge_1G_serdes_init, 21659ac0c16Sdavemq nxge_1G_xcvr_init, 21759ac0c16Sdavemq nxge_1G_fiber_link_intr_stop, 21859ac0c16Sdavemq nxge_1G_fiber_link_intr_start, 21959ac0c16Sdavemq nxge_check_mii_link, 2202d17280bSsbehera PCS_XCVR 22159ac0c16Sdavemq }; 22259ac0c16Sdavemq 22359ac0c16Sdavemq static nxge_xcvr_table_t nxge_10G_copper_table = { 22459ac0c16Sdavemq nxge_neptune_10G_serdes_init, 22559ac0c16Sdavemq NULL, 22659ac0c16Sdavemq NULL, 22759ac0c16Sdavemq NULL, 2282e59129aSraghus NULL, 2292d17280bSsbehera PCS_XCVR 23059ac0c16Sdavemq }; 23144961713Sgirish 23200161856Syc /* 23300161856Syc * NXGE_PORT_TN1010 is defined as, 23400161856Syc * NXGE_PORT_SPD_NONE | (NXGE_PHY_TN1010 << NXGE_PHY_SHIFT) 23500161856Syc * = 0 | 5 << 16 = 0x50000 23600161856Syc * 23700161856Syc * So NEPTUNE_2_TN1010 = 23800161856Syc * (NXGE_PORT_TN1010 | 23900161856Syc * (NXGE_PORT_TN1010 << 4) | 24000161856Syc * (NXGE_PORT_NONE << 8) | 24100161856Syc * (NXGE_PORT_NONE << 12)), 24200161856Syc * = 0x50000 | (0x50000 << 4) 24300161856Syc * = 0x550000 24400161856Syc * 24500161856Syc * This function partitions nxgep->nxge_hw_p->niu_type (which may have 24600161856Syc * value NEPTUNE_2_TN1010) and checks if a port has type = NXGE_PORT_TN1010 24700161856Syc * = 0x50000 24800161856Syc */ 24900161856Syc static boolean_t nxge_is_tn1010_phy(p_nxge_t nxgep) 25000161856Syc { 25100161856Syc uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 25200161856Syc 25300161856Syc if (((nxgep->nxge_hw_p->niu_type >> (NXGE_PORT_TYPE_SHIFT * portn)) 25400161856Syc & NXGE_PHY_MASK) == NXGE_PORT_TN1010) { 25500161856Syc return (B_TRUE); 25600161856Syc } else { 25700161856Syc return (B_FALSE); 25800161856Syc } 25900161856Syc } 26044961713Sgirish 261d81011f0Ssbehera 26200161856Syc /* 26300161856Syc * Figure out nxgep->mac.portmode from nxge.conf, OBP's device properties, 26400161856Syc * serial EEPROM or VPD if possible. Note that not all systems could get 26500161856Syc * the portmode information by calling this function. For example, the 26600161856Syc * Maramba system figures out the portmode information by calling function 26700161856Syc * nxge_setup_xcvr_table. 26800161856Syc */ 2692e59129aSraghus nxge_status_t 2702e59129aSraghus nxge_get_xcvr_type(p_nxge_t nxgep) 2712e59129aSraghus { 2722e59129aSraghus nxge_status_t status = NXGE_OK; 2732e59129aSraghus char *phy_type; 2742e59129aSraghus char *prop_val; 27500161856Syc uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 2761c7408c9Stc uint32_t val; 2771c7408c9Stc npi_status_t rs; 2781c7408c9Stc 2791c7408c9Stc /* For Opus NEM, skip xcvr checking if 10G Serdes link is up */ 2801c7408c9Stc if (nxgep->mac.portmode == PORT_10G_SERDES && 2811c7408c9Stc nxgep->statsp->mac_stats.link_up) { 2821c7408c9Stc nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 2831c7408c9Stc return (status); 2841c7408c9Stc } 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; 315*ef523517SMichael Speer if (portn > 1) { 316*ef523517SMichael Speer return (NXGE_ERROR); 317*ef523517SMichael Speer } 318*ef523517SMichael Speer 3192d17280bSsbehera /* 3202d17280bSsbehera * If this is the 2nd NIU port, then check 2 addresses 3212d17280bSsbehera * to take care of the Goa NEM card. Port 1 can have addr 17 3222d17280bSsbehera * (in the eval board) or 20 (in the P0 board). 3232d17280bSsbehera */ 3242d17280bSsbehera if (portn == 1) { 3252d17280bSsbehera if (nxge_is_phy_present(nxgep, 32600161856Syc ALT_GOA_CLAUSE45_PORT1_ADDR, BCM8706_DEV_ID, 3272d17280bSsbehera BCM_PHY_ID_MASK)) { 3282d17280bSsbehera nxgep->xcvr_addr = 32900161856Syc ALT_GOA_CLAUSE45_PORT1_ADDR; 3302d17280bSsbehera goto found_phy; 3312d17280bSsbehera } 3322d17280bSsbehera } 3332d17280bSsbehera if (nxge_is_phy_present(nxgep, 33400161856Syc GOA_CLAUSE45_PORT_ADDR_BASE + portn, 3352d17280bSsbehera BCM8706_DEV_ID, BCM_PHY_ID_MASK)) { 33600161856Syc nxgep->xcvr_addr = GOA_CLAUSE45_PORT_ADDR_BASE + 3372d17280bSsbehera portn; 3382d17280bSsbehera goto found_phy; 3392d17280bSsbehera } 3402d17280bSsbehera 3412d17280bSsbehera nxgep->phy_absent = B_TRUE; 3421c7408c9Stc 3431c7408c9Stc /* Check Serdes link to detect Opus NEM */ 3441c7408c9Stc rs = npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 3451c7408c9Stc XPCS_REG_STATUS, &val); 3461c7408c9Stc 3471c7408c9Stc if (rs == 0 && val & XPCS_STATUS_LANE_ALIGN) { 3481c7408c9Stc nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 3491c7408c9Stc nxgep->mac.portmode = PORT_10G_SERDES; 3501c7408c9Stc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3511c7408c9Stc "HSP 10G Serdes FOUND!!")); 3521c7408c9Stc } 3532d17280bSsbehera goto check_phy_done; 3542d17280bSsbehera found_phy: 3552d17280bSsbehera nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 3562d17280bSsbehera nxgep->mac.portmode = PORT_10G_FIBER; 3572d17280bSsbehera nxgep->phy_absent = B_FALSE; 3582d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Fiber Xcvr " 3592d17280bSsbehera "found for hot swappable phy")); 3602d17280bSsbehera check_phy_done: 3612d17280bSsbehera return (status); 3622d17280bSsbehera } 3632d17280bSsbehera 36400161856Syc /* Get phy-type property (May have been set by nxge.conf) */ 3652e59129aSraghus if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip, 3662e59129aSraghus DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 3672e59129aSraghus "phy-type", &prop_val)) == DDI_PROP_SUCCESS) { 3682e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3692e59129aSraghus "found conf file: phy-type %s", prop_val)); 3702e59129aSraghus if (strcmp("xgsd", prop_val) == 0) { 3712e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 3722e59129aSraghus nxgep->mac.portmode = PORT_10G_SERDES; 3732e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3742e59129aSraghus "found: 10G Serdes")); 3752e59129aSraghus } else if (strcmp("gsd", prop_val) == 0) { 3762e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 3772e59129aSraghus nxgep->mac.portmode = PORT_1G_SERDES; 3782e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Serdes")); 3792e59129aSraghus } else if (strcmp("mif", prop_val) == 0) { 3802e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR; 3812e59129aSraghus nxgep->mac.portmode = PORT_1G_COPPER; 3822e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Copper Xcvr")); 3832e59129aSraghus } else if (strcmp("pcs", prop_val) == 0) { 3842e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 3852e59129aSraghus nxgep->mac.portmode = PORT_1G_FIBER; 3862e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G FIBER Xcvr")); 387321febdeSsbehera } else if (strcmp("xgf", prop_val) == 0) { 38800161856Syc /* 38900161856Syc * Before OBP supports new phy-type property 39000161856Syc * value "xgc", the 10G copper XAUI may carry 39100161856Syc * "xgf" instead of "xgc". If the OBP is 39200161856Syc * upgraded to a newer version which supports 39300161856Syc * "xgc", then the TN1010 related code in this 39400161856Syc * "xgf" case will not be used anymore. 39500161856Syc */ 39600161856Syc if (nxge_is_tn1010_phy(nxgep)) { 39700161856Syc if ((status = nxge_set_tn1010_param(nxgep)) 39800161856Syc != NXGE_OK) { 39900161856Syc return (status); 40000161856Syc } 40100161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, "TN1010 Xcvr")); 40200161856Syc } else { /* For Fiber XAUI */ 40300161856Syc nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 40400161856Syc nxgep->mac.portmode = PORT_10G_FIBER; 40500161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 40600161856Syc "10G Fiber Xcvr")); 40700161856Syc } 40800161856Syc } else if (strcmp("xgc", prop_val) == 0) { 40900161856Syc if ((status = nxge_set_tn1010_param(nxgep)) != NXGE_OK) 41000161856Syc return (status); 41100161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, "TN1010 Xcvr")); 4122e59129aSraghus } 4132e59129aSraghus 4142e59129aSraghus (void) ddi_prop_update_string(DDI_DEV_T_NONE, nxgep->dip, 4152e59129aSraghus "phy-type", prop_val); 4162e59129aSraghus ddi_prop_free(prop_val); 4172e59129aSraghus 4182e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: " 4192e59129aSraghus "Got phy type [0x%x] from conf file", 4202e59129aSraghus nxgep->mac.portmode)); 4212e59129aSraghus 4222e59129aSraghus return (NXGE_OK); 4232e59129aSraghus } 4242d17280bSsbehera 4252d17280bSsbehera /* Get phy-type property from OBP */ 4262e59129aSraghus if (nxgep->niu_type == N2_NIU) { 4272e59129aSraghus if (ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip, 0, 4282e59129aSraghus "phy-type", &prop_val) == DDI_PROP_SUCCESS) { 4292e59129aSraghus if (strcmp("xgf", prop_val) == 0) { 43000161856Syc /* 43100161856Syc * Before OBP supports new phy-type property 43200161856Syc * value "xgc", the 10G copper XAUI may carry 43300161856Syc * "xgf" instead of "xgc". If the OBP is 43400161856Syc * upgraded to a newer version which supports 43500161856Syc * "xgc", then the TN1010 related code in this 43600161856Syc * "xgf" case will not be used anymore. 43700161856Syc */ 43800161856Syc if (nxge_is_tn1010_phy(nxgep)) { 43900161856Syc if ((status = 44000161856Syc nxge_set_tn1010_param(nxgep)) 44100161856Syc != NXGE_OK) { 44200161856Syc return (status); 44300161856Syc } 44400161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 44500161856Syc "TN1010 Xcvr")); 44600161856Syc } else { /* For Fiber XAUI */ 44700161856Syc nxgep->statsp->mac_stats.xcvr_inuse 44800161856Syc = XPCS_XCVR; 44900161856Syc nxgep->mac.portmode = PORT_10G_FIBER; 45000161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 45100161856Syc "10G Fiber Xcvr")); 45200161856Syc } 4532e59129aSraghus } else if (strcmp("mif", prop_val) == 0) { 4542e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = 4552e59129aSraghus INT_MII_XCVR; 4562e59129aSraghus nxgep->mac.portmode = PORT_1G_COPPER; 4572e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4582e59129aSraghus "1G Copper Xcvr")); 4592e59129aSraghus } else if (strcmp("pcs", prop_val) == 0) { 4602e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 4612e59129aSraghus nxgep->mac.portmode = PORT_1G_FIBER; 4622e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4632e59129aSraghus "1G Fiber Xcvr")); 4642e59129aSraghus } else if (strcmp("xgc", prop_val) == 0) { 46500161856Syc status = nxge_set_tn1010_param(nxgep); 46600161856Syc if (status != NXGE_OK) 46700161856Syc return (status); 46800161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, "TN1010 Xcvr")); 4692e59129aSraghus } else if (strcmp("xgsd", prop_val) == 0) { 4702e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 4712e59129aSraghus nxgep->mac.portmode = PORT_10G_SERDES; 4722e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4732e59129aSraghus "OBP: 10G Serdes")); 4742e59129aSraghus } else if (strcmp("gsd", prop_val) == 0) { 4752e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 4762e59129aSraghus nxgep->mac.portmode = PORT_1G_SERDES; 4772e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4782e59129aSraghus "OBP: 1G Serdes")); 4792e59129aSraghus } else { 4802e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4812e59129aSraghus "Unknown phy-type: %s", prop_val)); 4822e59129aSraghus ddi_prop_free(prop_val); 4832e59129aSraghus return (NXGE_ERROR); 4842e59129aSraghus } 4852e59129aSraghus status = NXGE_OK; 4862e59129aSraghus (void) ddi_prop_update_string(DDI_DEV_T_NONE, 4872e59129aSraghus nxgep->dip, "phy-type", prop_val); 4882e59129aSraghus ddi_prop_free(prop_val); 4892e59129aSraghus 4902e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: " 4912e59129aSraghus "Got phy type [0x%x] from OBP", 4922e59129aSraghus nxgep->mac.portmode)); 4932e59129aSraghus 4942e59129aSraghus return (status); 4952e59129aSraghus } else { 4962e59129aSraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4972e59129aSraghus "Exiting...phy-type property not found")); 4982e59129aSraghus return (NXGE_ERROR); 4992e59129aSraghus } 5002e59129aSraghus } 5012e59129aSraghus 5022e59129aSraghus 5032e59129aSraghus if (!nxgep->vpd_info.present) { 5042e59129aSraghus return (NXGE_OK); 5052e59129aSraghus } 5062e59129aSraghus 5072e59129aSraghus if (!nxgep->vpd_info.ver_valid) { 5082e59129aSraghus goto read_seeprom; 5092e59129aSraghus } 5102e59129aSraghus 5112e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5122e59129aSraghus "Reading phy type from expansion ROM")); 5132e59129aSraghus /* 5142e59129aSraghus * Try to read the phy type from the vpd data read off the 5152e59129aSraghus * expansion ROM. 5162e59129aSraghus */ 5172e59129aSraghus phy_type = nxgep->vpd_info.phy_type; 5182e59129aSraghus 519d81011f0Ssbehera if (strncmp(phy_type, "mif", 3) == 0) { 5202e59129aSraghus nxgep->mac.portmode = PORT_1G_COPPER; 5212e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR; 522d81011f0Ssbehera } else if (strncmp(phy_type, "xgf", 3) == 0) { 5232e59129aSraghus nxgep->mac.portmode = PORT_10G_FIBER; 5242e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 525d81011f0Ssbehera } else if (strncmp(phy_type, "pcs", 3) == 0) { 5262e59129aSraghus nxgep->mac.portmode = PORT_1G_FIBER; 5272e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 528d81011f0Ssbehera } else if (strncmp(phy_type, "xgc", 3) == 0) { 52900161856Syc status = nxge_set_tn1010_param(nxgep); 53000161856Syc if (status != NXGE_OK) { 53100161856Syc NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 53200161856Syc "nxge_get_xcvr_type: Failed to set TN1010 param")); 53300161856Syc goto read_seeprom; 53400161856Syc } 535d81011f0Ssbehera } else if (strncmp(phy_type, "xgsd", 4) == 0) { 536d81011f0Ssbehera nxgep->mac.portmode = PORT_10G_SERDES; 537d81011f0Ssbehera nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 538d81011f0Ssbehera } else if (strncmp(phy_type, "gsd", 3) == 0) { 539d81011f0Ssbehera nxgep->mac.portmode = PORT_1G_SERDES; 540d81011f0Ssbehera nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 5412e59129aSraghus } else { 542d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5432e59129aSraghus "nxge_get_xcvr_type: Unknown phy type [%c%c%c] in EEPROM", 5442e59129aSraghus phy_type[0], phy_type[1], phy_type[2])); 5452e59129aSraghus goto read_seeprom; 5462e59129aSraghus } 5472e59129aSraghus 5482e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: " 5492e59129aSraghus "Got phy type [0x%x] from VPD", nxgep->mac.portmode)); 5502e59129aSraghus 5512e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_get_xcvr_type")); 5522e59129aSraghus return (status); 5532e59129aSraghus 5542e59129aSraghus read_seeprom: 5552e59129aSraghus /* 5562e59129aSraghus * read the phy type from the SEEPROM - NCR registers 5572e59129aSraghus */ 5582e59129aSraghus status = nxge_espc_phy_type_get(nxgep); 5592e59129aSraghus if (status != NXGE_OK) { 5602e59129aSraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5612e59129aSraghus "Failed to get phy type")); 5622e59129aSraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "EEPROM version " 5632e59129aSraghus "[%s] invalid...please update", nxgep->vpd_info.ver)); 5642e59129aSraghus } 5652e59129aSraghus 5662e59129aSraghus return (status); 5672e59129aSraghus 5682e59129aSraghus } 5692e59129aSraghus 57059ac0c16Sdavemq /* Set up the PHY specific values. */ 57159ac0c16Sdavemq 57259ac0c16Sdavemq nxge_status_t 57359ac0c16Sdavemq nxge_setup_xcvr_table(p_nxge_t nxgep) 57459ac0c16Sdavemq { 57559ac0c16Sdavemq nxge_status_t status = NXGE_OK; 57659ac0c16Sdavemq uint32_t port_type; 57759ac0c16Sdavemq uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 5782e59129aSraghus uint32_t pcs_id = 0; 5792e59129aSraghus uint32_t pma_pmd_id = 0; 5802e59129aSraghus uint32_t phy_id = 0; 5812d17280bSsbehera uint16_t chip_id = 0; 58259ac0c16Sdavemq 58359ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_setup_xcvr_table: port<%d>", 58459ac0c16Sdavemq portn)); 58559ac0c16Sdavemq 5862e59129aSraghus switch (nxgep->niu_type) { 5872e59129aSraghus case N2_NIU: 5882e59129aSraghus switch (nxgep->mac.portmode) { 5892e59129aSraghus case PORT_1G_FIBER: 5902e59129aSraghus case PORT_1G_SERDES: 5912e59129aSraghus nxgep->xcvr = nxge_n2_1G_table; 5922d17280bSsbehera nxgep->xcvr_addr = portn; 5932e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 1G %s Xcvr", 5942e59129aSraghus (nxgep->mac.portmode == PORT_1G_FIBER) ? "Fiber" : 5952e59129aSraghus "Serdes")); 5962e59129aSraghus break; 5972e59129aSraghus case PORT_10G_FIBER: 5982e59129aSraghus case PORT_10G_SERDES: 5992e59129aSraghus nxgep->xcvr = nxge_n2_10G_table; 6002d17280bSsbehera if (nxgep->nxge_hw_p->xcvr_addr[portn]) { 6012d17280bSsbehera nxgep->xcvr_addr = 6022d17280bSsbehera nxgep->nxge_hw_p->xcvr_addr[portn]; 6032d17280bSsbehera } 6042e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 10G %s Xcvr", 6052e59129aSraghus (nxgep->mac.portmode == PORT_10G_FIBER) ? "Fiber" : 6062e59129aSraghus "Serdes")); 6072e59129aSraghus break; 60800161856Syc case PORT_1G_TN1010: 60900161856Syc nxgep->xcvr = nxge_n2_1G_tn1010_table; 61000161856Syc nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 61100161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 61200161856Syc "TN1010 Copper Xcvr in 1G")); 61300161856Syc break; 61400161856Syc case PORT_10G_TN1010: 61500161856Syc nxgep->xcvr = nxge_n2_10G_tn1010_table; 61600161856Syc nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 61700161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 61800161856Syc "TN1010 Copper Xcvr in 10G")); 61900161856Syc break; 6202d17280bSsbehera case PORT_HSP_MODE: 6212d17280bSsbehera nxgep->xcvr = nxge_n2_10G_table; 6222d17280bSsbehera nxgep->xcvr.xcvr_inuse = HSP_XCVR; 6232d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 10G Hot " 6242d17280bSsbehera "Swappable Xcvr (not present)")); 6252d17280bSsbehera break; 6262e59129aSraghus default: 6272e59129aSraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6282e59129aSraghus "<== nxge_setup_xcvr_table: " 6292e59129aSraghus "Unable to determine NIU portmode")); 6302e59129aSraghus return (NXGE_ERROR); 6312e59129aSraghus } 6322e59129aSraghus break; 6332e59129aSraghus default: 6342e59129aSraghus if (nxgep->mac.portmode == 0) { 6352e59129aSraghus /* 6362e59129aSraghus * Would be the case for platforms like Maramba 6372e59129aSraghus * in which the phy type could not be got from conf 6382e59129aSraghus * file, OBP, VPD or Serial PROM. 6392e59129aSraghus */ 6402e59129aSraghus if (!NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) { 6412e59129aSraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6422e59129aSraghus "<== nxge_setup_xcvr_table:" 6432e59129aSraghus " Invalid Neptune type [0x%x]", 6442e59129aSraghus nxgep->niu_type)); 6452e59129aSraghus return (NXGE_ERROR); 6462e59129aSraghus } 6472e59129aSraghus 6482e59129aSraghus port_type = nxgep->niu_type >> 6492e59129aSraghus (NXGE_PORT_TYPE_SHIFT * portn); 6502e59129aSraghus port_type = port_type & (NXGE_PORT_TYPE_MASK); 6512e59129aSraghus 6522e59129aSraghus switch (port_type) { 6532e59129aSraghus 6542e59129aSraghus case NXGE_PORT_1G_COPPER: 6552e59129aSraghus nxgep->mac.portmode = PORT_1G_COPPER; 6562e59129aSraghus break; 6572e59129aSraghus case NXGE_PORT_10G_COPPER: 6582e59129aSraghus nxgep->mac.portmode = PORT_10G_COPPER; 6592e59129aSraghus break; 6602e59129aSraghus case NXGE_PORT_1G_FIBRE: 6612e59129aSraghus nxgep->mac.portmode = PORT_1G_FIBER; 6622e59129aSraghus break; 6632e59129aSraghus case NXGE_PORT_10G_FIBRE: 6642e59129aSraghus nxgep->mac.portmode = PORT_10G_FIBER; 6652e59129aSraghus break; 6662e59129aSraghus case NXGE_PORT_1G_SERDES: 6672e59129aSraghus nxgep->mac.portmode = PORT_1G_SERDES; 6682e59129aSraghus break; 6692e59129aSraghus case NXGE_PORT_10G_SERDES: 6702e59129aSraghus nxgep->mac.portmode = PORT_10G_SERDES; 6712e59129aSraghus break; 67200161856Syc /* Ports 2 and 3 of Alonso or ARTM */ 6732e59129aSraghus case NXGE_PORT_1G_RGMII_FIBER: 6742e59129aSraghus nxgep->mac.portmode = PORT_1G_RGMII_FIBER; 6752e59129aSraghus break; 67600161856Syc case NXGE_PORT_TN1010: 67700161856Syc /* 67800161856Syc * If this port uses the TN1010 copper 67900161856Syc * PHY, then its speed is not known yet 68000161856Syc * because nxge_scan_ports_phy could only 68100161856Syc * figure out the vendor of the PHY but 68200161856Syc * not its speed. nxge_set_tn1010_param 68300161856Syc * will read the PHY speed and set 68400161856Syc * portmode accordingly. 68500161856Syc */ 68600161856Syc if ((status = nxge_set_tn1010_param(nxgep)) 68700161856Syc != NXGE_OK) { 68800161856Syc NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 68900161856Syc "nxge_set_tn1010_param failed")); 69000161856Syc return (status); 69100161856Syc } 69200161856Syc break; 6932e59129aSraghus default: 6942e59129aSraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6952e59129aSraghus "<== nxge_setup_xcvr_table: " 6962e59129aSraghus "Unknown port-type: 0x%x", port_type)); 6972e59129aSraghus return (NXGE_ERROR); 6982e59129aSraghus } 6992e59129aSraghus } 7002e59129aSraghus 70100161856Syc /* 70200161856Syc * Above switch has figured out nxge->mac.portmode, now set 70300161856Syc * nxgep->xcvr (the table) and nxgep->xcvr_addr according 70400161856Syc * to portmode. 70500161856Syc */ 7062e59129aSraghus switch (nxgep->mac.portmode) { 7072e59129aSraghus case PORT_1G_COPPER: 7082e59129aSraghus case PORT_1G_RGMII_FIBER: 70959ac0c16Sdavemq nxgep->xcvr = nxge_1G_copper_table; 7102d17280bSsbehera nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 71159ac0c16Sdavemq /* 71259ac0c16Sdavemq * For Altas 4-1G copper, Xcvr port numbers are 71359ac0c16Sdavemq * swapped with ethernet port number. This is 7142e59129aSraghus * designed for better signal integrity in 7152e59129aSraghus * routing. This is also the case for the 7162e59129aSraghus * on-board Neptune copper ports on the Maramba 7172e59129aSraghus * platform. 71859ac0c16Sdavemq */ 7192e59129aSraghus switch (nxgep->platform_type) { 7202e59129aSraghus case P_NEPTUNE_ATLAS_4PORT: 7212e59129aSraghus case P_NEPTUNE_MARAMBA_P0: 7222e59129aSraghus case P_NEPTUNE_MARAMBA_P1: 7232e59129aSraghus switch (portn) { 7242e59129aSraghus case 0: 7252d17280bSsbehera nxgep->xcvr_addr += 3; 7262e59129aSraghus break; 7272e59129aSraghus case 1: 7282d17280bSsbehera nxgep->xcvr_addr += 1; 7292e59129aSraghus break; 7302e59129aSraghus case 2: 7312d17280bSsbehera nxgep->xcvr_addr -= 1; 7322e59129aSraghus break; 7332e59129aSraghus case 3: 7342d17280bSsbehera nxgep->xcvr_addr -= 3; 7352e59129aSraghus break; 7362e59129aSraghus default: 7372e59129aSraghus return (NXGE_ERROR); 7382e59129aSraghus } 73959ac0c16Sdavemq break; 74059ac0c16Sdavemq default: 7412e59129aSraghus break; 74259ac0c16Sdavemq } 743d81011f0Ssbehera 7442e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G %s Xcvr", 7452e59129aSraghus (nxgep->mac.portmode == PORT_1G_COPPER) ? 7462e59129aSraghus "Copper" : "RGMII Fiber")); 74759ac0c16Sdavemq break; 74800161856Syc 7492e59129aSraghus case PORT_10G_COPPER: 75059ac0c16Sdavemq nxgep->xcvr = nxge_10G_copper_table; 75159ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Copper Xcvr")); 75259ac0c16Sdavemq break; 75300161856Syc 75400161856Syc case PORT_1G_TN1010: 75500161856Syc nxgep->xcvr = nxge_1G_tn1010_table; 75600161856Syc nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 75700161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 75800161856Syc "1G TN1010 copper Xcvr")); 75900161856Syc break; 76000161856Syc 76100161856Syc case PORT_10G_TN1010: 76200161856Syc nxgep->xcvr = nxge_10G_tn1010_table; 76300161856Syc nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 76400161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 76500161856Syc "10G TN1010 copper Xcvr")); 76600161856Syc break; 76700161856Syc 7682e59129aSraghus case PORT_1G_FIBER: 7692e59129aSraghus case PORT_1G_SERDES: 77059ac0c16Sdavemq nxgep->xcvr = nxge_1G_fiber_table; 7712d17280bSsbehera nxgep->xcvr_addr = portn; 7722e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G %s Xcvr", 7732e59129aSraghus (nxgep->mac.portmode == PORT_1G_FIBER) ? 7742e59129aSraghus "Fiber" : "Serdes")); 77559ac0c16Sdavemq break; 7762e59129aSraghus case PORT_10G_FIBER: 7772e59129aSraghus case PORT_10G_SERDES: 77859ac0c16Sdavemq nxgep->xcvr = nxge_10G_fiber_table; 7792d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G xcvr " 7802d17280bSsbehera "nxgep->nxge_hw_p->xcvr_addr[portn] = [%d] " 7812d17280bSsbehera "nxgep->xcvr_addr = [%d]", 7822d17280bSsbehera nxgep->nxge_hw_p->xcvr_addr[portn], 7832d17280bSsbehera nxgep->xcvr_addr)); 7842d17280bSsbehera if (nxgep->nxge_hw_p->xcvr_addr[portn]) { 7852d17280bSsbehera nxgep->xcvr_addr = 7862d17280bSsbehera nxgep->nxge_hw_p->xcvr_addr[portn]; 7872d17280bSsbehera } 7882e59129aSraghus switch (nxgep->platform_type) { 7892e59129aSraghus case P_NEPTUNE_MARAMBA_P0: 7902e59129aSraghus case P_NEPTUNE_MARAMBA_P1: 79159ac0c16Sdavemq /* 79259ac0c16Sdavemq * Switch off LED for corresponding copper 79359ac0c16Sdavemq * port 79459ac0c16Sdavemq */ 79559ac0c16Sdavemq nxge_bcm5464_link_led_off(nxgep); 7962e59129aSraghus break; 7972e59129aSraghus default: 7982e59129aSraghus break; 79959ac0c16Sdavemq } 8002e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G %s Xcvr", 8012e59129aSraghus (nxgep->mac.portmode == PORT_10G_FIBER) ? 8022e59129aSraghus "Fiber" : "Serdes")); 80359ac0c16Sdavemq break; 8042d17280bSsbehera 8052d17280bSsbehera case PORT_HSP_MODE: 8062d17280bSsbehera nxgep->xcvr = nxge_10G_fiber_table; 8072d17280bSsbehera nxgep->xcvr.xcvr_inuse = HSP_XCVR; 8082d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Neptune 10G Hot " 8092d17280bSsbehera "Swappable Xcvr (not present)")); 8102d17280bSsbehera break; 81159ac0c16Sdavemq default: 81259ac0c16Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 81359ac0c16Sdavemq "Unknown port-type: 0x%x", port_type)); 81459ac0c16Sdavemq return (NXGE_ERROR); 81559ac0c16Sdavemq } 81659ac0c16Sdavemq } 81759ac0c16Sdavemq 8182d17280bSsbehera if (nxgep->mac.portmode == PORT_10G_FIBER) { 81952cdd236Ssbehera uint32_t pma_pmd_id; 82052cdd236Ssbehera pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, 82152cdd236Ssbehera nxgep->xcvr_addr); 82252cdd236Ssbehera if ((pma_pmd_id & BCM_PHY_ID_MASK) == MARVELL_88X201X_PHY_ID) { 82352cdd236Ssbehera chip_id = MRVL88X201X_CHIP_ID; 82452cdd236Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 82552cdd236Ssbehera "nxge_setup_xcvr_table: " 82652cdd236Ssbehera "Chip ID MARVELL [0x%x] for 10G xcvr", chip_id)); 82752cdd236Ssbehera } else if ((status = nxge_mdio_read(nxgep, nxgep->xcvr_addr, 8282d17280bSsbehera BCM8704_PCS_DEV_ADDR, BCM8704_CHIP_ID_REG, 8292d17280bSsbehera &chip_id)) == NXGE_OK) { 8302d17280bSsbehera 8312d17280bSsbehera switch (chip_id) { 8322d17280bSsbehera case BCM8704_CHIP_ID: 8332d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8342d17280bSsbehera "nxge_setup_xcvr_table: " 8352d17280bSsbehera "Chip ID 8704 [0x%x] for 10G xcvr", 8362d17280bSsbehera chip_id)); 8372d17280bSsbehera break; 8382d17280bSsbehera case BCM8706_CHIP_ID: 8392d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8402d17280bSsbehera "nxge_setup_xcvr_table: " 8412d17280bSsbehera "Chip ID 8706 [0x%x] for 10G xcvr", 8422d17280bSsbehera chip_id)); 8432d17280bSsbehera break; 8442d17280bSsbehera default: 8452d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 8462d17280bSsbehera "nxge_setup_xcvr_table: " 8472d17280bSsbehera "Unknown Chip ID [0x%x] for 10G xcvr", 8482d17280bSsbehera chip_id)); 8492d17280bSsbehera break; 8502d17280bSsbehera } 8512d17280bSsbehera } 8522d17280bSsbehera } 8532d17280bSsbehera 85459ac0c16Sdavemq nxgep->statsp->mac_stats.xcvr_inuse = nxgep->xcvr.xcvr_inuse; 8552d17280bSsbehera nxgep->statsp->mac_stats.xcvr_portn = nxgep->xcvr_addr; 8562d17280bSsbehera nxgep->chip_id = chip_id; 8572e59129aSraghus 8582e59129aSraghus /* 8592e59129aSraghus * Get the actual device ID value returned by MDIO read. 8602e59129aSraghus */ 8612e59129aSraghus nxgep->statsp->mac_stats.xcvr_id = 0; 8622e59129aSraghus 8632d17280bSsbehera pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, nxgep->xcvr_addr); 8642e59129aSraghus if (nxge_is_supported_phy(pma_pmd_id, CLAUSE_45_TYPE)) { 8652e59129aSraghus nxgep->statsp->mac_stats.xcvr_id = pma_pmd_id; 8662e59129aSraghus } else { 8672d17280bSsbehera pcs_id = nxge_get_cl45_pcs_id(nxgep, nxgep->xcvr_addr); 8682e59129aSraghus if (nxge_is_supported_phy(pcs_id, CLAUSE_45_TYPE)) { 8692e59129aSraghus nxgep->statsp->mac_stats.xcvr_id = pcs_id; 8702e59129aSraghus } else { 8712e59129aSraghus phy_id = nxge_get_cl22_phy_id(nxgep, 8722d17280bSsbehera nxgep->xcvr_addr); 8732e59129aSraghus if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) { 8742e59129aSraghus nxgep->statsp->mac_stats.xcvr_id = phy_id; 8752e59129aSraghus } 8762e59129aSraghus } 8772e59129aSraghus } 8782e59129aSraghus 87959ac0c16Sdavemq nxgep->mac.linkchkmode = LINKCHK_TIMER; 88059ac0c16Sdavemq 8812e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_setup_xcvr_table: niu_type" 88223b952a3SSantwona Behera "[0x%x] platform type[0x%x] xcvr_addr[%d]", nxgep->niu_type, 8832d17280bSsbehera nxgep->platform_type, nxgep->xcvr_addr)); 8842e59129aSraghus 88559ac0c16Sdavemq return (status); 88659ac0c16Sdavemq } 88759ac0c16Sdavemq 88844961713Sgirish /* Initialize the entire MAC and physical layer */ 88944961713Sgirish 89044961713Sgirish nxge_status_t 89144961713Sgirish nxge_mac_init(p_nxge_t nxgep) 89244961713Sgirish { 89344961713Sgirish uint8_t portn; 89444961713Sgirish nxge_status_t status = NXGE_OK; 89544961713Sgirish portn = NXGE_GET_PORT_NUM(nxgep->function_num); 89644961713Sgirish 89744961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_init: port<%d>", portn)); 89844961713Sgirish 89944961713Sgirish nxgep->mac.portnum = portn; 90044961713Sgirish nxgep->mac.porttype = PORT_TYPE_XMAC; 90144961713Sgirish 90244961713Sgirish if ((portn == BMAC_PORT_0) || (portn == BMAC_PORT_1)) 90344961713Sgirish nxgep->mac.porttype = PORT_TYPE_BMAC; 90444961713Sgirish 90500161856Syc 90644961713Sgirish /* Initialize XIF to configure a network mode */ 90744961713Sgirish if ((status = nxge_xif_init(nxgep)) != NXGE_OK) { 90844961713Sgirish goto fail; 90944961713Sgirish } 91044961713Sgirish 91144961713Sgirish if ((status = nxge_pcs_init(nxgep)) != NXGE_OK) { 91244961713Sgirish goto fail; 91344961713Sgirish } 91444961713Sgirish 91544961713Sgirish /* Initialize TX and RX MACs */ 91644961713Sgirish /* 91744961713Sgirish * Always perform XIF init first, before TX and RX MAC init 91844961713Sgirish */ 91944961713Sgirish if ((status = nxge_tx_mac_reset(nxgep)) != NXGE_OK) 92044961713Sgirish goto fail; 92144961713Sgirish 92244961713Sgirish if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK) 92344961713Sgirish goto fail; 92444961713Sgirish 92544961713Sgirish if ((status = nxge_rx_mac_reset(nxgep)) != NXGE_OK) 92644961713Sgirish goto fail; 92744961713Sgirish 92844961713Sgirish if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK) 92944961713Sgirish goto fail; 93044961713Sgirish 93144961713Sgirish if ((status = nxge_tx_mac_enable(nxgep)) != NXGE_OK) 93244961713Sgirish goto fail; 93344961713Sgirish 934e759c33aSMichael Speer if (nxgep->nxge_mac_state == NXGE_MAC_STARTED) { 935e759c33aSMichael Speer if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 936e759c33aSMichael Speer goto fail; 937e759c33aSMichael Speer } 93844961713Sgirish 939cb9d3ae6Smisaki /* Initialize MAC control configuration */ 940cb9d3ae6Smisaki if ((status = nxge_mac_ctrl_init(nxgep)) != NXGE_OK) { 941cb9d3ae6Smisaki goto fail; 942cb9d3ae6Smisaki } 943cb9d3ae6Smisaki 94444961713Sgirish nxgep->statsp->mac_stats.mac_mtu = nxgep->mac.maxframesize; 94544961713Sgirish 946d81011f0Ssbehera /* The Neptune Serdes needs to be reinitialized again */ 947d81011f0Ssbehera if ((NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) && 948d81011f0Ssbehera ((nxgep->mac.portmode == PORT_1G_SERDES) || 94900161856Syc (nxgep->mac.portmode == PORT_1G_TN1010) || 950d81011f0Ssbehera (nxgep->mac.portmode == PORT_1G_FIBER)) && 951d81011f0Ssbehera ((portn == 0) || (portn == 1))) { 952d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 953d81011f0Ssbehera "nxge_mac_init: reinit Neptune 1G Serdes ")); 954d81011f0Ssbehera if ((status = nxge_1G_serdes_init(nxgep)) != NXGE_OK) { 955d81011f0Ssbehera goto fail; 956d81011f0Ssbehera } 957d81011f0Ssbehera } 958d81011f0Ssbehera 9592e59129aSraghus 96044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_init: port<%d>", portn)); 96144961713Sgirish 96244961713Sgirish return (NXGE_OK); 96344961713Sgirish fail: 96444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 96552ccf843Smisaki "nxge_mac_init: failed to initialize MAC port<%d>", portn)); 96644961713Sgirish return (status); 96744961713Sgirish } 96844961713Sgirish 96944961713Sgirish /* Initialize the Ethernet Link */ 97044961713Sgirish 97144961713Sgirish nxge_status_t 97244961713Sgirish nxge_link_init(p_nxge_t nxgep) 97344961713Sgirish { 97444961713Sgirish nxge_status_t status = NXGE_OK; 9752e59129aSraghus nxge_port_mode_t portmode; 97644961713Sgirish #ifdef NXGE_DEBUG 97744961713Sgirish uint8_t portn; 97844961713Sgirish 97944961713Sgirish portn = nxgep->mac.portnum; 98044961713Sgirish 98144961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_init: port<%d>", portn)); 98244961713Sgirish #endif 9831c7408c9Stc /* For Opus NEM, Serdes always needs to be initialized */ 98444961713Sgirish 9852e59129aSraghus portmode = nxgep->mac.portmode; 9862d17280bSsbehera 98700161856Syc /* 98800161856Syc * Workaround to get link up in both NIU ports. Some portmodes require 98900161856Syc * that the xcvr be initialized twice, the first time before calling 99000161856Syc * nxge_serdes_init. 99100161856Syc */ 9922e59129aSraghus if (nxgep->niu_type == N2_NIU && (portmode != PORT_10G_SERDES) && 99300161856Syc (portmode != PORT_10G_TN1010) && 99400161856Syc (portmode != PORT_1G_TN1010) && 9952e59129aSraghus (portmode != PORT_1G_SERDES)) { 9962e59129aSraghus if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK) { 99744961713Sgirish goto fail; 9982e59129aSraghus } 99944961713Sgirish } 100000161856Syc 100144961713Sgirish NXGE_DELAY(200000); 100244961713Sgirish /* Initialize internal serdes */ 100344961713Sgirish if ((status = nxge_serdes_init(nxgep)) != NXGE_OK) 100444961713Sgirish goto fail; 100544961713Sgirish NXGE_DELAY(200000); 100644961713Sgirish if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK) 100744961713Sgirish goto fail; 100844961713Sgirish 100944961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_init: port<%d>", portn)); 101044961713Sgirish 101144961713Sgirish return (NXGE_OK); 101244961713Sgirish 101344961713Sgirish fail: 101452ccf843Smisaki NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_link_init: ", 101552ccf843Smisaki "failed to initialize Ethernet link on port<%d>", portn)); 101644961713Sgirish 101744961713Sgirish return (status); 101844961713Sgirish } 101944961713Sgirish 102044961713Sgirish 102144961713Sgirish /* Initialize the XIF sub-block within the MAC */ 102244961713Sgirish 102344961713Sgirish nxge_status_t 102444961713Sgirish nxge_xif_init(p_nxge_t nxgep) 102544961713Sgirish { 102644961713Sgirish uint32_t xif_cfg = 0; 102744961713Sgirish npi_attr_t ap; 102844961713Sgirish uint8_t portn; 102944961713Sgirish nxge_port_t portt; 103044961713Sgirish nxge_port_mode_t portmode; 103144961713Sgirish p_nxge_stats_t statsp; 103244961713Sgirish npi_status_t rs = NPI_SUCCESS; 103344961713Sgirish npi_handle_t handle; 103444961713Sgirish 103544961713Sgirish portn = NXGE_GET_PORT_NUM(nxgep->function_num); 103644961713Sgirish 103744961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xif_init: port<%d>", portn)); 103844961713Sgirish 103944961713Sgirish handle = nxgep->npi_handle; 104044961713Sgirish portmode = nxgep->mac.portmode; 104144961713Sgirish portt = nxgep->mac.porttype; 104244961713Sgirish statsp = nxgep->statsp; 104344961713Sgirish 1044d81011f0Ssbehera if ((NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) && 1045d81011f0Ssbehera ((nxgep->mac.portmode == PORT_1G_SERDES) || 104600161856Syc (nxgep->mac.portmode == PORT_1G_TN1010) || 1047d81011f0Ssbehera (nxgep->mac.portmode == PORT_1G_FIBER)) && 1048d81011f0Ssbehera ((portn == 0) || (portn == 1))) { 1049d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1050d81011f0Ssbehera "nxge_xcvr_init: set ATCA mode")); 1051d81011f0Ssbehera npi_mac_mif_set_atca_mode(nxgep->npi_handle, B_TRUE); 1052d81011f0Ssbehera } 1053d81011f0Ssbehera 105444961713Sgirish if (portt == PORT_TYPE_XMAC) { 105544961713Sgirish 105644961713Sgirish /* Setup XIF Configuration for XMAC */ 105744961713Sgirish 105844961713Sgirish if ((portmode == PORT_10G_FIBER) || 10592e59129aSraghus (portmode == PORT_10G_COPPER) || 106000161856Syc (portmode == PORT_10G_TN1010) || 10611c7408c9Stc (portmode == PORT_HSP_MODE) || 10622e59129aSraghus (portmode == PORT_10G_SERDES)) 106344961713Sgirish xif_cfg |= CFG_XMAC_XIF_LFS; 106444961713Sgirish 106500161856Syc /* Bypass PCS so that RGMII will be used */ 106644961713Sgirish if (portmode == PORT_1G_COPPER) { 106744961713Sgirish xif_cfg |= CFG_XMAC_XIF_1G_PCS_BYPASS; 106844961713Sgirish } 106944961713Sgirish 107044961713Sgirish /* Set MAC Internal Loopback if necessary */ 107144961713Sgirish if (statsp->port_stats.lb_mode == nxge_lb_mac1000) 107244961713Sgirish xif_cfg |= CFG_XMAC_XIF_LOOPBACK; 107344961713Sgirish 107444961713Sgirish if (statsp->mac_stats.link_speed == 100) 107544961713Sgirish xif_cfg |= CFG_XMAC_XIF_SEL_CLK_25MHZ; 107644961713Sgirish 107744961713Sgirish xif_cfg |= CFG_XMAC_XIF_TX_OUTPUT; 107844961713Sgirish 10792e59129aSraghus if ((portmode == PORT_10G_FIBER) || 108000161856Syc (portmode == PORT_10G_TN1010) || 108100161856Syc (portmode == PORT_1G_TN1010) || 10821c7408c9Stc (portmode == PORT_HSP_MODE) || 10832e59129aSraghus (portmode == PORT_10G_SERDES)) { 108400161856Syc /* Assume LED same for 1G and 10G */ 108544961713Sgirish if (statsp->mac_stats.link_up) { 108644961713Sgirish xif_cfg |= CFG_XMAC_XIF_LED_POLARITY; 108744961713Sgirish } else { 108844961713Sgirish xif_cfg |= CFG_XMAC_XIF_LED_FORCE; 108944961713Sgirish } 109044961713Sgirish } 109144961713Sgirish 109244961713Sgirish rs = npi_xmac_xif_config(handle, INIT, portn, xif_cfg); 109344961713Sgirish if (rs != NPI_SUCCESS) 109444961713Sgirish goto fail; 109544961713Sgirish 109644961713Sgirish nxgep->mac.xif_config = xif_cfg; 109744961713Sgirish 109844961713Sgirish /* Set Port Mode */ 109944961713Sgirish if ((portmode == PORT_10G_FIBER) || 11002e59129aSraghus (portmode == PORT_10G_COPPER) || 110100161856Syc (portmode == PORT_10G_TN1010) || 11021c7408c9Stc (portmode == PORT_HSP_MODE) || 11032e59129aSraghus (portmode == PORT_10G_SERDES)) { 110444961713Sgirish SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE, 110552ccf843Smisaki MAC_XGMII_MODE, rs); 110644961713Sgirish if (rs != NPI_SUCCESS) 110744961713Sgirish goto fail; 110844961713Sgirish if (statsp->mac_stats.link_up) { 110944961713Sgirish if (nxge_10g_link_led_on(nxgep) != NXGE_OK) 111044961713Sgirish goto fail; 111144961713Sgirish } else { 111244961713Sgirish if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 111344961713Sgirish goto fail; 111444961713Sgirish } 111544961713Sgirish } else if ((portmode == PORT_1G_FIBER) || 11162e59129aSraghus (portmode == PORT_1G_COPPER) || 1117d81011f0Ssbehera (portmode == PORT_1G_SERDES) || 111800161856Syc (portmode == PORT_1G_TN1010) || 1119d81011f0Ssbehera (portmode == PORT_1G_RGMII_FIBER)) { 1120d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1121d81011f0Ssbehera "nxge_xif_init: Port[%d] Mode[%d] Speed[%d]", 1122d81011f0Ssbehera portn, portmode, statsp->mac_stats.link_speed)); 112344961713Sgirish if (statsp->mac_stats.link_speed == 1000) { 112444961713Sgirish SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE, 112552ccf843Smisaki MAC_GMII_MODE, rs); 112644961713Sgirish } else { 112744961713Sgirish SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE, 112852ccf843Smisaki MAC_MII_MODE, rs); 112944961713Sgirish } 113044961713Sgirish if (rs != NPI_SUCCESS) 113144961713Sgirish goto fail; 113244961713Sgirish } else { 113344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 113452ccf843Smisaki "nxge_xif_init: Unknown port mode (%d)" 113552ccf843Smisaki " for port<%d>", portmode, portn)); 113644961713Sgirish goto fail; 113744961713Sgirish } 113844961713Sgirish 1139d81011f0Ssbehera /* Enable ATCA mode */ 1140d81011f0Ssbehera 114144961713Sgirish } else if (portt == PORT_TYPE_BMAC) { 114244961713Sgirish 114344961713Sgirish /* Setup XIF Configuration for BMAC */ 114444961713Sgirish 1145d81011f0Ssbehera if ((portmode == PORT_1G_COPPER) || 1146d81011f0Ssbehera (portmode == PORT_1G_RGMII_FIBER)) { 114744961713Sgirish if (statsp->mac_stats.link_speed == 100) 114844961713Sgirish xif_cfg |= CFG_BMAC_XIF_SEL_CLK_25MHZ; 114944961713Sgirish } 115044961713Sgirish 115144961713Sgirish if (statsp->port_stats.lb_mode == nxge_lb_mac1000) 115244961713Sgirish xif_cfg |= CFG_BMAC_XIF_LOOPBACK; 115344961713Sgirish 115444961713Sgirish if (statsp->mac_stats.link_speed == 1000) 115544961713Sgirish xif_cfg |= CFG_BMAC_XIF_GMII_MODE; 115644961713Sgirish 115744961713Sgirish xif_cfg |= CFG_BMAC_XIF_TX_OUTPUT; 115844961713Sgirish 115944961713Sgirish rs = npi_bmac_xif_config(handle, INIT, portn, xif_cfg); 116044961713Sgirish if (rs != NPI_SUCCESS) 116144961713Sgirish goto fail; 116244961713Sgirish nxgep->mac.xif_config = xif_cfg; 116344961713Sgirish } 116444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xif_init: port<%d>", portn)); 116544961713Sgirish return (NXGE_OK); 116644961713Sgirish fail: 116744961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 116852ccf843Smisaki "nxge_xif_init: Failed to initialize XIF port<%d>", portn)); 116944961713Sgirish return (NXGE_ERROR | rs); 117044961713Sgirish } 117144961713Sgirish 117244961713Sgirish 117300161856Syc /* 117400161856Syc * Initialize the PCS sub-block in the MAC. Note that PCS does not 117500161856Syc * support loopback like XPCS. 117600161856Syc */ 117744961713Sgirish nxge_status_t 117844961713Sgirish nxge_pcs_init(p_nxge_t nxgep) 117944961713Sgirish { 118044961713Sgirish pcs_cfg_t pcs_cfg; 118144961713Sgirish uint32_t val; 118244961713Sgirish uint8_t portn; 118344961713Sgirish nxge_port_mode_t portmode; 118444961713Sgirish npi_handle_t handle; 118544961713Sgirish p_nxge_stats_t statsp; 118600161856Syc pcs_ctrl_t pcs_ctrl; 118744961713Sgirish npi_status_t rs = NPI_SUCCESS; 118800161856Syc uint8_t i; 118944961713Sgirish 119044961713Sgirish handle = nxgep->npi_handle; 119144961713Sgirish portmode = nxgep->mac.portmode; 119244961713Sgirish portn = nxgep->mac.portnum; 119344961713Sgirish statsp = nxgep->statsp; 119444961713Sgirish 119544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_init: port<%d>", portn)); 119644961713Sgirish 119700161856Syc if (portmode == PORT_1G_FIBER || 119800161856Syc portmode == PORT_1G_TN1010 || 119900161856Syc portmode == PORT_1G_SERDES) { 120000161856Syc if (portmode == PORT_1G_TN1010) { 120100161856Syc /* Reset PCS multiple time in PORT_1G_TN1010 mode */ 120200161856Syc for (i = 0; i < 6; i ++) { 120300161856Syc if ((rs = npi_mac_pcs_reset(handle, portn)) 120400161856Syc != NPI_SUCCESS) { 120500161856Syc goto fail; 120600161856Syc } 120700161856Syc } 120800161856Syc } else { 120900161856Syc if ((rs = npi_mac_pcs_reset(handle, portn)) 121000161856Syc != NPI_SUCCESS) 121100161856Syc goto fail; 12122e59129aSraghus } 12132e59129aSraghus 121444961713Sgirish /* Initialize port's PCS */ 121544961713Sgirish pcs_cfg.value = 0; 121644961713Sgirish pcs_cfg.bits.w0.enable = 1; 121744961713Sgirish pcs_cfg.bits.w0.mask = 1; 121844961713Sgirish PCS_REG_WR(handle, portn, PCS_CONFIG_REG, pcs_cfg.value); 121944961713Sgirish PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG, 0); 122044961713Sgirish 12212e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 12222e59129aSraghus "==> nxge_pcs_init: (1G) port<%d> write config 0x%llx", 12232e59129aSraghus portn, pcs_cfg.value)); 122400161856Syc 122500161856Syc if (portmode == PORT_1G_TN1010) { 122600161856Syc /* 122700161856Syc * Must disable PCS auto-negotiation when the the driver 122800161856Syc * is driving the TN1010 based XAUI card Otherwise the 122900161856Syc * autonegotiation between the PCS and the TN1010 PCS 123000161856Syc * will never complete and the Neptune/NIU will not work 123100161856Syc */ 123200161856Syc pcs_ctrl.value = 0; 123300161856Syc PCS_REG_WR(handle, portn, PCS_MII_CTRL_REG, 123400161856Syc pcs_ctrl.value); 123500161856Syc } 123600161856Syc } else if (portmode == PORT_10G_FIBER || 123700161856Syc portmode == PORT_10G_COPPER || 123800161856Syc portmode == PORT_10G_TN1010 || 12391c7408c9Stc portmode == PORT_HSP_MODE || 124000161856Syc portmode == PORT_10G_SERDES) { 124144961713Sgirish /* Use internal XPCS, bypass 1G PCS */ 124244961713Sgirish XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val); 124344961713Sgirish val &= ~XMAC_XIF_XPCS_BYPASS; 124444961713Sgirish XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val); 124544961713Sgirish 124644961713Sgirish if ((rs = npi_xmac_xpcs_reset(handle, portn)) != NPI_SUCCESS) 124744961713Sgirish goto fail; 124844961713Sgirish 124944961713Sgirish /* Set XPCS Internal Loopback if necessary */ 125044961713Sgirish if ((rs = npi_xmac_xpcs_read(handle, portn, 125152ccf843Smisaki XPCS_REG_CONTROL1, &val)) != NPI_SUCCESS) 125244961713Sgirish goto fail; 125300161856Syc 125444961713Sgirish if ((statsp->port_stats.lb_mode == nxge_lb_mac10g) || 125552ccf843Smisaki (statsp->port_stats.lb_mode == nxge_lb_mac1000)) 125644961713Sgirish val |= XPCS_CTRL1_LOOPBK; 125744961713Sgirish else 125844961713Sgirish val &= ~XPCS_CTRL1_LOOPBK; 125944961713Sgirish if ((rs = npi_xmac_xpcs_write(handle, portn, 126052ccf843Smisaki XPCS_REG_CONTROL1, val)) != NPI_SUCCESS) 126144961713Sgirish goto fail; 126244961713Sgirish 126344961713Sgirish /* Clear descw errors */ 126444961713Sgirish if ((rs = npi_xmac_xpcs_write(handle, portn, 126552ccf843Smisaki XPCS_REG_DESCWERR_COUNTER, 0)) != NPI_SUCCESS) 126644961713Sgirish goto fail; 126744961713Sgirish /* Clear symbol errors */ 126844961713Sgirish if ((rs = npi_xmac_xpcs_read(handle, portn, 126952ccf843Smisaki XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val)) != NPI_SUCCESS) 127044961713Sgirish goto fail; 127144961713Sgirish if ((rs = npi_xmac_xpcs_read(handle, portn, 127252ccf843Smisaki XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val)) != NPI_SUCCESS) 127344961713Sgirish goto fail; 127444961713Sgirish 1275d81011f0Ssbehera } else if ((portmode == PORT_1G_COPPER) || 1276d81011f0Ssbehera (portmode == PORT_1G_RGMII_FIBER)) { 1277d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1278d81011f0Ssbehera "==> nxge_pcs_init: (1G) copper port<%d>", portn)); 127944961713Sgirish if (portn < 4) { 128044961713Sgirish PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG, 128152ccf843Smisaki PCS_DATAPATH_MODE_MII); 128244961713Sgirish } 128344961713Sgirish if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS) 128444961713Sgirish goto fail; 128544961713Sgirish 128644961713Sgirish } else { 128744961713Sgirish goto fail; 128844961713Sgirish } 128944961713Sgirish pass: 129044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_init: port<%d>", portn)); 129144961713Sgirish return (NXGE_OK); 129244961713Sgirish fail: 129344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 129452ccf843Smisaki "nxge_pcs_init: Failed to initialize PCS port<%d>", portn)); 129544961713Sgirish return (NXGE_ERROR | rs); 129644961713Sgirish } 129744961713Sgirish 1298cb9d3ae6Smisaki /* 1299cb9d3ae6Smisaki * Initialize the MAC CTRL sub-block within the MAC 1300cb9d3ae6Smisaki * Only the receive-pause-cap is supported. 1301cb9d3ae6Smisaki */ 1302cb9d3ae6Smisaki nxge_status_t 1303cb9d3ae6Smisaki nxge_mac_ctrl_init(p_nxge_t nxgep) 1304cb9d3ae6Smisaki { 1305cb9d3ae6Smisaki uint8_t portn; 1306cb9d3ae6Smisaki nxge_port_t portt; 1307cb9d3ae6Smisaki p_nxge_stats_t statsp; 1308cb9d3ae6Smisaki npi_handle_t handle; 1309cb9d3ae6Smisaki uint32_t val; 1310cb9d3ae6Smisaki 1311cb9d3ae6Smisaki portn = NXGE_GET_PORT_NUM(nxgep->function_num); 1312cb9d3ae6Smisaki 1313cb9d3ae6Smisaki NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_ctrl_init: port<%d>", 1314cb9d3ae6Smisaki portn)); 1315cb9d3ae6Smisaki 1316cb9d3ae6Smisaki handle = nxgep->npi_handle; 1317cb9d3ae6Smisaki portt = nxgep->mac.porttype; 1318cb9d3ae6Smisaki statsp = nxgep->statsp; 1319cb9d3ae6Smisaki 1320cb9d3ae6Smisaki if (portt == PORT_TYPE_XMAC) { 132100161856Syc /* Reading the current XMAC Config Register for XMAC */ 1322cb9d3ae6Smisaki XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val); 1323cb9d3ae6Smisaki 1324cb9d3ae6Smisaki /* 1325cb9d3ae6Smisaki * Setup XMAC Configuration for XMAC 1326cb9d3ae6Smisaki * XMAC only supports receive-pause 1327cb9d3ae6Smisaki */ 1328cb9d3ae6Smisaki if (statsp->mac_stats.adv_cap_asmpause) { 1329cb9d3ae6Smisaki if (!statsp->mac_stats.adv_cap_pause) { 1330cb9d3ae6Smisaki /* 1331cb9d3ae6Smisaki * If adv_cap_asmpause is 1 and adv_cap_pause 1332cb9d3ae6Smisaki * is 0, enable receive pause. 1333cb9d3ae6Smisaki */ 1334cb9d3ae6Smisaki val |= XMAC_RX_CFG_RX_PAUSE_EN; 1335cb9d3ae6Smisaki } else { 1336cb9d3ae6Smisaki /* 1337cb9d3ae6Smisaki * If adv_cap_asmpause is 1 and adv_cap_pause 1338cb9d3ae6Smisaki * is 1, disable receive pause. Send pause is 1339cb9d3ae6Smisaki * not supported. 1340cb9d3ae6Smisaki */ 1341cb9d3ae6Smisaki val &= ~XMAC_RX_CFG_RX_PAUSE_EN; 1342cb9d3ae6Smisaki } 1343cb9d3ae6Smisaki } else { 13441bd6825cSml NXGE_DEBUG_MSG((nxgep, MAC_CTL, 13451bd6825cSml "==> nxge_mac_ctrl_init: port<%d>: pause", 13461bd6825cSml portn)); 1347cb9d3ae6Smisaki if (statsp->mac_stats.adv_cap_pause) { 13481bd6825cSml NXGE_DEBUG_MSG((nxgep, MAC_CTL, 13491bd6825cSml "==> nxge_mac_ctrl_init: port<%d>: " 13501bd6825cSml "enable pause", portn)); 1351cb9d3ae6Smisaki /* 1352cb9d3ae6Smisaki * If adv_cap_asmpause is 0 and adv_cap_pause 1353cb9d3ae6Smisaki * is 1, enable receive pause. 1354cb9d3ae6Smisaki */ 1355cb9d3ae6Smisaki val |= XMAC_RX_CFG_RX_PAUSE_EN; 1356cb9d3ae6Smisaki } else { 1357cb9d3ae6Smisaki /* 1358cb9d3ae6Smisaki * If adv_cap_asmpause is 0 and adv_cap_pause 1359cb9d3ae6Smisaki * is 0, disable receive pause. Send pause is 1360cb9d3ae6Smisaki * not supported 1361cb9d3ae6Smisaki */ 13621bd6825cSml NXGE_DEBUG_MSG((nxgep, MAC_CTL, 13631bd6825cSml "==> nxge_mac_ctrl_init: port<%d>: " 13641bd6825cSml "disable pause", portn)); 1365cb9d3ae6Smisaki val &= ~XMAC_RX_CFG_RX_PAUSE_EN; 1366cb9d3ae6Smisaki } 1367cb9d3ae6Smisaki } 1368cb9d3ae6Smisaki XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val); 1369cb9d3ae6Smisaki } else if (portt == PORT_TYPE_BMAC) { 137000161856Syc /* Reading the current MAC CTRL Config Register for BMAC */ 1371cb9d3ae6Smisaki BMAC_REG_RD(handle, portn, MAC_CTRL_CONFIG_REG, &val); 1372cb9d3ae6Smisaki 1373cb9d3ae6Smisaki /* Setup MAC CTRL Configuration for BMAC */ 1374cb9d3ae6Smisaki if (statsp->mac_stats.adv_cap_asmpause) { 1375cb9d3ae6Smisaki if (statsp->mac_stats.adv_cap_pause) { 1376cb9d3ae6Smisaki /* 1377cb9d3ae6Smisaki * If adv_cap_asmpause is 1 and adv_cap_pause 1378cb9d3ae6Smisaki * is 1, disable receive pause. Send pause 1379cb9d3ae6Smisaki * is not supported 1380cb9d3ae6Smisaki */ 1381cb9d3ae6Smisaki val &= ~MAC_CTRL_CFG_RECV_PAUSE_EN; 1382cb9d3ae6Smisaki } else { 1383cb9d3ae6Smisaki /* 1384cb9d3ae6Smisaki * If adv_cap_asmpause is 1 and adv_cap_pause 1385cb9d3ae6Smisaki * is 0, enable receive pause and disable 1386cb9d3ae6Smisaki * send pause. 1387cb9d3ae6Smisaki */ 1388cb9d3ae6Smisaki val |= MAC_CTRL_CFG_RECV_PAUSE_EN; 1389cb9d3ae6Smisaki val &= ~MAC_CTRL_CFG_SEND_PAUSE_EN; 1390cb9d3ae6Smisaki } 1391cb9d3ae6Smisaki } else { 1392cb9d3ae6Smisaki if (statsp->mac_stats.adv_cap_pause) { 1393cb9d3ae6Smisaki /* 1394cb9d3ae6Smisaki * If adv_cap_asmpause is 0 and adv_cap_pause 1395cb9d3ae6Smisaki * is 1, enable receive pause. Send pause is 1396cb9d3ae6Smisaki * not supported. 1397cb9d3ae6Smisaki */ 1398cb9d3ae6Smisaki val |= MAC_CTRL_CFG_RECV_PAUSE_EN; 1399cb9d3ae6Smisaki } else { 1400cb9d3ae6Smisaki /* 1401cb9d3ae6Smisaki * If adv_cap_asmpause is 0 and adv_cap_pause 1402cb9d3ae6Smisaki * is 0, pause capability is not available in 1403cb9d3ae6Smisaki * either direction. 1404cb9d3ae6Smisaki */ 1405cb9d3ae6Smisaki val &= (~MAC_CTRL_CFG_SEND_PAUSE_EN & 140652ccf843Smisaki ~MAC_CTRL_CFG_RECV_PAUSE_EN); 1407cb9d3ae6Smisaki } 1408cb9d3ae6Smisaki } 1409cb9d3ae6Smisaki BMAC_REG_WR(handle, portn, MAC_CTRL_CONFIG_REG, val); 1410cb9d3ae6Smisaki } 1411cb9d3ae6Smisaki 1412cb9d3ae6Smisaki NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_ctrl_init: port<%d>", 1413cb9d3ae6Smisaki portn)); 1414cb9d3ae6Smisaki 1415cb9d3ae6Smisaki return (NXGE_OK); 1416cb9d3ae6Smisaki } 1417cb9d3ae6Smisaki 141844961713Sgirish /* Initialize the Internal Serdes */ 141944961713Sgirish 142044961713Sgirish nxge_status_t 142144961713Sgirish nxge_serdes_init(p_nxge_t nxgep) 142244961713Sgirish { 142344961713Sgirish p_nxge_stats_t statsp; 142444961713Sgirish #ifdef NXGE_DEBUG 142544961713Sgirish uint8_t portn; 142644961713Sgirish #endif 142744961713Sgirish nxge_status_t status = NXGE_OK; 142844961713Sgirish 142944961713Sgirish #ifdef NXGE_DEBUG 143044961713Sgirish portn = nxgep->mac.portnum; 143144961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 143259ac0c16Sdavemq "==> nxge_serdes_init port<%d>", portn)); 143344961713Sgirish #endif 143444961713Sgirish 143559ac0c16Sdavemq if (nxgep->xcvr.serdes_init) { 143659ac0c16Sdavemq statsp = nxgep->statsp; 143759ac0c16Sdavemq status = nxgep->xcvr.serdes_init(nxgep); 143859ac0c16Sdavemq if (status != NXGE_OK) 143944961713Sgirish goto fail; 144059ac0c16Sdavemq statsp->mac_stats.serdes_inits++; 144144961713Sgirish } 144244961713Sgirish 144344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_serdes_init port<%d>", 144459ac0c16Sdavemq portn)); 144544961713Sgirish 144644961713Sgirish return (NXGE_OK); 144744961713Sgirish 144844961713Sgirish fail: 144944961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 145059ac0c16Sdavemq "nxge_serdes_init: Failed to initialize serdes for port<%d>", 145159ac0c16Sdavemq portn)); 145244961713Sgirish 145344961713Sgirish return (status); 145444961713Sgirish } 145544961713Sgirish 145644961713Sgirish /* Initialize the TI Hedwig Internal Serdes (N2-NIU only) */ 145744961713Sgirish 145859ac0c16Sdavemq static nxge_status_t 145944961713Sgirish nxge_n2_serdes_init(p_nxge_t nxgep) 146044961713Sgirish { 146144961713Sgirish uint8_t portn; 146244961713Sgirish int chan; 146344961713Sgirish esr_ti_cfgpll_l_t pll_cfg_l; 14642e59129aSraghus esr_ti_cfgpll_l_t pll_sts_l; 146544961713Sgirish esr_ti_cfgrx_l_t rx_cfg_l; 146644961713Sgirish esr_ti_cfgrx_h_t rx_cfg_h; 146744961713Sgirish esr_ti_cfgtx_l_t tx_cfg_l; 146844961713Sgirish esr_ti_cfgtx_h_t tx_cfg_h; 14692e59129aSraghus #ifdef NXGE_DEBUG 14702e59129aSraghus esr_ti_testcfg_t cfg; 14712e59129aSraghus #endif 147244961713Sgirish esr_ti_testcfg_t test_cfg; 147344961713Sgirish nxge_status_t status = NXGE_OK; 147444961713Sgirish 147544961713Sgirish portn = nxgep->mac.portnum; 147644961713Sgirish 147744961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_n2_serdes_init port<%d>", 147852ccf843Smisaki portn)); 147944961713Sgirish 148044961713Sgirish tx_cfg_l.value = 0; 148144961713Sgirish tx_cfg_h.value = 0; 148244961713Sgirish rx_cfg_l.value = 0; 148344961713Sgirish rx_cfg_h.value = 0; 148444961713Sgirish pll_cfg_l.value = 0; 14852e59129aSraghus pll_sts_l.value = 0; 148644961713Sgirish test_cfg.value = 0; 148744961713Sgirish 148800161856Syc /* 148900161856Syc * If the nxge driver has been plumbed without a link, then it will 149000161856Syc * detect a link up when a cable connecting to an anto-negotiation 149100161856Syc * partner is plugged into the port. Because the TN1010 PHY supports 149200161856Syc * both 1G and 10G speeds, the driver must re-configure the 149300161856Syc * Neptune/NIU according to the negotiated speed. nxge_n2_serdes_init 149400161856Syc * is called at the post-link-up reconfiguration time. Here it calls 149500161856Syc * nxge_set_tn1010_param to set portmode before re-initializing 149600161856Syc * the serdes. 149700161856Syc */ 149800161856Syc if (nxgep->mac.portmode == PORT_1G_TN1010 || 149900161856Syc nxgep->mac.portmode == PORT_10G_TN1010) { 150000161856Syc if (nxge_set_tn1010_param(nxgep) != NXGE_OK) { 150100161856Syc goto fail; 150200161856Syc } 150300161856Syc } 150400161856Syc 150500161856Syc if (nxgep->mac.portmode == PORT_10G_FIBER || 150600161856Syc nxgep->mac.portmode == PORT_10G_TN1010 || 15071c7408c9Stc nxgep->mac.portmode == PORT_HSP_MODE || 150800161856Syc nxgep->mac.portmode == PORT_10G_SERDES) { 150944961713Sgirish /* 0x0E01 */ 151044961713Sgirish tx_cfg_l.bits.entx = 1; 151144961713Sgirish tx_cfg_l.bits.swing = CFGTX_SWING_1375MV; 151244961713Sgirish 151344961713Sgirish /* 0x9101 */ 151444961713Sgirish rx_cfg_l.bits.enrx = 1; 151544961713Sgirish rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT; 151644961713Sgirish rx_cfg_l.bits.align = CFGRX_ALIGN_EN; 151744961713Sgirish rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES; 151844961713Sgirish 151944961713Sgirish /* 0x0008 */ 152044961713Sgirish rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF; 152144961713Sgirish 152244961713Sgirish /* Set loopback mode if necessary */ 152344961713Sgirish if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) { 152444961713Sgirish tx_cfg_l.bits.entest = 1; 152544961713Sgirish rx_cfg_l.bits.entest = 1; 152644961713Sgirish test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK; 152744961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, 152852ccf843Smisaki ESR_N2_DEV_ADDR, 152952ccf843Smisaki ESR_N2_TEST_CFG_REG, test_cfg.value)) != NXGE_OK) 153044961713Sgirish goto fail; 153144961713Sgirish } 153244961713Sgirish 153300161856Syc /* Initialize PLL for 10G */ 153400161856Syc pll_cfg_l.bits.mpy = CFGPLL_MPY_10X; 153500161856Syc pll_cfg_l.bits.enpll = 1; 153600161856Syc pll_sts_l.bits.enpll = 1; 153700161856Syc if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 153800161856Syc ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value)) != NXGE_OK) 153900161856Syc goto fail; 154000161856Syc 154100161856Syc if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 154200161856Syc ESR_N2_PLL_STS_L_REG, pll_sts_l.value)) != NXGE_OK) 154300161856Syc goto fail; 154444961713Sgirish 154500161856Syc #ifdef NXGE_DEBUG 154600161856Syc nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR, 154700161856Syc ESR_N2_PLL_CFG_L_REG, &cfg.value); 154800161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 154900161856Syc "==> nxge_n2_serdes_init port<%d>: PLL cfg.l 0x%x (0x%x)", 155000161856Syc portn, pll_cfg_l.value, cfg.value)); 155144961713Sgirish 155200161856Syc nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR, 155300161856Syc ESR_N2_PLL_STS_L_REG, &cfg.value); 155400161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 155500161856Syc "==> nxge_n2_serdes_init port<%d>: PLL sts.l 0x%x (0x%x)", 155600161856Syc portn, pll_sts_l.value, cfg.value)); 155700161856Syc #endif 155800161856Syc } else if (nxgep->mac.portmode == PORT_1G_FIBER || 155900161856Syc nxgep->mac.portmode == PORT_1G_TN1010 || 156000161856Syc nxgep->mac.portmode == PORT_1G_SERDES) { 156144961713Sgirish /* 0x0E21 */ 156244961713Sgirish tx_cfg_l.bits.entx = 1; 156344961713Sgirish tx_cfg_l.bits.rate = CFGTX_RATE_HALF; 156444961713Sgirish tx_cfg_l.bits.swing = CFGTX_SWING_1375MV; 156544961713Sgirish 156644961713Sgirish /* 0x9121 */ 156744961713Sgirish rx_cfg_l.bits.enrx = 1; 156844961713Sgirish rx_cfg_l.bits.rate = CFGRX_RATE_HALF; 156944961713Sgirish rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT; 157044961713Sgirish rx_cfg_l.bits.align = CFGRX_ALIGN_EN; 157144961713Sgirish rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES; 157244961713Sgirish 15732e59129aSraghus if (portn == 0) { 15742e59129aSraghus /* 0x8 */ 15752e59129aSraghus rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF; 15762e59129aSraghus } 157744961713Sgirish 157800161856Syc /* Initialize PLL for 1G */ 157944961713Sgirish pll_cfg_l.bits.mpy = CFGPLL_MPY_8X; 158044961713Sgirish pll_cfg_l.bits.enpll = 1; 15812e59129aSraghus pll_sts_l.bits.enpll = 1; 158244961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 158352ccf843Smisaki ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value)) != NXGE_OK) 158444961713Sgirish goto fail; 15852e59129aSraghus 15862e59129aSraghus if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 15872e59129aSraghus ESR_N2_PLL_STS_L_REG, pll_sts_l.value)) != NXGE_OK) 15882e59129aSraghus goto fail; 15892e59129aSraghus 15902e59129aSraghus #ifdef NXGE_DEBUG 15912e59129aSraghus nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR, 15922e59129aSraghus ESR_N2_PLL_CFG_L_REG, &cfg.value); 15932e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 15942e59129aSraghus "==> nxge_n2_serdes_init port<%d>: PLL cfg.l 0x%x (0x%x)", 15952e59129aSraghus portn, pll_cfg_l.value, cfg.value)); 15962e59129aSraghus 15972e59129aSraghus nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR, 15982e59129aSraghus ESR_N2_PLL_STS_L_REG, &cfg.value); 15992e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 16002e59129aSraghus "==> nxge_n2_serdes_init port<%d>: PLL sts.l 0x%x (0x%x)", 16012e59129aSraghus portn, pll_sts_l.value, cfg.value)); 16022e59129aSraghus #endif 16032e59129aSraghus 16042e59129aSraghus /* Set loopback mode if necessary */ 16052e59129aSraghus if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) { 16062e59129aSraghus tx_cfg_l.bits.entest = 1; 16072e59129aSraghus rx_cfg_l.bits.entest = 1; 16082e59129aSraghus test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK; 16092e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 16102e59129aSraghus "==> nxge_n2_serdes_init port<%d>: loopback 0x%x", 16112e59129aSraghus portn, test_cfg.value)); 16122e59129aSraghus if ((status = nxge_mdio_write(nxgep, portn, 16132e59129aSraghus ESR_N2_DEV_ADDR, 16142e59129aSraghus ESR_N2_TEST_CFG_REG, test_cfg.value)) != NXGE_OK) { 16152e59129aSraghus goto fail; 16162e59129aSraghus } 16172e59129aSraghus } 161844961713Sgirish } else { 161944961713Sgirish goto fail; 162044961713Sgirish } 162144961713Sgirish 162244961713Sgirish /* MIF_REG_WR(handle, MIF_MASK_REG, ~mask); */ 162344961713Sgirish 162444961713Sgirish NXGE_DELAY(20); 162544961713Sgirish 162644961713Sgirish /* init TX channels */ 162744961713Sgirish for (chan = 0; chan < 4; chan++) { 162844961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 162952ccf843Smisaki ESR_N2_TX_CFG_L_REG_ADDR(chan), tx_cfg_l.value)) != NXGE_OK) 163044961713Sgirish goto fail; 163144961713Sgirish 163244961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 163352ccf843Smisaki ESR_N2_TX_CFG_H_REG_ADDR(chan), tx_cfg_h.value)) != NXGE_OK) 163444961713Sgirish goto fail; 16352e59129aSraghus 16362e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 16372e59129aSraghus "==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_l 0x%x", 16382e59129aSraghus portn, chan, tx_cfg_l.value)); 16392e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 16402e59129aSraghus "==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_h 0x%x", 16412e59129aSraghus portn, chan, tx_cfg_h.value)); 164244961713Sgirish } 164344961713Sgirish 164444961713Sgirish /* init RX channels */ 164544961713Sgirish for (chan = 0; chan < 4; chan++) { 164644961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 164752ccf843Smisaki ESR_N2_RX_CFG_L_REG_ADDR(chan), rx_cfg_l.value)) != NXGE_OK) 164844961713Sgirish goto fail; 164944961713Sgirish 165044961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 165152ccf843Smisaki ESR_N2_RX_CFG_H_REG_ADDR(chan), rx_cfg_h.value)) != NXGE_OK) 165244961713Sgirish goto fail; 16532e59129aSraghus 16542e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 16552e59129aSraghus "==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_l 0x%x", 16562e59129aSraghus portn, chan, rx_cfg_l.value)); 165700161856Syc 16582e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 16592e59129aSraghus "==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_h 0x%x", 16602e59129aSraghus portn, chan, rx_cfg_h.value)); 166144961713Sgirish } 166244961713Sgirish 166344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_n2_serdes_init port<%d>", 166452ccf843Smisaki portn)); 166544961713Sgirish 166644961713Sgirish return (NXGE_OK); 166744961713Sgirish fail: 16682d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 16692d17280bSsbehera "nxge_n2_serdes_init: Failed to initialize N2 serdes for port<%d>", 16702d17280bSsbehera portn)); 167144961713Sgirish 167244961713Sgirish return (status); 167344961713Sgirish } 167444961713Sgirish 167559ac0c16Sdavemq /* Initialize the Neptune Internal Serdes for 10G (Neptune only) */ 167644961713Sgirish 167759ac0c16Sdavemq static nxge_status_t 167859ac0c16Sdavemq nxge_neptune_10G_serdes_init(p_nxge_t nxgep) 167944961713Sgirish { 168044961713Sgirish npi_handle_t handle; 168144961713Sgirish uint8_t portn; 1682321febdeSsbehera int chan, i; 168344961713Sgirish sr_rx_tx_ctrl_l_t rx_tx_ctrl_l; 168444961713Sgirish sr_rx_tx_ctrl_h_t rx_tx_ctrl_h; 168544961713Sgirish sr_glue_ctrl0_l_t glue_ctrl0_l; 168644961713Sgirish sr_glue_ctrl0_h_t glue_ctrl0_h; 168744961713Sgirish uint64_t val; 168844961713Sgirish uint16_t val16l; 168944961713Sgirish uint16_t val16h; 169044961713Sgirish nxge_status_t status = NXGE_OK; 169144961713Sgirish 169244961713Sgirish portn = nxgep->mac.portnum; 169344961713Sgirish 169444961713Sgirish if ((portn != 0) && (portn != 1)) 169544961713Sgirish return (NXGE_OK); 169644961713Sgirish 169759ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 169859ac0c16Sdavemq "==> nxge_neptune_10G_serdes_init port<%d>", portn)); 169944961713Sgirish handle = nxgep->npi_handle; 170059ac0c16Sdavemq switch (portn) { 170159ac0c16Sdavemq case 0: 17024202ea4bSsbehera /* Reset Serdes */ 17034202ea4bSsbehera ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0); 17044202ea4bSsbehera NXGE_DELAY(20); 17054202ea4bSsbehera ESR_REG_WR(handle, ESR_RESET_REG, 0x0); 17064202ea4bSsbehera NXGE_DELAY(2000); 17074202ea4bSsbehera 17084202ea4bSsbehera /* Configure Serdes to 10G mode */ 17094202ea4bSsbehera ESR_REG_WR(handle, ESR_0_PLL_CONFIG_REG, 17104202ea4bSsbehera ESR_PLL_CFG_10G_SERDES); 17114202ea4bSsbehera 171259ac0c16Sdavemq ESR_REG_WR(handle, ESR_0_CONTROL_REG, 171359ac0c16Sdavemq ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 | 171459ac0c16Sdavemq ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 | 171559ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) | 171659ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) | 171759ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) | 171859ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 171959ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 172059ac0c16Sdavemq (0x1 << ESR_CTL_LOSADJ_0_SHIFT) | 172159ac0c16Sdavemq (0x1 << ESR_CTL_LOSADJ_1_SHIFT) | 172259ac0c16Sdavemq (0x1 << ESR_CTL_LOSADJ_2_SHIFT) | 172359ac0c16Sdavemq (0x1 << ESR_CTL_LOSADJ_3_SHIFT)); 172459ac0c16Sdavemq 172559ac0c16Sdavemq /* Set Serdes0 Internal Loopback if necessary */ 172659ac0c16Sdavemq if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) { 172759ac0c16Sdavemq ESR_REG_WR(handle, 172859ac0c16Sdavemq ESR_0_TEST_CONFIG_REG, 172959ac0c16Sdavemq ESR_PAD_LOOPBACK_CH3 | 173059ac0c16Sdavemq ESR_PAD_LOOPBACK_CH2 | 173159ac0c16Sdavemq ESR_PAD_LOOPBACK_CH1 | 173259ac0c16Sdavemq ESR_PAD_LOOPBACK_CH0); 173359ac0c16Sdavemq } else { 173459ac0c16Sdavemq ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0); 173544961713Sgirish } 173659ac0c16Sdavemq break; 173759ac0c16Sdavemq case 1: 17384202ea4bSsbehera /* Reset Serdes */ 17394202ea4bSsbehera ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_1); 17404202ea4bSsbehera NXGE_DELAY(20); 17414202ea4bSsbehera ESR_REG_WR(handle, ESR_RESET_REG, 0x0); 17424202ea4bSsbehera NXGE_DELAY(2000); 17434202ea4bSsbehera 17444202ea4bSsbehera /* Configure Serdes to 10G mode */ 17454202ea4bSsbehera ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG, 17464202ea4bSsbehera ESR_PLL_CFG_10G_SERDES); 17474202ea4bSsbehera 174859ac0c16Sdavemq ESR_REG_WR(handle, ESR_1_CONTROL_REG, 174959ac0c16Sdavemq ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 | 175059ac0c16Sdavemq ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 | 175159ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) | 175259ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) | 175359ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) | 175459ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 175559ac0c16Sdavemq (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 175659ac0c16Sdavemq (0x1 << ESR_CTL_LOSADJ_0_SHIFT) | 175759ac0c16Sdavemq (0x1 << ESR_CTL_LOSADJ_1_SHIFT) | 175859ac0c16Sdavemq (0x1 << ESR_CTL_LOSADJ_2_SHIFT) | 175959ac0c16Sdavemq (0x1 << ESR_CTL_LOSADJ_3_SHIFT)); 176059ac0c16Sdavemq 176159ac0c16Sdavemq /* Set Serdes1 Internal Loopback if necessary */ 176259ac0c16Sdavemq if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) { 176359ac0c16Sdavemq ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 176459ac0c16Sdavemq ESR_PAD_LOOPBACK_CH3 | ESR_PAD_LOOPBACK_CH2 | 176559ac0c16Sdavemq ESR_PAD_LOOPBACK_CH1 | ESR_PAD_LOOPBACK_CH0); 176659ac0c16Sdavemq } else { 176759ac0c16Sdavemq ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0); 176844961713Sgirish } 176959ac0c16Sdavemq break; 177059ac0c16Sdavemq default: 177159ac0c16Sdavemq /* Nothing to do here */ 177259ac0c16Sdavemq goto done; 177359ac0c16Sdavemq } 177444961713Sgirish 177559ac0c16Sdavemq /* init TX RX channels */ 177659ac0c16Sdavemq for (chan = 0; chan < 4; chan++) { 177759ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, portn, 177859ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 177959ac0c16Sdavemq &rx_tx_ctrl_l.value)) != NXGE_OK) 178044961713Sgirish goto fail; 178159ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, portn, 178259ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 178359ac0c16Sdavemq &rx_tx_ctrl_h.value)) != NXGE_OK) 178444961713Sgirish goto fail; 178559ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, portn, 178659ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 178759ac0c16Sdavemq &glue_ctrl0_l.value)) != NXGE_OK) 178859ac0c16Sdavemq goto fail; 178959ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, portn, 179059ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 179159ac0c16Sdavemq &glue_ctrl0_h.value)) != NXGE_OK) 179259ac0c16Sdavemq goto fail; 179359ac0c16Sdavemq rx_tx_ctrl_l.bits.enstretch = 1; 179459ac0c16Sdavemq rx_tx_ctrl_h.bits.vmuxlo = 2; 179559ac0c16Sdavemq rx_tx_ctrl_h.bits.vpulselo = 2; 179659ac0c16Sdavemq glue_ctrl0_l.bits.rxlosenable = 1; 179759ac0c16Sdavemq glue_ctrl0_l.bits.samplerate = 0xF; 179859ac0c16Sdavemq glue_ctrl0_l.bits.thresholdcount = 0xFF; 179959ac0c16Sdavemq glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES; 180044961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, 180159ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 180259ac0c16Sdavemq rx_tx_ctrl_l.value)) != NXGE_OK) 180344961713Sgirish goto fail; 180444961713Sgirish if ((status = nxge_mdio_write(nxgep, portn, 180559ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 180659ac0c16Sdavemq rx_tx_ctrl_h.value)) != NXGE_OK) 180744961713Sgirish goto fail; 180859ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, portn, 180959ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 181059ac0c16Sdavemq glue_ctrl0_l.value)) != NXGE_OK) 181144961713Sgirish goto fail; 181259ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, portn, 181359ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 181459ac0c16Sdavemq glue_ctrl0_h.value)) != NXGE_OK) 181544961713Sgirish goto fail; 181644961713Sgirish } 181744961713Sgirish 181859ac0c16Sdavemq /* Apply Tx core reset */ 181959ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, portn, 182059ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), 182159ac0c16Sdavemq (uint16_t)0)) != NXGE_OK) 182259ac0c16Sdavemq goto fail; 182359ac0c16Sdavemq 182459ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 182559ac0c16Sdavemq ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) != 182659ac0c16Sdavemq NXGE_OK) 182759ac0c16Sdavemq goto fail; 182859ac0c16Sdavemq 182959ac0c16Sdavemq NXGE_DELAY(200); 183059ac0c16Sdavemq 183159ac0c16Sdavemq /* Apply Rx core reset */ 183259ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 183359ac0c16Sdavemq ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) != 183459ac0c16Sdavemq NXGE_OK) 183559ac0c16Sdavemq goto fail; 183659ac0c16Sdavemq 183759ac0c16Sdavemq NXGE_DELAY(200); 183859ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 183959ac0c16Sdavemq ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK) 184059ac0c16Sdavemq goto fail; 184159ac0c16Sdavemq 184259ac0c16Sdavemq NXGE_DELAY(200); 184359ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, portn, 184459ac0c16Sdavemq ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), 184559ac0c16Sdavemq &val16l)) != NXGE_OK) 184659ac0c16Sdavemq goto fail; 184759ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 184859ac0c16Sdavemq ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK) 184959ac0c16Sdavemq goto fail; 185059ac0c16Sdavemq if ((val16l != 0) || (val16h != 0)) { 185159ac0c16Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1852d81011f0Ssbehera "Failed to reset port<%d> XAUI Serdes " 1853d81011f0Ssbehera "(val16l 0x%x val16h 0x%x)", 1854d81011f0Ssbehera portn, val16l, val16h)); 185559ac0c16Sdavemq } 185659ac0c16Sdavemq 185759ac0c16Sdavemq if (portn == 0) { 1858321febdeSsbehera /* Wait for serdes to be ready */ 1859321febdeSsbehera for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) { 1860321febdeSsbehera ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val); 1861321febdeSsbehera if ((val & ESR_SIG_P0_BITS_MASK) != 1862321febdeSsbehera (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0 | 1863321febdeSsbehera ESR_SIG_XSERDES_RDY_P0 | 1864321febdeSsbehera ESR_SIG_XDETECT_P0_CH3 | 1865321febdeSsbehera ESR_SIG_XDETECT_P0_CH2 | 1866321febdeSsbehera ESR_SIG_XDETECT_P0_CH1 | 1867321febdeSsbehera ESR_SIG_XDETECT_P0_CH0)) 1868321febdeSsbehera 1869321febdeSsbehera NXGE_DELAY(SERDES_RDY_WT_INTERVAL); 1870321febdeSsbehera else 1871321febdeSsbehera break; 1872321febdeSsbehera } 1873321febdeSsbehera 1874321febdeSsbehera if (i == MAX_SERDES_RDY_RETRIES) { 1875ab6abb7aSjoycey /* 1876ab6abb7aSjoycey * RDY signal stays low may due to the absent of the 1877ab6abb7aSjoycey * external PHY, it is not an error condition. But still 1878ab6abb7aSjoycey * print the message for the debugging purpose when link 1879ab6abb7aSjoycey * stays down 1880ab6abb7aSjoycey */ 1881321febdeSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1882321febdeSsbehera "nxge_neptune_10G_serdes_init: " 1883321febdeSsbehera "Serdes/signal for port<%d> not ready", portn)); 188400161856Syc goto done; 188559ac0c16Sdavemq } 188659ac0c16Sdavemq } else if (portn == 1) { 1887321febdeSsbehera /* Wait for serdes to be ready */ 1888321febdeSsbehera for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) { 1889321febdeSsbehera ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val); 1890321febdeSsbehera if ((val & ESR_SIG_P1_BITS_MASK) != 1891321febdeSsbehera (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1 | 1892321febdeSsbehera ESR_SIG_XSERDES_RDY_P1 | 1893321febdeSsbehera ESR_SIG_XDETECT_P1_CH3 | 1894321febdeSsbehera ESR_SIG_XDETECT_P1_CH2 | 1895321febdeSsbehera ESR_SIG_XDETECT_P1_CH1 | 1896321febdeSsbehera ESR_SIG_XDETECT_P1_CH0)) 1897321febdeSsbehera 1898321febdeSsbehera NXGE_DELAY(SERDES_RDY_WT_INTERVAL); 1899321febdeSsbehera else 1900321febdeSsbehera break; 1901321febdeSsbehera } 1902321febdeSsbehera 1903321febdeSsbehera if (i == MAX_SERDES_RDY_RETRIES) { 1904ab6abb7aSjoycey /* 1905ab6abb7aSjoycey * RDY signal stays low may due to the absent of the 1906ab6abb7aSjoycey * external PHY, it is not an error condition. But still 1907ab6abb7aSjoycey * print the message for the debugging purpose when link 1908ab6abb7aSjoycey * stays down 1909ab6abb7aSjoycey */ 1910321febdeSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1911321febdeSsbehera "nxge_neptune_10G_serdes_init: " 1912321febdeSsbehera "Serdes/signal for port<%d> not ready", portn)); 191300161856Syc goto done; 191444961713Sgirish } 191544961713Sgirish } 191644961713Sgirish 191744961713Sgirish done: 191859ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 191959ac0c16Sdavemq "<== nxge_neptune_10G_serdes_init port<%d>", portn)); 192059ac0c16Sdavemq 192144961713Sgirish return (NXGE_OK); 192244961713Sgirish fail: 19232d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 192459ac0c16Sdavemq "nxge_neptune_10G_serdes_init: " 192559ac0c16Sdavemq "Failed to initialize Neptune serdes for port<%d>", portn)); 192644961713Sgirish 192744961713Sgirish return (status); 192844961713Sgirish } 192944961713Sgirish 193059ac0c16Sdavemq /* Initialize Neptune Internal Serdes for 1G (Neptune only) */ 193144961713Sgirish 193259ac0c16Sdavemq static nxge_status_t 193359ac0c16Sdavemq nxge_1G_serdes_init(p_nxge_t nxgep) 193444961713Sgirish { 193559ac0c16Sdavemq npi_handle_t handle; 193659ac0c16Sdavemq uint8_t portn; 1937d81011f0Ssbehera int chan; 1938d81011f0Ssbehera sr_rx_tx_ctrl_l_t rx_tx_ctrl_l; 1939d81011f0Ssbehera sr_rx_tx_ctrl_h_t rx_tx_ctrl_h; 1940d81011f0Ssbehera sr_glue_ctrl0_l_t glue_ctrl0_l; 1941d81011f0Ssbehera sr_glue_ctrl0_h_t glue_ctrl0_h; 194259ac0c16Sdavemq uint64_t val; 1943d81011f0Ssbehera uint16_t val16l; 1944d81011f0Ssbehera uint16_t val16h; 1945d81011f0Ssbehera nxge_status_t status = NXGE_OK; 194644961713Sgirish 194744961713Sgirish portn = nxgep->mac.portnum; 194844961713Sgirish 194959ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 195059ac0c16Sdavemq "==> nxge_1G_serdes_init port<%d>", portn)); 195144961713Sgirish 195259ac0c16Sdavemq handle = nxgep->npi_handle; 195344961713Sgirish 195459ac0c16Sdavemq switch (portn) { 195559ac0c16Sdavemq case 0: 1956d81011f0Ssbehera /* Assert the reset register */ 1957d81011f0Ssbehera ESR_REG_RD(handle, ESR_RESET_REG, &val); 1958d81011f0Ssbehera val |= ESR_RESET_0; 1959d81011f0Ssbehera ESR_REG_WR(handle, ESR_RESET_REG, val); 1960d81011f0Ssbehera 1961d81011f0Ssbehera /* Set the PLL register to 0x79 */ 1962d81011f0Ssbehera ESR_REG_WR(handle, ESR_0_PLL_CONFIG_REG, 1963d81011f0Ssbehera ESR_PLL_CFG_1G_SERDES); 1964d81011f0Ssbehera 1965d81011f0Ssbehera /* Set the control register to 0x249249f */ 1966d81011f0Ssbehera ESR_REG_WR(handle, ESR_0_CONTROL_REG, ESR_CTL_1G_SERDES); 1967d81011f0Ssbehera 1968d81011f0Ssbehera /* Set Serdes0 Internal Loopback if necessary */ 1969d81011f0Ssbehera if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) { 1970d81011f0Ssbehera /* Set pad loopback modes 0xaa */ 1971d81011f0Ssbehera ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 1972d81011f0Ssbehera ESR_TSTCFG_LBTEST_PAD); 1973d81011f0Ssbehera } else { 1974d81011f0Ssbehera ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0); 1975d81011f0Ssbehera } 1976d81011f0Ssbehera 1977d81011f0Ssbehera /* Deassert the reset register */ 1978d81011f0Ssbehera ESR_REG_RD(handle, ESR_RESET_REG, &val); 1979d81011f0Ssbehera val &= ~ESR_RESET_0; 1980d81011f0Ssbehera ESR_REG_WR(handle, ESR_RESET_REG, val); 198159ac0c16Sdavemq break; 1982d81011f0Ssbehera 198359ac0c16Sdavemq case 1: 1984d81011f0Ssbehera /* Assert the reset register */ 1985d81011f0Ssbehera ESR_REG_RD(handle, ESR_RESET_REG, &val); 1986d81011f0Ssbehera val |= ESR_RESET_1; 1987d81011f0Ssbehera ESR_REG_WR(handle, ESR_RESET_REG, val); 1988d81011f0Ssbehera 1989d81011f0Ssbehera /* Set PLL register to 0x79 */ 1990d81011f0Ssbehera ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG, 1991d81011f0Ssbehera ESR_PLL_CFG_1G_SERDES); 1992d81011f0Ssbehera 1993d81011f0Ssbehera /* Set the control register to 0x249249f */ 1994d81011f0Ssbehera ESR_REG_WR(handle, ESR_1_CONTROL_REG, ESR_CTL_1G_SERDES); 1995d81011f0Ssbehera 1996d81011f0Ssbehera /* Set Serdes1 Internal Loopback if necessary */ 1997d81011f0Ssbehera if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) { 1998d81011f0Ssbehera /* Set pad loopback mode 0xaa */ 1999d81011f0Ssbehera ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 2000d81011f0Ssbehera ESR_TSTCFG_LBTEST_PAD); 2001d81011f0Ssbehera } else { 2002d81011f0Ssbehera ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0); 2003d81011f0Ssbehera } 2004d81011f0Ssbehera 2005d81011f0Ssbehera /* Deassert the reset register */ 2006d81011f0Ssbehera ESR_REG_RD(handle, ESR_RESET_REG, &val); 2007d81011f0Ssbehera val &= ~ESR_RESET_1; 2008d81011f0Ssbehera ESR_REG_WR(handle, ESR_RESET_REG, val); 200959ac0c16Sdavemq break; 2010d81011f0Ssbehera 201159ac0c16Sdavemq default: 2012d81011f0Ssbehera /* Nothing to do here */ 2013d81011f0Ssbehera goto done; 2014d81011f0Ssbehera } 2015d81011f0Ssbehera 2016d81011f0Ssbehera /* init TX RX channels */ 2017d81011f0Ssbehera for (chan = 0; chan < 4; chan++) { 2018d81011f0Ssbehera if ((status = nxge_mdio_read(nxgep, portn, 2019d81011f0Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 2020d81011f0Ssbehera &rx_tx_ctrl_l.value)) != NXGE_OK) { 2021d81011f0Ssbehera goto fail; 2022d81011f0Ssbehera } 2023d81011f0Ssbehera if ((status = nxge_mdio_read(nxgep, portn, 2024d81011f0Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 2025d81011f0Ssbehera &rx_tx_ctrl_h.value)) != NXGE_OK) { 2026d81011f0Ssbehera goto fail; 2027d81011f0Ssbehera } 2028d81011f0Ssbehera if ((status = nxge_mdio_read(nxgep, portn, 2029d81011f0Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 2030d81011f0Ssbehera &glue_ctrl0_l.value)) != NXGE_OK) { 2031d81011f0Ssbehera goto fail; 2032d81011f0Ssbehera } 2033d81011f0Ssbehera if ((status = nxge_mdio_read(nxgep, portn, 2034d81011f0Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 2035d81011f0Ssbehera &glue_ctrl0_h.value)) != NXGE_OK) { 2036d81011f0Ssbehera goto fail; 2037d81011f0Ssbehera } 2038d81011f0Ssbehera 2039d81011f0Ssbehera rx_tx_ctrl_l.bits.enstretch = 1; 2040d81011f0Ssbehera rx_tx_ctrl_h.bits.vmuxlo = 2; 2041d81011f0Ssbehera rx_tx_ctrl_h.bits.vpulselo = 2; 2042d81011f0Ssbehera glue_ctrl0_l.bits.rxlosenable = 1; 2043d81011f0Ssbehera glue_ctrl0_l.bits.samplerate = 0xF; 2044d81011f0Ssbehera glue_ctrl0_l.bits.thresholdcount = 0xFF; 2045d81011f0Ssbehera glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES; 2046d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, 2047d81011f0Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 2048d81011f0Ssbehera rx_tx_ctrl_l.value)) != NXGE_OK) { 2049d81011f0Ssbehera goto fail; 2050d81011f0Ssbehera } 2051d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, 2052d81011f0Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 2053d81011f0Ssbehera rx_tx_ctrl_h.value)) != NXGE_OK) { 2054d81011f0Ssbehera goto fail; 2055d81011f0Ssbehera } 2056d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, 2057d81011f0Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 2058d81011f0Ssbehera glue_ctrl0_l.value)) != NXGE_OK) { 2059d81011f0Ssbehera goto fail; 2060d81011f0Ssbehera } 2061d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, 2062d81011f0Ssbehera ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 2063d81011f0Ssbehera glue_ctrl0_h.value)) != NXGE_OK) { 2064d81011f0Ssbehera goto fail; 2065d81011f0Ssbehera } 2066d81011f0Ssbehera } 2067d81011f0Ssbehera 2068d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2069d81011f0Ssbehera ESR_NEP_RX_POWER_CONTROL_L_ADDR(), 0xfff)) != NXGE_OK) { 2070d81011f0Ssbehera goto fail; 2071d81011f0Ssbehera } 2072d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2073d81011f0Ssbehera ESR_NEP_RX_POWER_CONTROL_H_ADDR(), 0xfff)) != NXGE_OK) { 2074d81011f0Ssbehera goto fail; 2075d81011f0Ssbehera } 2076d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2077d81011f0Ssbehera ESR_NEP_TX_POWER_CONTROL_L_ADDR(), 0x70)) != NXGE_OK) { 2078d81011f0Ssbehera goto fail; 2079d81011f0Ssbehera } 2080d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2081d81011f0Ssbehera ESR_NEP_TX_POWER_CONTROL_H_ADDR(), 0xfff)) != NXGE_OK) { 208259ac0c16Sdavemq goto fail; 208344961713Sgirish } 208444961713Sgirish 2085d81011f0Ssbehera /* Apply Tx core reset */ 2086d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2087d81011f0Ssbehera ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0)) != NXGE_OK) { 2088d81011f0Ssbehera goto fail; 2089d81011f0Ssbehera } 2090d81011f0Ssbehera 2091d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2092d81011f0Ssbehera ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) != 2093d81011f0Ssbehera NXGE_OK) { 2094d81011f0Ssbehera goto fail; 2095d81011f0Ssbehera } 2096d81011f0Ssbehera 2097d81011f0Ssbehera NXGE_DELAY(200); 2098d81011f0Ssbehera 2099d81011f0Ssbehera /* Apply Rx core reset */ 2100d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2101d81011f0Ssbehera ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) != 2102d81011f0Ssbehera NXGE_OK) { 2103d81011f0Ssbehera goto fail; 2104d81011f0Ssbehera } 2105d81011f0Ssbehera 2106d81011f0Ssbehera NXGE_DELAY(200); 2107d81011f0Ssbehera if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2108d81011f0Ssbehera ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK) { 2109d81011f0Ssbehera goto fail; 2110d81011f0Ssbehera } 2111d81011f0Ssbehera 2112d81011f0Ssbehera NXGE_DELAY(200); 2113d81011f0Ssbehera if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2114d81011f0Ssbehera ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), &val16l)) != NXGE_OK) { 2115d81011f0Ssbehera goto fail; 2116d81011f0Ssbehera } 2117d81011f0Ssbehera if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2118d81011f0Ssbehera ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK) { 2119d81011f0Ssbehera goto fail; 2120d81011f0Ssbehera } 2121d81011f0Ssbehera if ((val16l != 0) || (val16h != 0)) { 2122d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2123d81011f0Ssbehera "Failed to reset port<%d> XAUI Serdes " 2124d81011f0Ssbehera "(val16l 0x%x val16h 0x%x)", portn, val16l, val16h)); 2125d81011f0Ssbehera status = NXGE_ERROR; 2126d81011f0Ssbehera goto fail; 2127d81011f0Ssbehera } 2128d81011f0Ssbehera 2129d81011f0Ssbehera NXGE_DELAY(200); 2130d81011f0Ssbehera ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val); 2131d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2132d81011f0Ssbehera "nxge_neptune_serdes_init: read internal signal reg port<%d> " 2133d81011f0Ssbehera "val 0x%x", portn, val)); 2134d81011f0Ssbehera if (portn == 0) { 2135d81011f0Ssbehera if ((val & ESR_SIG_P0_BITS_MASK_1G) != 2136d81011f0Ssbehera (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0)) { 2137ab6abb7aSjoycey /* 2138ab6abb7aSjoycey * RDY signal stays low may due to the absent of the 2139ab6abb7aSjoycey * external PHY, it is not an error condition. But still 2140ab6abb7aSjoycey * print the message for the debugging purpose when link 2141ab6abb7aSjoycey * stays down 2142ab6abb7aSjoycey */ 2143d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2144ab6abb7aSjoycey "nxge_neptune_1G_serdes_init: " 2145ab6abb7aSjoycey "Serdes/signal for port<%d> not ready", portn)); 214600161856Syc goto done; 2147d81011f0Ssbehera } 2148d81011f0Ssbehera } else if (portn == 1) { 2149d81011f0Ssbehera if ((val & ESR_SIG_P1_BITS_MASK_1G) != 2150d81011f0Ssbehera (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1)) { 2151ab6abb7aSjoycey /* 2152ab6abb7aSjoycey * RDY signal stays low may due to the absent of the 2153ab6abb7aSjoycey * external PHY, it is not an error condition. But still 2154ab6abb7aSjoycey * print the message for the debugging purpose when link 2155ab6abb7aSjoycey * stays down 2156ab6abb7aSjoycey */ 2157d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2158ab6abb7aSjoycey "nxge_neptune_1G_serdes_init: " 2159ab6abb7aSjoycey "Serdes/signal for port<%d> not ready", portn)); 216000161856Syc goto done; 216100161856Syc 2162d81011f0Ssbehera } 2163d81011f0Ssbehera } 2164d81011f0Ssbehera done: 216559ac0c16Sdavemq 216659ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 216759ac0c16Sdavemq "<== nxge_1G_serdes_init port<%d>", portn)); 216844961713Sgirish return (NXGE_OK); 216959ac0c16Sdavemq fail: 2170d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 217159ac0c16Sdavemq "nxge_1G_serdes_init: " 217259ac0c16Sdavemq "Failed to initialize Neptune serdes for port<%d>", 217359ac0c16Sdavemq portn)); 217459ac0c16Sdavemq 2175d81011f0Ssbehera return (status); 217644961713Sgirish } 217744961713Sgirish 21782d17280bSsbehera /* Initialize the BCM 8704 xcvr */ 217944961713Sgirish 218059ac0c16Sdavemq static nxge_status_t 21812d17280bSsbehera nxge_BCM8704_xcvr_init(p_nxge_t nxgep) 218244961713Sgirish { 218344961713Sgirish uint16_t val; 218444961713Sgirish #ifdef NXGE_DEBUG 218514ea4bb7Ssd uint8_t portn; 218644961713Sgirish uint16_t val1; 218744961713Sgirish #endif 218844961713Sgirish uint8_t phy_port_addr; 218944961713Sgirish pmd_tx_control_t tx_ctl; 219044961713Sgirish control_t ctl; 219144961713Sgirish phyxs_control_t phyxs_ctl; 219244961713Sgirish pcs_control_t pcs_ctl; 219344961713Sgirish uint32_t delay = 0; 219444961713Sgirish optics_dcntr_t op_ctr; 219544961713Sgirish nxge_status_t status = NXGE_OK; 219614ea4bb7Ssd #ifdef NXGE_DEBUG 219744961713Sgirish portn = nxgep->mac.portnum; 219814ea4bb7Ssd #endif 21992d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8704_xcvr_init: port<%d>", 220059ac0c16Sdavemq portn)); 220144961713Sgirish 220259ac0c16Sdavemq phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn; 220359ac0c16Sdavemq 220459ac0c16Sdavemq /* Reset the transceiver */ 220559ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 220659ac0c16Sdavemq BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK) 220759ac0c16Sdavemq goto fail; 220859ac0c16Sdavemq 220959ac0c16Sdavemq phyxs_ctl.bits.reset = 1; 221059ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 221159ac0c16Sdavemq BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK) 221259ac0c16Sdavemq goto fail; 221359ac0c16Sdavemq 221459ac0c16Sdavemq do { 221559ac0c16Sdavemq drv_usecwait(500); 221659ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 221759ac0c16Sdavemq BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG, 221859ac0c16Sdavemq &phyxs_ctl.value)) != NXGE_OK) 221959ac0c16Sdavemq goto fail; 222059ac0c16Sdavemq delay++; 222159ac0c16Sdavemq } while ((phyxs_ctl.bits.reset) && (delay < 100)); 222259ac0c16Sdavemq if (delay == 100) { 222359ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: " 222459ac0c16Sdavemq "failed to reset Transceiver on port<%d>", portn)); 222559ac0c16Sdavemq status = NXGE_ERROR; 222659ac0c16Sdavemq goto fail; 222759ac0c16Sdavemq } 222844961713Sgirish 222959ac0c16Sdavemq /* Set to 0x7FBF */ 223059ac0c16Sdavemq ctl.value = 0; 223159ac0c16Sdavemq ctl.bits.res1 = 0x3F; 223259ac0c16Sdavemq ctl.bits.optxon_lvl = 1; 223359ac0c16Sdavemq ctl.bits.oprxflt_lvl = 1; 223459ac0c16Sdavemq ctl.bits.optrxlos_lvl = 1; 223559ac0c16Sdavemq ctl.bits.optxflt_lvl = 1; 223659ac0c16Sdavemq ctl.bits.opprflt_lvl = 1; 223759ac0c16Sdavemq ctl.bits.obtmpflt_lvl = 1; 223859ac0c16Sdavemq ctl.bits.opbiasflt_lvl = 1; 223959ac0c16Sdavemq ctl.bits.optxrst_lvl = 1; 224059ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, 224159ac0c16Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, ctl.value)) 224259ac0c16Sdavemq != NXGE_OK) 224359ac0c16Sdavemq goto fail; 224459ac0c16Sdavemq 224559ac0c16Sdavemq /* Set to 0x164 */ 224659ac0c16Sdavemq tx_ctl.value = 0; 224759ac0c16Sdavemq tx_ctl.bits.tsck_lpwren = 1; 224859ac0c16Sdavemq tx_ctl.bits.tx_dac_txck = 0x2; 224959ac0c16Sdavemq tx_ctl.bits.tx_dac_txd = 0x1; 225059ac0c16Sdavemq tx_ctl.bits.xfp_clken = 1; 225159ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, 225259ac0c16Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, 225359ac0c16Sdavemq tx_ctl.value)) != NXGE_OK) 225459ac0c16Sdavemq goto fail; 225544961713Sgirish /* 225659ac0c16Sdavemq * According to Broadcom's instruction, SW needs to read 225759ac0c16Sdavemq * back these registers twice after written. 225844961713Sgirish */ 225959ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 226059ac0c16Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val)) 226159ac0c16Sdavemq != NXGE_OK) 226259ac0c16Sdavemq goto fail; 226344961713Sgirish 226459ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 226559ac0c16Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val)) 226659ac0c16Sdavemq != NXGE_OK) 226759ac0c16Sdavemq goto fail; 226844961713Sgirish 226959ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 227059ac0c16Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val)) 227159ac0c16Sdavemq != NXGE_OK) 227259ac0c16Sdavemq goto fail; 227344961713Sgirish 227459ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 227559ac0c16Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val)) 227659ac0c16Sdavemq != NXGE_OK) 227759ac0c16Sdavemq goto fail; 227844961713Sgirish 227959ac0c16Sdavemq /* Enable Tx and Rx LEDs to be driven by traffic */ 228059ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 228159ac0c16Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 228259ac0c16Sdavemq &op_ctr.value)) != NXGE_OK) 228359ac0c16Sdavemq goto fail; 2284cb9d3ae6Smisaki if (NXGE_IS_XAUI_PLATFORM(nxgep)) { 2285cb9d3ae6Smisaki op_ctr.bits.gpio_sel = 0x1; 2286cb9d3ae6Smisaki } else { 2287cb9d3ae6Smisaki op_ctr.bits.gpio_sel = 0x3; 2288cb9d3ae6Smisaki } 228959ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, 229059ac0c16Sdavemq BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 229159ac0c16Sdavemq op_ctr.value)) != NXGE_OK) 229259ac0c16Sdavemq goto fail; 229344961713Sgirish 229459ac0c16Sdavemq NXGE_DELAY(1000000); 229544961713Sgirish 229659ac0c16Sdavemq /* Set BCM8704 Internal Loopback mode if necessary */ 229759ac0c16Sdavemq if ((status = nxge_mdio_read(nxgep, phy_port_addr, 229859ac0c16Sdavemq BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value)) 229959ac0c16Sdavemq != NXGE_OK) 230059ac0c16Sdavemq goto fail; 230159ac0c16Sdavemq if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g) 230259ac0c16Sdavemq pcs_ctl.bits.loopback = 1; 230359ac0c16Sdavemq else 230459ac0c16Sdavemq pcs_ctl.bits.loopback = 0; 230559ac0c16Sdavemq if ((status = nxge_mdio_write(nxgep, phy_port_addr, 230659ac0c16Sdavemq BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value)) 230759ac0c16Sdavemq != NXGE_OK) 230859ac0c16Sdavemq goto fail; 230944961713Sgirish 231059ac0c16Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 0x1, 0xA, &val); 231159ac0c16Sdavemq if (status != NXGE_OK) 231259ac0c16Sdavemq goto fail; 231359ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 231459ac0c16Sdavemq "BCM8704 port<%d> Dev 1 Reg 0xA = 0x%x\n", portn, val)); 231559ac0c16Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0x20, &val); 231659ac0c16Sdavemq if (status != NXGE_OK) 231759ac0c16Sdavemq goto fail; 231859ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 231959ac0c16Sdavemq "BCM8704 port<%d> Dev 3 Reg 0x20 = 0x%x\n", portn, val)); 232059ac0c16Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, &val); 232159ac0c16Sdavemq if (status != NXGE_OK) 232259ac0c16Sdavemq goto fail; 232359ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 232459ac0c16Sdavemq "BCM8704 port<%d> Dev 4 Reg 0x18 = 0x%x\n", portn, val)); 232544961713Sgirish 232659ac0c16Sdavemq #ifdef NXGE_DEBUG 232759ac0c16Sdavemq /* Diagnose link issue if link is not up */ 232859ac0c16Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_USER_DEV3_ADDR, 232959ac0c16Sdavemq BCM8704_USER_ANALOG_STATUS0_REG, 233059ac0c16Sdavemq &val); 233159ac0c16Sdavemq if (status != NXGE_OK) 233259ac0c16Sdavemq goto fail; 233344961713Sgirish 233459ac0c16Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 233552ccf843Smisaki BCM8704_USER_DEV3_ADDR, BCM8704_USER_ANALOG_STATUS0_REG, &val); 233659ac0c16Sdavemq if (status != NXGE_OK) 233759ac0c16Sdavemq goto fail; 233844961713Sgirish 233959ac0c16Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 234052ccf843Smisaki BCM8704_USER_DEV3_ADDR, BCM8704_USER_TX_ALARM_STATUS_REG, &val1); 234159ac0c16Sdavemq if (status != NXGE_OK) 234259ac0c16Sdavemq goto fail; 234344961713Sgirish 234459ac0c16Sdavemq status = nxge_mdio_read(nxgep, phy_port_addr, 234552ccf843Smisaki BCM8704_USER_DEV3_ADDR, BCM8704_USER_TX_ALARM_STATUS_REG, &val1); 234659ac0c16Sdavemq if (status != NXGE_OK) 234759ac0c16Sdavemq goto fail; 234844961713Sgirish 234959ac0c16Sdavemq if (val != 0x3FC) { 235059ac0c16Sdavemq if ((val == 0x43BC) && (val1 != 0)) { 235159ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 235259ac0c16Sdavemq "Cable not connected to peer or bad" 235359ac0c16Sdavemq " cable on port<%d>\n", portn)); 235459ac0c16Sdavemq } else if (val == 0x639C) { 235559ac0c16Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 235659ac0c16Sdavemq "Optical module (XFP) is bad or absent" 235759ac0c16Sdavemq " on port<%d>\n", portn)); 235859ac0c16Sdavemq } 235959ac0c16Sdavemq } 236059ac0c16Sdavemq #endif 236144961713Sgirish 23622d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8704_xcvr_init: port<%d>", 23632d17280bSsbehera portn)); 23642d17280bSsbehera return (NXGE_OK); 23652d17280bSsbehera 23662d17280bSsbehera fail: 23672d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 23682d17280bSsbehera "nxge_BCM8704_xcvr_init: failed to initialize transceiver for " 23692d17280bSsbehera "port<%d>", nxgep->mac.portnum)); 23702d17280bSsbehera return (NXGE_ERROR); 23712d17280bSsbehera } 23722d17280bSsbehera 23732d17280bSsbehera /* Initialize the BCM 8706 Transceiver */ 23742d17280bSsbehera 23752d17280bSsbehera static nxge_status_t 23762d17280bSsbehera nxge_BCM8706_xcvr_init(p_nxge_t nxgep) 23772d17280bSsbehera { 23782d17280bSsbehera uint8_t phy_port_addr; 23792d17280bSsbehera phyxs_control_t phyxs_ctl; 23802d17280bSsbehera pcs_control_t pcs_ctl; 23812d17280bSsbehera uint32_t delay = 0; 23822d17280bSsbehera optics_dcntr_t op_ctr; 23832d17280bSsbehera nxge_status_t status = NXGE_OK; 23842d17280bSsbehera #ifdef NXGE_DEBUG 23852d17280bSsbehera uint8_t portn = nxgep->mac.portnum; 23862d17280bSsbehera #endif 23872d17280bSsbehera 23882d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8706_xcvr_init: port<%d>", 23892d17280bSsbehera portn)); 23902d17280bSsbehera 23912d17280bSsbehera phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn; 23922d17280bSsbehera 23932d17280bSsbehera /* Reset the transceiver */ 23942d17280bSsbehera if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 23952d17280bSsbehera BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK) 23962d17280bSsbehera goto fail; 23972d17280bSsbehera 23982d17280bSsbehera phyxs_ctl.bits.reset = 1; 23992d17280bSsbehera if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 24002d17280bSsbehera BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK) 24012d17280bSsbehera goto fail; 24022d17280bSsbehera do { 24032d17280bSsbehera drv_usecwait(500); 24042d17280bSsbehera if ((status = nxge_mdio_read(nxgep, phy_port_addr, 24052d17280bSsbehera BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG, 24062d17280bSsbehera &phyxs_ctl.value)) != NXGE_OK) 24072d17280bSsbehera goto fail; 24082d17280bSsbehera delay++; 24092d17280bSsbehera } while ((phyxs_ctl.bits.reset) && (delay < 100)); 24102d17280bSsbehera 24112d17280bSsbehera if (delay == 100) { 24122d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: " 24132d17280bSsbehera "failed to reset Transceiver on port<%d>", portn)); 24142d17280bSsbehera status = NXGE_ERROR; 24152d17280bSsbehera goto fail; 24162d17280bSsbehera } 24172d17280bSsbehera 24182d17280bSsbehera NXGE_DELAY(1000000); 24192d17280bSsbehera 24202d17280bSsbehera /* Set BCM8706 Internal Loopback mode if necessary */ 24212d17280bSsbehera if ((status = nxge_mdio_read(nxgep, phy_port_addr, 24222d17280bSsbehera BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value)) 24232d17280bSsbehera != NXGE_OK) 24242d17280bSsbehera goto fail; 24252d17280bSsbehera if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g) 24262d17280bSsbehera pcs_ctl.bits.loopback = 1; 24272d17280bSsbehera else 24282d17280bSsbehera pcs_ctl.bits.loopback = 0; 24292d17280bSsbehera if ((status = nxge_mdio_write(nxgep, phy_port_addr, 24302d17280bSsbehera BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value)) 24312d17280bSsbehera != NXGE_OK) 24322d17280bSsbehera goto fail; 24332d17280bSsbehera 24342d17280bSsbehera /* Enable Tx and Rx LEDs to be driven by traffic */ 24352d17280bSsbehera if ((status = nxge_mdio_read(nxgep, phy_port_addr, 24362d17280bSsbehera BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 24372d17280bSsbehera &op_ctr.value)) != NXGE_OK) 24382d17280bSsbehera goto fail; 24392d17280bSsbehera op_ctr.bits.gpio_sel = 0x3; 24402d17280bSsbehera op_ctr.bits.res2 = 0x1; 24412d17280bSsbehera 24422d17280bSsbehera if ((status = nxge_mdio_write(nxgep, phy_port_addr, 24432d17280bSsbehera BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 24442d17280bSsbehera op_ctr.value)) != NXGE_OK) 24452d17280bSsbehera goto fail; 24462d17280bSsbehera 24472d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8706_xcvr_init: port<%d>", 24482d17280bSsbehera portn)); 24492d17280bSsbehera return (NXGE_OK); 24502d17280bSsbehera 24512d17280bSsbehera fail: 24522d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 24532d17280bSsbehera "nxge_BCM8706_xcvr_init: failed to initialize transceiver for " 24542d17280bSsbehera "port<%d>", nxgep->mac.portnum)); 24552d17280bSsbehera return (status); 24562d17280bSsbehera } 24572d17280bSsbehera 245852cdd236Ssbehera #define CHK_STAT(x) status = (x); if (status != NXGE_OK) goto fail 245952cdd236Ssbehera 246052cdd236Ssbehera #define MRVL88X2011_RD(nxgep, port, d, r, p) \ 246152cdd236Ssbehera CHK_STAT(nxge_mdio_read(nxgep, port, d, r, p)) 246252cdd236Ssbehera 246352cdd236Ssbehera #define MRVL88X2011_WR(nxgep, port, d, r, p) \ 246452cdd236Ssbehera CHK_STAT(nxge_mdio_write(nxgep, port, d, r, p)) 246552cdd236Ssbehera 246652cdd236Ssbehera 246752cdd236Ssbehera static void 246852cdd236Ssbehera nxge_mrvl88x2011_led_blink_rate(p_nxge_t nxgep, uint16_t rate) 246952cdd236Ssbehera { 247052cdd236Ssbehera uint16_t value; 247152cdd236Ssbehera uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn; 247252cdd236Ssbehera 247352cdd236Ssbehera if (nxge_mdio_read(nxgep, phy, MRVL_88X2011_USER_DEV2_ADDR, 247452cdd236Ssbehera MRVL_88X2011_LED_BLINK_CTL, &value) == NXGE_OK) { 247552cdd236Ssbehera value &= ~MRVL_88X2011_LED_BLK_MASK; 247652cdd236Ssbehera value |= (rate << MRVL_88X2011_LED_BLK_SHIFT); 247752cdd236Ssbehera (void) nxge_mdio_write(nxgep, phy, 247852cdd236Ssbehera MRVL_88X2011_USER_DEV2_ADDR, MRVL_88X2011_LED_BLINK_CTL, 247952cdd236Ssbehera value); 248052cdd236Ssbehera } 248152cdd236Ssbehera } 248252cdd236Ssbehera 248352cdd236Ssbehera static nxge_status_t 248452cdd236Ssbehera nxge_mrvl88x2011_setup_lb(p_nxge_t nxgep) 248552cdd236Ssbehera { 248652cdd236Ssbehera nxge_status_t status; 248752cdd236Ssbehera pcs_control_t pcs_ctl; 248852cdd236Ssbehera uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn; 248952cdd236Ssbehera 249052cdd236Ssbehera MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR, 249152cdd236Ssbehera MRVL_88X2011_PMA_PMD_CTL_1, &pcs_ctl.value); 249252cdd236Ssbehera 249352cdd236Ssbehera if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g) 249452cdd236Ssbehera pcs_ctl.bits.loopback = 1; 249552cdd236Ssbehera else 249652cdd236Ssbehera pcs_ctl.bits.loopback = 0; 249752cdd236Ssbehera 249852cdd236Ssbehera MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR, 249952cdd236Ssbehera MRVL_88X2011_PMA_PMD_CTL_1, pcs_ctl.value); 250052cdd236Ssbehera 250152cdd236Ssbehera fail: 250252cdd236Ssbehera return (status); 250352cdd236Ssbehera } 250452cdd236Ssbehera 250552cdd236Ssbehera 250652cdd236Ssbehera static void 250752cdd236Ssbehera nxge_mrvl88x2011_led(p_nxge_t nxgep, uint16_t val) 250852cdd236Ssbehera { 250952cdd236Ssbehera uint16_t val2; 251052cdd236Ssbehera uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn; 251152cdd236Ssbehera 251252cdd236Ssbehera val2 = MRVL_88X2011_LED(MRVL_88X2011_LED_ACT, val); 251352cdd236Ssbehera val2 &= ~MRVL_88X2011_LED(MRVL_88X2011_LED_ACT, 251452cdd236Ssbehera MRVL_88X2011_LED_CTL_MASK); 251552cdd236Ssbehera val2 |= MRVL_88X2011_LED(MRVL_88X2011_LED_ACT, val); 251652cdd236Ssbehera 251752cdd236Ssbehera if (nxge_mdio_write(nxgep, phy, MRVL_88X2011_USER_DEV2_ADDR, 251852cdd236Ssbehera MRVL_88X2011_LED_8_TO_11_CTL, val2) != NXGE_OK) { 251952cdd236Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 252052cdd236Ssbehera "nxge_mrvl88x2011_led: nxge_mdio_write failed!!")); 252152cdd236Ssbehera } 252252cdd236Ssbehera } 252352cdd236Ssbehera 252452cdd236Ssbehera 252552cdd236Ssbehera static nxge_status_t 252652cdd236Ssbehera nxge_mrvl88x2011_xcvr_init(p_nxge_t nxgep) 252752cdd236Ssbehera { 252852cdd236Ssbehera uint8_t phy; 252952cdd236Ssbehera nxge_status_t status; 253052cdd236Ssbehera uint16_t clk; 253152cdd236Ssbehera 253252cdd236Ssbehera phy = nxgep->statsp->mac_stats.xcvr_portn; 253352cdd236Ssbehera 253452cdd236Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 253552cdd236Ssbehera "==> nxge_mrvl88x2011_xcvr_init: port<%d> addr<0x%x>", 253652cdd236Ssbehera nxgep->mac.portnum, phy)); 253752cdd236Ssbehera 253852cdd236Ssbehera /* Set LED functions */ 253952cdd236Ssbehera nxge_mrvl88x2011_led_blink_rate(nxgep, MRVL_88X2011_LED_BLK134MS); 254052cdd236Ssbehera /* PCS activity */ 254152cdd236Ssbehera nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_ACT); 254252cdd236Ssbehera 254352cdd236Ssbehera MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR, 254452cdd236Ssbehera MRVL_88X2011_GEN_CTL, &clk); 254552cdd236Ssbehera clk |= MRVL_88X2011_ENA_XFPREFCLK; 254652cdd236Ssbehera MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR, 254752cdd236Ssbehera MRVL_88X2011_GEN_CTL, clk); 254852cdd236Ssbehera 254952cdd236Ssbehera /* Set internal loopback mode if necessary */ 255052cdd236Ssbehera 255152cdd236Ssbehera CHK_STAT(nxge_mrvl88x2011_setup_lb(nxgep)); 255252cdd236Ssbehera 255352cdd236Ssbehera /* Enable PMD */ 255452cdd236Ssbehera MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR, 255552cdd236Ssbehera MRVL_88X2011_10G_PMD_TX_DIS, MRVL_88X2011_ENA_PMDTX); 255652cdd236Ssbehera 255752cdd236Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, " nxge_mrvl88x2011_reset: OK")); 255852cdd236Ssbehera 255952cdd236Ssbehera fail: 256052cdd236Ssbehera return (status); 256152cdd236Ssbehera } 256252cdd236Ssbehera 256352cdd236Ssbehera 256452cdd236Ssbehera 25652d17280bSsbehera /* Initialize the 10G Transceiver */ 25662d17280bSsbehera 25672d17280bSsbehera static nxge_status_t 25682d17280bSsbehera nxge_10G_xcvr_init(p_nxge_t nxgep) 25692d17280bSsbehera { 25702d17280bSsbehera p_nxge_stats_t statsp; 25711bd6825cSml p_nxge_param_t param_arr = nxgep->param_arr; 25722d17280bSsbehera nxge_status_t status = NXGE_OK; 25732d17280bSsbehera #ifdef NXGE_DEBUG 25742d17280bSsbehera uint8_t portn = nxgep->mac.portnum; 25752d17280bSsbehera #endif 25762d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>", 25772d17280bSsbehera portn)); 25782d17280bSsbehera 25792d17280bSsbehera statsp = nxgep->statsp; 25802d17280bSsbehera 25811c7408c9Stc /* Disable Link LEDs, with or without PHY */ 25821c7408c9Stc if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 25832d17280bSsbehera goto done; 25842d17280bSsbehera 25851c7408c9Stc /* Skip MDIO, if PHY absent */ 25861c7408c9Stc if (nxgep->mac.portmode == PORT_10G_SERDES || nxgep->phy_absent) { 25871c7408c9Stc goto done; 25881c7408c9Stc } 25892d17280bSsbehera 25902d17280bSsbehera /* Set Clause 45 */ 25912d17280bSsbehera npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE); 25922d17280bSsbehera 25932d17280bSsbehera switch (nxgep->chip_id) { 25942d17280bSsbehera case BCM8704_CHIP_ID: 259500161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_10G_xcvr_init: " 25962d17280bSsbehera "Chip ID 8704 [0x%x] for 10G xcvr", nxgep->chip_id)); 25972d17280bSsbehera status = nxge_BCM8704_xcvr_init(nxgep); 25982d17280bSsbehera break; 25992d17280bSsbehera case BCM8706_CHIP_ID: 260000161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_10G_xcvr_init: " 26012d17280bSsbehera "Chip ID 8706 [0x%x] for 10G xcvr", nxgep->chip_id)); 26022d17280bSsbehera status = nxge_BCM8706_xcvr_init(nxgep); 26032d17280bSsbehera break; 260452cdd236Ssbehera case MRVL88X201X_CHIP_ID: 260500161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_10G_xcvr_init: " 260652cdd236Ssbehera "Chip ID 8706 [0x%x] for 10G xcvr", nxgep->chip_id)); 260752cdd236Ssbehera status = nxge_mrvl88x2011_xcvr_init(nxgep); 260852cdd236Ssbehera break; 26092d17280bSsbehera default: 26102d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_xcvr_init: " 26112d17280bSsbehera "Unknown chip ID 0x%x for 10G xcvr addr[%d]", 26122d17280bSsbehera nxgep->chip_id, nxgep->statsp->mac_stats.xcvr_portn)); 26132d17280bSsbehera goto fail; 26142d17280bSsbehera } 26152d17280bSsbehera 26162d17280bSsbehera if (status != NXGE_OK) { 26172d17280bSsbehera goto fail; 26182d17280bSsbehera } 26192e59129aSraghus done: 262059ac0c16Sdavemq statsp->mac_stats.cap_10gfdx = 1; 262159ac0c16Sdavemq statsp->mac_stats.lp_cap_10gfdx = 1; 26221bd6825cSml statsp->mac_stats.adv_cap_asmpause = 26231bd6825cSml param_arr[param_anar_asmpause].value; 26241bd6825cSml statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value; 262544961713Sgirish 262659ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>", 262759ac0c16Sdavemq portn)); 262859ac0c16Sdavemq return (NXGE_OK); 262944961713Sgirish 263059ac0c16Sdavemq fail: 26312d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 263259ac0c16Sdavemq "nxge_10G_xcvr_init: failed to initialize transceiver for " 26332d17280bSsbehera "port<%d>", nxgep->mac.portnum)); 26342d17280bSsbehera return (NXGE_ERROR); 263559ac0c16Sdavemq } 263644961713Sgirish 263759ac0c16Sdavemq /* Initialize the 1G copper (BCM 5464) Transceiver */ 263844961713Sgirish 263959ac0c16Sdavemq static nxge_status_t 264059ac0c16Sdavemq nxge_1G_xcvr_init(p_nxge_t nxgep) 264159ac0c16Sdavemq { 264259ac0c16Sdavemq p_nxge_param_t param_arr = nxgep->param_arr; 264359ac0c16Sdavemq p_nxge_stats_t statsp = nxgep->statsp; 264459ac0c16Sdavemq nxge_status_t status = NXGE_OK; 264544961713Sgirish 26462e59129aSraghus if (nxgep->mac.portmode == PORT_1G_SERDES) { 26472e59129aSraghus statsp->mac_stats.cap_1000fdx = 26482e59129aSraghus param_arr[param_anar_1000fdx].value; 26492e59129aSraghus goto done; 26502e59129aSraghus } 26512e59129aSraghus 265259ac0c16Sdavemq /* Set Clause 22 */ 265359ac0c16Sdavemq npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_FALSE); 265444961713Sgirish 265559ac0c16Sdavemq /* Set capability flags */ 265659ac0c16Sdavemq statsp->mac_stats.cap_1000fdx = param_arr[param_anar_1000fdx].value; 26572e59129aSraghus if ((nxgep->mac.portmode == PORT_1G_COPPER) || 26582e59129aSraghus (nxgep->mac.portmode == PORT_1G_FIBER)) { 26592e59129aSraghus statsp->mac_stats.cap_100fdx = 26602e59129aSraghus param_arr[param_anar_100fdx].value; 26612e59129aSraghus statsp->mac_stats.cap_10fdx = 26622e59129aSraghus param_arr[param_anar_10fdx].value; 26632e59129aSraghus } 266444961713Sgirish 266559ac0c16Sdavemq status = nxge_mii_xcvr_init(nxgep); 26662e59129aSraghus done: 266759ac0c16Sdavemq return (status); 266859ac0c16Sdavemq } 266959ac0c16Sdavemq 267000161856Syc /* 267100161856Syc * Although the Teranetics copper transceiver (TN1010) does not need 267200161856Syc * to be initialized by the driver for passing packets, this funtion 267300161856Syc * initializes the members of nxgep->statsp->mac_stats struct for 267400161856Syc * kstat based on the value of nxgep->statsp->ports_stats.lb_mode. 267500161856Syc * It also configures the TN1010 for PHY loopback to support SunVTS. 267600161856Syc * 267700161856Syc * TN1010 only has the option to disable advertisement for the 10G 267800161856Syc * mode. So we can set it to either Dual Mode or 1G Only mode but 267900161856Syc * can't set it to 10G Only mode. 268000161856Syc * 268100161856Syc * ndd -set command can set the following 6 speed/duplex related parameters. 268200161856Syc * 268300161856Syc * ---------------------------------------------------------------- 268400161856Syc * ndd -set /dev/nxgeX param n kstat nxge:X | grep param 268500161856Syc * ---------------------------------------------------------------- 268600161856Syc * adv_autoneg_cap kstat nxge:1 | grep adv_cap_autoneg 268700161856Syc * adv_10gfdx_cap 268800161856Syc * adv_1000fdx_cap kstat nxge:1 | grep adv_cap_1000fdx 268900161856Syc * adv_100fdx_cap kstat nxge:1 | grep adv_cap_100fdx 269000161856Syc * adv_10fdx_cap kstat nxge:1 | grep adv_cap_10fdx 269100161856Syc * adv_pause_cap kstat nxge:1 | grep adv_cap_pause 269200161856Syc * ---------------------------------------------------------------- 269300161856Syc */ 269400161856Syc static nxge_status_t 269500161856Syc nxge_tn1010_xcvr_init(p_nxge_t nxgep) 269600161856Syc { 269700161856Syc p_nxge_param_t param_arr; 269800161856Syc p_nxge_stats_t statsp; 269900161856Syc tn1010_pcs_ctrl_t tn1010_pcs_ctrl; 270000161856Syc uint16_t speed; 270100161856Syc uint8_t phy_port_addr; 270200161856Syc uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 270300161856Syc int status = NXGE_OK; 270400161856Syc 270500161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_1G_tn1010_xcvr_init")); 270600161856Syc 270700161856Syc param_arr = nxgep->param_arr; 270800161856Syc statsp = nxgep->statsp; 270900161856Syc 271000161856Syc /* 271100161856Syc * Initialize the xcvr statistics which are NOT controlled by ndd 271200161856Syc */ 271300161856Syc statsp->mac_stats.cap_autoneg = 1; /* TN1010 autoneg is always on */ 271400161856Syc statsp->mac_stats.cap_100T4 = 0; 271500161856Syc 271600161856Syc /* 271700161856Syc * Read the TN1010 link speed and initialize capabilities kstat. Note 271800161856Syc * that function nxge_check_tn1010_link repeatedly invoked by the 271900161856Syc * timer will update link_speed real time. 272000161856Syc */ 272100161856Syc if (nxge_get_tn1010_speed(nxgep, &speed) != NXGE_OK) { 272200161856Syc goto fail; 272300161856Syc } 272400161856Syc if (speed == TN1010_SPEED_1G) { 272500161856Syc statsp->mac_stats.cap_10gfdx = 0; 272600161856Syc } else { 272700161856Syc statsp->mac_stats.cap_10gfdx = 1; 272800161856Syc } 272900161856Syc 273000161856Syc /* Whether we are in 1G or 10G mode, we always have the 1G capability */ 273100161856Syc statsp->mac_stats.cap_1000fdx = 1; 273200161856Syc 273300161856Syc /* TN1010 is not able to operate in the following states */ 273400161856Syc statsp->mac_stats.cap_1000hdx = 0; 273500161856Syc statsp->mac_stats.cap_100fdx = 0; 273600161856Syc statsp->mac_stats.cap_100hdx = 0; 273700161856Syc statsp->mac_stats.cap_10fdx = 0; 273800161856Syc statsp->mac_stats.cap_10hdx = 0; 273900161856Syc 274000161856Syc /* param_anar_pause can be modified by ndd -set */ 274100161856Syc statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value; 274200161856Syc 274300161856Syc /* 274400161856Syc * The following 4 lines actually overwrites what ever the ndd command 274500161856Syc * has set. For example, by command 274600161856Syc * ndd -set /dev/nxge1 adv_autoneg_cap n (n = 0 or 1) 274700161856Syc * we could set param_arr[param_autoneg].value to n. However, because 274800161856Syc * here we assign constants to these parameters, whatever we set with 274900161856Syc * the "ndd -set" command will be replaced. So command 275000161856Syc * kstat nxge:X | grep param 275100161856Syc * will always show those constant values. In other words, the 275200161856Syc * "ndd -set" command can NOT change the values of these 4 parameters 275300161856Syc * even though the command appears to be successful. 275400161856Syc * 275500161856Syc * Note: TN1010 auto negotiation is always enabled. 275600161856Syc */ 275700161856Syc statsp->mac_stats.adv_cap_autoneg 275800161856Syc = param_arr[param_autoneg].value = 1; 275900161856Syc statsp->mac_stats.adv_cap_1000fdx 276000161856Syc = param_arr[param_anar_1000fdx].value = 1; 276100161856Syc statsp->mac_stats.adv_cap_100fdx 276200161856Syc = param_arr[param_anar_100fdx].value = 0; 276300161856Syc statsp->mac_stats.adv_cap_10fdx 276400161856Syc = param_arr[param_anar_10fdx].value = 0; 276500161856Syc 276600161856Syc /* 276700161856Syc * The following 4 ndd params have type NXGE_PARAM_MAC_DONT_SHOW as 276800161856Syc * defined in nxge_param_arr[], therefore they are not seen by the 276900161856Syc * "ndd -get" command and can not be changed by ndd. We just set 277000161856Syc * them (both ndd param and kstat values) to constant 0 because TN1010 277100161856Syc * does not support those speeds. 277200161856Syc */ 277300161856Syc statsp->mac_stats.adv_cap_100T4 277400161856Syc = param_arr[param_anar_100T4].value = 0; 277500161856Syc statsp->mac_stats.adv_cap_1000hdx 277600161856Syc = param_arr[param_anar_1000hdx].value = 0; 277700161856Syc statsp->mac_stats.adv_cap_100hdx 277800161856Syc = param_arr[param_anar_100hdx].value = 0; 277900161856Syc statsp->mac_stats.adv_cap_10hdx 278000161856Syc = param_arr[param_anar_10hdx].value = 0; 278100161856Syc 278200161856Syc /* 278300161856Syc * adv_cap_pause has type NXGE_PARAM_MAC_RW, so it can be modified 278400161856Syc * by ndd 278500161856Syc */ 278600161856Syc statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value; 278700161856Syc 278800161856Syc /* 278900161856Syc * nxge_param_arr[] defines the adv_cap_asmpause with type 279000161856Syc * NXGE_PARAM_DONT_SHOW, therefore they are NOT seen by the 279100161856Syc * "ndd -get" command and can not be changed by ndd. Here we do not 279200161856Syc * assign a constant to it so the default value defined in 279300161856Syc * nxge_param_arr[] will be used to set the parameter and 279400161856Syc * will be shown by the kstat. 279500161856Syc */ 279600161856Syc statsp->mac_stats.adv_cap_asmpause 279700161856Syc = param_arr[param_anar_asmpause].value; 279800161856Syc 279900161856Syc /* 280000161856Syc * Initialize the link statistics. 280100161856Syc */ 280200161856Syc statsp->mac_stats.link_T4 = 0; 280300161856Syc statsp->mac_stats.link_asmpause = 0; 280400161856Syc statsp->mac_stats.link_pause = 0; 280500161856Syc if (speed == TN1010_SPEED_1G) { 280600161856Syc statsp->mac_stats.link_speed = 1000; 280700161856Syc statsp->mac_stats.link_duplex = 2; /* Full duplex */ 280800161856Syc statsp->mac_stats.link_up = 1; 280900161856Syc } else { 281000161856Syc statsp->mac_stats.link_speed = 10000; 281100161856Syc statsp->mac_stats.link_duplex = 2; 281200161856Syc statsp->mac_stats.link_up = 1; 281300161856Syc } 281400161856Syc 281500161856Syc /* 281600161856Syc * Because TN1010 does not have a link partner register, to 281700161856Syc * figure out the link partner's capabilities is tricky. Here we 281800161856Syc * just set the kstat based on our knowledge about the partner 281900161856Syc * (The partner must support auto-neg because auto-negotiation 282000161856Syc * has completed, it must support 1G or 10G because that is the 282100161856Syc * negotiated speed we are using.) 282200161856Syc * 282300161856Syc * Note: Current kstat does not show lp_cap_10gfdx and 282400161856Syc * lp_cap_10ghdx. 282500161856Syc */ 282600161856Syc if (speed == TN1010_SPEED_1G) { 282700161856Syc statsp->mac_stats.lp_cap_1000fdx = 1; 282800161856Syc statsp->mac_stats.lp_cap_10gfdx = 0; 282900161856Syc } else { 283000161856Syc statsp->mac_stats.lp_cap_1000fdx = 0; 283100161856Syc statsp->mac_stats.lp_cap_10gfdx = 1; 283200161856Syc } 283300161856Syc statsp->mac_stats.lp_cap_10ghdx = 0; 283400161856Syc statsp->mac_stats.lp_cap_1000hdx = 0; 283500161856Syc statsp->mac_stats.lp_cap_100fdx = 0; 283600161856Syc statsp->mac_stats.lp_cap_100hdx = 0; 283700161856Syc statsp->mac_stats.lp_cap_10fdx = 0; 283800161856Syc statsp->mac_stats.lp_cap_10hdx = 0; 283900161856Syc statsp->mac_stats.lp_cap_10gfdx = 0; 284000161856Syc statsp->mac_stats.lp_cap_10ghdx = 0; 284100161856Syc statsp->mac_stats.lp_cap_100T4 = 0; 284200161856Syc statsp->mac_stats.lp_cap_autoneg = 1; 284300161856Syc statsp->mac_stats.lp_cap_asmpause = 0; 284400161856Syc statsp->mac_stats.lp_cap_pause = 0; 284500161856Syc 284600161856Syc /* Handle PHY loopback for SunVTS loopback test */ 284700161856Syc npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE); 284800161856Syc phy_port_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 284900161856Syc 285000161856Syc if ((status = nxge_mdio_read(nxgep, phy_port_addr, 285100161856Syc TN1010_PCS_DEV_ADDR, TN1010_PCS_CONTROL_REG, 285200161856Syc &tn1010_pcs_ctrl.value)) != NXGE_OK) { 285300161856Syc goto fail; 285400161856Syc } 285500161856Syc if ((statsp->port_stats.lb_mode == nxge_lb_phy1000) || 285600161856Syc (statsp->port_stats.lb_mode == nxge_lb_phy10g)) { 285700161856Syc tn1010_pcs_ctrl.bits.loopback = 1; 285800161856Syc } else { 285900161856Syc tn1010_pcs_ctrl.bits.loopback = 0; 286000161856Syc } 286100161856Syc if ((status = nxge_mdio_write(nxgep, phy_port_addr, 286200161856Syc TN1010_PCS_DEV_ADDR, TN1010_PCS_CONTROL_REG, 286300161856Syc tn1010_pcs_ctrl.value)) != NXGE_OK) { 286400161856Syc goto fail; 286500161856Syc } 286600161856Syc 286700161856Syc statsp->mac_stats.xcvr_inits++; 286800161856Syc 286900161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 287000161856Syc "<== nxge_1G_tn1010_xcvr_init status 0x%x", status)); 287100161856Syc return (status); 287200161856Syc fail: 287300161856Syc NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 287400161856Syc "<== nxge_1G_tn1010_xcvr_init status 0x%x", status)); 287500161856Syc return (status); 287600161856Syc } 287700161856Syc 287859ac0c16Sdavemq /* Initialize transceiver */ 287959ac0c16Sdavemq 288059ac0c16Sdavemq nxge_status_t 288159ac0c16Sdavemq nxge_xcvr_init(p_nxge_t nxgep) 288259ac0c16Sdavemq { 288359ac0c16Sdavemq p_nxge_stats_t statsp; 288459ac0c16Sdavemq #ifdef NXGE_DEBUG 288559ac0c16Sdavemq uint8_t portn; 288644961713Sgirish #endif 288744961713Sgirish 288859ac0c16Sdavemq nxge_status_t status = NXGE_OK; 288959ac0c16Sdavemq #ifdef NXGE_DEBUG 289059ac0c16Sdavemq portn = nxgep->mac.portnum; 289159ac0c16Sdavemq #endif 289259ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", portn)); 289359ac0c16Sdavemq statsp = nxgep->statsp; 289444961713Sgirish 289559ac0c16Sdavemq /* 289600161856Syc * Initialize the xcvr statistics. nxgep->xcvr.xcvr_init will 289700161856Syc * modify mac_stats. 289859ac0c16Sdavemq */ 289959ac0c16Sdavemq statsp->mac_stats.cap_autoneg = 0; 290059ac0c16Sdavemq statsp->mac_stats.cap_100T4 = 0; 290159ac0c16Sdavemq statsp->mac_stats.cap_100fdx = 0; 290259ac0c16Sdavemq statsp->mac_stats.cap_100hdx = 0; 290359ac0c16Sdavemq statsp->mac_stats.cap_10fdx = 0; 290459ac0c16Sdavemq statsp->mac_stats.cap_10hdx = 0; 290559ac0c16Sdavemq statsp->mac_stats.cap_asmpause = 0; 290659ac0c16Sdavemq statsp->mac_stats.cap_pause = 0; 290759ac0c16Sdavemq statsp->mac_stats.cap_1000fdx = 0; 290859ac0c16Sdavemq statsp->mac_stats.cap_1000hdx = 0; 290959ac0c16Sdavemq statsp->mac_stats.cap_10gfdx = 0; 291059ac0c16Sdavemq statsp->mac_stats.cap_10ghdx = 0; 291159ac0c16Sdavemq 291259ac0c16Sdavemq /* 291359ac0c16Sdavemq * Initialize the link statistics. 291459ac0c16Sdavemq */ 291559ac0c16Sdavemq statsp->mac_stats.link_T4 = 0; 291659ac0c16Sdavemq statsp->mac_stats.link_asmpause = 0; 291759ac0c16Sdavemq statsp->mac_stats.link_pause = 0; 291844961713Sgirish 291959ac0c16Sdavemq if (nxgep->xcvr.xcvr_init) { 292059ac0c16Sdavemq status = nxgep->xcvr.xcvr_init(nxgep); 292159ac0c16Sdavemq if (status != NXGE_OK) 292244961713Sgirish goto fail; 292359ac0c16Sdavemq statsp->mac_stats.xcvr_inits++; 292444961713Sgirish } 292544961713Sgirish 292659ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", 292759ac0c16Sdavemq portn)); 292844961713Sgirish return (NXGE_OK); 292944961713Sgirish 293044961713Sgirish fail: 293144961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 293259ac0c16Sdavemq "nxge_xcvr_init: failed to initialize transceiver for port<%d>", 293359ac0c16Sdavemq portn)); 293444961713Sgirish return (status); 293544961713Sgirish } 293644961713Sgirish 29372e59129aSraghus /* Look for transceiver type */ 29382e59129aSraghus 29392e59129aSraghus nxge_status_t 29402e59129aSraghus nxge_xcvr_find(p_nxge_t nxgep) 29412e59129aSraghus { 2942d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_find: port<%d>", 2943d81011f0Ssbehera nxgep->mac.portnum)); 29442e59129aSraghus 29452e59129aSraghus if (nxge_get_xcvr_type(nxgep) != NXGE_OK) 29462e59129aSraghus return (NXGE_ERROR); 29472e59129aSraghus 29482e59129aSraghus if (nxge_setup_xcvr_table(nxgep) != NXGE_OK) 29492e59129aSraghus return (NXGE_ERROR); 29502e59129aSraghus 29512e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xcvr_find: xcvr_inuse = %d", 29522e59129aSraghus nxgep->statsp->mac_stats.xcvr_inuse)); 29532e59129aSraghus return (NXGE_OK); 29542e59129aSraghus } 295544961713Sgirish 295644961713Sgirish /* Initialize the TxMAC sub-block */ 295744961713Sgirish 295844961713Sgirish nxge_status_t 295944961713Sgirish nxge_tx_mac_init(p_nxge_t nxgep) 296044961713Sgirish { 296144961713Sgirish npi_attr_t ap; 296244961713Sgirish uint8_t portn; 296344961713Sgirish nxge_port_mode_t portmode; 296444961713Sgirish nxge_port_t portt; 296544961713Sgirish npi_handle_t handle; 296644961713Sgirish npi_status_t rs = NPI_SUCCESS; 296744961713Sgirish 296844961713Sgirish portn = NXGE_GET_PORT_NUM(nxgep->function_num); 296944961713Sgirish portt = nxgep->mac.porttype; 297044961713Sgirish handle = nxgep->npi_handle; 297144961713Sgirish portmode = nxgep->mac.portmode; 297244961713Sgirish 297344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_init: port<%d>", 297452ccf843Smisaki portn)); 297544961713Sgirish /* Set Max and Min Frame Size */ 29761bd6825cSml /* 29771bd6825cSml * Use maxframesize to configure the hardware maxframe size 297800161856Syc * and minframesize to configure the hardware minframe size. 29791bd6825cSml */ 29801bd6825cSml NXGE_DEBUG_MSG((nxgep, MAC_CTL, 29811bd6825cSml "==> nxge_tx_mac_init: port<%d> " 29821bd6825cSml "min framesize %d max framesize %d ", 29831bd6825cSml nxgep->mac.minframesize, 29841bd6825cSml nxgep->mac.maxframesize, 29851bd6825cSml portn)); 298644961713Sgirish 29871bd6825cSml SET_MAC_ATTR2(handle, ap, portn, 29881bd6825cSml MAC_PORT_FRAME_SIZE, 29891bd6825cSml nxgep->mac.minframesize, 29901bd6825cSml nxgep->mac.maxframesize, 29911bd6825cSml rs); 299244961713Sgirish if (rs != NPI_SUCCESS) 299344961713Sgirish goto fail; 299444961713Sgirish 299544961713Sgirish if (portt == PORT_TYPE_XMAC) { 299644961713Sgirish if ((rs = npi_xmac_tx_iconfig(handle, INIT, portn, 299752ccf843Smisaki 0)) != NPI_SUCCESS) 299844961713Sgirish goto fail; 299944961713Sgirish nxgep->mac.tx_iconfig = NXGE_XMAC_TX_INTRS; 300044961713Sgirish if ((portmode == PORT_10G_FIBER) || 30012e59129aSraghus (portmode == PORT_10G_COPPER) || 300200161856Syc (portmode == PORT_10G_TN1010) || 30031c7408c9Stc (portmode == PORT_HSP_MODE) || 30042e59129aSraghus (portmode == PORT_10G_SERDES)) { 300544961713Sgirish SET_MAC_ATTR1(handle, ap, portn, XMAC_10G_PORT_IPG, 300652ccf843Smisaki XGMII_IPG_12_15, rs); 300744961713Sgirish if (rs != NPI_SUCCESS) 300844961713Sgirish goto fail; 300944961713Sgirish nxgep->mac.ipg[0] = XGMII_IPG_12_15; 301044961713Sgirish } else { 301144961713Sgirish SET_MAC_ATTR1(handle, ap, portn, XMAC_PORT_IPG, 301252ccf843Smisaki MII_GMII_IPG_12, rs); 301344961713Sgirish if (rs != NPI_SUCCESS) 301444961713Sgirish goto fail; 301544961713Sgirish nxgep->mac.ipg[0] = MII_GMII_IPG_12; 301644961713Sgirish } 301744961713Sgirish if ((rs = npi_xmac_tx_config(handle, INIT, portn, 301852ccf843Smisaki CFG_XMAC_TX_CRC | CFG_XMAC_TX)) != NPI_SUCCESS) 301944961713Sgirish goto fail; 302044961713Sgirish nxgep->mac.tx_config = CFG_XMAC_TX_CRC | CFG_XMAC_TX; 302144961713Sgirish nxgep->mac.maxburstsize = 0; /* not programmable */ 302244961713Sgirish nxgep->mac.ctrltype = 0; /* not programmable */ 302344961713Sgirish nxgep->mac.pa_size = 0; /* not programmable */ 302444961713Sgirish 302544961713Sgirish if ((rs = npi_xmac_zap_tx_counters(handle, portn)) 302652ccf843Smisaki != NPI_SUCCESS) 302744961713Sgirish goto fail; 302844961713Sgirish 302944961713Sgirish } else { 303044961713Sgirish if ((rs = npi_bmac_tx_iconfig(handle, INIT, portn, 303152ccf843Smisaki 0)) != NPI_SUCCESS) 303244961713Sgirish goto fail; 303344961713Sgirish nxgep->mac.tx_iconfig = NXGE_BMAC_TX_INTRS; 303444961713Sgirish 303544961713Sgirish SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_CTRL_TYPE, 0x8808, 303652ccf843Smisaki rs); 303744961713Sgirish if (rs != NPI_SUCCESS) 303844961713Sgirish goto fail; 303944961713Sgirish nxgep->mac.ctrltype = 0x8808; 304044961713Sgirish 304144961713Sgirish SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_PA_SIZE, 0x7, rs); 304244961713Sgirish if (rs != NPI_SUCCESS) 304344961713Sgirish goto fail; 304444961713Sgirish nxgep->mac.pa_size = 0x7; 304544961713Sgirish 304644961713Sgirish if ((rs = npi_bmac_tx_config(handle, INIT, portn, 304752ccf843Smisaki CFG_BMAC_TX_CRC | CFG_BMAC_TX)) != NPI_SUCCESS) 304844961713Sgirish goto fail; 304944961713Sgirish nxgep->mac.tx_config = CFG_BMAC_TX_CRC | CFG_BMAC_TX; 305044961713Sgirish } 305144961713Sgirish 305244961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_init: port<%d>", 305352ccf843Smisaki portn)); 305444961713Sgirish 305544961713Sgirish return (NXGE_OK); 305644961713Sgirish fail: 305744961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 305852ccf843Smisaki "nxge_tx_mac_init: failed to initialize port<%d> TXMAC", portn)); 305944961713Sgirish 306044961713Sgirish return (NXGE_ERROR | rs); 306144961713Sgirish } 306244961713Sgirish 3063678453a8Sspeer 306444961713Sgirish /* Initialize the RxMAC sub-block */ 306544961713Sgirish 306644961713Sgirish nxge_status_t 306744961713Sgirish nxge_rx_mac_init(p_nxge_t nxgep) 306844961713Sgirish { 306944961713Sgirish npi_attr_t ap; 307044961713Sgirish uint32_t i; 307144961713Sgirish uint16_t hashtab_e; 307244961713Sgirish p_hash_filter_t hash_filter; 307344961713Sgirish nxge_port_t portt; 307444961713Sgirish uint8_t portn; 307544961713Sgirish npi_handle_t handle; 307644961713Sgirish npi_status_t rs = NPI_SUCCESS; 307744961713Sgirish uint16_t *addr16p; 307844961713Sgirish uint16_t addr0, addr1, addr2; 307944961713Sgirish xmac_rx_config_t xconfig; 308044961713Sgirish bmac_rx_config_t bconfig; 308144961713Sgirish 308244961713Sgirish portn = NXGE_GET_PORT_NUM(nxgep->function_num); 308344961713Sgirish 308444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_init: port<%d>\n", 308552ccf843Smisaki portn)); 308644961713Sgirish handle = nxgep->npi_handle; 308744961713Sgirish portt = nxgep->mac.porttype; 308844961713Sgirish 308944961713Sgirish addr16p = (uint16_t *)nxgep->ouraddr.ether_addr_octet; 309044961713Sgirish addr0 = ntohs(addr16p[2]); 309144961713Sgirish addr1 = ntohs(addr16p[1]); 309244961713Sgirish addr2 = ntohs(addr16p[0]); 309344961713Sgirish SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR, addr0, addr1, addr2, 309452ccf843Smisaki rs); 309544961713Sgirish 309644961713Sgirish if (rs != NPI_SUCCESS) 309744961713Sgirish goto fail; 309844961713Sgirish SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR_FILTER, 0, 0, 0, rs); 309944961713Sgirish if (rs != NPI_SUCCESS) 310044961713Sgirish goto fail; 310144961713Sgirish SET_MAC_ATTR2(handle, ap, portn, MAC_PORT_ADDR_FILTER_MASK, 0, 0, rs); 310244961713Sgirish if (rs != NPI_SUCCESS) 310344961713Sgirish goto fail; 310444961713Sgirish 310544961713Sgirish /* 310644961713Sgirish * Load the multicast hash filter bits. 310744961713Sgirish */ 310844961713Sgirish hash_filter = nxgep->hash_filter; 310944961713Sgirish for (i = 0; i < MAC_MAX_HASH_ENTRY; i++) { 311044961713Sgirish if (hash_filter != NULL) { 311144961713Sgirish hashtab_e = (uint16_t)hash_filter->hash_filter_regs[ 311252ccf843Smisaki (NMCFILTER_REGS - 1) - i]; 311344961713Sgirish } else { 311444961713Sgirish hashtab_e = 0; 311544961713Sgirish } 311644961713Sgirish 311744961713Sgirish if ((rs = npi_mac_hashtab_entry(handle, OP_SET, portn, i, 311852ccf843Smisaki (uint16_t *)&hashtab_e)) != NPI_SUCCESS) 311944961713Sgirish goto fail; 312044961713Sgirish } 312144961713Sgirish 312244961713Sgirish if (portt == PORT_TYPE_XMAC) { 312344961713Sgirish if ((rs = npi_xmac_rx_iconfig(handle, INIT, portn, 312452ccf843Smisaki 0)) != NPI_SUCCESS) 312544961713Sgirish goto fail; 312644961713Sgirish nxgep->mac.rx_iconfig = NXGE_XMAC_RX_INTRS; 312744961713Sgirish 312844961713Sgirish (void) nxge_fflp_init_hostinfo(nxgep); 312944961713Sgirish 313044961713Sgirish xconfig = CFG_XMAC_RX_ERRCHK | CFG_XMAC_RX_CRC_CHK | 313152ccf843Smisaki CFG_XMAC_RX | CFG_XMAC_RX_CODE_VIO_CHK & 313252ccf843Smisaki ~CFG_XMAC_RX_STRIP_CRC; 313344961713Sgirish 313444961713Sgirish if (nxgep->filter.all_phys_cnt != 0) 313544961713Sgirish xconfig |= CFG_XMAC_RX_PROMISCUOUS; 313644961713Sgirish 313744961713Sgirish if (nxgep->filter.all_multicast_cnt != 0) 313844961713Sgirish xconfig |= CFG_XMAC_RX_PROMISCUOUSGROUP; 313944961713Sgirish 314044961713Sgirish xconfig |= CFG_XMAC_RX_HASH_FILTER; 314144961713Sgirish 314244961713Sgirish if ((rs = npi_xmac_rx_config(handle, INIT, portn, 314352ccf843Smisaki xconfig)) != NPI_SUCCESS) 314444961713Sgirish goto fail; 314544961713Sgirish nxgep->mac.rx_config = xconfig; 314644961713Sgirish 314744961713Sgirish /* Comparison of mac unique address is always enabled on XMAC */ 314844961713Sgirish 314944961713Sgirish if ((rs = npi_xmac_zap_rx_counters(handle, portn)) 315052ccf843Smisaki != NPI_SUCCESS) 315144961713Sgirish goto fail; 315244961713Sgirish } else { 315344961713Sgirish (void) nxge_fflp_init_hostinfo(nxgep); 315444961713Sgirish 315544961713Sgirish if (npi_bmac_rx_iconfig(nxgep->npi_handle, INIT, portn, 315652ccf843Smisaki 0) != NPI_SUCCESS) 315744961713Sgirish goto fail; 315844961713Sgirish nxgep->mac.rx_iconfig = NXGE_BMAC_RX_INTRS; 315944961713Sgirish 3160a3c5bd6dSspeer bconfig = CFG_BMAC_RX_DISCARD_ON_ERR | CFG_BMAC_RX & 316152ccf843Smisaki ~CFG_BMAC_RX_STRIP_CRC; 316244961713Sgirish 316344961713Sgirish if (nxgep->filter.all_phys_cnt != 0) 316444961713Sgirish bconfig |= CFG_BMAC_RX_PROMISCUOUS; 316544961713Sgirish 316644961713Sgirish if (nxgep->filter.all_multicast_cnt != 0) 316744961713Sgirish bconfig |= CFG_BMAC_RX_PROMISCUOUSGROUP; 316844961713Sgirish 316944961713Sgirish bconfig |= CFG_BMAC_RX_HASH_FILTER; 317044961713Sgirish if ((rs = npi_bmac_rx_config(handle, INIT, portn, 317152ccf843Smisaki bconfig)) != NPI_SUCCESS) 317244961713Sgirish goto fail; 317344961713Sgirish nxgep->mac.rx_config = bconfig; 317444961713Sgirish 317544961713Sgirish /* Always enable comparison of mac unique address */ 317644961713Sgirish if ((rs = npi_mac_altaddr_enable(handle, portn, 0)) 317752ccf843Smisaki != NPI_SUCCESS) 317844961713Sgirish goto fail; 317944961713Sgirish } 318044961713Sgirish 318144961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_init: port<%d>\n", 318252ccf843Smisaki portn)); 318344961713Sgirish 318444961713Sgirish return (NXGE_OK); 318544961713Sgirish 318644961713Sgirish fail: 318744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 318852ccf843Smisaki "nxge_rx_mac_init: Failed to Initialize port<%d> RxMAC", portn)); 318944961713Sgirish 319044961713Sgirish return (NXGE_ERROR | rs); 319144961713Sgirish } 319244961713Sgirish 319344961713Sgirish /* Enable TXMAC */ 319444961713Sgirish 319544961713Sgirish nxge_status_t 319644961713Sgirish nxge_tx_mac_enable(p_nxge_t nxgep) 319744961713Sgirish { 319844961713Sgirish npi_handle_t handle; 319944961713Sgirish npi_status_t rs = NPI_SUCCESS; 320044961713Sgirish nxge_status_t status = NXGE_OK; 320144961713Sgirish 320244961713Sgirish handle = nxgep->npi_handle; 320344961713Sgirish 320444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_enable: port<%d>", 320552ccf843Smisaki nxgep->mac.portnum)); 320644961713Sgirish 320744961713Sgirish if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK) 320844961713Sgirish goto fail; 320944961713Sgirish 321044961713Sgirish /* based on speed */ 321144961713Sgirish nxgep->msg_min = ETHERMIN; 321244961713Sgirish 321344961713Sgirish if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 321444961713Sgirish if ((rs = npi_xmac_tx_config(handle, ENABLE, nxgep->mac.portnum, 321552ccf843Smisaki CFG_XMAC_TX)) != NPI_SUCCESS) 321644961713Sgirish goto fail; 321744961713Sgirish } else { 321844961713Sgirish if ((rs = npi_bmac_tx_config(handle, ENABLE, nxgep->mac.portnum, 321952ccf843Smisaki CFG_BMAC_TX)) != NPI_SUCCESS) 322044961713Sgirish goto fail; 322144961713Sgirish } 322244961713Sgirish 322344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_enable: port<%d>", 322452ccf843Smisaki nxgep->mac.portnum)); 322544961713Sgirish 322644961713Sgirish return (NXGE_OK); 322744961713Sgirish fail: 322844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 322952ccf843Smisaki "nxgep_tx_mac_enable: Failed to enable port<%d> TxMAC", 323052ccf843Smisaki nxgep->mac.portnum)); 323144961713Sgirish if (rs != NPI_SUCCESS) 323244961713Sgirish return (NXGE_ERROR | rs); 323344961713Sgirish else 323444961713Sgirish return (status); 323544961713Sgirish } 323644961713Sgirish 323744961713Sgirish /* Disable TXMAC */ 323844961713Sgirish 323944961713Sgirish nxge_status_t 324044961713Sgirish nxge_tx_mac_disable(p_nxge_t nxgep) 324144961713Sgirish { 324244961713Sgirish npi_handle_t handle; 324344961713Sgirish npi_status_t rs = NPI_SUCCESS; 324444961713Sgirish 3245678453a8Sspeer if (isLDOMguest(nxgep)) 3246678453a8Sspeer return (NXGE_OK); 3247678453a8Sspeer 324844961713Sgirish handle = nxgep->npi_handle; 324944961713Sgirish 325044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_disable: port<%d>", 325152ccf843Smisaki nxgep->mac.portnum)); 325244961713Sgirish 325344961713Sgirish if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 325444961713Sgirish if ((rs = npi_xmac_tx_config(handle, DISABLE, 325552ccf843Smisaki nxgep->mac.portnum, CFG_XMAC_TX)) != NPI_SUCCESS) 325644961713Sgirish goto fail; 325744961713Sgirish } else { 325844961713Sgirish if ((rs = npi_bmac_tx_config(handle, DISABLE, 325952ccf843Smisaki nxgep->mac.portnum, CFG_BMAC_TX)) != NPI_SUCCESS) 326044961713Sgirish goto fail; 326144961713Sgirish } 326244961713Sgirish 326344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_disable: port<%d>", 326452ccf843Smisaki nxgep->mac.portnum)); 326544961713Sgirish return (NXGE_OK); 326644961713Sgirish fail: 326744961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 326852ccf843Smisaki "nxge_tx_mac_disable: Failed to disable port<%d> TxMAC", 326952ccf843Smisaki nxgep->mac.portnum)); 327044961713Sgirish return (NXGE_ERROR | rs); 327144961713Sgirish } 327244961713Sgirish 327344961713Sgirish /* Enable RXMAC */ 327444961713Sgirish 327544961713Sgirish nxge_status_t 327644961713Sgirish nxge_rx_mac_enable(p_nxge_t nxgep) 327744961713Sgirish { 327844961713Sgirish npi_handle_t handle; 327944961713Sgirish uint8_t portn; 328044961713Sgirish npi_status_t rs = NPI_SUCCESS; 328144961713Sgirish nxge_status_t status = NXGE_OK; 328244961713Sgirish 3283678453a8Sspeer /* This is a service-domain-only activity. */ 3284678453a8Sspeer if (isLDOMguest(nxgep)) 3285678453a8Sspeer return (status); 3286678453a8Sspeer 328744961713Sgirish handle = nxgep->npi_handle; 328844961713Sgirish portn = nxgep->mac.portnum; 328944961713Sgirish 329044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_enable: port<%d>", 329152ccf843Smisaki portn)); 329244961713Sgirish 329344961713Sgirish if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK) 329444961713Sgirish goto fail; 329544961713Sgirish 329644961713Sgirish if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 329744961713Sgirish if ((rs = npi_xmac_rx_config(handle, ENABLE, portn, 3298678453a8Sspeer CFG_XMAC_RX)) != NPI_SUCCESS) 329944961713Sgirish goto fail; 330044961713Sgirish } else { 330144961713Sgirish if ((rs = npi_bmac_rx_config(handle, ENABLE, portn, 3302678453a8Sspeer CFG_BMAC_RX)) != NPI_SUCCESS) 330344961713Sgirish goto fail; 330444961713Sgirish } 330544961713Sgirish 3306678453a8Sspeer NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3307678453a8Sspeer "<== nxge_rx_mac_enable: port<%d>", portn)); 330844961713Sgirish 330944961713Sgirish return (NXGE_OK); 331044961713Sgirish fail: 331144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3312678453a8Sspeer "nxgep_rx_mac_enable: Failed to enable port<%d> RxMAC", portn)); 331344961713Sgirish 331444961713Sgirish if (rs != NPI_SUCCESS) 331544961713Sgirish return (NXGE_ERROR | rs); 331644961713Sgirish else 331744961713Sgirish return (status); 331844961713Sgirish } 331944961713Sgirish 332044961713Sgirish /* Disable RXMAC */ 332144961713Sgirish 332244961713Sgirish nxge_status_t 332344961713Sgirish nxge_rx_mac_disable(p_nxge_t nxgep) 332444961713Sgirish { 332544961713Sgirish npi_handle_t handle; 332644961713Sgirish uint8_t portn; 332744961713Sgirish npi_status_t rs = NPI_SUCCESS; 332844961713Sgirish 3329678453a8Sspeer /* If we are a guest domain driver, don't bother. */ 3330678453a8Sspeer if (isLDOMguest(nxgep)) 3331678453a8Sspeer return (NXGE_OK); 3332678453a8Sspeer 333344961713Sgirish handle = nxgep->npi_handle; 333444961713Sgirish portn = nxgep->mac.portnum; 333544961713Sgirish 333644961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_disable: port<%d>", 333752ccf843Smisaki portn)); 333844961713Sgirish 333944961713Sgirish if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 334044961713Sgirish if ((rs = npi_xmac_rx_config(handle, DISABLE, portn, 334152ccf843Smisaki CFG_XMAC_RX)) != NPI_SUCCESS) 334244961713Sgirish goto fail; 334344961713Sgirish } else { 334444961713Sgirish if ((rs = npi_bmac_rx_config(handle, DISABLE, portn, 334552ccf843Smisaki CFG_BMAC_RX)) != NPI_SUCCESS) 334644961713Sgirish goto fail; 334744961713Sgirish } 334844961713Sgirish 334944961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_disable: port<%d>", 335052ccf843Smisaki portn)); 335144961713Sgirish return (NXGE_OK); 335244961713Sgirish fail: 335344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 335452ccf843Smisaki "nxgep_rx_mac_disable: Failed to disable port<%d> RxMAC", portn)); 335544961713Sgirish 335644961713Sgirish return (NXGE_ERROR | rs); 335744961713Sgirish } 335844961713Sgirish 335944961713Sgirish /* Reset TXMAC */ 336044961713Sgirish 336144961713Sgirish nxge_status_t 336244961713Sgirish nxge_tx_mac_reset(p_nxge_t nxgep) 336344961713Sgirish { 336444961713Sgirish npi_handle_t handle; 336544961713Sgirish uint8_t portn; 336644961713Sgirish npi_status_t rs = NPI_SUCCESS; 336744961713Sgirish 336844961713Sgirish handle = nxgep->npi_handle; 336944961713Sgirish portn = nxgep->mac.portnum; 337044961713Sgirish 337144961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_reset: port<%d>", 337252ccf843Smisaki portn)); 337344961713Sgirish 337444961713Sgirish if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 337544961713Sgirish if ((rs = npi_xmac_reset(handle, portn, XTX_MAC_RESET_ALL)) 337644961713Sgirish != NPI_SUCCESS) 337744961713Sgirish goto fail; 337844961713Sgirish } else { 337944961713Sgirish if ((rs = npi_bmac_reset(handle, portn, TX_MAC_RESET)) 338052ccf843Smisaki != NPI_SUCCESS) 338144961713Sgirish goto fail; 338244961713Sgirish } 338344961713Sgirish 338444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_reset: port<%d>", 338552ccf843Smisaki portn)); 338644961713Sgirish 338744961713Sgirish return (NXGE_OK); 338844961713Sgirish fail: 338944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 339052ccf843Smisaki "nxge_tx_mac_reset: Failed to Reset TxMAC port<%d>", portn)); 339144961713Sgirish 339244961713Sgirish return (NXGE_ERROR | rs); 339344961713Sgirish } 339444961713Sgirish 339544961713Sgirish /* Reset RXMAC */ 339644961713Sgirish 339744961713Sgirish nxge_status_t 339844961713Sgirish nxge_rx_mac_reset(p_nxge_t nxgep) 339944961713Sgirish { 340044961713Sgirish npi_handle_t handle; 340144961713Sgirish uint8_t portn; 340244961713Sgirish npi_status_t rs = NPI_SUCCESS; 340344961713Sgirish 340444961713Sgirish handle = nxgep->npi_handle; 340544961713Sgirish portn = nxgep->mac.portnum; 340644961713Sgirish 340744961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_reset: port<%d>", 340852ccf843Smisaki portn)); 340944961713Sgirish 341044961713Sgirish if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 341144961713Sgirish if ((rs = npi_xmac_reset(handle, portn, XRX_MAC_RESET_ALL)) 341244961713Sgirish != NPI_SUCCESS) 341344961713Sgirish goto fail; 341444961713Sgirish } else { 341544961713Sgirish if ((rs = npi_bmac_reset(handle, portn, RX_MAC_RESET)) 341652ccf843Smisaki != NPI_SUCCESS) 341744961713Sgirish goto fail; 341844961713Sgirish } 341944961713Sgirish 342044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_reset: port<%d>", 342152ccf843Smisaki portn)); 342244961713Sgirish 342359ac0c16Sdavemq return (NXGE_OK); 342459ac0c16Sdavemq fail: 342559ac0c16Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 342652ccf843Smisaki "nxge_rx_mac_reset: Failed to Reset RxMAC port<%d>", portn)); 342759ac0c16Sdavemq return (NXGE_ERROR | rs); 342859ac0c16Sdavemq } 342959ac0c16Sdavemq 343059ac0c16Sdavemq /* 10G fiber link interrupt start routine */ 343159ac0c16Sdavemq 343259ac0c16Sdavemq static nxge_status_t 343359ac0c16Sdavemq nxge_10G_link_intr_start(p_nxge_t nxgep) 343459ac0c16Sdavemq { 343559ac0c16Sdavemq npi_status_t rs = NPI_SUCCESS; 343659ac0c16Sdavemq uint8_t portn = nxgep->mac.portnum; 343759ac0c16Sdavemq 343859ac0c16Sdavemq rs = npi_xmac_xpcs_link_intr_enable(nxgep->npi_handle, portn); 343959ac0c16Sdavemq 344059ac0c16Sdavemq if (rs != NPI_SUCCESS) 344159ac0c16Sdavemq return (NXGE_ERROR | rs); 344259ac0c16Sdavemq else 344359ac0c16Sdavemq return (NXGE_OK); 344459ac0c16Sdavemq } 344559ac0c16Sdavemq 344659ac0c16Sdavemq /* 10G fiber link interrupt stop routine */ 344759ac0c16Sdavemq 344859ac0c16Sdavemq static nxge_status_t 344959ac0c16Sdavemq nxge_10G_link_intr_stop(p_nxge_t nxgep) 345059ac0c16Sdavemq { 345159ac0c16Sdavemq npi_status_t rs = NPI_SUCCESS; 345259ac0c16Sdavemq uint8_t portn = nxgep->mac.portnum; 345359ac0c16Sdavemq 345459ac0c16Sdavemq rs = npi_xmac_xpcs_link_intr_disable(nxgep->npi_handle, portn); 345559ac0c16Sdavemq 345659ac0c16Sdavemq if (rs != NPI_SUCCESS) 345759ac0c16Sdavemq return (NXGE_ERROR | rs); 345859ac0c16Sdavemq else 345959ac0c16Sdavemq return (NXGE_OK); 346059ac0c16Sdavemq } 346159ac0c16Sdavemq 346259ac0c16Sdavemq /* 1G fiber link interrupt start routine */ 346359ac0c16Sdavemq 346459ac0c16Sdavemq static nxge_status_t 346559ac0c16Sdavemq nxge_1G_fiber_link_intr_start(p_nxge_t nxgep) 346659ac0c16Sdavemq { 346759ac0c16Sdavemq npi_status_t rs = NPI_SUCCESS; 346859ac0c16Sdavemq uint8_t portn = nxgep->mac.portnum; 346959ac0c16Sdavemq 347059ac0c16Sdavemq rs = npi_mac_pcs_link_intr_enable(nxgep->npi_handle, portn); 347159ac0c16Sdavemq if (rs != NPI_SUCCESS) 347259ac0c16Sdavemq return (NXGE_ERROR | rs); 347359ac0c16Sdavemq else 347459ac0c16Sdavemq return (NXGE_OK); 347559ac0c16Sdavemq } 347659ac0c16Sdavemq 347759ac0c16Sdavemq /* 1G fiber link interrupt stop routine */ 347859ac0c16Sdavemq 347959ac0c16Sdavemq static nxge_status_t 348059ac0c16Sdavemq nxge_1G_fiber_link_intr_stop(p_nxge_t nxgep) 348159ac0c16Sdavemq { 348259ac0c16Sdavemq npi_status_t rs = NPI_SUCCESS; 348359ac0c16Sdavemq uint8_t portn = nxgep->mac.portnum; 348459ac0c16Sdavemq 348559ac0c16Sdavemq rs = npi_mac_pcs_link_intr_disable(nxgep->npi_handle, portn); 348659ac0c16Sdavemq 348759ac0c16Sdavemq if (rs != NPI_SUCCESS) 348859ac0c16Sdavemq return (NXGE_ERROR | rs); 348959ac0c16Sdavemq else 349059ac0c16Sdavemq return (NXGE_OK); 349159ac0c16Sdavemq } 349259ac0c16Sdavemq 349359ac0c16Sdavemq /* 1G copper link interrupt start routine */ 349459ac0c16Sdavemq 349559ac0c16Sdavemq static nxge_status_t 349659ac0c16Sdavemq nxge_1G_copper_link_intr_start(p_nxge_t nxgep) 349759ac0c16Sdavemq { 349859ac0c16Sdavemq npi_status_t rs = NPI_SUCCESS; 349959ac0c16Sdavemq uint8_t portn = nxgep->mac.portnum; 350059ac0c16Sdavemq 350159ac0c16Sdavemq rs = npi_mac_mif_link_intr_enable(nxgep->npi_handle, portn, 35026b438925Ssbehera MII_STATUS, MII_STATUS_LINKUP); 350359ac0c16Sdavemq 350459ac0c16Sdavemq if (rs != NPI_SUCCESS) 350559ac0c16Sdavemq return (NXGE_ERROR | rs); 350659ac0c16Sdavemq else 350759ac0c16Sdavemq return (NXGE_OK); 350844961713Sgirish } 350944961713Sgirish 351059ac0c16Sdavemq /* 1G copper link interrupt stop routine */ 351159ac0c16Sdavemq 351259ac0c16Sdavemq static nxge_status_t 351359ac0c16Sdavemq nxge_1G_copper_link_intr_stop(p_nxge_t nxgep) 351459ac0c16Sdavemq { 351559ac0c16Sdavemq npi_status_t rs = NPI_SUCCESS; 351659ac0c16Sdavemq uint8_t portn = nxgep->mac.portnum; 351759ac0c16Sdavemq 351859ac0c16Sdavemq rs = npi_mac_mif_link_intr_disable(nxgep->npi_handle, portn); 351959ac0c16Sdavemq 352059ac0c16Sdavemq if (rs != NPI_SUCCESS) 352159ac0c16Sdavemq return (NXGE_ERROR | rs); 352259ac0c16Sdavemq else 352359ac0c16Sdavemq return (NXGE_OK); 352459ac0c16Sdavemq } 352544961713Sgirish 352659ac0c16Sdavemq /* Enable/Disable Link Status change interrupt */ 352744961713Sgirish 352844961713Sgirish nxge_status_t 352944961713Sgirish nxge_link_intr(p_nxge_t nxgep, link_intr_enable_t enable) 353044961713Sgirish { 353159ac0c16Sdavemq uint8_t portn; 353259ac0c16Sdavemq nxge_status_t status = NXGE_OK; 353344961713Sgirish 353444961713Sgirish portn = nxgep->mac.portnum; 353544961713Sgirish 353644961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_intr: port<%d>", portn)); 353759ac0c16Sdavemq if (!nxgep->xcvr.link_intr_stop || !nxgep->xcvr.link_intr_start) 353859ac0c16Sdavemq return (NXGE_OK); 353944961713Sgirish 354059ac0c16Sdavemq if (enable == LINK_INTR_START) 354159ac0c16Sdavemq status = nxgep->xcvr.link_intr_start(nxgep); 354259ac0c16Sdavemq else if (enable == LINK_INTR_STOP) 354359ac0c16Sdavemq status = nxgep->xcvr.link_intr_stop(nxgep); 354459ac0c16Sdavemq if (status != NXGE_OK) 354559ac0c16Sdavemq goto fail; 354644961713Sgirish 354744961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_intr: port<%d>", portn)); 354844961713Sgirish 354944961713Sgirish return (NXGE_OK); 355044961713Sgirish fail: 355144961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 355252ccf843Smisaki "nxge_link_intr: Failed to set port<%d> mif intr mode", portn)); 355344961713Sgirish 355459ac0c16Sdavemq return (status); 355544961713Sgirish } 355644961713Sgirish 355744961713Sgirish /* Initialize 1G Fiber / Copper transceiver using Clause 22 */ 355844961713Sgirish 355944961713Sgirish nxge_status_t 356044961713Sgirish nxge_mii_xcvr_init(p_nxge_t nxgep) 356144961713Sgirish { 356244961713Sgirish p_nxge_param_t param_arr; 356344961713Sgirish p_nxge_stats_t statsp; 356444961713Sgirish uint8_t xcvr_portn; 356544961713Sgirish p_mii_regs_t mii_regs; 356644961713Sgirish mii_bmcr_t bmcr; 356744961713Sgirish mii_bmsr_t bmsr; 356844961713Sgirish mii_anar_t anar; 356944961713Sgirish mii_gcr_t gcr; 357044961713Sgirish mii_esr_t esr; 357144961713Sgirish mii_aux_ctl_t bcm5464r_aux; 357244961713Sgirish int status = NXGE_OK; 357344961713Sgirish 357444961713Sgirish uint_t delay; 357544961713Sgirish 357644961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_init")); 357744961713Sgirish 357844961713Sgirish param_arr = nxgep->param_arr; 357944961713Sgirish statsp = nxgep->statsp; 358044961713Sgirish xcvr_portn = statsp->mac_stats.xcvr_portn; 358144961713Sgirish 358244961713Sgirish mii_regs = NULL; 358344961713Sgirish 358444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 358552ccf843Smisaki "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value)); 358644961713Sgirish 3587d81011f0Ssbehera /* 3588d81011f0Ssbehera * The mif phy mode may be connected to either a copper link 3589d81011f0Ssbehera * or fiber link. Read the mode control register to get the fiber 3590d81011f0Ssbehera * configuration if it is hard-wired to fiber link. 3591d81011f0Ssbehera */ 3592d81011f0Ssbehera (void) nxge_mii_get_link_mode(nxgep); 3593d81011f0Ssbehera if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) { 3594d81011f0Ssbehera return (nxge_mii_xcvr_fiber_init(nxgep)); 3595d81011f0Ssbehera } 3596d81011f0Ssbehera 359744961713Sgirish /* 359844961713Sgirish * Reset the transceiver. 359944961713Sgirish */ 360044961713Sgirish delay = 0; 360144961713Sgirish bmcr.value = 0; 360244961713Sgirish bmcr.bits.reset = 1; 360344961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 3604adfcba55Sjoycey #if defined(__i386) 360552ccf843Smisaki (uint8_t)(uint32_t)&mii_regs->bmcr, 3606adfcba55Sjoycey #else 360752ccf843Smisaki (uint8_t)(uint64_t)&mii_regs->bmcr, 3608adfcba55Sjoycey #endif 360952ccf843Smisaki bmcr.value)) != NXGE_OK) 361044961713Sgirish goto fail; 361144961713Sgirish do { 361244961713Sgirish drv_usecwait(500); 361344961713Sgirish if ((status = nxge_mii_read(nxgep, xcvr_portn, 3614adfcba55Sjoycey #if defined(__i386) 361552ccf843Smisaki (uint8_t)(uint32_t)&mii_regs->bmcr, 3616adfcba55Sjoycey #else 361752ccf843Smisaki (uint8_t)(uint64_t)&mii_regs->bmcr, 3618adfcba55Sjoycey #endif 361952ccf843Smisaki &bmcr.value)) != NXGE_OK) 362044961713Sgirish goto fail; 362144961713Sgirish delay++; 362244961713Sgirish } while ((bmcr.bits.reset) && (delay < 1000)); 362344961713Sgirish if (delay == 1000) { 362444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed.")); 362544961713Sgirish goto fail; 362644961713Sgirish } 362744961713Sgirish 362844961713Sgirish if ((status = nxge_mii_read(nxgep, xcvr_portn, 3629adfcba55Sjoycey #if defined(__i386) 363052ccf843Smisaki (uint8_t)(uint32_t)(&mii_regs->bmsr), 3631adfcba55Sjoycey #else 363252ccf843Smisaki (uint8_t)(uint64_t)(&mii_regs->bmsr), 3633adfcba55Sjoycey #endif 363452ccf843Smisaki &bmsr.value)) != NXGE_OK) 363544961713Sgirish goto fail; 363644961713Sgirish 363744961713Sgirish param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able; 363844961713Sgirish param_arr[param_anar_100T4].value &= bmsr.bits.link_100T4; 363944961713Sgirish param_arr[param_anar_100fdx].value &= bmsr.bits.link_100fdx; 364044961713Sgirish param_arr[param_anar_100hdx].value = 0; 364144961713Sgirish param_arr[param_anar_10fdx].value &= bmsr.bits.link_10fdx; 364244961713Sgirish param_arr[param_anar_10hdx].value = 0; 364344961713Sgirish 364444961713Sgirish /* 364558324dfcSspeer * Initialize the xcvr statistics. 364644961713Sgirish */ 364744961713Sgirish statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able; 364844961713Sgirish statsp->mac_stats.cap_100T4 = bmsr.bits.link_100T4; 364944961713Sgirish statsp->mac_stats.cap_100fdx = bmsr.bits.link_100fdx; 365044961713Sgirish statsp->mac_stats.cap_100hdx = 0; 365144961713Sgirish statsp->mac_stats.cap_10fdx = bmsr.bits.link_10fdx; 365244961713Sgirish statsp->mac_stats.cap_10hdx = 0; 365344961713Sgirish statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value; 365444961713Sgirish statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value; 365544961713Sgirish 365644961713Sgirish /* 365700161856Syc * Initialize the xcvr advertised capability statistics. 365844961713Sgirish */ 365944961713Sgirish statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value; 366044961713Sgirish statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 366144961713Sgirish statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 366244961713Sgirish statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value; 366344961713Sgirish statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value; 366444961713Sgirish statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value; 366544961713Sgirish statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value; 366644961713Sgirish statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value; 366744961713Sgirish statsp->mac_stats.adv_cap_asmpause = 366852ccf843Smisaki param_arr[param_anar_asmpause].value; 366944961713Sgirish statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value; 367044961713Sgirish 367144961713Sgirish 367244961713Sgirish /* 367344961713Sgirish * Check for extended status just in case we're 367444961713Sgirish * running a Gigibit phy. 367544961713Sgirish */ 367644961713Sgirish if (bmsr.bits.extend_status) { 367744961713Sgirish if ((status = nxge_mii_read(nxgep, xcvr_portn, 3678adfcba55Sjoycey #if defined(__i386) 367952ccf843Smisaki (uint8_t)(uint32_t)(&mii_regs->esr), 3680adfcba55Sjoycey #else 368152ccf843Smisaki (uint8_t)(uint64_t)(&mii_regs->esr), 3682adfcba55Sjoycey #endif 368352ccf843Smisaki &esr.value)) != NXGE_OK) 368444961713Sgirish goto fail; 368552ccf843Smisaki param_arr[param_anar_1000fdx].value &= esr.bits.link_1000fdx; 368644961713Sgirish param_arr[param_anar_1000hdx].value = 0; 368744961713Sgirish 368844961713Sgirish statsp->mac_stats.cap_1000fdx = 368952ccf843Smisaki (esr.bits.link_1000Xfdx || esr.bits.link_1000fdx); 369044961713Sgirish statsp->mac_stats.cap_1000hdx = 0; 369144961713Sgirish } else { 369244961713Sgirish param_arr[param_anar_1000fdx].value = 0; 369344961713Sgirish param_arr[param_anar_1000hdx].value = 0; 369444961713Sgirish } 369544961713Sgirish 369644961713Sgirish /* 369744961713Sgirish * Initialize 1G Statistics once the capability is established. 369844961713Sgirish */ 369944961713Sgirish statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 370044961713Sgirish statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 370144961713Sgirish 370244961713Sgirish /* 370300161856Syc * Initialize the link statistics. 370444961713Sgirish */ 370544961713Sgirish statsp->mac_stats.link_T4 = 0; 370644961713Sgirish statsp->mac_stats.link_asmpause = 0; 370744961713Sgirish statsp->mac_stats.link_pause = 0; 370844961713Sgirish statsp->mac_stats.link_speed = 0; 370944961713Sgirish statsp->mac_stats.link_duplex = 0; 371044961713Sgirish statsp->mac_stats.link_up = 0; 371144961713Sgirish 371244961713Sgirish /* 371344961713Sgirish * Switch off Auto-negotiation, 100M and full duplex. 371444961713Sgirish */ 371544961713Sgirish bmcr.value = 0; 371644961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 3717adfcba55Sjoycey #if defined(__i386) 371852ccf843Smisaki (uint8_t)(uint32_t)(&mii_regs->bmcr), 3719adfcba55Sjoycey #else 372052ccf843Smisaki (uint8_t)(uint64_t)(&mii_regs->bmcr), 3721adfcba55Sjoycey #endif 372252ccf843Smisaki bmcr.value)) != NXGE_OK) 372344961713Sgirish goto fail; 372444961713Sgirish 372544961713Sgirish if ((statsp->port_stats.lb_mode == nxge_lb_phy) || 372652ccf843Smisaki (statsp->port_stats.lb_mode == nxge_lb_phy1000)) { 372744961713Sgirish bmcr.bits.loopback = 1; 372844961713Sgirish bmcr.bits.enable_autoneg = 0; 372944961713Sgirish if (statsp->port_stats.lb_mode == nxge_lb_phy1000) 373044961713Sgirish bmcr.bits.speed_1000_sel = 1; 373144961713Sgirish bmcr.bits.duplex_mode = 1; 373244961713Sgirish param_arr[param_autoneg].value = 0; 373344961713Sgirish } else { 373444961713Sgirish bmcr.bits.loopback = 0; 373544961713Sgirish } 373644961713Sgirish 373744961713Sgirish if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) || 373852ccf843Smisaki (statsp->port_stats.lb_mode == nxge_lb_ext100) || 373952ccf843Smisaki (statsp->port_stats.lb_mode == nxge_lb_ext10)) { 374044961713Sgirish param_arr[param_autoneg].value = 0; 374144961713Sgirish bcm5464r_aux.value = 0; 374244961713Sgirish bcm5464r_aux.bits.ext_lb = 1; 374344961713Sgirish bcm5464r_aux.bits.write_1 = 1; 374444961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 374552ccf843Smisaki BCM5464R_AUX_CTL, bcm5464r_aux.value)) != NXGE_OK) 374644961713Sgirish goto fail; 374744961713Sgirish } 374844961713Sgirish 374900161856Syc /* If auto-negotiation is desired */ 375044961713Sgirish if (param_arr[param_autoneg].value) { 375144961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 375252ccf843Smisaki "Restarting Auto-negotiation.")); 375344961713Sgirish /* 375444961713Sgirish * Setup our Auto-negotiation advertisement register. 375544961713Sgirish */ 375644961713Sgirish anar.value = 0; 375744961713Sgirish anar.bits.selector = 1; 375844961713Sgirish anar.bits.cap_100T4 = param_arr[param_anar_100T4].value; 375944961713Sgirish anar.bits.cap_100fdx = param_arr[param_anar_100fdx].value; 376044961713Sgirish anar.bits.cap_100hdx = param_arr[param_anar_100hdx].value; 376144961713Sgirish anar.bits.cap_10fdx = param_arr[param_anar_10fdx].value; 376244961713Sgirish anar.bits.cap_10hdx = param_arr[param_anar_10hdx].value; 376344961713Sgirish anar.bits.cap_asmpause = 0; 376444961713Sgirish anar.bits.cap_pause = 0; 376544961713Sgirish if (param_arr[param_anar_1000fdx].value || 376652ccf843Smisaki param_arr[param_anar_100fdx].value || 376752ccf843Smisaki param_arr[param_anar_10fdx].value) { 376844961713Sgirish anar.bits.cap_asmpause = statsp->mac_stats.cap_asmpause; 376944961713Sgirish anar.bits.cap_pause = statsp->mac_stats.cap_pause; 377044961713Sgirish } 377144961713Sgirish 377200161856Syc /* Write to the auto-negotiation advertisement register */ 377344961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 3774adfcba55Sjoycey #if defined(__i386) 377552ccf843Smisaki (uint8_t)(uint32_t)(&mii_regs->anar), 3776adfcba55Sjoycey #else 377752ccf843Smisaki (uint8_t)(uint64_t)(&mii_regs->anar), 3778adfcba55Sjoycey #endif 377952ccf843Smisaki anar.value)) != NXGE_OK) 378044961713Sgirish goto fail; 378144961713Sgirish if (bmsr.bits.extend_status) { 378244961713Sgirish gcr.value = 0; 378344961713Sgirish gcr.bits.ms_mode_en = 378452ccf843Smisaki param_arr[param_master_cfg_enable].value; 378544961713Sgirish gcr.bits.master = 378652ccf843Smisaki param_arr[param_master_cfg_value].value; 378744961713Sgirish gcr.bits.link_1000fdx = 378852ccf843Smisaki param_arr[param_anar_1000fdx].value; 378944961713Sgirish gcr.bits.link_1000hdx = 379052ccf843Smisaki param_arr[param_anar_1000hdx].value; 379144961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 3792adfcba55Sjoycey #if defined(__i386) 379352ccf843Smisaki (uint8_t)(uint32_t)(&mii_regs->gcr), 3794adfcba55Sjoycey #else 379552ccf843Smisaki (uint8_t)(uint64_t)(&mii_regs->gcr), 3796adfcba55Sjoycey #endif 379752ccf843Smisaki gcr.value)) != NXGE_OK) 379844961713Sgirish goto fail; 379944961713Sgirish } 380044961713Sgirish 380144961713Sgirish bmcr.bits.enable_autoneg = 1; 380244961713Sgirish bmcr.bits.restart_autoneg = 1; 380344961713Sgirish 380444961713Sgirish } else { 380544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode.")); 380644961713Sgirish bmcr.bits.speed_1000_sel = 380752ccf843Smisaki param_arr[param_anar_1000fdx].value | 380852ccf843Smisaki param_arr[param_anar_1000hdx].value; 380944961713Sgirish bmcr.bits.speed_sel = (~bmcr.bits.speed_1000_sel) & 381052ccf843Smisaki (param_arr[param_anar_100fdx].value | 381152ccf843Smisaki param_arr[param_anar_100hdx].value); 381200161856Syc 381300161856Syc /* Force to 1G */ 381444961713Sgirish if (bmcr.bits.speed_1000_sel) { 381544961713Sgirish statsp->mac_stats.link_speed = 1000; 381644961713Sgirish gcr.value = 0; 381744961713Sgirish gcr.bits.ms_mode_en = 381852ccf843Smisaki param_arr[param_master_cfg_enable].value; 381944961713Sgirish gcr.bits.master = 382052ccf843Smisaki param_arr[param_master_cfg_value].value; 382144961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 3822adfcba55Sjoycey #if defined(__i386) 382352ccf843Smisaki (uint8_t)(uint32_t)(&mii_regs->gcr), 3824adfcba55Sjoycey #else 382552ccf843Smisaki (uint8_t)(uint64_t)(&mii_regs->gcr), 3826adfcba55Sjoycey #endif 382752ccf843Smisaki gcr.value)) != NXGE_OK) 382844961713Sgirish goto fail; 382944961713Sgirish if (param_arr[param_anar_1000fdx].value) { 383044961713Sgirish bmcr.bits.duplex_mode = 1; 383144961713Sgirish statsp->mac_stats.link_duplex = 2; 383244961713Sgirish } else 383344961713Sgirish statsp->mac_stats.link_duplex = 1; 383400161856Syc 383500161856Syc /* Force to 100M */ 383644961713Sgirish } else if (bmcr.bits.speed_sel) { 383744961713Sgirish statsp->mac_stats.link_speed = 100; 383844961713Sgirish if (param_arr[param_anar_100fdx].value) { 383944961713Sgirish bmcr.bits.duplex_mode = 1; 384044961713Sgirish statsp->mac_stats.link_duplex = 2; 384144961713Sgirish } else 384244961713Sgirish statsp->mac_stats.link_duplex = 1; 384300161856Syc 384400161856Syc /* Force to 10M */ 384544961713Sgirish } else { 384644961713Sgirish statsp->mac_stats.link_speed = 10; 384744961713Sgirish if (param_arr[param_anar_10fdx].value) { 384844961713Sgirish bmcr.bits.duplex_mode = 1; 384944961713Sgirish statsp->mac_stats.link_duplex = 2; 385044961713Sgirish } else 385144961713Sgirish statsp->mac_stats.link_duplex = 1; 385244961713Sgirish } 385344961713Sgirish if (statsp->mac_stats.link_duplex != 1) { 385444961713Sgirish statsp->mac_stats.link_asmpause = 385552ccf843Smisaki statsp->mac_stats.cap_asmpause; 385644961713Sgirish statsp->mac_stats.link_pause = 385752ccf843Smisaki statsp->mac_stats.cap_pause; 385844961713Sgirish } 385944961713Sgirish 386044961713Sgirish if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) || 386152ccf843Smisaki (statsp->port_stats.lb_mode == nxge_lb_ext100) || 386252ccf843Smisaki (statsp->port_stats.lb_mode == nxge_lb_ext10)) { 386344961713Sgirish if (statsp->port_stats.lb_mode == nxge_lb_ext1000) { 386444961713Sgirish /* BCM5464R 1000mbps external loopback mode */ 386544961713Sgirish gcr.value = 0; 386644961713Sgirish gcr.bits.ms_mode_en = 1; 386744961713Sgirish gcr.bits.master = 1; 386844961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 3869adfcba55Sjoycey #if defined(__i386) 387052ccf843Smisaki (uint8_t)(uint32_t)(&mii_regs->gcr), 3871adfcba55Sjoycey #else 387252ccf843Smisaki (uint8_t)(uint64_t)(&mii_regs->gcr), 3873adfcba55Sjoycey #endif 387452ccf843Smisaki gcr.value)) != NXGE_OK) 387544961713Sgirish goto fail; 387644961713Sgirish bmcr.value = 0; 387744961713Sgirish bmcr.bits.speed_1000_sel = 1; 387844961713Sgirish statsp->mac_stats.link_speed = 1000; 387944961713Sgirish } else if (statsp->port_stats.lb_mode 388044961713Sgirish == nxge_lb_ext100) { 388144961713Sgirish /* BCM5464R 100mbps external loopback mode */ 388244961713Sgirish bmcr.value = 0; 388344961713Sgirish bmcr.bits.speed_sel = 1; 388444961713Sgirish bmcr.bits.duplex_mode = 1; 388544961713Sgirish statsp->mac_stats.link_speed = 100; 388644961713Sgirish } else if (statsp->port_stats.lb_mode 388744961713Sgirish == nxge_lb_ext10) { 388844961713Sgirish /* BCM5464R 10mbps external loopback mode */ 388944961713Sgirish bmcr.value = 0; 389044961713Sgirish bmcr.bits.duplex_mode = 1; 389144961713Sgirish statsp->mac_stats.link_speed = 10; 389244961713Sgirish } 389344961713Sgirish } 389444961713Sgirish } 389544961713Sgirish 389644961713Sgirish if ((status = nxge_mii_write(nxgep, xcvr_portn, 3897adfcba55Sjoycey #if defined(__i386) 389852ccf843Smisaki (uint8_t)(uint32_t)(&mii_regs->bmcr), 3899adfcba55Sjoycey #else 390052ccf843Smisaki (uint8_t)(uint64_t)(&mii_regs->bmcr), 3901adfcba55Sjoycey #endif 390252ccf843Smisaki bmcr.value)) != NXGE_OK) 390344961713Sgirish goto fail; 390444961713Sgirish 390544961713Sgirish if ((status = nxge_mii_read(nxgep, xcvr_portn, 3906adfcba55Sjoycey #if defined(__i386) 390752ccf843Smisaki (uint8_t)(uint32_t)(&mii_regs->bmcr), 3908adfcba55Sjoycey #else 390952ccf843Smisaki (uint8_t)(uint64_t)(&mii_regs->bmcr), 3910adfcba55Sjoycey #endif 391152ccf843Smisaki &bmcr.value)) != NXGE_OK) 391244961713Sgirish goto fail; 391344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "bmcr = 0x%04X", bmcr.value)); 391444961713Sgirish 391544961713Sgirish /* 391644961713Sgirish * Initialize the xcvr status kept in the context structure. 391744961713Sgirish */ 391844961713Sgirish nxgep->soft_bmsr.value = 0; 391944961713Sgirish 392044961713Sgirish if ((status = nxge_mii_read(nxgep, xcvr_portn, 3921adfcba55Sjoycey #if defined(__i386) 392252ccf843Smisaki (uint8_t)(uint32_t)(&mii_regs->bmsr), 3923adfcba55Sjoycey #else 392452ccf843Smisaki (uint8_t)(uint64_t)(&mii_regs->bmsr), 3925adfcba55Sjoycey #endif 392652ccf843Smisaki &nxgep->bmsr.value)) != NXGE_OK) 392744961713Sgirish goto fail; 392844961713Sgirish 392944961713Sgirish statsp->mac_stats.xcvr_inits++; 393044961713Sgirish nxgep->bmsr.value = 0; 393144961713Sgirish 393244961713Sgirish fail: 393344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 393452ccf843Smisaki "<== nxge_mii_xcvr_init status 0x%x", status)); 393544961713Sgirish return (status); 393644961713Sgirish } 393744961713Sgirish 3938d81011f0Ssbehera nxge_status_t 3939d81011f0Ssbehera nxge_mii_xcvr_fiber_init(p_nxge_t nxgep) 3940d81011f0Ssbehera { 3941d81011f0Ssbehera p_nxge_param_t param_arr; 3942d81011f0Ssbehera p_nxge_stats_t statsp; 3943d81011f0Ssbehera uint8_t xcvr_portn; 3944d81011f0Ssbehera p_mii_regs_t mii_regs; 3945d81011f0Ssbehera mii_bmcr_t bmcr; 3946d81011f0Ssbehera mii_bmsr_t bmsr; 3947d81011f0Ssbehera mii_gcr_t gcr; 3948d81011f0Ssbehera mii_esr_t esr; 3949d81011f0Ssbehera mii_aux_ctl_t bcm5464r_aux; 3950d81011f0Ssbehera int status = NXGE_OK; 3951d81011f0Ssbehera 3952d81011f0Ssbehera uint_t delay; 3953d81011f0Ssbehera 3954d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_fiber_init")); 3955d81011f0Ssbehera 3956d81011f0Ssbehera param_arr = nxgep->param_arr; 3957d81011f0Ssbehera statsp = nxgep->statsp; 3958d81011f0Ssbehera xcvr_portn = statsp->mac_stats.xcvr_portn; 3959d81011f0Ssbehera 3960d81011f0Ssbehera mii_regs = NULL; 3961d81011f0Ssbehera 3962d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3963d81011f0Ssbehera "nxge_mii_xcvr_fiber_init: " 3964d81011f0Ssbehera "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value)); 3965d81011f0Ssbehera 3966d81011f0Ssbehera /* 3967d81011f0Ssbehera * Reset the transceiver. 3968d81011f0Ssbehera */ 3969d81011f0Ssbehera delay = 0; 3970d81011f0Ssbehera bmcr.value = 0; 3971d81011f0Ssbehera bmcr.bits.reset = 1; 3972d81011f0Ssbehera 3973d81011f0Ssbehera #if defined(__i386) 3974d81011f0Ssbehera 3975d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 3976d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 3977d81011f0Ssbehera goto fail; 3978d81011f0Ssbehera #else 3979d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 3980d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 3981d81011f0Ssbehera goto fail; 3982d81011f0Ssbehera #endif 3983d81011f0Ssbehera do { 3984d81011f0Ssbehera drv_usecwait(500); 3985d81011f0Ssbehera #if defined(__i386) 3986d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 3987d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) 3988d81011f0Ssbehera != NXGE_OK) 3989d81011f0Ssbehera goto fail; 3990d81011f0Ssbehera #else 3991d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 3992d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) 3993d81011f0Ssbehera != NXGE_OK) 3994d81011f0Ssbehera goto fail; 3995d81011f0Ssbehera #endif 3996d81011f0Ssbehera delay++; 3997d81011f0Ssbehera } while ((bmcr.bits.reset) && (delay < 1000)); 3998d81011f0Ssbehera if (delay == 1000) { 3999d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed.")); 4000d81011f0Ssbehera goto fail; 4001d81011f0Ssbehera } 4002d81011f0Ssbehera 4003d81011f0Ssbehera #if defined(__i386) 4004d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 4005d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK) 4006d81011f0Ssbehera goto fail; 4007d81011f0Ssbehera #else 4008d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 4009d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK) 4010d81011f0Ssbehera goto fail; 4011d81011f0Ssbehera #endif 4012d81011f0Ssbehera 4013d81011f0Ssbehera param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able; 4014d81011f0Ssbehera param_arr[param_anar_100T4].value = 0; 4015d81011f0Ssbehera param_arr[param_anar_100fdx].value = 0; 4016d81011f0Ssbehera param_arr[param_anar_100hdx].value = 0; 4017d81011f0Ssbehera param_arr[param_anar_10fdx].value = 0; 4018d81011f0Ssbehera param_arr[param_anar_10hdx].value = 0; 4019d81011f0Ssbehera 4020d81011f0Ssbehera /* 4021d81011f0Ssbehera * Initialize the xcvr statistics. 4022d81011f0Ssbehera */ 4023d81011f0Ssbehera statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able; 4024d81011f0Ssbehera statsp->mac_stats.cap_100T4 = 0; 4025d81011f0Ssbehera statsp->mac_stats.cap_100fdx = 0; 4026d81011f0Ssbehera statsp->mac_stats.cap_100hdx = 0; 4027d81011f0Ssbehera statsp->mac_stats.cap_10fdx = 0; 4028d81011f0Ssbehera statsp->mac_stats.cap_10hdx = 0; 4029d81011f0Ssbehera statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value; 4030d81011f0Ssbehera statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value; 4031d81011f0Ssbehera 4032d81011f0Ssbehera /* 4033d81011f0Ssbehera * Initialize the xcvr advertised capability statistics. 4034d81011f0Ssbehera */ 4035d81011f0Ssbehera statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value; 4036d81011f0Ssbehera statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 4037d81011f0Ssbehera statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 4038d81011f0Ssbehera statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value; 4039d81011f0Ssbehera statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value; 4040d81011f0Ssbehera statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value; 4041d81011f0Ssbehera statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value; 4042d81011f0Ssbehera statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value; 4043d81011f0Ssbehera statsp->mac_stats.adv_cap_asmpause = 4044d81011f0Ssbehera param_arr[param_anar_asmpause].value; 4045d81011f0Ssbehera statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value; 4046d81011f0Ssbehera 4047d81011f0Ssbehera /* 4048d81011f0Ssbehera * Check for extended status just in case we're 4049d81011f0Ssbehera * running a Gigibit phy. 4050d81011f0Ssbehera */ 4051d81011f0Ssbehera if (bmsr.bits.extend_status) { 4052d81011f0Ssbehera #if defined(__i386) 4053d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 4054d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->esr), &esr.value)) != 4055d81011f0Ssbehera NXGE_OK) 4056d81011f0Ssbehera goto fail; 4057d81011f0Ssbehera #else 4058d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 4059d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->esr), &esr.value)) != 4060d81011f0Ssbehera NXGE_OK) 4061d81011f0Ssbehera goto fail; 4062d81011f0Ssbehera #endif 4063d81011f0Ssbehera param_arr[param_anar_1000fdx].value &= 4064d81011f0Ssbehera esr.bits.link_1000fdx; 4065d81011f0Ssbehera param_arr[param_anar_1000hdx].value = 0; 4066d81011f0Ssbehera 4067d81011f0Ssbehera statsp->mac_stats.cap_1000fdx = 4068d81011f0Ssbehera (esr.bits.link_1000Xfdx || esr.bits.link_1000fdx); 4069d81011f0Ssbehera statsp->mac_stats.cap_1000hdx = 0; 4070d81011f0Ssbehera } else { 4071d81011f0Ssbehera param_arr[param_anar_1000fdx].value = 0; 4072d81011f0Ssbehera param_arr[param_anar_1000hdx].value = 0; 4073d81011f0Ssbehera } 4074d81011f0Ssbehera 4075d81011f0Ssbehera /* 4076d81011f0Ssbehera * Initialize 1G Statistics once the capability is established. 4077d81011f0Ssbehera */ 4078d81011f0Ssbehera statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 4079d81011f0Ssbehera statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 4080d81011f0Ssbehera 4081d81011f0Ssbehera /* 4082d81011f0Ssbehera * Initialize the link statistics. 4083d81011f0Ssbehera */ 4084d81011f0Ssbehera statsp->mac_stats.link_T4 = 0; 4085d81011f0Ssbehera statsp->mac_stats.link_asmpause = 0; 4086d81011f0Ssbehera statsp->mac_stats.link_pause = 0; 4087d81011f0Ssbehera statsp->mac_stats.link_speed = 0; 4088d81011f0Ssbehera statsp->mac_stats.link_duplex = 0; 4089d81011f0Ssbehera statsp->mac_stats.link_up = 0; 4090d81011f0Ssbehera 4091d81011f0Ssbehera /* 4092d81011f0Ssbehera * Switch off Auto-negotiation, 100M and full duplex. 4093d81011f0Ssbehera */ 4094d81011f0Ssbehera bmcr.value = 0; 4095d81011f0Ssbehera #if defined(__i386) 4096d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 4097d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 4098d81011f0Ssbehera goto fail; 4099d81011f0Ssbehera #else 4100d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 4101d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 4102d81011f0Ssbehera goto fail; 4103d81011f0Ssbehera #endif 4104d81011f0Ssbehera 4105d81011f0Ssbehera if ((statsp->port_stats.lb_mode == nxge_lb_phy) || 4106d81011f0Ssbehera (statsp->port_stats.lb_mode == nxge_lb_phy1000)) { 4107d81011f0Ssbehera bmcr.bits.loopback = 1; 4108d81011f0Ssbehera bmcr.bits.enable_autoneg = 0; 4109d81011f0Ssbehera if (statsp->port_stats.lb_mode == nxge_lb_phy1000) 4110d81011f0Ssbehera bmcr.bits.speed_1000_sel = 1; 4111d81011f0Ssbehera bmcr.bits.duplex_mode = 1; 4112d81011f0Ssbehera param_arr[param_autoneg].value = 0; 4113d81011f0Ssbehera } else { 4114d81011f0Ssbehera bmcr.bits.loopback = 0; 4115d81011f0Ssbehera } 4116d81011f0Ssbehera 4117d81011f0Ssbehera if (statsp->port_stats.lb_mode == nxge_lb_ext1000) { 4118d81011f0Ssbehera param_arr[param_autoneg].value = 0; 4119d81011f0Ssbehera bcm5464r_aux.value = 0; 4120d81011f0Ssbehera bcm5464r_aux.bits.ext_lb = 1; 4121d81011f0Ssbehera bcm5464r_aux.bits.write_1 = 1; 4122d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 4123d81011f0Ssbehera BCM5464R_AUX_CTL, bcm5464r_aux.value)) != NXGE_OK) 4124d81011f0Ssbehera goto fail; 4125d81011f0Ssbehera } 4126d81011f0Ssbehera 4127d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode.")); 4128d81011f0Ssbehera bmcr.bits.speed_1000_sel = 1; 4129d81011f0Ssbehera bmcr.bits.speed_sel = 0; 4130d81011f0Ssbehera bmcr.bits.duplex_mode = 1; 4131d81011f0Ssbehera statsp->mac_stats.link_speed = 1000; 4132d81011f0Ssbehera statsp->mac_stats.link_duplex = 2; 4133d81011f0Ssbehera 4134d81011f0Ssbehera if ((statsp->port_stats.lb_mode == nxge_lb_ext1000)) { 4135d81011f0Ssbehera /* BCM5464R 1000mbps external loopback mode */ 4136d81011f0Ssbehera gcr.value = 0; 4137d81011f0Ssbehera gcr.bits.ms_mode_en = 1; 4138d81011f0Ssbehera gcr.bits.master = 1; 4139d81011f0Ssbehera #if defined(__i386) 4140d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 4141d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->gcr), 4142d81011f0Ssbehera gcr.value)) != NXGE_OK) 4143d81011f0Ssbehera goto fail; 4144d81011f0Ssbehera #else 4145d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 4146d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->gcr), 4147d81011f0Ssbehera gcr.value)) != NXGE_OK) 4148d81011f0Ssbehera goto fail; 4149d81011f0Ssbehera #endif 4150d81011f0Ssbehera bmcr.value = 0; 4151d81011f0Ssbehera bmcr.bits.speed_1000_sel = 1; 4152d81011f0Ssbehera statsp->mac_stats.link_speed = 1000; 4153d81011f0Ssbehera } 4154d81011f0Ssbehera 4155d81011f0Ssbehera #if defined(__i386) 4156d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 4157d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmcr), 4158d81011f0Ssbehera bmcr.value)) != NXGE_OK) 4159d81011f0Ssbehera goto fail; 4160d81011f0Ssbehera #else 4161d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 4162d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmcr), 4163d81011f0Ssbehera bmcr.value)) != NXGE_OK) 4164d81011f0Ssbehera goto fail; 4165d81011f0Ssbehera #endif 4166d81011f0Ssbehera 4167d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4168d81011f0Ssbehera "nxge_mii_xcvr_fiber_init: value wrote bmcr = 0x%x", 4169d81011f0Ssbehera bmcr.value)); 4170d81011f0Ssbehera 4171d81011f0Ssbehera #if defined(__i386) 4172d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 4173d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK) 4174d81011f0Ssbehera goto fail; 4175d81011f0Ssbehera #else 4176d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 4177d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK) 4178d81011f0Ssbehera goto fail; 4179d81011f0Ssbehera #endif 4180d81011f0Ssbehera 4181d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4182d81011f0Ssbehera "nxge_mii_xcvr_fiber_init: read bmcr = 0x%04X", bmcr.value)); 4183d81011f0Ssbehera 4184d81011f0Ssbehera /* 4185d81011f0Ssbehera * Initialize the xcvr status kept in the context structure. 4186d81011f0Ssbehera */ 4187d81011f0Ssbehera nxgep->soft_bmsr.value = 0; 4188d81011f0Ssbehera #if defined(__i386) 4189d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 4190d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmsr), 4191d81011f0Ssbehera &nxgep->bmsr.value)) != NXGE_OK) 4192d81011f0Ssbehera goto fail; 4193d81011f0Ssbehera #else 4194d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 4195d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmsr), 4196d81011f0Ssbehera &nxgep->bmsr.value)) != NXGE_OK) 4197d81011f0Ssbehera goto fail; 4198d81011f0Ssbehera #endif 4199d81011f0Ssbehera 4200d81011f0Ssbehera statsp->mac_stats.xcvr_inits++; 4201d81011f0Ssbehera nxgep->bmsr.value = 0; 4202d81011f0Ssbehera 4203d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4204d81011f0Ssbehera "<== nxge_mii_xcvr_fiber_init status 0x%x", status)); 4205d81011f0Ssbehera return (status); 4206d81011f0Ssbehera 4207d81011f0Ssbehera fail: 4208d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4209d81011f0Ssbehera "<== nxge_mii_xcvr_fiber_init status 0x%x", status)); 4210d81011f0Ssbehera return (status); 4211d81011f0Ssbehera } 4212d81011f0Ssbehera 421344961713Sgirish /* Read from a MII compliant register */ 421444961713Sgirish 421544961713Sgirish nxge_status_t 421644961713Sgirish nxge_mii_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg, 421744961713Sgirish uint16_t *value) 421844961713Sgirish { 421944961713Sgirish npi_status_t rs = NPI_SUCCESS; 422044961713Sgirish 422144961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_read: xcvr_port<%d>" 422252ccf843Smisaki "xcvr_reg<%d>", xcvr_portn, xcvr_reg)); 422344961713Sgirish 4224321febdeSsbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 422544961713Sgirish 4226d81011f0Ssbehera if ((nxgep->mac.portmode == PORT_1G_COPPER) || 4227d81011f0Ssbehera (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) { 422844961713Sgirish if ((rs = npi_mac_mif_mii_read(nxgep->npi_handle, 422952ccf843Smisaki xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 423044961713Sgirish goto fail; 42312e59129aSraghus } else if ((nxgep->mac.portmode == PORT_1G_FIBER) || 42322e59129aSraghus (nxgep->mac.portmode == PORT_1G_SERDES)) { 423344961713Sgirish if ((rs = npi_mac_pcs_mii_read(nxgep->npi_handle, 423452ccf843Smisaki xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 423544961713Sgirish goto fail; 423644961713Sgirish } else 423744961713Sgirish goto fail; 423844961713Sgirish 4239321febdeSsbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 424044961713Sgirish 424144961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_read: xcvr_port<%d>" 424252ccf843Smisaki "xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg, *value)); 424344961713Sgirish return (NXGE_OK); 424444961713Sgirish fail: 4245321febdeSsbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 424644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 424752ccf843Smisaki "nxge_mii_read: Failed to read mii on xcvr %d", xcvr_portn)); 424844961713Sgirish 424944961713Sgirish return (NXGE_ERROR | rs); 425044961713Sgirish } 425144961713Sgirish 425244961713Sgirish /* Write to a MII compliant Register */ 425344961713Sgirish 425444961713Sgirish nxge_status_t 425544961713Sgirish nxge_mii_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg, 425644961713Sgirish uint16_t value) 425744961713Sgirish { 425844961713Sgirish npi_status_t rs = NPI_SUCCESS; 425944961713Sgirish 426044961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_write: xcvr_port<%d>" 426152ccf843Smisaki "xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg, value)); 426244961713Sgirish 4263321febdeSsbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 426444961713Sgirish 4265d81011f0Ssbehera if ((nxgep->mac.portmode == PORT_1G_COPPER) || 4266d81011f0Ssbehera (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) { 426744961713Sgirish if ((rs = npi_mac_mif_mii_write(nxgep->npi_handle, 426852ccf843Smisaki xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 426944961713Sgirish goto fail; 42702e59129aSraghus } else if ((nxgep->mac.portmode == PORT_1G_FIBER) || 42712e59129aSraghus (nxgep->mac.portmode == PORT_1G_SERDES)) { 427244961713Sgirish if ((rs = npi_mac_pcs_mii_write(nxgep->npi_handle, 427352ccf843Smisaki xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 427444961713Sgirish goto fail; 427544961713Sgirish } else 427644961713Sgirish goto fail; 427744961713Sgirish 4278321febdeSsbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 427944961713Sgirish 428044961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_write: xcvr_port<%d>" 428152ccf843Smisaki "xcvr_reg<%d>", xcvr_portn, xcvr_reg)); 428244961713Sgirish return (NXGE_OK); 428344961713Sgirish fail: 4284321febdeSsbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 428544961713Sgirish 428644961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 428752ccf843Smisaki "nxge_mii_write: Failed to write mii on xcvr %d", xcvr_portn)); 428844961713Sgirish 428944961713Sgirish return (NXGE_ERROR | rs); 429044961713Sgirish } 429144961713Sgirish 429200161856Syc /* 429300161856Syc * Perform write to Clause45 serdes / transceiver device 429400161856Syc * Arguments: 429500161856Syc * xcvr_portn: The IEEE 802.3 Clause45 PHYAD, it is the same as port 429600161856Syc * number if nxge_mdio_write is used for accessing the 429700161856Syc * internal LSIL serdes. Otherwise PHYAD is different 429800161856Syc * for different platforms. 429900161856Syc * device: With each PHYAD, the driver can use MDIO to control 430000161856Syc * multiple devices inside the PHY, here "device" is an 430100161856Syc * MMD (MDIO managable device). 430200161856Syc * xcvr_reg: Each device has multiple registers. xcvr_reg specifies 430300161856Syc * the register which the driver will write value to. 430400161856Syc * value: The register value will be filled in. 430500161856Syc */ 430644961713Sgirish nxge_status_t 430744961713Sgirish nxge_mdio_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device, 430844961713Sgirish uint16_t xcvr_reg, uint16_t *value) 430944961713Sgirish { 431044961713Sgirish npi_status_t rs = NPI_SUCCESS; 431144961713Sgirish 431244961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_read: xcvr_port<%d>", 431352ccf843Smisaki xcvr_portn)); 431444961713Sgirish 431553560810Ssbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 431644961713Sgirish 431744961713Sgirish if ((rs = npi_mac_mif_mdio_read(nxgep->npi_handle, 431852ccf843Smisaki xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS) 431944961713Sgirish goto fail; 432044961713Sgirish 432153560810Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 432244961713Sgirish 432344961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_read: xcvr_port<%d>", 432452ccf843Smisaki xcvr_portn)); 432544961713Sgirish return (NXGE_OK); 432644961713Sgirish fail: 432753560810Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 432844961713Sgirish 432944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 433052ccf843Smisaki "nxge_mdio_read: Failed to read mdio on xcvr %d", xcvr_portn)); 433144961713Sgirish 433244961713Sgirish return (NXGE_ERROR | rs); 433344961713Sgirish } 433444961713Sgirish 433544961713Sgirish /* Perform write to Clause45 serdes / transceiver device */ 433644961713Sgirish 433744961713Sgirish nxge_status_t 433844961713Sgirish nxge_mdio_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device, 433944961713Sgirish uint16_t xcvr_reg, uint16_t value) 434044961713Sgirish { 434144961713Sgirish npi_status_t rs = NPI_SUCCESS; 434244961713Sgirish 434344961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_write: xcvr_port<%d>", 434452ccf843Smisaki xcvr_portn)); 434544961713Sgirish 434653560810Ssbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 434744961713Sgirish 434844961713Sgirish if ((rs = npi_mac_mif_mdio_write(nxgep->npi_handle, 434952ccf843Smisaki xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS) 435044961713Sgirish goto fail; 435144961713Sgirish 435253560810Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 435344961713Sgirish 435444961713Sgirish NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_write: xcvr_port<%d>", 435552ccf843Smisaki xcvr_portn)); 435644961713Sgirish return (NXGE_OK); 435744961713Sgirish fail: 435853560810Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 435944961713Sgirish 436044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 436152ccf843Smisaki "nxge_mdio_write: Failed to write mdio on xcvr %d", xcvr_portn)); 436244961713Sgirish 436344961713Sgirish return (NXGE_ERROR | rs); 436444961713Sgirish } 436544961713Sgirish 436644961713Sgirish 436744961713Sgirish /* Check MII to see if there is any link status change */ 436844961713Sgirish 436944961713Sgirish nxge_status_t 4370a3c5bd6dSspeer nxge_mii_check(p_nxge_t nxgep, mii_bmsr_t bmsr, mii_bmsr_t bmsr_ints, 4371a3c5bd6dSspeer nxge_link_state_t *link_up) 437244961713Sgirish { 437344961713Sgirish p_nxge_param_t param_arr; 437444961713Sgirish p_nxge_stats_t statsp; 437544961713Sgirish p_mii_regs_t mii_regs; 437644961713Sgirish p_mii_bmsr_t soft_bmsr; 437744961713Sgirish mii_anar_t anar; 437844961713Sgirish mii_anlpar_t anlpar; 437944961713Sgirish mii_anar_t an_common; 438044961713Sgirish mii_aner_t aner; 438144961713Sgirish mii_gsr_t gsr; 438244961713Sgirish nxge_status_t status = NXGE_OK; 438344961713Sgirish 438444961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_check")); 438544961713Sgirish 438644961713Sgirish mii_regs = NULL; 438744961713Sgirish param_arr = nxgep->param_arr; 438844961713Sgirish statsp = nxgep->statsp; 438944961713Sgirish soft_bmsr = &nxgep->soft_bmsr; 4390a3c5bd6dSspeer *link_up = LINK_NO_CHANGE; 439144961713Sgirish 4392d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4393d81011f0Ssbehera "==> nxge_mii_check bmsr 0x%x bmsr_int 0x%x", 4394d81011f0Ssbehera bmsr.value, bmsr_ints.value)); 4395d81011f0Ssbehera 439644961713Sgirish if (bmsr_ints.bits.link_status) { 4397d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4398d81011f0Ssbehera "==> nxge_mii_check (link up) bmsr 0x%x bmsr_int 0x%x", 4399d81011f0Ssbehera bmsr.value, bmsr_ints.value)); 440044961713Sgirish if (bmsr.bits.link_status) { 440144961713Sgirish soft_bmsr->bits.link_status = 1; 4402d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4403d81011f0Ssbehera "==> nxge_mii_check (link up) soft bmsr 0x%x bmsr_int " 4404d81011f0Ssbehera "0x%x", bmsr.value, bmsr_ints.value)); 440544961713Sgirish } else { 440644961713Sgirish statsp->mac_stats.link_up = 0; 440744961713Sgirish soft_bmsr->bits.link_status = 0; 440844961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 440952ccf843Smisaki "Link down cable problem")); 4410a3c5bd6dSspeer *link_up = LINK_IS_DOWN; 441144961713Sgirish } 441244961713Sgirish } 441344961713Sgirish 4414d81011f0Ssbehera if (nxgep->mac.portmode == PORT_1G_COPPER && 4415d81011f0Ssbehera param_arr[param_autoneg].value) { 441644961713Sgirish if (bmsr_ints.bits.auto_neg_complete) { 441744961713Sgirish if (bmsr.bits.auto_neg_complete) 441844961713Sgirish soft_bmsr->bits.auto_neg_complete = 1; 441944961713Sgirish else 442044961713Sgirish soft_bmsr->bits.auto_neg_complete = 0; 442144961713Sgirish } 442244961713Sgirish if (soft_bmsr->bits.link_status == 0) { 442344961713Sgirish statsp->mac_stats.link_T4 = 0; 442444961713Sgirish statsp->mac_stats.link_speed = 0; 442544961713Sgirish statsp->mac_stats.link_duplex = 0; 442644961713Sgirish statsp->mac_stats.link_asmpause = 0; 442744961713Sgirish statsp->mac_stats.link_pause = 0; 442844961713Sgirish statsp->mac_stats.lp_cap_autoneg = 0; 442944961713Sgirish statsp->mac_stats.lp_cap_100T4 = 0; 443044961713Sgirish statsp->mac_stats.lp_cap_1000fdx = 0; 443144961713Sgirish statsp->mac_stats.lp_cap_1000hdx = 0; 443244961713Sgirish statsp->mac_stats.lp_cap_100fdx = 0; 443344961713Sgirish statsp->mac_stats.lp_cap_100hdx = 0; 443444961713Sgirish statsp->mac_stats.lp_cap_10fdx = 0; 443544961713Sgirish statsp->mac_stats.lp_cap_10hdx = 0; 443644961713Sgirish statsp->mac_stats.lp_cap_10gfdx = 0; 443744961713Sgirish statsp->mac_stats.lp_cap_10ghdx = 0; 443844961713Sgirish statsp->mac_stats.lp_cap_asmpause = 0; 443944961713Sgirish statsp->mac_stats.lp_cap_pause = 0; 444044961713Sgirish } 444144961713Sgirish } else 444244961713Sgirish soft_bmsr->bits.auto_neg_complete = 1; 444344961713Sgirish 444444961713Sgirish if ((bmsr_ints.bits.link_status || 444552ccf843Smisaki bmsr_ints.bits.auto_neg_complete) && 444652ccf843Smisaki soft_bmsr->bits.link_status && 444752ccf843Smisaki soft_bmsr->bits.auto_neg_complete) { 444844961713Sgirish statsp->mac_stats.link_up = 1; 4449d81011f0Ssbehera 4450d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4451d81011f0Ssbehera "==> nxge_mii_check " 4452d81011f0Ssbehera "(auto negotiation complete or link up) " 4453d81011f0Ssbehera "soft bmsr 0x%x bmsr_int 0x%x", 4454d81011f0Ssbehera bmsr.value, bmsr_ints.value)); 4455d81011f0Ssbehera 4456d81011f0Ssbehera if (nxgep->mac.portmode == PORT_1G_COPPER && 4457d81011f0Ssbehera param_arr[param_autoneg].value) { 445844961713Sgirish if ((status = nxge_mii_read(nxgep, 445952ccf843Smisaki statsp->mac_stats.xcvr_portn, 4460adfcba55Sjoycey #if defined(__i386) 446152ccf843Smisaki (uint8_t)(uint32_t)(&mii_regs->anar), 4462adfcba55Sjoycey #else 446352ccf843Smisaki (uint8_t)(uint64_t)(&mii_regs->anar), 4464adfcba55Sjoycey #endif 446552ccf843Smisaki &anar.value)) != NXGE_OK) 446644961713Sgirish goto fail; 446744961713Sgirish if ((status = nxge_mii_read(nxgep, 446852ccf843Smisaki statsp->mac_stats.xcvr_portn, 4469adfcba55Sjoycey #if defined(__i386) 447052ccf843Smisaki (uint8_t)(uint32_t)(&mii_regs->anlpar), 4471adfcba55Sjoycey #else 447252ccf843Smisaki (uint8_t)(uint64_t)(&mii_regs->anlpar), 4473adfcba55Sjoycey #endif 447452ccf843Smisaki &anlpar.value)) != NXGE_OK) 447544961713Sgirish goto fail; 447644961713Sgirish if ((status = nxge_mii_read(nxgep, 447752ccf843Smisaki statsp->mac_stats.xcvr_portn, 4478adfcba55Sjoycey #if defined(__i386) 447952ccf843Smisaki (uint8_t)(uint32_t)(&mii_regs->aner), 4480adfcba55Sjoycey #else 448152ccf843Smisaki (uint8_t)(uint64_t)(&mii_regs->aner), 4482adfcba55Sjoycey #endif 448352ccf843Smisaki &aner.value)) != NXGE_OK) 448444961713Sgirish goto fail; 448544961713Sgirish statsp->mac_stats.lp_cap_autoneg = aner.bits.lp_an_able; 448644961713Sgirish statsp->mac_stats.lp_cap_100T4 = anlpar.bits.cap_100T4; 448744961713Sgirish statsp->mac_stats.lp_cap_100fdx = 448852ccf843Smisaki anlpar.bits.cap_100fdx; 448944961713Sgirish statsp->mac_stats.lp_cap_100hdx = 449052ccf843Smisaki anlpar.bits.cap_100hdx; 449144961713Sgirish statsp->mac_stats.lp_cap_10fdx = anlpar.bits.cap_10fdx; 449244961713Sgirish statsp->mac_stats.lp_cap_10hdx = anlpar.bits.cap_10hdx; 449344961713Sgirish statsp->mac_stats.lp_cap_asmpause = 449452ccf843Smisaki anlpar.bits.cap_asmpause; 449544961713Sgirish statsp->mac_stats.lp_cap_pause = anlpar.bits.cap_pause; 449644961713Sgirish an_common.value = anar.value & anlpar.value; 449744961713Sgirish if (param_arr[param_anar_1000fdx].value || 449852ccf843Smisaki param_arr[param_anar_1000hdx].value) { 449944961713Sgirish if ((status = nxge_mii_read(nxgep, 450052ccf843Smisaki statsp->mac_stats.xcvr_portn, 4501adfcba55Sjoycey #if defined(__i386) 450252ccf843Smisaki (uint8_t)(uint32_t)(&mii_regs->gsr), 4503adfcba55Sjoycey #else 450452ccf843Smisaki (uint8_t)(uint64_t)(&mii_regs->gsr), 4505adfcba55Sjoycey #endif 450652ccf843Smisaki &gsr.value)) != NXGE_OK) 450744961713Sgirish goto fail; 450844961713Sgirish statsp->mac_stats.lp_cap_1000fdx = 450952ccf843Smisaki gsr.bits.link_1000fdx; 451044961713Sgirish statsp->mac_stats.lp_cap_1000hdx = 451152ccf843Smisaki gsr.bits.link_1000hdx; 451244961713Sgirish if (param_arr[param_anar_1000fdx].value && 451352ccf843Smisaki gsr.bits.link_1000fdx) { 451444961713Sgirish statsp->mac_stats.link_speed = 1000; 451544961713Sgirish statsp->mac_stats.link_duplex = 2; 451644961713Sgirish } else if ( 451752ccf843Smisaki param_arr[param_anar_1000hdx].value && 451852ccf843Smisaki gsr.bits.link_1000hdx) { 451944961713Sgirish statsp->mac_stats.link_speed = 1000; 452044961713Sgirish statsp->mac_stats.link_duplex = 1; 452144961713Sgirish } 452244961713Sgirish } 452344961713Sgirish if ((an_common.value != 0) && 452452ccf843Smisaki !(statsp->mac_stats.link_speed)) { 452544961713Sgirish if (an_common.bits.cap_100T4) { 452644961713Sgirish statsp->mac_stats.link_T4 = 1; 452744961713Sgirish statsp->mac_stats.link_speed = 100; 452844961713Sgirish statsp->mac_stats.link_duplex = 1; 452944961713Sgirish } else if (an_common.bits.cap_100fdx) { 453044961713Sgirish statsp->mac_stats.link_speed = 100; 453144961713Sgirish statsp->mac_stats.link_duplex = 2; 453244961713Sgirish } else if (an_common.bits.cap_100hdx) { 453344961713Sgirish statsp->mac_stats.link_speed = 100; 453444961713Sgirish statsp->mac_stats.link_duplex = 1; 453544961713Sgirish } else if (an_common.bits.cap_10fdx) { 453644961713Sgirish statsp->mac_stats.link_speed = 10; 453744961713Sgirish statsp->mac_stats.link_duplex = 2; 453844961713Sgirish } else if (an_common.bits.cap_10hdx) { 453944961713Sgirish statsp->mac_stats.link_speed = 10; 454044961713Sgirish statsp->mac_stats.link_duplex = 1; 454144961713Sgirish } else { 454244961713Sgirish goto fail; 454344961713Sgirish } 454444961713Sgirish } 454544961713Sgirish if (statsp->mac_stats.link_duplex != 1) { 454652ccf843Smisaki int link_pause; 454752ccf843Smisaki int cp, lcp; 454852ccf843Smisaki 454944961713Sgirish statsp->mac_stats.link_asmpause = 455052ccf843Smisaki an_common.bits.cap_asmpause; 455152ccf843Smisaki cp = statsp->mac_stats.cap_pause; 455252ccf843Smisaki lcp = statsp->mac_stats.lp_cap_pause; 455352ccf843Smisaki if (statsp->mac_stats.link_asmpause) { 455452ccf843Smisaki if ((cp == 0) && (lcp == 1)) { 455552ccf843Smisaki link_pause = 0; 455652ccf843Smisaki } else { 455752ccf843Smisaki link_pause = 1; 455852ccf843Smisaki } 455952ccf843Smisaki } else { 456052ccf843Smisaki link_pause = an_common.bits.cap_pause; 456152ccf843Smisaki } 456252ccf843Smisaki statsp->mac_stats.link_pause = link_pause; 456344961713Sgirish } 4564d81011f0Ssbehera } else if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) { 4565d81011f0Ssbehera statsp->mac_stats.link_speed = 1000; 4566d81011f0Ssbehera statsp->mac_stats.link_duplex = 2; 456744961713Sgirish } 4568a3c5bd6dSspeer *link_up = LINK_IS_UP; 4569a3c5bd6dSspeer } 4570a3c5bd6dSspeer 4571a3c5bd6dSspeer if (nxgep->link_notify) { 4572a3c5bd6dSspeer *link_up = ((statsp->mac_stats.link_up) ? LINK_IS_UP : 457352ccf843Smisaki LINK_IS_DOWN); 4574a3c5bd6dSspeer nxgep->link_notify = B_FALSE; 457544961713Sgirish } 457644961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mii_check")); 457744961713Sgirish return (NXGE_OK); 457844961713Sgirish fail: 457944961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 458052ccf843Smisaki "nxge_mii_check: Unable to check MII")); 458144961713Sgirish return (status); 458244961713Sgirish } 458344961713Sgirish 458400161856Syc /* 458500161856Syc * Check PCS to see if there is any link status change. 458600161856Syc * This function is called by PORT_1G_SERDES only. 458700161856Syc */ 458800161856Syc void 45892e59129aSraghus nxge_pcs_check(p_nxge_t nxgep, uint8_t portn, nxge_link_state_t *link_up) 45902e59129aSraghus { 45912e59129aSraghus p_nxge_stats_t statsp; 45922e59129aSraghus boolean_t linkup; 45932e59129aSraghus 45942e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_check")); 45952e59129aSraghus 45962e59129aSraghus statsp = nxgep->statsp; 45972e59129aSraghus *link_up = LINK_NO_CHANGE; 45982e59129aSraghus 45992e59129aSraghus (void) npi_mac_get_link_status(nxgep->npi_handle, portn, &linkup); 46002e59129aSraghus if (linkup) { 46012e59129aSraghus if (nxgep->link_notify || 46022e59129aSraghus nxgep->statsp->mac_stats.link_up == 0) { 46032e59129aSraghus statsp->mac_stats.link_up = 1; 46042e59129aSraghus statsp->mac_stats.link_speed = 1000; 46052e59129aSraghus statsp->mac_stats.link_duplex = 2; 46062e59129aSraghus *link_up = LINK_IS_UP; 46072e59129aSraghus nxgep->link_notify = B_FALSE; 46082e59129aSraghus } 46092e59129aSraghus } else { 46102e59129aSraghus if (nxgep->link_notify || 46112e59129aSraghus nxgep->statsp->mac_stats.link_up == 1) { 46122e59129aSraghus statsp->mac_stats.link_up = 0; 46132e59129aSraghus statsp->mac_stats.link_speed = 0; 46142e59129aSraghus statsp->mac_stats.link_duplex = 0; 46152e59129aSraghus *link_up = LINK_IS_DOWN; 46162e59129aSraghus nxgep->link_notify = B_FALSE; 46172e59129aSraghus } 46182e59129aSraghus } 46192e59129aSraghus 46202e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_check")); 46212e59129aSraghus } 46222e59129aSraghus 462344961713Sgirish /* Add a multicast address entry into the HW hash table */ 462444961713Sgirish 462544961713Sgirish nxge_status_t 462644961713Sgirish nxge_add_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp) 462744961713Sgirish { 462844961713Sgirish uint32_t mchash; 462944961713Sgirish p_hash_filter_t hash_filter; 463044961713Sgirish uint16_t hash_bit; 463144961713Sgirish boolean_t rx_init = B_FALSE; 463244961713Sgirish uint_t j; 463344961713Sgirish nxge_status_t status = NXGE_OK; 463444961713Sgirish 463544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_add_mcast_addr")); 463644961713Sgirish 463744961713Sgirish RW_ENTER_WRITER(&nxgep->filter_lock); 463844961713Sgirish mchash = crc32_mchash(addrp); 463944961713Sgirish if (nxgep->hash_filter == NULL) { 464044961713Sgirish NXGE_DEBUG_MSG((NULL, STR_CTL, 464152ccf843Smisaki "Allocating hash filter storage.")); 464244961713Sgirish nxgep->hash_filter = KMEM_ZALLOC(sizeof (hash_filter_t), 464352ccf843Smisaki KM_SLEEP); 464444961713Sgirish } 464544961713Sgirish hash_filter = nxgep->hash_filter; 464644961713Sgirish j = mchash / HASH_REG_WIDTH; 464744961713Sgirish hash_bit = (1 << (mchash % HASH_REG_WIDTH)); 464844961713Sgirish hash_filter->hash_filter_regs[j] |= hash_bit; 464944961713Sgirish hash_filter->hash_bit_ref_cnt[mchash]++; 465044961713Sgirish if (hash_filter->hash_bit_ref_cnt[mchash] == 1) { 465144961713Sgirish hash_filter->hash_ref_cnt++; 465244961713Sgirish rx_init = B_TRUE; 465344961713Sgirish } 465444961713Sgirish if (rx_init) { 465544961713Sgirish if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 465644961713Sgirish goto fail; 465744961713Sgirish if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 465844961713Sgirish goto fail; 465944961713Sgirish } 466044961713Sgirish 466144961713Sgirish RW_EXIT(&nxgep->filter_lock); 466244961713Sgirish 466344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_add_mcast_addr")); 466444961713Sgirish 466544961713Sgirish return (NXGE_OK); 466644961713Sgirish fail: 466744961713Sgirish RW_EXIT(&nxgep->filter_lock); 466844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_add_mcast_addr: " 466952ccf843Smisaki "Unable to add multicast address")); 467044961713Sgirish return (status); 467144961713Sgirish } 467244961713Sgirish 467344961713Sgirish /* Remove a multicast address entry from the HW hash table */ 467444961713Sgirish 467544961713Sgirish nxge_status_t 467644961713Sgirish nxge_del_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp) 467744961713Sgirish { 467844961713Sgirish uint32_t mchash; 467944961713Sgirish p_hash_filter_t hash_filter; 468044961713Sgirish uint16_t hash_bit; 468144961713Sgirish boolean_t rx_init = B_FALSE; 468244961713Sgirish uint_t j; 468344961713Sgirish nxge_status_t status = NXGE_OK; 468444961713Sgirish 468544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_del_mcast_addr")); 468644961713Sgirish RW_ENTER_WRITER(&nxgep->filter_lock); 468744961713Sgirish mchash = crc32_mchash(addrp); 468844961713Sgirish if (nxgep->hash_filter == NULL) { 468944961713Sgirish NXGE_DEBUG_MSG((NULL, STR_CTL, 469052ccf843Smisaki "Hash filter already de_allocated.")); 469144961713Sgirish RW_EXIT(&nxgep->filter_lock); 469244961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr")); 469344961713Sgirish return (NXGE_OK); 469444961713Sgirish } 469544961713Sgirish hash_filter = nxgep->hash_filter; 469644961713Sgirish hash_filter->hash_bit_ref_cnt[mchash]--; 469744961713Sgirish if (hash_filter->hash_bit_ref_cnt[mchash] == 0) { 469844961713Sgirish j = mchash / HASH_REG_WIDTH; 469944961713Sgirish hash_bit = (1 << (mchash % HASH_REG_WIDTH)); 470044961713Sgirish hash_filter->hash_filter_regs[j] &= ~hash_bit; 470144961713Sgirish hash_filter->hash_ref_cnt--; 470244961713Sgirish rx_init = B_TRUE; 470344961713Sgirish } 470444961713Sgirish if (hash_filter->hash_ref_cnt == 0) { 470544961713Sgirish NXGE_DEBUG_MSG((NULL, STR_CTL, 470652ccf843Smisaki "De-allocating hash filter storage.")); 470744961713Sgirish KMEM_FREE(hash_filter, sizeof (hash_filter_t)); 470844961713Sgirish nxgep->hash_filter = NULL; 470944961713Sgirish } 471044961713Sgirish 471144961713Sgirish if (rx_init) { 471244961713Sgirish if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 471344961713Sgirish goto fail; 471444961713Sgirish if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 471544961713Sgirish goto fail; 471644961713Sgirish } 471744961713Sgirish RW_EXIT(&nxgep->filter_lock); 471844961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr")); 471944961713Sgirish 472044961713Sgirish return (NXGE_OK); 472144961713Sgirish fail: 472244961713Sgirish RW_EXIT(&nxgep->filter_lock); 472344961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_del_mcast_addr: " 472452ccf843Smisaki "Unable to remove multicast address")); 472544961713Sgirish 472644961713Sgirish return (status); 472744961713Sgirish } 472844961713Sgirish 472944961713Sgirish /* Set MAC address into MAC address HW registers */ 473044961713Sgirish 473144961713Sgirish nxge_status_t 473244961713Sgirish nxge_set_mac_addr(p_nxge_t nxgep, struct ether_addr *addrp) 473344961713Sgirish { 473444961713Sgirish nxge_status_t status = NXGE_OK; 473544961713Sgirish 473644961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_mac_addr")); 473744961713Sgirish 473844961713Sgirish MUTEX_ENTER(&nxgep->ouraddr_lock); 473944961713Sgirish /* 474044961713Sgirish * Exit if the address is same as ouraddr or multicast or broadcast 474144961713Sgirish */ 474244961713Sgirish if (((addrp->ether_addr_octet[0] & 01) == 1) || 474352ccf843Smisaki (ether_cmp(addrp, ðerbroadcastaddr) == 0) || 474452ccf843Smisaki (ether_cmp(addrp, &nxgep->ouraddr) == 0)) { 474544961713Sgirish goto nxge_set_mac_addr_exit; 474644961713Sgirish } 474744961713Sgirish nxgep->ouraddr = *addrp; 474844961713Sgirish /* 474944961713Sgirish * Set new interface local address and re-init device. 475044961713Sgirish * This is destructive to any other streams attached 475144961713Sgirish * to this device. 475244961713Sgirish */ 475344961713Sgirish RW_ENTER_WRITER(&nxgep->filter_lock); 475444961713Sgirish if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 475544961713Sgirish goto fail; 475644961713Sgirish if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 475744961713Sgirish goto fail; 475844961713Sgirish 475944961713Sgirish RW_EXIT(&nxgep->filter_lock); 476044961713Sgirish MUTEX_EXIT(&nxgep->ouraddr_lock); 476144961713Sgirish goto nxge_set_mac_addr_end; 476244961713Sgirish nxge_set_mac_addr_exit: 476344961713Sgirish MUTEX_EXIT(&nxgep->ouraddr_lock); 476444961713Sgirish nxge_set_mac_addr_end: 476544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_mac_addr")); 476644961713Sgirish 476744961713Sgirish return (NXGE_OK); 476844961713Sgirish fail: 476944961713Sgirish MUTEX_EXIT(&nxgep->ouraddr_lock); 477044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_mac_addr: " 477152ccf843Smisaki "Unable to set mac address")); 477244961713Sgirish return (status); 477344961713Sgirish } 477444961713Sgirish 477598ecde52Stm static 477698ecde52Stm check_link_state_t 477700161856Syc nxge_check_link_stop(nxge_t *nxge) 477898ecde52Stm { 477998ecde52Stm /* If the poll has been cancelled, return STOP. */ 478098ecde52Stm MUTEX_ENTER(&nxge->poll_lock); 478198ecde52Stm if (nxge->suspended || nxge->poll_state == LINK_MONITOR_STOPPING) { 478298ecde52Stm nxge->poll_state = LINK_MONITOR_STOP; 478398ecde52Stm nxge->nxge_link_poll_timerid = 0; 478498ecde52Stm cv_broadcast(&nxge->poll_cv); 478598ecde52Stm MUTEX_EXIT(&nxge->poll_lock); 478698ecde52Stm 478798ecde52Stm NXGE_DEBUG_MSG((nxge, MAC_CTL, 478898ecde52Stm "nxge_check_%s_link(port<%d>) stopped.", 478998ecde52Stm nxge->mac.portmode == PORT_10G_FIBER ? "10g" : "mii", 479098ecde52Stm nxge->mac.portnum)); 479198ecde52Stm return (CHECK_LINK_STOP); 479298ecde52Stm } 479398ecde52Stm MUTEX_EXIT(&nxge->poll_lock); 479498ecde52Stm 479598ecde52Stm return (CHECK_LINK_RESCHEDULE); 479698ecde52Stm } 479798ecde52Stm 479800161856Syc /* 479900161856Syc * Check status of MII (MIF or PCS) link. 480000161856Syc * This function is called once per second, that is because this function 480100161856Syc * calls nxge_link_monitor with LINK_MONITOR_START, which starts a timer to 480200161856Syc * call this function recursively. 480300161856Syc */ 480459ac0c16Sdavemq static nxge_status_t 480544961713Sgirish nxge_check_mii_link(p_nxge_t nxgep) 480644961713Sgirish { 480744961713Sgirish mii_bmsr_t bmsr_ints, bmsr_data; 480844961713Sgirish mii_anlpar_t anlpar; 480944961713Sgirish mii_gsr_t gsr; 481044961713Sgirish p_mii_regs_t mii_regs; 481144961713Sgirish nxge_status_t status = NXGE_OK; 481244961713Sgirish uint8_t portn; 4813a3c5bd6dSspeer nxge_link_state_t link_up; 481444961713Sgirish 481598ecde52Stm if (nxgep->nxge_magic != NXGE_MAGIC) 481698ecde52Stm return (NXGE_ERROR); 481798ecde52Stm 481898ecde52Stm if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 481998ecde52Stm return (NXGE_OK); 482098ecde52Stm 482144961713Sgirish portn = nxgep->mac.portnum; 482244961713Sgirish 482344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_mii_link port<%d>", 482498ecde52Stm portn)); 482544961713Sgirish 482644961713Sgirish mii_regs = NULL; 482744961713Sgirish 482844961713Sgirish RW_ENTER_WRITER(&nxgep->filter_lock); 482944961713Sgirish 483044961713Sgirish if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10) 483144961713Sgirish goto nxge_check_mii_link_exit; 483244961713Sgirish 48332e59129aSraghus switch (nxgep->mac.portmode) { 48342e59129aSraghus default: 4835d81011f0Ssbehera bmsr_data.value = 0; 483644961713Sgirish if ((status = nxge_mii_read(nxgep, 48372e59129aSraghus nxgep->statsp->mac_stats.xcvr_portn, 4838adfcba55Sjoycey #if defined(__i386) 4839adfcba55Sjoycey (uint8_t)(uint32_t)(&mii_regs->bmsr), 4840adfcba55Sjoycey #else 48412e59129aSraghus (uint8_t)(uint64_t)(&mii_regs->bmsr), 4842adfcba55Sjoycey #endif 48432e59129aSraghus &bmsr_data.value)) != NXGE_OK) { 484444961713Sgirish goto fail; 484544961713Sgirish } 484644961713Sgirish 4847d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4848d81011f0Ssbehera "==> nxge_check_mii_link port<0x%x> " 4849d81011f0Ssbehera "RIGHT AFTER READ bmsr_data 0x%x (nxgep->bmsr 0x%x ", 48502d17280bSsbehera portn, bmsr_data.value, nxgep->bmsr.value)); 4851d81011f0Ssbehera 48522e59129aSraghus if (nxgep->param_arr[param_autoneg].value) { 48532e59129aSraghus if ((status = nxge_mii_read(nxgep, 485452ccf843Smisaki nxgep->statsp->mac_stats.xcvr_portn, 4855adfcba55Sjoycey #if defined(__i386) 485652ccf843Smisaki (uint8_t)(uint32_t)(&mii_regs->gsr), 4857adfcba55Sjoycey #else 485852ccf843Smisaki (uint8_t)(uint64_t)(&mii_regs->gsr), 4859adfcba55Sjoycey #endif 486052ccf843Smisaki &gsr.value)) != NXGE_OK) 48612e59129aSraghus goto fail; 48622e59129aSraghus if ((status = nxge_mii_read(nxgep, 486352ccf843Smisaki nxgep->statsp->mac_stats.xcvr_portn, 4864adfcba55Sjoycey #if defined(__i386) 486552ccf843Smisaki (uint8_t)(uint32_t)(&mii_regs->anlpar), 4866adfcba55Sjoycey #else 486752ccf843Smisaki (uint8_t)(uint64_t)(&mii_regs->anlpar), 4868adfcba55Sjoycey #endif 486952ccf843Smisaki &anlpar.value)) != NXGE_OK) 48702e59129aSraghus goto fail; 4871d81011f0Ssbehera if (nxgep->mac.portmode != PORT_1G_RGMII_FIBER) { 4872d81011f0Ssbehera 4873d81011f0Ssbehera if (nxgep->statsp->mac_stats.link_up && 4874d81011f0Ssbehera ((nxgep->statsp->mac_stats.lp_cap_1000fdx ^ 4875d81011f0Ssbehera gsr.bits.link_1000fdx) || 4876d81011f0Ssbehera (nxgep->statsp->mac_stats.lp_cap_1000hdx ^ 4877d81011f0Ssbehera gsr.bits.link_1000hdx) || 4878d81011f0Ssbehera (nxgep->statsp->mac_stats.lp_cap_100T4 ^ 4879d81011f0Ssbehera anlpar.bits.cap_100T4) || 4880d81011f0Ssbehera (nxgep->statsp->mac_stats.lp_cap_100fdx ^ 4881d81011f0Ssbehera anlpar.bits.cap_100fdx) || 4882d81011f0Ssbehera (nxgep->statsp->mac_stats.lp_cap_100hdx ^ 4883d81011f0Ssbehera anlpar.bits.cap_100hdx) || 4884d81011f0Ssbehera (nxgep->statsp->mac_stats.lp_cap_10fdx ^ 4885d81011f0Ssbehera anlpar.bits.cap_10fdx) || 4886d81011f0Ssbehera (nxgep->statsp->mac_stats.lp_cap_10hdx ^ 4887d81011f0Ssbehera anlpar.bits.cap_10hdx))) { 4888d81011f0Ssbehera bmsr_data.bits.link_status = 0; 4889d81011f0Ssbehera } 48902e59129aSraghus } 48912e59129aSraghus } 489244961713Sgirish 48932e59129aSraghus /* Workaround for link down issue */ 48942e59129aSraghus if (bmsr_data.value == 0) { 48952e59129aSraghus cmn_err(CE_NOTE, "!LINK DEBUG: Read zero bmsr\n"); 48962e59129aSraghus goto nxge_check_mii_link_exit; 48972e59129aSraghus } 48982e59129aSraghus 4899d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4900d81011f0Ssbehera "==> nxge_check_mii_link port<0x%x> :" 4901d81011f0Ssbehera "BEFORE BMSR ^ nxgep->bmsr 0x%x bmsr_data 0x%x", 49022d17280bSsbehera portn, nxgep->bmsr.value, bmsr_data.value)); 4903d81011f0Ssbehera 49042e59129aSraghus bmsr_ints.value = nxgep->bmsr.value ^ bmsr_data.value; 49052e59129aSraghus nxgep->bmsr.value = bmsr_data.value; 4906d81011f0Ssbehera 4907d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4908d81011f0Ssbehera "==> nxge_check_mii_link port<0x%x> CALLING " 4909d81011f0Ssbehera "bmsr_data 0x%x bmsr_ints.value 0x%x", 49102d17280bSsbehera portn, bmsr_data.value, bmsr_ints.value)); 4911d81011f0Ssbehera 49122e59129aSraghus if ((status = nxge_mii_check(nxgep, bmsr_data, bmsr_ints, 49132e59129aSraghus &link_up)) != NXGE_OK) { 49142e59129aSraghus goto fail; 49152e59129aSraghus } 49162e59129aSraghus break; 49172e59129aSraghus 49182e59129aSraghus case PORT_1G_SERDES: 491900161856Syc /* 492000161856Syc * Above default is for all cases except PORT_1G_SERDES. 492100161856Syc * The default case gets information from the PHY, but a 492200161856Syc * nxge whose portmode equals PORT_1G_SERDES does not 492300161856Syc * have a PHY. 492400161856Syc */ 49252e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 49262e59129aSraghus "==> nxge_check_mii_link port<%d> (SERDES)", portn)); 492700161856Syc nxge_pcs_check(nxgep, portn, &link_up); 49282e59129aSraghus break; 49292e59129aSraghus } 493044961713Sgirish 493144961713Sgirish nxge_check_mii_link_exit: 493244961713Sgirish RW_EXIT(&nxgep->filter_lock); 4933a3c5bd6dSspeer if (link_up == LINK_IS_UP) { 4934a3c5bd6dSspeer nxge_link_is_up(nxgep); 4935a3c5bd6dSspeer } else if (link_up == LINK_IS_DOWN) { 4936a3c5bd6dSspeer nxge_link_is_down(nxgep); 4937a3c5bd6dSspeer } 493844961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 493944961713Sgirish 494044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_mii_link port<%d>", 494152ccf843Smisaki portn)); 494244961713Sgirish return (NXGE_OK); 494344961713Sgirish 494444961713Sgirish fail: 494544961713Sgirish RW_EXIT(&nxgep->filter_lock); 494644961713Sgirish 494744961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 494844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 494952ccf843Smisaki "nxge_check_mii_link: Failed to check link port<%d>", portn)); 495044961713Sgirish return (status); 495144961713Sgirish } 495244961713Sgirish 495344961713Sgirish /*ARGSUSED*/ 495459ac0c16Sdavemq static nxge_status_t 495544961713Sgirish nxge_check_10g_link(p_nxge_t nxgep) 495644961713Sgirish { 495744961713Sgirish uint8_t portn; 495844961713Sgirish nxge_status_t status = NXGE_OK; 4959763fcc44Ssbehera boolean_t link_up; 49602e59129aSraghus uint32_t val; 49612e59129aSraghus npi_status_t rs; 496244961713Sgirish 496398ecde52Stm if (nxgep->nxge_magic != NXGE_MAGIC) 496498ecde52Stm return (NXGE_ERROR); 496598ecde52Stm 496698ecde52Stm if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 496798ecde52Stm return (NXGE_OK); 496898ecde52Stm 496944961713Sgirish portn = nxgep->mac.portnum; 4970d81011f0Ssbehera val = 0; 4971d81011f0Ssbehera rs = NPI_SUCCESS; 497244961713Sgirish 497344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_10g_link port<%d>", 497498ecde52Stm portn)); 497544961713Sgirish 49762e59129aSraghus switch (nxgep->mac.portmode) { 49772e59129aSraghus default: 49782d17280bSsbehera /* 49792d17280bSsbehera * Check if the phy is present in case of hot swappable phy 49802d17280bSsbehera */ 49812d17280bSsbehera if (nxgep->hot_swappable_phy) { 49822d17280bSsbehera boolean_t phy_present_now = B_FALSE; 49832d17280bSsbehera 49842d17280bSsbehera /* 49852d17280bSsbehera * If this is the 2nd Goa port, then check 2 addresses 49862d17280bSsbehera * to take care of the Goa NEM card requirements. 49872d17280bSsbehera */ 49882d17280bSsbehera if (portn == 1) { 49892d17280bSsbehera if (nxge_is_phy_present(nxgep, 499000161856Syc ALT_GOA_CLAUSE45_PORT1_ADDR, 49912d17280bSsbehera BCM8706_DEV_ID, BCM_PHY_ID_MASK)) { 49922d17280bSsbehera phy_present_now = B_TRUE; 49932d17280bSsbehera nxgep->xcvr_addr = 499400161856Syc ALT_GOA_CLAUSE45_PORT1_ADDR; 49952d17280bSsbehera goto phy_check_done; 49962d17280bSsbehera } 49972d17280bSsbehera } 49982d17280bSsbehera if (nxge_is_phy_present(nxgep, 499900161856Syc (GOA_CLAUSE45_PORT_ADDR_BASE) + portn, 50002d17280bSsbehera BCM8706_DEV_ID, BCM_PHY_ID_MASK)) { 50012d17280bSsbehera nxgep->xcvr_addr = 500200161856Syc (GOA_CLAUSE45_PORT_ADDR_BASE) + portn; 50032d17280bSsbehera phy_present_now = B_TRUE; 50042d17280bSsbehera } 50052d17280bSsbehera 50062d17280bSsbehera phy_check_done: 50071c7408c9Stc /* Check back-to-back XAUI connect to detect Opus NEM */ 50081c7408c9Stc rs = npi_xmac_xpcs_read(nxgep->npi_handle, 50091c7408c9Stc nxgep->mac.portnum, XPCS_REG_STATUS, &val); 50101c7408c9Stc if (rs != 0) 50111c7408c9Stc goto fail; 50121c7408c9Stc 50131c7408c9Stc link_up = B_FALSE; 50141c7408c9Stc if (val & XPCS_STATUS_LANE_ALIGN) { 50151c7408c9Stc link_up = B_TRUE; 50161c7408c9Stc } 50171c7408c9Stc 50182d17280bSsbehera if (nxgep->phy_absent) { 50192d17280bSsbehera if (phy_present_now) { 50202d17280bSsbehera /* 50212d17280bSsbehera * Detect, Initialize phy and do link up 50222d17280bSsbehera * set xcvr vals, link_init, nxge_init 50232d17280bSsbehera */ 50242d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 50252d17280bSsbehera "Hot swappable phy DETECTED!!")); 50262d17280bSsbehera nxgep->phy_absent = B_FALSE; 50272d17280bSsbehera (void) nxge_xcvr_find(nxgep); 50282d17280bSsbehera (void) nxge_link_init(nxgep); 50292d17280bSsbehera if (!(nxgep->drv_state & 50302d17280bSsbehera STATE_HW_INITIALIZED)) { 50312d17280bSsbehera status = nxge_init(nxgep); 50322d17280bSsbehera if (status != NXGE_OK) { 50332d17280bSsbehera NXGE_ERROR_MSG((nxgep, 50342d17280bSsbehera NXGE_ERR_CTL, 50352d17280bSsbehera "Hot swappable " 50362d17280bSsbehera "phy present, but" 50372d17280bSsbehera " driver init" 50382d17280bSsbehera " failed...")); 50392d17280bSsbehera goto fail; 50402d17280bSsbehera } 50412d17280bSsbehera } 50421c7408c9Stc } else if (link_up) { /* XAUI linkup, no PHY */ 504348056c53SMichael Speer /* 50441c7408c9Stc * This is the back-to-back XAUI 50451c7408c9Stc * connect case for Opus NEM. 50461c7408c9Stc */ 50471c7408c9Stc nxgep->statsp->mac_stats.xcvr_inuse = 50481c7408c9Stc XPCS_XCVR; 50491c7408c9Stc nxgep->mac.portmode = PORT_10G_SERDES; 50501c7408c9Stc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 50511c7408c9Stc "HSP 10G Serdes DETECTED!!")); 50521c7408c9Stc break; 50532d17280bSsbehera } 50542d17280bSsbehera 50552d17280bSsbehera goto start_link_check; 50562d17280bSsbehera 50572d17280bSsbehera } else if (!phy_present_now) { 50582d17280bSsbehera /* 50592d17280bSsbehera * Phy gone, bring link down reset xcvr vals 50602d17280bSsbehera */ 50612d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 50622d17280bSsbehera "Hot swappable phy REMOVED!!")); 50632d17280bSsbehera nxgep->phy_absent = B_TRUE; 50642d17280bSsbehera nxgep->statsp->mac_stats.link_up = 0; 50652d17280bSsbehera nxgep->statsp->mac_stats.link_speed = 0; 50662d17280bSsbehera nxgep->statsp->mac_stats.link_duplex = 0; 50672d17280bSsbehera nxge_link_is_down(nxgep); 50682d17280bSsbehera nxgep->link_notify = B_FALSE; 50692d17280bSsbehera 50702d17280bSsbehera (void) nxge_xcvr_find(nxgep); 50712d17280bSsbehera 50722d17280bSsbehera goto start_link_check; 50732d17280bSsbehera 50742d17280bSsbehera } 50752d17280bSsbehera } 507652cdd236Ssbehera if (nxgep->chip_id == MRVL88X201X_CHIP_ID) { 507700161856Syc status = nxge_check_mrvl88x2011_link(nxgep, &link_up); 507852cdd236Ssbehera } else { 507952cdd236Ssbehera status = nxge_check_bcm8704_link(nxgep, &link_up); 508052cdd236Ssbehera } 50812e59129aSraghus if (status != NXGE_OK) 50822e59129aSraghus goto fail; 50832e59129aSraghus break; 50842e59129aSraghus case PORT_10G_SERDES: 50852e59129aSraghus rs = npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 5086763fcc44Ssbehera XPCS_REG_STATUS, &val); 50872e59129aSraghus if (rs != 0) 50882e59129aSraghus goto fail; 50892e59129aSraghus 50902e59129aSraghus link_up = B_FALSE; 5091763fcc44Ssbehera if (val & XPCS_STATUS_LANE_ALIGN) { 5092763fcc44Ssbehera link_up = B_TRUE; 50932e59129aSraghus } 50942e59129aSraghus 50952e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 50962e59129aSraghus "==> nxge_check_10g_link port<%d> " 5097763fcc44Ssbehera "XPCS_REG_STATUS2 0x%x link_up %d", 5098763fcc44Ssbehera portn, val, link_up)); 50992e59129aSraghus 51002e59129aSraghus break; 51012e59129aSraghus } 510244961713Sgirish 510344961713Sgirish if (link_up) { 5104a3c5bd6dSspeer if (nxgep->link_notify || 510552ccf843Smisaki nxgep->statsp->mac_stats.link_up == 0) { 510644961713Sgirish if (nxge_10g_link_led_on(nxgep) != NXGE_OK) 510744961713Sgirish goto fail; 510844961713Sgirish nxgep->statsp->mac_stats.link_up = 1; 510944961713Sgirish nxgep->statsp->mac_stats.link_speed = 10000; 511044961713Sgirish nxgep->statsp->mac_stats.link_duplex = 2; 511144961713Sgirish 511244961713Sgirish nxge_link_is_up(nxgep); 5113a3c5bd6dSspeer nxgep->link_notify = B_FALSE; 511444961713Sgirish } 511544961713Sgirish } else { 5116a3c5bd6dSspeer if (nxgep->link_notify || 511752ccf843Smisaki nxgep->statsp->mac_stats.link_up == 1) { 511844961713Sgirish if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 511944961713Sgirish goto fail; 512044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 512152ccf843Smisaki "Link down cable problem")); 512244961713Sgirish nxgep->statsp->mac_stats.link_up = 0; 512344961713Sgirish nxgep->statsp->mac_stats.link_speed = 0; 512444961713Sgirish nxgep->statsp->mac_stats.link_duplex = 0; 512544961713Sgirish 512644961713Sgirish nxge_link_is_down(nxgep); 5127a3c5bd6dSspeer nxgep->link_notify = B_FALSE; 51281c7408c9Stc 51291c7408c9Stc if (nxgep->mac.portmode == PORT_10G_SERDES) { 51301c7408c9Stc /* 51311c7408c9Stc * NEM was unplugged, set up xcvr table 51321c7408c9Stc * to find another xcvr in the future. 51331c7408c9Stc */ 51341c7408c9Stc (void) nxge_xcvr_find(nxgep); 51351c7408c9Stc } 513644961713Sgirish } 513744961713Sgirish } 513844961713Sgirish 51392d17280bSsbehera start_link_check: 514044961713Sgirish (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 514144961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_10g_link port<%d>", 514298ecde52Stm portn)); 514344961713Sgirish return (NXGE_OK); 514444961713Sgirish 514544961713Sgirish fail: 514698ecde52Stm (void) nxge_check_link_stop(nxgep); 514798ecde52Stm 514844961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 514998ecde52Stm "nxge_check_10g_link: Failed to check link port<%d>", 515098ecde52Stm portn)); 515144961713Sgirish return (status); 515244961713Sgirish } 515344961713Sgirish 515444961713Sgirish 515544961713Sgirish /* Declare link down */ 515644961713Sgirish 515744961713Sgirish void 515844961713Sgirish nxge_link_is_down(p_nxge_t nxgep) 515944961713Sgirish { 516059ac0c16Sdavemq p_nxge_stats_t statsp; 516159ac0c16Sdavemq char link_stat_msg[64]; 516259ac0c16Sdavemq 516344961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_down")); 516444961713Sgirish 516559ac0c16Sdavemq statsp = nxgep->statsp; 516659ac0c16Sdavemq (void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is down", 516759ac0c16Sdavemq statsp->mac_stats.xcvr_portn); 516859ac0c16Sdavemq 516959ac0c16Sdavemq if (nxge_no_msg == B_FALSE) { 517059ac0c16Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg)); 517159ac0c16Sdavemq } 517259ac0c16Sdavemq 517344961713Sgirish mac_link_update(nxgep->mach, LINK_STATE_DOWN); 517444961713Sgirish 517544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_down")); 517644961713Sgirish } 517744961713Sgirish 517844961713Sgirish /* Declare link up */ 517944961713Sgirish 518044961713Sgirish void 518144961713Sgirish nxge_link_is_up(p_nxge_t nxgep) 518244961713Sgirish { 518359ac0c16Sdavemq p_nxge_stats_t statsp; 518459ac0c16Sdavemq char link_stat_msg[64]; 518544961713Sgirish uint32_t val; 518644961713Sgirish 518744961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_up")); 518844961713Sgirish 518959ac0c16Sdavemq statsp = nxgep->statsp; 519059ac0c16Sdavemq (void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is up %d Mbps ", 519159ac0c16Sdavemq statsp->mac_stats.xcvr_portn, 519259ac0c16Sdavemq statsp->mac_stats.link_speed); 519359ac0c16Sdavemq 519459ac0c16Sdavemq if (statsp->mac_stats.link_T4) 519559ac0c16Sdavemq (void) strcat(link_stat_msg, "T4"); 519659ac0c16Sdavemq else if (statsp->mac_stats.link_duplex == 2) 519759ac0c16Sdavemq (void) strcat(link_stat_msg, "full duplex"); 519859ac0c16Sdavemq else 519959ac0c16Sdavemq (void) strcat(link_stat_msg, "half duplex"); 520059ac0c16Sdavemq 520144961713Sgirish 520244961713Sgirish /* Clean up symbol errors incurred during link transition */ 52032e59129aSraghus if ((nxgep->mac.portmode == PORT_10G_FIBER) || 52042e59129aSraghus (nxgep->mac.portmode == PORT_10G_SERDES)) { 520544961713Sgirish (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 520652ccf843Smisaki XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val); 520744961713Sgirish (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 520852ccf843Smisaki XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val); 520944961713Sgirish } 521044961713Sgirish 521100161856Syc /* 521200161856Syc * If the driver was plumbed without a link (therefore auto-negotiation 521300161856Syc * could not complete), the driver will detect a link up when a cable 521400161856Syc * conneting to a link partner is plugged into the port. By the time 521500161856Syc * link-up is detected, auto-negotiation should have completed (The 521600161856Syc * TN1010 tries to contact a link partner every 8~24ms). Here we re- 521700161856Syc * configure the Neptune/NIU according to the newly negotiated speed. 521800161856Syc * This is necessary only for the TN1010 basad device because only the 521900161856Syc * TN1010 supports dual speeds. 522000161856Syc */ 522100161856Syc if (nxgep->mac.portmode == PORT_1G_TN1010 || 522200161856Syc nxgep->mac.portmode == PORT_10G_TN1010) { 522300161856Syc 522400161856Syc (void) nxge_set_tn1010_param(nxgep); 522500161856Syc 522600161856Syc /* 522700161856Syc * nxge_xcvr_find calls nxge_get_xcvr_type (which sets 522800161856Syc * nxgep->portmode) and nxge_setup_xcvr_table (which sets 522900161856Syc * the nxgep->xcvr to the proper nxge_xcvr_table_t struct). 523000161856Syc */ 523100161856Syc if (nxge_xcvr_find(nxgep) != NXGE_OK) { 523200161856Syc NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 523300161856Syc "nxge_link_is_up: nxge_xcvr_find failed")); 523400161856Syc } 523500161856Syc 523600161856Syc /* nxge_link_init calls nxge_xcvr_init and nxge_serdes_init */ 523700161856Syc if (nxge_link_init(nxgep) != NXGE_OK) { 523800161856Syc NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 523900161856Syc "nxge_link_is_up: nxge_link_init failed")); 524000161856Syc } 524100161856Syc 524200161856Syc /* 524300161856Syc * nxge_mac_init calls many subroutines including 524400161856Syc * nxge_xif_init which sets XGMII or GMII mode 524500161856Syc */ 524600161856Syc if (nxge_mac_init(nxgep) != NXGE_OK) { 524700161856Syc NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 524800161856Syc "nxge_link_is_up: nxge_mac_init failed")); 524900161856Syc } 525000161856Syc } else { 525100161856Syc (void) nxge_xif_init(nxgep); 525200161856Syc } 525300161856Syc 525459ac0c16Sdavemq if (nxge_no_msg == B_FALSE) { 525559ac0c16Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg)); 525659ac0c16Sdavemq } 525759ac0c16Sdavemq 525844961713Sgirish mac_link_update(nxgep->mach, LINK_STATE_UP); 525944961713Sgirish 526044961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_up")); 526144961713Sgirish } 526244961713Sgirish 526300161856Syc #ifdef NXGE_DEBUG 526400161856Syc /* Dump all TN1010 Status registers */ 526500161856Syc static void 526600161856Syc nxge_dump_tn1010_status_regs(p_nxge_t nxgep) 526700161856Syc { 526800161856Syc uint16_t val; 526900161856Syc 527000161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 527100161856Syc TN1010_PMA_PMD_DEV_ADDR, 1, &val); 527200161856Syc cmn_err(CE_NOTE, "PMA status1 = 0x%x", val); 527300161856Syc 527400161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 527500161856Syc TN1010_PMA_PMD_DEV_ADDR, 8, &val); 527600161856Syc cmn_err(CE_NOTE, "PMA status2 = 0x%x", val); 527700161856Syc 527800161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 527900161856Syc TN1010_PMA_PMD_DEV_ADDR, 129, &val); 528000161856Syc cmn_err(CE_NOTE, "10BASET-T status = 0x%x", val); 528100161856Syc 528200161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 528300161856Syc TN1010_PCS_DEV_ADDR, 1, &val); 528400161856Syc cmn_err(CE_NOTE, "PCS status1 = 0x%x", val); 528500161856Syc 528600161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 528700161856Syc TN1010_PCS_DEV_ADDR, 8, &val); 528800161856Syc cmn_err(CE_NOTE, "PCS status2 = 0x%x", val); 528900161856Syc 529000161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 529100161856Syc TN1010_PCS_DEV_ADDR, 32, &val); 529200161856Syc cmn_err(CE_NOTE, "10GBASE-R status1 = 0x%x", val); 529300161856Syc 529400161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 529500161856Syc TN1010_PCS_DEV_ADDR, 33, &val); 529600161856Syc cmn_err(CE_NOTE, "10GBASE-R Status2 = 0x%x", val); 529700161856Syc 529800161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 529900161856Syc TN1010_PHYXS_DEV_ADDR, 1, &val); 530000161856Syc cmn_err(CE_NOTE, "PHYXS status1 = 0x%x", val); 530100161856Syc 530200161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 530300161856Syc TN1010_PHYXS_DEV_ADDR, 8, &val); 530400161856Syc cmn_err(CE_NOTE, "PHYXS status2 = 0x%x", val); 530500161856Syc 530600161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 530700161856Syc TN1010_PHYXS_DEV_ADDR, 24, &val); 530800161856Syc cmn_err(CE_NOTE, "XGXS Lane status = 0x%x", val); 530900161856Syc 531000161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 531100161856Syc TN1010_AUTONEG_DEV_ADDR, 1, &val); 531200161856Syc cmn_err(CE_NOTE, "Autoneg status = 0x%x", val); 531300161856Syc 531400161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 531500161856Syc TN1010_AUTONEG_DEV_ADDR, 33, &val); 531600161856Syc cmn_err(CE_NOTE, "10Gbase-T An status = 0x%x", val); 531700161856Syc 531800161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 531900161856Syc TN1010_VENDOR_MMD1_DEV_ADDR, 1, &val); 532000161856Syc cmn_err(CE_NOTE, "TN1010 status = 0x%x", val); 532100161856Syc 532200161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 532300161856Syc TN1010_VENDOR_MMD1_DEV_ADDR, 8, &val); 532400161856Syc cmn_err(CE_NOTE, "Device status = 0x%x", val); 532500161856Syc 532600161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 532700161856Syc TN1010_VENDOR_MMD1_DEV_ADDR, 16, &val); 532800161856Syc cmn_err(CE_NOTE, "DDR status = 0x%x", val); 532900161856Syc 533000161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 533100161856Syc TN1010_VENDOR_MMD1_DEV_ADDR, 17, &val); 533200161856Syc cmn_err(CE_NOTE, "DDR fault status = 0x%x", val); 533300161856Syc 533400161856Syc nxge_mdio_read(nxgep, nxgep->xcvr_addr, 533500161856Syc TN1010_VENDOR_MMD1_DEV_ADDR, 11, &val); 533600161856Syc cmn_err(CE_NOTE, "Firmware Revision = 0x%x Major = 0x%x Minor = 0x%x", 533700161856Syc val, (val & 0xFF00) >> 8, val & 0x00FF); 533800161856Syc } 533900161856Syc #endif 534000161856Syc 534144961713Sgirish /* 534244961713Sgirish * Calculate the bit in the multicast address filter 534344961713Sgirish * that selects the given * address. 534444961713Sgirish * Note: For GEM, the last 8-bits are used. 534544961713Sgirish */ 534644961713Sgirish uint32_t 534744961713Sgirish crc32_mchash(p_ether_addr_t addr) 534844961713Sgirish { 534944961713Sgirish uint8_t *cp; 535044961713Sgirish uint32_t crc; 535144961713Sgirish uint32_t c; 535244961713Sgirish int byte; 535344961713Sgirish int bit; 535444961713Sgirish 535544961713Sgirish cp = (uint8_t *)addr; 535644961713Sgirish crc = (uint32_t)0xffffffff; 535744961713Sgirish for (byte = 0; byte < 6; byte++) { 535844961713Sgirish c = (uint32_t)cp[byte]; 535944961713Sgirish for (bit = 0; bit < 8; bit++) { 536044961713Sgirish if ((c & 0x1) ^ (crc & 0x1)) 536144961713Sgirish crc = (crc >> 1)^0xedb88320; 536244961713Sgirish else 536344961713Sgirish crc = (crc >> 1); 536444961713Sgirish c >>= 1; 536544961713Sgirish } 536644961713Sgirish } 536744961713Sgirish return ((~crc) >> (32 - HASH_BITS)); 536844961713Sgirish } 536944961713Sgirish 537044961713Sgirish /* Reset serdes */ 537144961713Sgirish 537244961713Sgirish nxge_status_t 537344961713Sgirish nxge_serdes_reset(p_nxge_t nxgep) 537444961713Sgirish { 537544961713Sgirish npi_handle_t handle; 537644961713Sgirish 537744961713Sgirish handle = nxgep->npi_handle; 537844961713Sgirish 537944961713Sgirish ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0 | ESR_RESET_1); 538044961713Sgirish drv_usecwait(500); 538144961713Sgirish ESR_REG_WR(handle, ESR_CONFIG_REG, 0); 538244961713Sgirish 538344961713Sgirish return (NXGE_OK); 538444961713Sgirish } 538544961713Sgirish 538600161856Syc /* 538700161856Syc * This function monitors link status using interrupt or polling. 538800161856Syc * It calls nxgep->xcvr.check_link, a member function of 538900161856Syc * nxge_xcvr_table_t. But nxgep->xcvr.check_link calls this 539000161856Syc * function back, that is why the check_link routine is 539100161856Syc * executed periodically. 539200161856Syc */ 539344961713Sgirish nxge_status_t 539444961713Sgirish nxge_link_monitor(p_nxge_t nxgep, link_mon_enable_t enable) 539544961713Sgirish { 539644961713Sgirish nxge_status_t status = NXGE_OK; 539744961713Sgirish 5398678453a8Sspeer /* If we are a guest domain driver, don't bother. */ 5399678453a8Sspeer if (isLDOMguest(nxgep)) 5400678453a8Sspeer return (status); 5401678453a8Sspeer 540244961713Sgirish /* 540398ecde52Stm * Return immediately if this is an imaginary XMAC port. 540498ecde52Stm * (At least, we don't have 4-port XMAC cards yet.) 540544961713Sgirish */ 54062e59129aSraghus if ((nxgep->mac.portmode == PORT_10G_FIBER || 54072e59129aSraghus nxgep->mac.portmode == PORT_10G_SERDES) && 54082e59129aSraghus (nxgep->mac.portnum > 1)) 540944961713Sgirish return (NXGE_OK); 541044961713Sgirish 541144961713Sgirish if (nxgep->statsp == NULL) { 541244961713Sgirish /* stats has not been allocated. */ 541344961713Sgirish return (NXGE_OK); 541444961713Sgirish } 5415321febdeSsbehera /* Don't check link if we're in internal loopback mode */ 5416321febdeSsbehera if (nxgep->statsp->port_stats.lb_mode >= nxge_lb_serdes10g) 541744961713Sgirish return (NXGE_OK); 541844961713Sgirish 541944961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 542098ecde52Stm "==> nxge_link_monitor port<%d> enable=%d", 542198ecde52Stm nxgep->mac.portnum, enable)); 542244961713Sgirish if (enable == LINK_MONITOR_START) { 542344961713Sgirish if (nxgep->mac.linkchkmode == LINKCHK_INTR) { 542444961713Sgirish if ((status = nxge_link_intr(nxgep, LINK_INTR_START)) 542598ecde52Stm != NXGE_OK) 542644961713Sgirish goto fail; 542744961713Sgirish } else { 542898ecde52Stm timeout_id_t timerid; 542900161856Syc /* 543000161856Syc * check_link_stop means "Stop the link check", so 543100161856Syc * we return without starting the timer. 543200161856Syc */ 543398ecde52Stm if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 543498ecde52Stm return (NXGE_OK); 543598ecde52Stm 543600161856Syc /* 543700161856Syc * Otherwise fire the timer for the nxge to check 543800161856Syc * the link using the check_link function 543900161856Syc * of the nxge_xcvr_table and pass "nxgep" as the 544000161856Syc * argument to the check_link function. 544100161856Syc */ 544259ac0c16Sdavemq if (nxgep->xcvr.check_link) { 544359ac0c16Sdavemq timerid = timeout( 544459ac0c16Sdavemq (fptrv_t)(nxgep->xcvr.check_link), 544598ecde52Stm nxgep, 544698ecde52Stm drv_usectohz(LINK_MONITOR_PERIOD)); 544759ac0c16Sdavemq MUTEX_ENTER(&nxgep->poll_lock); 544859ac0c16Sdavemq nxgep->nxge_link_poll_timerid = timerid; 544959ac0c16Sdavemq MUTEX_EXIT(&nxgep->poll_lock); 545059ac0c16Sdavemq } else { 545198ecde52Stm return (NXGE_ERROR); 545244961713Sgirish } 545344961713Sgirish } 545444961713Sgirish } else { 545544961713Sgirish if (nxgep->mac.linkchkmode == LINKCHK_INTR) { 545644961713Sgirish if ((status = nxge_link_intr(nxgep, LINK_INTR_STOP)) 545798ecde52Stm != NXGE_OK) 545844961713Sgirish goto fail; 545944961713Sgirish } else { 546098ecde52Stm clock_t rv; 546198ecde52Stm 546298ecde52Stm MUTEX_ENTER(&nxgep->poll_lock); 546398ecde52Stm 546498ecde52Stm /* If <timerid> == 0, the link monitor has */ 546598ecde52Stm /* never been started, or just now stopped. */ 546698ecde52Stm if (nxgep->nxge_link_poll_timerid == 0) { 546798ecde52Stm MUTEX_EXIT(&nxgep->poll_lock); 546898ecde52Stm return (NXGE_OK); 546998ecde52Stm } 547098ecde52Stm 547198ecde52Stm nxgep->poll_state = LINK_MONITOR_STOPPING; 547298ecde52Stm rv = cv_timedwait(&nxgep->poll_cv, 547398ecde52Stm &nxgep->poll_lock, 547498ecde52Stm ddi_get_lbolt() + 547598ecde52Stm drv_usectohz(LM_WAIT_MULTIPLIER * 547698ecde52Stm LINK_MONITOR_PERIOD)); 547798ecde52Stm if (rv == -1) { 547898ecde52Stm NXGE_DEBUG_MSG((nxgep, MAC_CTL, 547998ecde52Stm "==> stopping port %d: " 548098ecde52Stm "cv_timedwait(%d) timed out", 548198ecde52Stm nxgep->mac.portnum, nxgep->poll_state)); 548298ecde52Stm nxgep->poll_state = LINK_MONITOR_STOP; 548344961713Sgirish nxgep->nxge_link_poll_timerid = 0; 548444961713Sgirish } 548598ecde52Stm 548698ecde52Stm MUTEX_EXIT(&nxgep->poll_lock); 548744961713Sgirish } 548844961713Sgirish } 548944961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, 549098ecde52Stm "<== nxge_link_monitor port<%d> enable=%d", 549198ecde52Stm nxgep->mac.portnum, enable)); 5492678453a8Sspeer 549344961713Sgirish return (NXGE_OK); 549444961713Sgirish fail: 549544961713Sgirish return (status); 549600161856Syc 549700161856Syc } 549800161856Syc 549900161856Syc nxge_status_t 550000161856Syc nxge_check_tn1010_link(p_nxge_t nxgep) 550100161856Syc { 550200161856Syc nxge_status_t status = NXGE_OK; 550300161856Syc nxge_link_state_t link_up; 550400161856Syc 550500161856Syc if (nxgep->nxge_magic != NXGE_MAGIC) { 550600161856Syc /* magic is 0 if driver is not attached */ 550700161856Syc return (NXGE_ERROR); 550800161856Syc } 550900161856Syc 551000161856Syc /* Link has been stopped, no need to continue */ 551100161856Syc if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) { 551200161856Syc return (NXGE_OK); 551300161856Syc } 551400161856Syc 551500161856Syc if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10) 551600161856Syc goto nxge_check_tn1010_link_exit; 551700161856Syc 551800161856Syc if ((status = nxge_tn1010_check(nxgep, &link_up)) != NXGE_OK) 551900161856Syc goto fail; 552000161856Syc 552100161856Syc nxge_check_tn1010_link_exit: 552200161856Syc if (link_up == LINK_IS_UP) 552300161856Syc nxge_link_is_up(nxgep); 552400161856Syc else if (link_up == LINK_IS_DOWN) 552500161856Syc nxge_link_is_down(nxgep); 552600161856Syc 552700161856Syc /* 552800161856Syc * nxge_link_monitor will call (nxgep->xcvr.check_link) 552900161856Syc * which could be THIS function. 553000161856Syc */ 553100161856Syc (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 553200161856Syc 553300161856Syc return (NXGE_OK); 553400161856Syc 553500161856Syc fail: 553600161856Syc (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 553700161856Syc 553800161856Syc NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 553900161856Syc "nxge_check_tn1010_link: Failed to check link")); 554000161856Syc return (status); 554100161856Syc } 554200161856Syc 554300161856Syc 554400161856Syc /* 554500161856Syc * Fill variable "link_up" with either LINK_IS_UP or LINK_IS_DOWN. 554600161856Syc */ 554700161856Syc static nxge_status_t 554800161856Syc nxge_tn1010_check(p_nxge_t nxgep, nxge_link_state_t *link_up) 554900161856Syc { 555000161856Syc nxge_status_t status = NXGE_OK; 555100161856Syc p_nxge_stats_t statsp; 555200161856Syc uint8_t phy_port_addr, portn; 555300161856Syc uint16_t val; 555400161856Syc 555500161856Syc *link_up = LINK_NO_CHANGE; 555600161856Syc 555700161856Syc portn = NXGE_GET_PORT_NUM(nxgep->function_num); 555800161856Syc phy_port_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 555900161856Syc statsp = nxgep->statsp; 556000161856Syc 556100161856Syc /* Check if link is up */ 556200161856Syc if ((status = nxge_mdio_read(nxgep, phy_port_addr, 556300161856Syc TN1010_AUTONEG_DEV_ADDR, TN1010_AUTONEG_STATUS_REG, &val)) 556400161856Syc != NXGE_OK) { 556500161856Syc goto fail; 556600161856Syc } 556700161856Syc /* 556800161856Syc * nxge_link_is_up has called nxge_set_tn1010_param and set 556900161856Syc * portmode and link_speed 557000161856Syc */ 557100161856Syc if (val & TN1010_AN_LINK_STAT_BIT) { 557200161856Syc if (nxgep->link_notify || 557300161856Syc nxgep->statsp->mac_stats.link_up == 0) { 557400161856Syc statsp->mac_stats.link_up = 1; 557500161856Syc statsp->mac_stats.link_duplex = 2; 557600161856Syc *link_up = LINK_IS_UP; 557700161856Syc nxgep->link_notify = B_FALSE; 557800161856Syc } 557900161856Syc } else { 558000161856Syc if (nxgep->link_notify || 558100161856Syc nxgep->statsp->mac_stats.link_up == 1) { 558200161856Syc statsp->mac_stats.link_up = 0; 558300161856Syc statsp->mac_stats.link_speed = 0; 558400161856Syc statsp->mac_stats.link_duplex = 0; 558500161856Syc *link_up = LINK_IS_DOWN; 558600161856Syc nxgep->link_notify = B_FALSE; 558700161856Syc } 558800161856Syc } 558900161856Syc return (NXGE_OK); 559000161856Syc 559100161856Syc fail: 559200161856Syc NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 559300161856Syc "nxge_tn1010_check: Unable to check TN1010")); 559400161856Syc return (status); 559544961713Sgirish } 559644961713Sgirish 559700161856Syc 559844961713Sgirish /* Set promiscous mode */ 559944961713Sgirish 560044961713Sgirish nxge_status_t 560144961713Sgirish nxge_set_promisc(p_nxge_t nxgep, boolean_t on) 560244961713Sgirish { 560344961713Sgirish nxge_status_t status = NXGE_OK; 560444961713Sgirish 560559ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_promisc: on %d", on)); 560644961713Sgirish 560744961713Sgirish nxgep->filter.all_phys_cnt = ((on) ? 1 : 0); 560844961713Sgirish 560944961713Sgirish RW_ENTER_WRITER(&nxgep->filter_lock); 561044961713Sgirish 561144961713Sgirish if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) { 561244961713Sgirish goto fail; 561344961713Sgirish } 561444961713Sgirish if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) { 561544961713Sgirish goto fail; 561644961713Sgirish } 561744961713Sgirish 561844961713Sgirish RW_EXIT(&nxgep->filter_lock); 561944961713Sgirish 562044961713Sgirish if (on) 562144961713Sgirish nxgep->statsp->mac_stats.promisc = B_TRUE; 562244961713Sgirish else 562344961713Sgirish nxgep->statsp->mac_stats.promisc = B_FALSE; 562444961713Sgirish 562544961713Sgirish NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_promisc")); 562644961713Sgirish 562744961713Sgirish return (NXGE_OK); 562844961713Sgirish fail: 562944961713Sgirish RW_EXIT(&nxgep->filter_lock); 563044961713Sgirish NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_promisc: " 563159ac0c16Sdavemq "Unable to set promisc (%d)", on)); 563244961713Sgirish 563344961713Sgirish return (status); 563444961713Sgirish } 563544961713Sgirish 563644961713Sgirish /*ARGSUSED*/ 563744961713Sgirish uint_t 563844961713Sgirish nxge_mif_intr(void *arg1, void *arg2) 563944961713Sgirish { 564044961713Sgirish #ifdef NXGE_DEBUG 564144961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg2; 564244961713Sgirish #endif 564344961713Sgirish #if NXGE_MIF 564444961713Sgirish p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1; 564544961713Sgirish uint32_t status; 564644961713Sgirish npi_handle_t handle; 564744961713Sgirish uint8_t portn; 564844961713Sgirish p_nxge_stats_t statsp; 564944961713Sgirish #endif 565044961713Sgirish 565144961713Sgirish #ifdef NXGE_MIF 565244961713Sgirish if (arg2 == NULL || (void *)ldvp->nxgep != arg2) { 565344961713Sgirish nxgep = ldvp->nxgep; 565444961713Sgirish } 565544961713Sgirish nxgep = ldvp->nxgep; 565644961713Sgirish #endif 565744961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mif_intr")); 565844961713Sgirish 565944961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr")); 566044961713Sgirish return (DDI_INTR_CLAIMED); 566144961713Sgirish 566244961713Sgirish mif_intr_fail: 566344961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr")); 566444961713Sgirish return (DDI_INTR_UNCLAIMED); 566544961713Sgirish } 566644961713Sgirish 566744961713Sgirish /*ARGSUSED*/ 566844961713Sgirish uint_t 566944961713Sgirish nxge_mac_intr(void *arg1, void *arg2) 567044961713Sgirish { 567144961713Sgirish p_nxge_t nxgep = (p_nxge_t)arg2; 567244961713Sgirish p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1; 567344961713Sgirish p_nxge_ldg_t ldgp; 567444961713Sgirish uint32_t status; 567544961713Sgirish npi_handle_t handle; 567644961713Sgirish uint8_t portn; 567744961713Sgirish p_nxge_stats_t statsp; 567844961713Sgirish npi_status_t rs = NPI_SUCCESS; 567944961713Sgirish 568044961713Sgirish if (arg2 == NULL || (void *)ldvp->nxgep != arg2) { 568144961713Sgirish nxgep = ldvp->nxgep; 568244961713Sgirish } 568344961713Sgirish 568444961713Sgirish ldgp = ldvp->ldgp; 568544961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mac_intr: " 568659ac0c16Sdavemq "group %d", ldgp->ldg)); 568744961713Sgirish 568844961713Sgirish handle = NXGE_DEV_NPI_HANDLE(nxgep); 568944961713Sgirish /* 569044961713Sgirish * This interrupt handler is for a specific 569144961713Sgirish * mac port. 569244961713Sgirish */ 569344961713Sgirish statsp = (p_nxge_stats_t)nxgep->statsp; 569444961713Sgirish portn = nxgep->mac.portnum; 569544961713Sgirish 569644961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, 569759ac0c16Sdavemq "==> nxge_mac_intr: reading mac stats: port<%d>", portn)); 569844961713Sgirish 569944961713Sgirish if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 570044961713Sgirish rs = npi_xmac_tx_get_istatus(handle, portn, 570152ccf843Smisaki (xmac_tx_iconfig_t *)&status); 570244961713Sgirish if (rs != NPI_SUCCESS) 570344961713Sgirish goto npi_fail; 570444961713Sgirish if (status & ICFG_XMAC_TX_ALL) { 570544961713Sgirish if (status & ICFG_XMAC_TX_UNDERRUN) { 570644961713Sgirish statsp->xmac_stats.tx_underflow_err++; 570744961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 570852ccf843Smisaki NXGE_FM_EREPORT_TXMAC_UNDERFLOW); 570944961713Sgirish } 571044961713Sgirish if (status & ICFG_XMAC_TX_MAX_PACKET_ERR) { 571144961713Sgirish statsp->xmac_stats.tx_maxpktsize_err++; 5712f6485eecSyc /* 5713f6485eecSyc * Do not send FMA ereport because this 5714f6485eecSyc * error does not indicate HW failure. 5715f6485eecSyc */ 571644961713Sgirish } 571744961713Sgirish if (status & ICFG_XMAC_TX_OVERFLOW) { 571844961713Sgirish statsp->xmac_stats.tx_overflow_err++; 571944961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 572052ccf843Smisaki NXGE_FM_EREPORT_TXMAC_OVERFLOW); 572144961713Sgirish } 572244961713Sgirish if (status & ICFG_XMAC_TX_FIFO_XFR_ERR) { 572344961713Sgirish statsp->xmac_stats.tx_fifo_xfr_err++; 572444961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 572552ccf843Smisaki NXGE_FM_EREPORT_TXMAC_TXFIFO_XFR_ERR); 572644961713Sgirish } 572744961713Sgirish if (status & ICFG_XMAC_TX_BYTE_CNT_EXP) { 572844961713Sgirish statsp->xmac_stats.tx_byte_cnt += 572952ccf843Smisaki XTXMAC_BYTE_CNT_MASK; 573044961713Sgirish } 573144961713Sgirish if (status & ICFG_XMAC_TX_FRAME_CNT_EXP) { 573244961713Sgirish statsp->xmac_stats.tx_frame_cnt += 573352ccf843Smisaki XTXMAC_FRM_CNT_MASK; 573444961713Sgirish } 573544961713Sgirish } 573644961713Sgirish 573744961713Sgirish rs = npi_xmac_rx_get_istatus(handle, portn, 573852ccf843Smisaki (xmac_rx_iconfig_t *)&status); 573944961713Sgirish if (rs != NPI_SUCCESS) 574044961713Sgirish goto npi_fail; 574144961713Sgirish if (status & ICFG_XMAC_RX_ALL) { 574244961713Sgirish if (status & ICFG_XMAC_RX_OVERFLOW) 574344961713Sgirish statsp->xmac_stats.rx_overflow_err++; 574444961713Sgirish if (status & ICFG_XMAC_RX_UNDERFLOW) { 574544961713Sgirish statsp->xmac_stats.rx_underflow_err++; 574644961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 574752ccf843Smisaki NXGE_FM_EREPORT_RXMAC_UNDERFLOW); 574844961713Sgirish } 5749f6485eecSyc /* 5750f6485eecSyc * Do not send FMA ereport for the following 3 errors 5751f6485eecSyc * because they do not indicate HW failures. 5752f6485eecSyc */ 575344961713Sgirish if (status & ICFG_XMAC_RX_CRC_ERR_CNT_EXP) { 575444961713Sgirish statsp->xmac_stats.rx_crc_err_cnt += 575552ccf843Smisaki XRXMAC_CRC_ER_CNT_MASK; 575644961713Sgirish } 575744961713Sgirish if (status & ICFG_XMAC_RX_LEN_ERR_CNT_EXP) { 575844961713Sgirish statsp->xmac_stats.rx_len_err_cnt += 575952ccf843Smisaki MAC_LEN_ER_CNT_MASK; 576044961713Sgirish } 576144961713Sgirish if (status & ICFG_XMAC_RX_VIOL_ERR_CNT_EXP) { 576244961713Sgirish statsp->xmac_stats.rx_viol_err_cnt += 576352ccf843Smisaki XRXMAC_CD_VIO_CNT_MASK; 576444961713Sgirish } 576544961713Sgirish if (status & ICFG_XMAC_RX_OCT_CNT_EXP) { 576644961713Sgirish statsp->xmac_stats.rx_byte_cnt += 576752ccf843Smisaki XRXMAC_BT_CNT_MASK; 576844961713Sgirish } 576944961713Sgirish if (status & ICFG_XMAC_RX_HST_CNT1_EXP) { 577044961713Sgirish statsp->xmac_stats.rx_hist1_cnt += 577152ccf843Smisaki XRXMAC_HIST_CNT1_MASK; 577244961713Sgirish } 577344961713Sgirish if (status & ICFG_XMAC_RX_HST_CNT2_EXP) { 577444961713Sgirish statsp->xmac_stats.rx_hist2_cnt += 577552ccf843Smisaki XRXMAC_HIST_CNT2_MASK; 577644961713Sgirish } 577744961713Sgirish if (status & ICFG_XMAC_RX_HST_CNT3_EXP) { 577844961713Sgirish statsp->xmac_stats.rx_hist3_cnt += 577952ccf843Smisaki XRXMAC_HIST_CNT3_MASK; 578044961713Sgirish } 578144961713Sgirish if (status & ICFG_XMAC_RX_HST_CNT4_EXP) { 578244961713Sgirish statsp->xmac_stats.rx_hist4_cnt += 578352ccf843Smisaki XRXMAC_HIST_CNT4_MASK; 578444961713Sgirish } 578544961713Sgirish if (status & ICFG_XMAC_RX_HST_CNT5_EXP) { 578644961713Sgirish statsp->xmac_stats.rx_hist5_cnt += 578752ccf843Smisaki XRXMAC_HIST_CNT5_MASK; 578844961713Sgirish } 578944961713Sgirish if (status & ICFG_XMAC_RX_HST_CNT6_EXP) { 579044961713Sgirish statsp->xmac_stats.rx_hist6_cnt += 579152ccf843Smisaki XRXMAC_HIST_CNT6_MASK; 579244961713Sgirish } 579344961713Sgirish if (status & ICFG_XMAC_RX_BCAST_CNT_EXP) { 579444961713Sgirish statsp->xmac_stats.rx_broadcast_cnt += 579552ccf843Smisaki XRXMAC_BC_FRM_CNT_MASK; 579644961713Sgirish } 579744961713Sgirish if (status & ICFG_XMAC_RX_MCAST_CNT_EXP) { 579844961713Sgirish statsp->xmac_stats.rx_mult_cnt += 579952ccf843Smisaki XRXMAC_MC_FRM_CNT_MASK; 580044961713Sgirish } 5801f6485eecSyc /* 5802f6485eecSyc * Do not send FMA ereport for the following 3 errors 5803f6485eecSyc * because they do not indicate HW failures. 5804f6485eecSyc */ 580544961713Sgirish if (status & ICFG_XMAC_RX_FRAG_CNT_EXP) { 580644961713Sgirish statsp->xmac_stats.rx_frag_cnt += 580752ccf843Smisaki XRXMAC_FRAG_CNT_MASK; 580844961713Sgirish } 580944961713Sgirish if (status & ICFG_XMAC_RX_ALIGNERR_CNT_EXP) { 581044961713Sgirish statsp->xmac_stats.rx_frame_align_err_cnt += 581152ccf843Smisaki XRXMAC_AL_ER_CNT_MASK; 581244961713Sgirish } 581344961713Sgirish if (status & ICFG_XMAC_RX_LINK_FLT_CNT_EXP) { 581444961713Sgirish statsp->xmac_stats.rx_linkfault_err_cnt += 581552ccf843Smisaki XMAC_LINK_FLT_CNT_MASK; 581644961713Sgirish } 581744961713Sgirish if (status & ICFG_XMAC_RX_REMOTE_FLT_DET) { 581844961713Sgirish statsp->xmac_stats.rx_remotefault_err++; 581944961713Sgirish } 582044961713Sgirish if (status & ICFG_XMAC_RX_LOCAL_FLT_DET) { 582144961713Sgirish statsp->xmac_stats.rx_localfault_err++; 582244961713Sgirish } 582344961713Sgirish } 582444961713Sgirish 582544961713Sgirish rs = npi_xmac_ctl_get_istatus(handle, portn, 582652ccf843Smisaki (xmac_ctl_iconfig_t *)&status); 582744961713Sgirish if (rs != NPI_SUCCESS) 582844961713Sgirish goto npi_fail; 582944961713Sgirish if (status & ICFG_XMAC_CTRL_ALL) { 583044961713Sgirish if (status & ICFG_XMAC_CTRL_PAUSE_RCVD) 583144961713Sgirish statsp->xmac_stats.rx_pause_cnt++; 583244961713Sgirish if (status & ICFG_XMAC_CTRL_PAUSE_STATE) 583344961713Sgirish statsp->xmac_stats.tx_pause_state++; 583444961713Sgirish if (status & ICFG_XMAC_CTRL_NOPAUSE_STATE) 583544961713Sgirish statsp->xmac_stats.tx_nopause_state++; 583644961713Sgirish } 583744961713Sgirish } else if (nxgep->mac.porttype == PORT_TYPE_BMAC) { 583844961713Sgirish rs = npi_bmac_tx_get_istatus(handle, portn, 583952ccf843Smisaki (bmac_tx_iconfig_t *)&status); 584044961713Sgirish if (rs != NPI_SUCCESS) 584144961713Sgirish goto npi_fail; 584244961713Sgirish if (status & ICFG_BMAC_TX_ALL) { 584344961713Sgirish if (status & ICFG_BMAC_TX_UNDERFLOW) { 584444961713Sgirish statsp->bmac_stats.tx_underrun_err++; 584544961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 584652ccf843Smisaki NXGE_FM_EREPORT_TXMAC_UNDERFLOW); 584744961713Sgirish } 584844961713Sgirish if (status & ICFG_BMAC_TX_MAXPKTSZ_ERR) { 584944961713Sgirish statsp->bmac_stats.tx_max_pkt_err++; 585044961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 585152ccf843Smisaki NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR); 585244961713Sgirish } 585344961713Sgirish if (status & ICFG_BMAC_TX_BYTE_CNT_EXP) { 585444961713Sgirish statsp->bmac_stats.tx_byte_cnt += 585552ccf843Smisaki BTXMAC_BYTE_CNT_MASK; 585644961713Sgirish } 585744961713Sgirish if (status & ICFG_BMAC_TX_FRAME_CNT_EXP) { 585844961713Sgirish statsp->bmac_stats.tx_frame_cnt += 585952ccf843Smisaki BTXMAC_FRM_CNT_MASK; 586044961713Sgirish } 586144961713Sgirish } 586244961713Sgirish 586344961713Sgirish rs = npi_bmac_rx_get_istatus(handle, portn, 586452ccf843Smisaki (bmac_rx_iconfig_t *)&status); 586544961713Sgirish if (rs != NPI_SUCCESS) 586644961713Sgirish goto npi_fail; 586744961713Sgirish if (status & ICFG_BMAC_RX_ALL) { 586844961713Sgirish if (status & ICFG_BMAC_RX_OVERFLOW) { 586944961713Sgirish statsp->bmac_stats.rx_overflow_err++; 587044961713Sgirish } 587144961713Sgirish if (status & ICFG_BMAC_RX_FRAME_CNT_EXP) { 587244961713Sgirish statsp->bmac_stats.rx_frame_cnt += 587352ccf843Smisaki RXMAC_FRM_CNT_MASK; 587444961713Sgirish } 587544961713Sgirish if (status & ICFG_BMAC_RX_CRC_ERR_CNT_EXP) { 587644961713Sgirish statsp->bmac_stats.rx_crc_err_cnt += 587752ccf843Smisaki BMAC_CRC_ER_CNT_MASK; 587844961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 587952ccf843Smisaki NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP); 588044961713Sgirish } 588144961713Sgirish if (status & ICFG_BMAC_RX_LEN_ERR_CNT_EXP) { 588244961713Sgirish statsp->bmac_stats.rx_len_err_cnt += 588352ccf843Smisaki MAC_LEN_ER_CNT_MASK; 588444961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 588552ccf843Smisaki NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP); 588644961713Sgirish } 588744961713Sgirish if (status & ICFG_BMAC_RX_VIOL_ERR_CNT_EXP) 588844961713Sgirish statsp->bmac_stats.rx_viol_err_cnt += 588952ccf843Smisaki BMAC_CD_VIO_CNT_MASK; 589044961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 589152ccf843Smisaki NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP); 589244961713Sgirish } 589344961713Sgirish if (status & ICFG_BMAC_RX_BYTE_CNT_EXP) { 589444961713Sgirish statsp->bmac_stats.rx_byte_cnt += 589552ccf843Smisaki BRXMAC_BYTE_CNT_MASK; 589644961713Sgirish } 589744961713Sgirish if (status & ICFG_BMAC_RX_ALIGNERR_CNT_EXP) { 589844961713Sgirish statsp->bmac_stats.rx_align_err_cnt += 589952ccf843Smisaki BMAC_AL_ER_CNT_MASK; 590044961713Sgirish NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 590152ccf843Smisaki NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP); 590244961713Sgirish } 590344961713Sgirish 590444961713Sgirish rs = npi_bmac_ctl_get_istatus(handle, portn, 590552ccf843Smisaki (bmac_ctl_iconfig_t *)&status); 590644961713Sgirish if (rs != NPI_SUCCESS) 590744961713Sgirish goto npi_fail; 590844961713Sgirish 590944961713Sgirish if (status & ICFG_BMAC_CTL_ALL) { 591044961713Sgirish if (status & ICFG_BMAC_CTL_RCVPAUSE) 591144961713Sgirish statsp->bmac_stats.rx_pause_cnt++; 591244961713Sgirish if (status & ICFG_BMAC_CTL_INPAUSE_ST) 591344961713Sgirish statsp->bmac_stats.tx_pause_state++; 591444961713Sgirish if (status & ICFG_BMAC_CTL_INNOTPAUSE_ST) 591544961713Sgirish statsp->bmac_stats.tx_nopause_state++; 591644961713Sgirish } 591744961713Sgirish } 591844961713Sgirish 591944961713Sgirish if (ldgp->nldvs == 1) { 592044961713Sgirish (void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg, 592152ccf843Smisaki B_TRUE, ldgp->ldg_timer); 592244961713Sgirish } 592344961713Sgirish 592444961713Sgirish NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mac_intr")); 592544961713Sgirish return (DDI_INTR_CLAIMED); 592644961713Sgirish 592744961713Sgirish npi_fail: 592844961713Sgirish NXGE_ERROR_MSG((nxgep, INT_CTL, "<== nxge_mac_intr")); 592944961713Sgirish return (DDI_INTR_UNCLAIMED); 593044961713Sgirish } 593144961713Sgirish 593244961713Sgirish nxge_status_t 593344961713Sgirish nxge_check_bcm8704_link(p_nxge_t nxgep, boolean_t *link_up) 593444961713Sgirish { 593544961713Sgirish uint8_t phy_port_addr; 593644961713Sgirish nxge_status_t status = NXGE_OK; 593744961713Sgirish boolean_t rx_sig_ok; 593844961713Sgirish boolean_t pcs_blk_lock; 593944961713Sgirish boolean_t link_align; 594044961713Sgirish uint16_t val1, val2, val3; 594144961713Sgirish #ifdef NXGE_DEBUG_SYMBOL_ERR 594244961713Sgirish uint16_t val_debug; 594344961713Sgirish uint16_t val; 594444961713Sgirish #endif 594544961713Sgirish 594644961713Sgirish phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn; 594744961713Sgirish 594844961713Sgirish #ifdef NXGE_DEBUG_SYMBOL_ERR 594944961713Sgirish /* Check Device 3 Register Device 3 0xC809 */ 595044961713Sgirish (void) nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0xC809, &val_debug); 595144961713Sgirish if ((val_debug & ~0x200) != 0) { 595244961713Sgirish cmn_err(CE_NOTE, "!Port%d BCM8704 Dev3 Reg 0xc809 = 0x%x\n", 595352ccf843Smisaki nxgep->mac.portnum, val_debug); 595444961713Sgirish (void) nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, 595552ccf843Smisaki &val_debug); 595644961713Sgirish cmn_err(CE_NOTE, "!Port%d BCM8704 Dev4 Reg 0x18 = 0x%x\n", 595752ccf843Smisaki nxgep->mac.portnum, val_debug); 595844961713Sgirish } 595944961713Sgirish 596044961713Sgirish (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 596152ccf843Smisaki XPCS_REG_DESCWERR_COUNTER, &val); 596244961713Sgirish if (val != 0) 596344961713Sgirish cmn_err(CE_NOTE, "!XPCS DESCWERR = 0x%x\n", val); 596444961713Sgirish 596544961713Sgirish (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 596652ccf843Smisaki XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val); 596744961713Sgirish if (val != 0) 596844961713Sgirish cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L0_1 = 0x%x\n", val); 596944961713Sgirish 597044961713Sgirish (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 597152ccf843Smisaki XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val); 597244961713Sgirish if (val != 0) 597344961713Sgirish cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L2_3 = 0x%x\n", val); 597444961713Sgirish #endif 597544961713Sgirish 597644961713Sgirish /* Check from BCM8704 if 10G link is up or down */ 597744961713Sgirish 597844961713Sgirish /* Check Device 1 Register 0xA bit0 */ 597952ccf843Smisaki status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PMA_PMD_DEV_ADDR, 598052ccf843Smisaki BCM8704_PMD_RECEIVE_SIG_DETECT, &val1); 598144961713Sgirish if (status != NXGE_OK) 598244961713Sgirish goto fail; 598344961713Sgirish rx_sig_ok = ((val1 & GLOB_PMD_RX_SIG_OK) ? B_TRUE : B_FALSE); 598444961713Sgirish 598544961713Sgirish /* Check Device 3 Register 0x20 bit0 */ 598652ccf843Smisaki if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PCS_DEV_ADDR, 598752ccf843Smisaki BCM8704_10GBASE_R_PCS_STATUS_REG, &val2)) != NPI_SUCCESS) 598844961713Sgirish goto fail; 598944961713Sgirish pcs_blk_lock = ((val2 & PCS_10GBASE_R_PCS_BLK_LOCK) ? B_TRUE : B_FALSE); 599044961713Sgirish 599144961713Sgirish /* Check Device 4 Register 0x18 bit12 */ 599252ccf843Smisaki status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 599352ccf843Smisaki BCM8704_PHYXS_XGXS_LANE_STATUS_REG, &val3); 599444961713Sgirish if (status != NXGE_OK) 599544961713Sgirish goto fail; 59962d17280bSsbehera 59972d17280bSsbehera switch (nxgep->chip_id) { 59982d17280bSsbehera case BCM8704_CHIP_ID: 59992d17280bSsbehera link_align = (val3 == (XGXS_LANE_ALIGN_STATUS | 60002d17280bSsbehera XGXS_LANE3_SYNC | XGXS_LANE2_SYNC | XGXS_LANE1_SYNC | 60012d17280bSsbehera XGXS_LANE0_SYNC | 0x400)) ? B_TRUE : B_FALSE; 60022d17280bSsbehera break; 60032d17280bSsbehera case BCM8706_CHIP_ID: 60042d17280bSsbehera link_align = ((val3 & XGXS_LANE_ALIGN_STATUS) && 60052d17280bSsbehera (val3 & XGXS_LANE3_SYNC) && (val3 & XGXS_LANE2_SYNC) && 60062d17280bSsbehera (val3 & XGXS_LANE1_SYNC) && (val3 & XGXS_LANE0_SYNC)) ? 60072d17280bSsbehera B_TRUE : B_FALSE; 60082d17280bSsbehera break; 60092d17280bSsbehera default: 60102d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_check_bcm8704_link:" 60112d17280bSsbehera "Unknown chip ID [0x%x]", nxgep->chip_id)); 60122d17280bSsbehera goto fail; 60132d17280bSsbehera } 60142d17280bSsbehera 601544961713Sgirish 601644961713Sgirish #ifdef NXGE_DEBUG_ALIGN_ERR 601744961713Sgirish /* Temp workaround for link down issue */ 601844961713Sgirish if (pcs_blk_lock == B_FALSE) { 601944961713Sgirish if (val2 != 0x4) { 602044961713Sgirish pcs_blk_lock = B_TRUE; 602152ccf843Smisaki cmn_err(CE_NOTE, "!LINK DEBUG: port%d PHY Dev3 " 602252ccf843Smisaki "Reg 0x20 = 0x%x\n", nxgep->mac.portnum, val2); 602344961713Sgirish } 602444961713Sgirish } 602544961713Sgirish 602644961713Sgirish if (link_align == B_FALSE) { 602744961713Sgirish if (val3 != 0x140f) { 602844961713Sgirish link_align = B_TRUE; 602952ccf843Smisaki cmn_err(CE_NOTE, "!LINK DEBUG: port%d PHY Dev4 " 603052ccf843Smisaki "Reg 0x18 = 0x%x\n", nxgep->mac.portnum, val3); 603144961713Sgirish } 603244961713Sgirish } 603344961713Sgirish 603444961713Sgirish if (rx_sig_ok == B_FALSE) { 603544961713Sgirish if ((val2 == 0) || (val3 == 0)) { 603644961713Sgirish rx_sig_ok = B_TRUE; 603744961713Sgirish cmn_err(CE_NOTE, 603852ccf843Smisaki "!LINK DEBUG: port %d Dev3 or Dev4 read zero\n", 603952ccf843Smisaki nxgep->mac.portnum); 604044961713Sgirish } 604144961713Sgirish } 604244961713Sgirish #endif 604344961713Sgirish 604444961713Sgirish *link_up = ((rx_sig_ok == B_TRUE) && (pcs_blk_lock == B_TRUE) && 604552ccf843Smisaki (link_align == B_TRUE)) ? B_TRUE : B_FALSE; 604644961713Sgirish 604744961713Sgirish return (NXGE_OK); 604844961713Sgirish fail: 604944961713Sgirish return (status); 605044961713Sgirish } 605144961713Sgirish 605252cdd236Ssbehera static nxge_status_t 605300161856Syc nxge_check_mrvl88x2011_link(p_nxge_t nxgep, boolean_t *link_up) 605452cdd236Ssbehera { 605552cdd236Ssbehera uint8_t phy; 605652cdd236Ssbehera nxge_status_t status = NXGE_OK; 605752cdd236Ssbehera boolean_t pma_status; 605852cdd236Ssbehera boolean_t pcs_status; 605952cdd236Ssbehera boolean_t xgxs_status; 606052cdd236Ssbehera uint16_t val; 606152cdd236Ssbehera 606252cdd236Ssbehera phy = nxgep->statsp->mac_stats.xcvr_portn; 606352cdd236Ssbehera 606452cdd236Ssbehera MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR, 606552cdd236Ssbehera MRVL_88X2011_10G_PMD_STAT_2, &val); 606652cdd236Ssbehera 606752cdd236Ssbehera *link_up = B_FALSE; 606852cdd236Ssbehera 606952cdd236Ssbehera /* Check from Marvell 88X2011 if 10G link is up or down */ 607052cdd236Ssbehera 607152cdd236Ssbehera /* Check PMA/PMD Register: 1.0001.2 == 1 */ 607252cdd236Ssbehera MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR, 607352cdd236Ssbehera MRVL_88X2011_PMA_PMD_STAT_1, &val); 607452cdd236Ssbehera 607552cdd236Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 607652cdd236Ssbehera "nxge_check_mrvl88x2011_link: pmd=0x%x", val)); 607752cdd236Ssbehera 607852cdd236Ssbehera pma_status = ((val & MRVL_88X2011_LNK_STATUS_OK) ? B_TRUE : B_FALSE); 607952cdd236Ssbehera 608052cdd236Ssbehera /* Check PMC Register : 3.0001.2 == 1: read twice */ 608152cdd236Ssbehera MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR, 608252cdd236Ssbehera MRVL_88X2011_PMA_PMD_STAT_1, &val); 608352cdd236Ssbehera MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR, 608452cdd236Ssbehera MRVL_88X2011_PMA_PMD_STAT_1, &val); 608552cdd236Ssbehera 608652cdd236Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 608752cdd236Ssbehera "nxge_check_mrvl88x2011_link: pcs=0x%x", val)); 608852cdd236Ssbehera 608952cdd236Ssbehera pcs_status = ((val & MRVL_88X2011_LNK_STATUS_OK) ? B_TRUE : B_FALSE); 609052cdd236Ssbehera 609152cdd236Ssbehera /* Check XGXS Register : 4.0018.[0-3,12] */ 609252cdd236Ssbehera MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV4_ADDR, 609352cdd236Ssbehera MRVL_88X2011_10G_XGXS_LANE_STAT, &val); 609452cdd236Ssbehera 609552cdd236Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 609652cdd236Ssbehera "nxge_check_mrvl88x2011_link: xgxs=0x%x", val)); 609752cdd236Ssbehera 609852cdd236Ssbehera xgxs_status = (val == (XGXS_LANE_ALIGN_STATUS | XGXS_LANE3_SYNC | 609952cdd236Ssbehera XGXS_LANE2_SYNC | XGXS_LANE1_SYNC | 610052cdd236Ssbehera XGXS_LANE0_SYNC | XGXS_PATTERN_TEST_ABILITY | 610152cdd236Ssbehera XGXS_LANE_STAT_MAGIC)) ? B_TRUE : B_FALSE; 610252cdd236Ssbehera 610352cdd236Ssbehera *link_up = (pma_status && pcs_status && xgxs_status) ? 610452cdd236Ssbehera B_TRUE : B_FALSE; 610552cdd236Ssbehera 610652cdd236Ssbehera fail: 610752cdd236Ssbehera 610852cdd236Ssbehera if (*link_up == B_FALSE) { 610952cdd236Ssbehera /* PCS OFF */ 611052cdd236Ssbehera nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_CTL_OFF); 611152cdd236Ssbehera } else { 611252cdd236Ssbehera /* PCS Activity */ 611352cdd236Ssbehera nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_CTL_PCS_ACT); 611452cdd236Ssbehera } 611552cdd236Ssbehera 611652cdd236Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 611752cdd236Ssbehera " <== nxge_check_mrvl88x2011_link: up=%d", *link_up)); 611852cdd236Ssbehera 611952cdd236Ssbehera return (status); 612052cdd236Ssbehera } 612152cdd236Ssbehera 612259ac0c16Sdavemq nxge_status_t 612359ac0c16Sdavemq nxge_10g_link_led_on(p_nxge_t nxgep) 612459ac0c16Sdavemq { 612559ac0c16Sdavemq if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_TRUE) 612659ac0c16Sdavemq != NPI_SUCCESS) 612759ac0c16Sdavemq return (NXGE_ERROR); 612859ac0c16Sdavemq else 612959ac0c16Sdavemq return (NXGE_OK); 613059ac0c16Sdavemq } 613144961713Sgirish 613244961713Sgirish nxge_status_t 613359ac0c16Sdavemq nxge_10g_link_led_off(p_nxge_t nxgep) 613444961713Sgirish { 613559ac0c16Sdavemq if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_FALSE) 613659ac0c16Sdavemq != NPI_SUCCESS) 613759ac0c16Sdavemq return (NXGE_ERROR); 613859ac0c16Sdavemq else 613959ac0c16Sdavemq return (NXGE_OK); 614059ac0c16Sdavemq } 614144961713Sgirish 61422d17280bSsbehera static boolean_t 61432d17280bSsbehera nxge_is_phy_present(p_nxge_t nxgep, int addr, uint32_t id, uint32_t mask) 61442d17280bSsbehera { 61452d17280bSsbehera uint32_t pma_pmd_id = 0; 61462d17280bSsbehera uint32_t pcs_id = 0; 61472d17280bSsbehera uint32_t phy_id = 0; 61482d17280bSsbehera 61492d17280bSsbehera pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, addr); 61502d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 61512d17280bSsbehera "nxge_is_phy_present: pma_pmd_id[0x%x]", pma_pmd_id)); 61522d17280bSsbehera if ((pma_pmd_id & mask) == (id & mask)) 61532d17280bSsbehera goto found_phy; 61542d17280bSsbehera pcs_id = nxge_get_cl45_pcs_id(nxgep, addr); 61552d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 61562d17280bSsbehera "nxge_is_phy_present: pcs_id[0x%x]", pcs_id)); 61572d17280bSsbehera if ((pcs_id & mask) == (id & mask)) 61582d17280bSsbehera goto found_phy; 61592d17280bSsbehera phy_id = nxge_get_cl22_phy_id(nxgep, addr); 61602d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 61612d17280bSsbehera "nxge_is_phy_present: phy_id[0x%x]", phy_id)); 61622d17280bSsbehera if ((phy_id & mask) == (id & mask)) 61632d17280bSsbehera goto found_phy; 61642d17280bSsbehera 61652d17280bSsbehera return (B_FALSE); 61662d17280bSsbehera 61672d17280bSsbehera found_phy: 61682d17280bSsbehera return (B_TRUE); 61692d17280bSsbehera } 61702d17280bSsbehera 617159ac0c16Sdavemq /* Check if the given id read using the given MDIO Clause is supported */ 617259ac0c16Sdavemq 617359ac0c16Sdavemq static boolean_t 617459ac0c16Sdavemq nxge_is_supported_phy(uint32_t id, uint8_t type) 617559ac0c16Sdavemq { 617659ac0c16Sdavemq int i; 617759ac0c16Sdavemq boolean_t found = B_FALSE; 617859ac0c16Sdavemq 617959ac0c16Sdavemq switch (type) { 618059ac0c16Sdavemq case CLAUSE_45_TYPE: 618100161856Syc for (i = 0; i < NUM_CLAUSE_45_IDS; i++) { 618200161856Syc if (((nxge_supported_cl45_ids[i] & BCM_PHY_ID_MASK) == 618300161856Syc (id & BCM_PHY_ID_MASK)) || 618400161856Syc (TN1010_DEV_ID == (id & TN1010_DEV_ID_MASK))) { 618559ac0c16Sdavemq found = B_TRUE; 618659ac0c16Sdavemq break; 618759ac0c16Sdavemq } 618859ac0c16Sdavemq } 618959ac0c16Sdavemq break; 619059ac0c16Sdavemq case CLAUSE_22_TYPE: 619100161856Syc for (i = 0; i < NUM_CLAUSE_22_IDS; i++) { 619230505775Ssbehera if ((nxge_supported_cl22_ids[i] & BCM_PHY_ID_MASK) == 619330505775Ssbehera (id & BCM_PHY_ID_MASK)) { 619459ac0c16Sdavemq found = B_TRUE; 619559ac0c16Sdavemq break; 619656d930aeSspeer } 619744961713Sgirish } 619859ac0c16Sdavemq break; 619959ac0c16Sdavemq default: 620059ac0c16Sdavemq break; 620156d930aeSspeer } 620256d930aeSspeer 620359ac0c16Sdavemq return (found); 620459ac0c16Sdavemq } 620559ac0c16Sdavemq 62062e59129aSraghus static uint32_t 62072e59129aSraghus nxge_get_cl45_pma_pmd_id(p_nxge_t nxgep, int phy_port) 62082e59129aSraghus { 62092e59129aSraghus uint16_t val1 = 0; 62102e59129aSraghus uint16_t val2 = 0; 62112e59129aSraghus uint32_t pma_pmd_dev_id = 0; 62122e59129aSraghus npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep); 62132e59129aSraghus 621453560810Ssbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 62152e59129aSraghus (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR, 62162e59129aSraghus NXGE_DEV_ID_REG_1, &val1); 62172e59129aSraghus (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR, 62182e59129aSraghus NXGE_DEV_ID_REG_2, &val2); 621953560810Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 62202e59129aSraghus 622100161856Syc /* Concatenate the Device ID stored in two registers. */ 62222e59129aSraghus pma_pmd_dev_id = val1; 62232e59129aSraghus pma_pmd_dev_id = (pma_pmd_dev_id << 16); 62242e59129aSraghus pma_pmd_dev_id |= val2; 62252e59129aSraghus 62262e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PMA/PMD " 62272e59129aSraghus "devid[0x%llx]", phy_port, pma_pmd_dev_id)); 62282e59129aSraghus 62292e59129aSraghus return (pma_pmd_dev_id); 62302e59129aSraghus } 62312e59129aSraghus 62322e59129aSraghus static uint32_t 62332e59129aSraghus nxge_get_cl45_pcs_id(p_nxge_t nxgep, int phy_port) 62342e59129aSraghus { 62352e59129aSraghus uint16_t val1 = 0; 62362e59129aSraghus uint16_t val2 = 0; 62372e59129aSraghus uint32_t pcs_dev_id = 0; 62382e59129aSraghus npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep); 62392e59129aSraghus 624053560810Ssbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 62412e59129aSraghus (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR, 62422e59129aSraghus NXGE_DEV_ID_REG_1, &val1); 62432e59129aSraghus (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR, 62442e59129aSraghus NXGE_DEV_ID_REG_2, &val2); 624553560810Ssbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 62462e59129aSraghus 62472e59129aSraghus pcs_dev_id = val1; 62482e59129aSraghus pcs_dev_id = (pcs_dev_id << 16); 62492e59129aSraghus pcs_dev_id |= val2; 62502e59129aSraghus 62512e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS " 62522e59129aSraghus "devid[0x%llx]", phy_port, pcs_dev_id)); 62532e59129aSraghus 62542e59129aSraghus return (pcs_dev_id); 62552e59129aSraghus } 62562e59129aSraghus 62572e59129aSraghus static uint32_t 62582e59129aSraghus nxge_get_cl22_phy_id(p_nxge_t nxgep, int phy_port) 62592e59129aSraghus { 62602e59129aSraghus uint16_t val1 = 0; 62612e59129aSraghus uint16_t val2 = 0; 62622e59129aSraghus uint32_t phy_id = 0; 62632e59129aSraghus npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep); 62642e59129aSraghus npi_status_t npi_status = NPI_SUCCESS; 62652e59129aSraghus 6266321febdeSsbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 62672e59129aSraghus npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_1, 62682e59129aSraghus &val1); 62692e59129aSraghus if (npi_status != NPI_SUCCESS) { 62702e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] " 62712e59129aSraghus "clause 22 read to reg 2 failed!!!")); 62722e59129aSraghus goto exit; 62732e59129aSraghus } 62742e59129aSraghus npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_2, 62752e59129aSraghus &val2); 62762e59129aSraghus if (npi_status != 0) { 62772e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] " 62782e59129aSraghus "clause 22 read to reg 3 failed!!!")); 62792e59129aSraghus goto exit; 62802e59129aSraghus } 62812e59129aSraghus phy_id = val1; 62822e59129aSraghus phy_id = (phy_id << 16); 62832e59129aSraghus phy_id |= val2; 62842e59129aSraghus 62852e59129aSraghus exit: 6286321febdeSsbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 62872e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID [0x%llx]", 62882e59129aSraghus phy_port, phy_id)); 62892e59129aSraghus 62902e59129aSraghus return (phy_id); 62912e59129aSraghus } 62922e59129aSraghus 629359ac0c16Sdavemq /* 629459ac0c16Sdavemq * Scan the PHY ports 0 through 31 to get the PHY ID using Clause 22 MDIO 629559ac0c16Sdavemq * read and the PMA/PMD device ID and the PCS device ID using Clause 45 MDIO 629659ac0c16Sdavemq * read. Then use the values obtained to determine the phy type of each port 629759ac0c16Sdavemq * and the Neptune type. 629800161856Syc * 629900161856Syc * This function sets hw_p->xcvr_addr[i] for future MDIO access and set 630000161856Syc * hw_p->niu_type for each nxge instance to figure out nxgep->mac.portmode 630100161856Syc * in case the portmode information is not available via OBP, nxge.conf, 630200161856Syc * VPD or SEEPROM. 630359ac0c16Sdavemq */ 630459ac0c16Sdavemq nxge_status_t 630559ac0c16Sdavemq nxge_scan_ports_phy(p_nxge_t nxgep, p_nxge_hw_list_t hw_p) 630659ac0c16Sdavemq { 630759a835ddSjoycey int i, j, l; 630859ac0c16Sdavemq uint32_t pma_pmd_dev_id = 0; 630959ac0c16Sdavemq uint32_t pcs_dev_id = 0; 631059ac0c16Sdavemq uint32_t phy_id = 0; 631130505775Ssbehera uint32_t port_pma_pmd_dev_id[NXGE_PORTS_NEPTUNE]; 631230505775Ssbehera uint32_t port_pcs_dev_id[NXGE_PORTS_NEPTUNE]; 631330505775Ssbehera uint32_t port_phy_id[NXGE_PORTS_NEPTUNE]; 631459ac0c16Sdavemq uint8_t pma_pmd_dev_fd[NXGE_MAX_PHY_PORTS]; 631559ac0c16Sdavemq uint8_t pcs_dev_fd[NXGE_MAX_PHY_PORTS]; 63162d17280bSsbehera uint8_t phy_fd_arr[NXGE_MAX_PHY_PORTS]; 63172d17280bSsbehera uint8_t port_fd_arr[NXGE_MAX_PHY_PORTS]; 631859ac0c16Sdavemq uint8_t total_port_fd, total_phy_fd; 631900161856Syc uint8_t num_xaui; 632059ac0c16Sdavemq nxge_status_t status = NXGE_OK; 632156d930aeSspeer 632259ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_scan_ports_phy: ")); 632356d930aeSspeer NXGE_DEBUG_MSG((nxgep, MAC_CTL, 632459ac0c16Sdavemq "==> nxge_scan_ports_phy: nxge niu_type[0x%x]", 632559ac0c16Sdavemq nxgep->niu_type)); 632659ac0c16Sdavemq 6327678453a8Sspeer if (isLDOMguest(nxgep)) { 6328678453a8Sspeer hw_p->niu_type = NIU_TYPE_NONE; 6329678453a8Sspeer hw_p->platform_type = P_NEPTUNE_NONE; 6330678453a8Sspeer return (NXGE_OK); 6331678453a8Sspeer } 6332678453a8Sspeer 633359a835ddSjoycey j = l = 0; 633459ac0c16Sdavemq total_port_fd = total_phy_fd = 0; 633556d930aeSspeer /* 633623b952a3SSantwona Behera * Clause 45 and Clause 22 port/phy addresses 0 through 5 are reserved 633723b952a3SSantwona Behera * for on chip serdes usages. "i" in the following for loop starts at 6. 633856d930aeSspeer */ 633959ac0c16Sdavemq for (i = NXGE_EXT_PHY_PORT_ST; i < NXGE_MAX_PHY_PORTS; i++) { 63402e59129aSraghus 63412e59129aSraghus pma_pmd_dev_id = nxge_get_cl45_pma_pmd_id(nxgep, i); 634259ac0c16Sdavemq 634359ac0c16Sdavemq if (nxge_is_supported_phy(pma_pmd_dev_id, CLAUSE_45_TYPE)) { 634459ac0c16Sdavemq pma_pmd_dev_fd[i] = 1; 634559ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] " 634652cdd236Ssbehera "PMA/PMD dev %x found", i, pma_pmd_dev_id)); 634730505775Ssbehera if (j < NXGE_PORTS_NEPTUNE) { 634800161856Syc if ((pma_pmd_dev_id & TN1010_DEV_ID_MASK) 634900161856Syc == TN1010_DEV_ID) { 635000161856Syc port_pma_pmd_dev_id[j] = TN1010_DEV_ID; 635100161856Syc } else { 635200161856Syc port_pma_pmd_dev_id[j] = 635352ccf843Smisaki pma_pmd_dev_id & BCM_PHY_ID_MASK; 635400161856Syc } 63552d17280bSsbehera port_fd_arr[j] = (uint8_t)i; 635659ac0c16Sdavemq j++; 635759ac0c16Sdavemq } 635859ac0c16Sdavemq } else { 635959ac0c16Sdavemq pma_pmd_dev_fd[i] = 0; 636059ac0c16Sdavemq } 636159ac0c16Sdavemq 63622e59129aSraghus pcs_dev_id = nxge_get_cl45_pcs_id(nxgep, i); 636359ac0c16Sdavemq 636459ac0c16Sdavemq if (nxge_is_supported_phy(pcs_dev_id, CLAUSE_45_TYPE)) { 636559ac0c16Sdavemq pcs_dev_fd[i] = 1; 636659ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS " 636752cdd236Ssbehera "dev %x found", i, pcs_dev_id)); 636859a835ddSjoycey if (pma_pmd_dev_fd[i] == 1) { 636900161856Syc if ((pcs_dev_id & TN1010_DEV_ID_MASK) 637000161856Syc == TN1010_DEV_ID) { 637100161856Syc port_pcs_dev_id[j - 1] = 637200161856Syc TN1010_DEV_ID; 637300161856Syc } else { 637400161856Syc port_pcs_dev_id[j - 1] = 637500161856Syc pcs_dev_id & 637600161856Syc BCM_PHY_ID_MASK; 637700161856Syc } 637859a835ddSjoycey } else { 637959a835ddSjoycey if (j < NXGE_PORTS_NEPTUNE) { 638000161856Syc if ((pcs_dev_id & TN1010_DEV_ID_MASK) 638152ccf843Smisaki == TN1010_DEV_ID) { 638200161856Syc port_pcs_dev_id[j] = 638300161856Syc TN1010_DEV_ID; 638400161856Syc } else { 638500161856Syc port_pcs_dev_id[j] = 638600161856Syc pcs_dev_id & 638700161856Syc BCM_PHY_ID_MASK; 638800161856Syc } 638959a835ddSjoycey port_fd_arr[j] = (uint8_t)i; 639059a835ddSjoycey j++; 639159a835ddSjoycey } 639259ac0c16Sdavemq } 639359ac0c16Sdavemq } else { 639459ac0c16Sdavemq pcs_dev_fd[i] = 0; 639559ac0c16Sdavemq } 639659ac0c16Sdavemq 63972d17280bSsbehera if (pcs_dev_fd[i] || pma_pmd_dev_fd[i]) { 63982d17280bSsbehera total_port_fd ++; 63992d17280bSsbehera } 640059ac0c16Sdavemq 64012e59129aSraghus phy_id = nxge_get_cl22_phy_id(nxgep, i); 640259ac0c16Sdavemq if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) { 64032d17280bSsbehera total_phy_fd ++; 640459ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID" 640552cdd236Ssbehera "%x found", i, phy_id)); 640630505775Ssbehera if (l < NXGE_PORTS_NEPTUNE) { 640700161856Syc if ((phy_id & TN1010_DEV_ID_MASK) 640800161856Syc == TN1010_DEV_ID) { 640900161856Syc port_phy_id[l] = TN1010_DEV_ID; 641000161856Syc } else { 641100161856Syc port_phy_id[l] 641200161856Syc = phy_id & BCM_PHY_ID_MASK; 641300161856Syc } 64142d17280bSsbehera phy_fd_arr[l] = (uint8_t)i; 641559ac0c16Sdavemq l++; 641659ac0c16Sdavemq } 641759ac0c16Sdavemq } 641859ac0c16Sdavemq } 641959ac0c16Sdavemq 642059ac0c16Sdavemq switch (total_port_fd) { 642159ac0c16Sdavemq case 2: 642259ac0c16Sdavemq switch (total_phy_fd) { 642359ac0c16Sdavemq case 2: 642423b952a3SSantwona Behera /* 2 10G, 2 1G RGMII Fiber / copper */ 642559a835ddSjoycey if ((((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) && 642659a835ddSjoycey (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) || 642759a835ddSjoycey ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) && 642859a835ddSjoycey (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) && 642959a835ddSjoycey ((port_phy_id[0] == PHY_BCM5482_FAMILY) && 643059a835ddSjoycey (port_phy_id[1] == PHY_BCM5482_FAMILY))) { 643159a835ddSjoycey 643223b952a3SSantwona Behera switch (hw_p->platform_type) { 643323b952a3SSantwona Behera case P_NEPTUNE_ROCK: 643423b952a3SSantwona Behera hw_p->niu_type = NEPTUNE_2_10GF_2_1GC; 643523b952a3SSantwona Behera /* 643623b952a3SSantwona Behera * ROCK platform has assigned a lower 643723b952a3SSantwona Behera * addr to port 1. (port 0 = 0x9 and 643823b952a3SSantwona Behera * port 1 = 0x8). 643923b952a3SSantwona Behera */ 644023b952a3SSantwona Behera hw_p->xcvr_addr[1] = port_fd_arr[0]; 644123b952a3SSantwona Behera hw_p->xcvr_addr[0] = port_fd_arr[1]; 644223b952a3SSantwona Behera 644323b952a3SSantwona Behera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 644423b952a3SSantwona Behera "Rock with 2 10G, 2 1GC")); 644523b952a3SSantwona Behera break; 644623b952a3SSantwona Behera 644723b952a3SSantwona Behera case P_NEPTUNE_NONE: 644823b952a3SSantwona Behera default: 644923b952a3SSantwona Behera hw_p->platform_type = 645023b952a3SSantwona Behera P_NEPTUNE_GENERIC; 645123b952a3SSantwona Behera hw_p->niu_type = NEPTUNE_2_10GF_2_1GRF; 645259a835ddSjoycey 645323b952a3SSantwona Behera hw_p->xcvr_addr[0] = port_fd_arr[0]; 645423b952a3SSantwona Behera hw_p->xcvr_addr[1] = port_fd_arr[1]; 645523b952a3SSantwona Behera 645623b952a3SSantwona Behera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 645723b952a3SSantwona Behera "ARTM card with 2 10G, 2 1GF")); 645823b952a3SSantwona Behera break; 645923b952a3SSantwona Behera } 646059a835ddSjoycey 646159a835ddSjoycey hw_p->xcvr_addr[2] = phy_fd_arr[0]; 646259a835ddSjoycey hw_p->xcvr_addr[3] = phy_fd_arr[1]; 646359a835ddSjoycey 646459a835ddSjoycey } else { 646559a835ddSjoycey NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 646659a835ddSjoycey "Unsupported neptune type 1")); 646759a835ddSjoycey goto error_exit; 646859a835ddSjoycey } 646959a835ddSjoycey break; 647059a835ddSjoycey 647159ac0c16Sdavemq case 1: 647259ac0c16Sdavemq /* TODO - 2 10G, 1 1G */ 647359ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 647459ac0c16Sdavemq "Unsupported neptune type 2 10G, 1 1G")); 647559ac0c16Sdavemq goto error_exit; 647659ac0c16Sdavemq case 0: 647700161856Syc /* 647800161856Syc * 2 10G: 2XGF NIC, Marvell, Goa, Huron with 2 XAUI 647900161856Syc * cards, etc. 648000161856Syc */ 648130505775Ssbehera if (((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) && 648230505775Ssbehera (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) || 648330505775Ssbehera ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) && 648452cdd236Ssbehera (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY)) || 648552cdd236Ssbehera ((port_pcs_dev_id[0] == MARVELL_88X201X_PHY_ID) && 648652cdd236Ssbehera (port_pcs_dev_id[1] == MARVELL_88X201X_PHY_ID)) || 648752cdd236Ssbehera ((port_pma_pmd_dev_id[0] == 648852cdd236Ssbehera MARVELL_88X201X_PHY_ID) && 648952cdd236Ssbehera (port_pma_pmd_dev_id[1] == 649052cdd236Ssbehera MARVELL_88X201X_PHY_ID))) { 64912e59129aSraghus 64922e59129aSraghus /* 64932e59129aSraghus * Check the first phy port address against 64942e59129aSraghus * the known phy start addresses to determine 64952e59129aSraghus * the platform type. 64962e59129aSraghus */ 64972d17280bSsbehera 64982d17280bSsbehera switch (port_fd_arr[0]) { 649900161856Syc case NEPTUNE_CLAUSE45_PORT_ADDR_BASE: 650052cdd236Ssbehera /* 650152cdd236Ssbehera * The Marvell case also falls into 650252cdd236Ssbehera * this case as 650352cdd236Ssbehera * MRVL88X2011_NEPTUNE_PORT_ADDR_BASE 650400161856Syc * == NEPTUNE_CLAUSE45_PORT_ADDR_BASE. 650552cdd236Ssbehera * This is OK for the 2 10G case. 650652cdd236Ssbehera */ 65072e59129aSraghus hw_p->niu_type = NEPTUNE_2_10GF; 65082e59129aSraghus hw_p->platform_type = 65092e59129aSraghus P_NEPTUNE_ATLAS_2PORT; 65102d17280bSsbehera break; 651100161856Syc case GOA_CLAUSE45_PORT_ADDR_BASE: 65122d17280bSsbehera if (hw_p->platform_type != 65132d17280bSsbehera P_NEPTUNE_NIU) { 65142d17280bSsbehera hw_p->platform_type = 65152d17280bSsbehera P_NEPTUNE_GENERIC; 65162d17280bSsbehera hw_p->niu_type = 65172d17280bSsbehera NEPTUNE_2_10GF; 65182d17280bSsbehera } 65192d17280bSsbehera break; 65202d17280bSsbehera default: 65212d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 65222e59129aSraghus "Unsupported neptune type 2 - 1")); 65232e59129aSraghus goto error_exit; 65242e59129aSraghus } 65252d17280bSsbehera 65262d17280bSsbehera for (i = 0; i < 2; i++) { 65272d17280bSsbehera hw_p->xcvr_addr[i] = port_fd_arr[i]; 65282d17280bSsbehera } 652900161856Syc 653000161856Syc /* Both XAUI slots have copper XAUI cards */ 653100161856Syc } else if ((((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 653200161856Syc == TN1010_DEV_ID) && 653300161856Syc ((port_pcs_dev_id[1] & TN1010_DEV_ID_MASK) 653400161856Syc == TN1010_DEV_ID)) || 653500161856Syc (((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK) 653600161856Syc == TN1010_DEV_ID) && 653700161856Syc ((port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK) 653800161856Syc == TN1010_DEV_ID))) { 653900161856Syc hw_p->niu_type = NEPTUNE_2_TN1010; 654000161856Syc hw_p->xcvr_addr[0] = port_fd_arr[0]; 654100161856Syc hw_p->xcvr_addr[1] = port_fd_arr[1]; 654200161856Syc 654300161856Syc /* Slot0 has fiber XAUI, slot1 has copper XAUI */ 654400161856Syc } else if ((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY && 654500161856Syc (port_pcs_dev_id[1] & TN1010_DEV_ID_MASK) 654600161856Syc == TN1010_DEV_ID) || 654700161856Syc (port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY && 654800161856Syc (port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK) == 654900161856Syc TN1010_DEV_ID)) { 655000161856Syc hw_p->niu_type = NEPTUNE_1_10GF_1_TN1010; 655100161856Syc hw_p->xcvr_addr[0] = port_fd_arr[0]; 655200161856Syc hw_p->xcvr_addr[1] = port_fd_arr[1]; 655300161856Syc 655400161856Syc /* Slot0 has copper XAUI, slot1 has fiber XAUI */ 655500161856Syc } else if ((port_pcs_dev_id[1] == PHY_BCM8704_FAMILY && 655600161856Syc (port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 655700161856Syc == TN1010_DEV_ID) || 655800161856Syc (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY && 655900161856Syc (port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK) 656000161856Syc == TN1010_DEV_ID)) { 656100161856Syc hw_p->niu_type = NEPTUNE_1_TN1010_1_10GF; 656200161856Syc hw_p->xcvr_addr[0] = port_fd_arr[0]; 656300161856Syc hw_p->xcvr_addr[1] = port_fd_arr[1]; 656400161856Syc 656559ac0c16Sdavemq } else { 656659ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 656759ac0c16Sdavemq "Unsupported neptune type 2")); 656859ac0c16Sdavemq goto error_exit; 656959ac0c16Sdavemq } 657059ac0c16Sdavemq break; 657100161856Syc 657259ac0c16Sdavemq case 4: 657300161856Syc if (nxge_get_num_of_xaui( 657400161856Syc port_pma_pmd_dev_id, port_pcs_dev_id, 657500161856Syc port_phy_id, &num_xaui) == NXGE_ERROR) { 657600161856Syc goto error_exit; 657700161856Syc } 657800161856Syc if (num_xaui != 2) 657900161856Syc goto error_exit; 658059ac0c16Sdavemq 658100161856Syc /* 658200161856Syc * Maramba with 2 XAUIs (either fiber or copper) 658300161856Syc * 658400161856Syc * Check the first phy port address against 658500161856Syc * the known phy start addresses to determine 658600161856Syc * the platform type. 658700161856Syc */ 658800161856Syc switch (phy_fd_arr[0]) { 658900161856Syc case MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE: 659000161856Syc hw_p->platform_type = 659100161856Syc P_NEPTUNE_MARAMBA_P0; 659200161856Syc break; 659300161856Syc case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE: 659400161856Syc hw_p->platform_type = 659500161856Syc P_NEPTUNE_MARAMBA_P1; 659600161856Syc break; 659700161856Syc default: 659800161856Syc NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 659900161856Syc "Unknown port %d...Cannot " 660000161856Syc "determine platform type", i)); 660100161856Syc goto error_exit; 660200161856Syc } 66032d17280bSsbehera 660400161856Syc hw_p->xcvr_addr[0] = port_fd_arr[0]; 660500161856Syc hw_p->xcvr_addr[1] = port_fd_arr[1]; 660600161856Syc hw_p->xcvr_addr[2] = phy_fd_arr[2]; 660700161856Syc hw_p->xcvr_addr[3] = phy_fd_arr[3]; 660800161856Syc 660900161856Syc /* slot0 has fiber XAUI, slot1 has Cu XAUI */ 661000161856Syc if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY && 661100161856Syc (port_pcs_dev_id[1] & TN1010_DEV_ID_MASK) 661200161856Syc == TN1010_DEV_ID) { 661300161856Syc hw_p->niu_type = NEPTUNE_1_10GF_1_TN1010_2_1GC; 661400161856Syc 661500161856Syc /* slot0 has Cu XAUI, slot1 has fiber XAUI */ 661600161856Syc } else if (((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 661700161856Syc == TN1010_DEV_ID) && 661800161856Syc port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) { 661900161856Syc hw_p->niu_type = NEPTUNE_1_TN1010_1_10GF_2_1GC; 662000161856Syc 662100161856Syc /* Both slots have fiber XAUI */ 662200161856Syc } else if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY && 662300161856Syc port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) { 66242e59129aSraghus hw_p->niu_type = NEPTUNE_2_10GF_2_1GC; 66252e59129aSraghus 662600161856Syc /* Both slots have copper XAUI */ 662700161856Syc } else if (((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 662800161856Syc == TN1010_DEV_ID) && 662900161856Syc (port_pcs_dev_id[1] & TN1010_DEV_ID_MASK) 663000161856Syc == TN1010_DEV_ID) { 663100161856Syc hw_p->niu_type = NEPTUNE_2_TN1010_2_1GC; 66322d17280bSsbehera 663359ac0c16Sdavemq } else { 663459ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 663559ac0c16Sdavemq "Unsupported neptune type 3")); 663659ac0c16Sdavemq goto error_exit; 663759ac0c16Sdavemq } 663859ac0c16Sdavemq break; 663959ac0c16Sdavemq default: 664059ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 664159ac0c16Sdavemq "Unsupported neptune type 5")); 664259ac0c16Sdavemq goto error_exit; 664359ac0c16Sdavemq } 664430505775Ssbehera break; 664500161856Syc case 1: /* Only one clause45 port */ 664600161856Syc switch (total_phy_fd) { /* Number of clause22 ports */ 664759ac0c16Sdavemq case 3: 66482e59129aSraghus /* 66492e59129aSraghus * TODO 3 1G, 1 10G mode. 66502e59129aSraghus * Differentiate between 1_1G_1_10G_2_1G and 66512e59129aSraghus * 1_10G_3_1G 66522e59129aSraghus */ 66532e59129aSraghus NXGE_DEBUG_MSG((nxgep, MAC_CTL, 66542e59129aSraghus "Unsupported neptune type 7")); 66552e59129aSraghus goto error_exit; 665659ac0c16Sdavemq case 2: 665759ac0c16Sdavemq /* 665859ac0c16Sdavemq * TODO 2 1G, 1 10G mode. 665959ac0c16Sdavemq * Differentiate between 1_1G_1_10G_1_1G and 666059ac0c16Sdavemq * 1_10G_2_1G 666159ac0c16Sdavemq */ 666259ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 666359ac0c16Sdavemq "Unsupported neptune type 8")); 666459ac0c16Sdavemq goto error_exit; 666559ac0c16Sdavemq case 1: 666659ac0c16Sdavemq /* 666759ac0c16Sdavemq * TODO 1 1G, 1 10G mode. 666859ac0c16Sdavemq * Differentiate between 1_1G_1_10G and 666959ac0c16Sdavemq * 1_10G_1_1G 667059ac0c16Sdavemq */ 667159ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 667259ac0c16Sdavemq "Unsupported neptune type 9")); 667359ac0c16Sdavemq goto error_exit; 667400161856Syc case 0: /* N2 with 1 XAUI (fiber or copper) */ 667500161856Syc /* Fiber XAUI */ 66762d17280bSsbehera if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY || 66772d17280bSsbehera port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) { 66782d17280bSsbehera 66792d17280bSsbehera /* 66802d17280bSsbehera * Check the first phy port address against 66812d17280bSsbehera * the known phy start addresses to determine 66822d17280bSsbehera * the platform type. 66832d17280bSsbehera */ 66842d17280bSsbehera 66852d17280bSsbehera switch (port_fd_arr[0]) { 668600161856Syc case N2_CLAUSE45_PORT_ADDR_BASE: 668700161856Syc case (N2_CLAUSE45_PORT_ADDR_BASE + 1): 668800161856Syc case ALT_GOA_CLAUSE45_PORT1_ADDR: 668900161856Syc /* 669000161856Syc * If hw_p->platform_type == 669100161856Syc * P_NEPTUNE_NIU, then portmode 669200161856Syc * is already known, so there is 669300161856Syc * no need to figure out hw_p-> 669400161856Syc * platform_type because 669500161856Syc * platform_type is only for 669600161856Syc * figuring out portmode. 669700161856Syc */ 66982d17280bSsbehera if (hw_p->platform_type != 66992d17280bSsbehera P_NEPTUNE_NIU) { 67002d17280bSsbehera hw_p->platform_type = 67012d17280bSsbehera P_NEPTUNE_GENERIC; 67022d17280bSsbehera hw_p->niu_type = 67032d17280bSsbehera NEPTUNE_2_10GF; 67042d17280bSsbehera } 67052d17280bSsbehera break; 67062d17280bSsbehera default: 67072d17280bSsbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 67082d17280bSsbehera "Unsupported neptune type 10")); 67092d17280bSsbehera goto error_exit; 67102d17280bSsbehera } 6711321febdeSsbehera /* 6712321febdeSsbehera * For GOA, which is a hot swappable PHY, the 6713321febdeSsbehera * phy address to function number mapping 6714321febdeSsbehera * should be preserved, i.e., addr 16 is 6715321febdeSsbehera * assigned to function 0 and 20 to function 1 6716321febdeSsbehera * But for Huron XAUI, the assignment should 6717321febdeSsbehera * be by function number, i.e., whichever 6718321febdeSsbehera * function number attaches should be 6719321febdeSsbehera * assigned the available PHY (this is required 6720321febdeSsbehera * primarily to support pre-production Huron 6721321febdeSsbehera * boards where function 0 is mapped to addr 17 6722321febdeSsbehera */ 6723321febdeSsbehera if (port_fd_arr[0] == 672400161856Syc ALT_GOA_CLAUSE45_PORT1_ADDR) { 6725321febdeSsbehera hw_p->xcvr_addr[1] = port_fd_arr[0]; 6726321febdeSsbehera } else { 6727321febdeSsbehera hw_p->xcvr_addr[nxgep->function_num] = 6728321febdeSsbehera port_fd_arr[0]; 6729321febdeSsbehera } 673000161856Syc 673100161856Syc /* A 10G copper XAUI in either slot0 or slot1 */ 673200161856Syc } else if ((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 673300161856Syc == TN1010_DEV_ID || 673400161856Syc (port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK) 673500161856Syc == TN1010_DEV_ID) { 673600161856Syc switch (port_fd_arr[0]) { 673700161856Syc /* The XAUI is in slot0 */ 673800161856Syc case N2_CLAUSE45_PORT_ADDR_BASE: 673900161856Syc hw_p->niu_type = NEPTUNE_1_TN1010; 674000161856Syc break; 674100161856Syc 674200161856Syc /* The XAUI is in slot1 */ 674300161856Syc case (N2_CLAUSE45_PORT_ADDR_BASE + 1): 674400161856Syc hw_p->niu_type 674500161856Syc = NEPTUNE_1_NONE_1_TN1010; 674600161856Syc break; 674700161856Syc default: 674800161856Syc NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 674900161856Syc "Unsupported XAUI port address")); 675000161856Syc goto error_exit; 675100161856Syc } 675200161856Syc hw_p->xcvr_addr[nxgep->function_num] 675300161856Syc = port_fd_arr[0]; 675400161856Syc 67552d17280bSsbehera } else { 67562d17280bSsbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 675700161856Syc "Unsupported PHY type")); 67582d17280bSsbehera goto error_exit; 67592d17280bSsbehera } 67602d17280bSsbehera break; 676100161856Syc case 4: /* Maramba always have 4 clause 45 ports */ 676259ac0c16Sdavemq 676300161856Syc /* Maramba with 1 XAUI */ 676452ccf843Smisaki if ((port_pcs_dev_id[0] != PHY_BCM8704_FAMILY) && 676552ccf843Smisaki (port_pma_pmd_dev_id[0] != PHY_BCM8704_FAMILY) && 676600161856Syc ((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 676752ccf843Smisaki != TN1010_DEV_ID) && 676800161856Syc ((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK) 676952ccf843Smisaki != TN1010_DEV_ID)) { 677052ccf843Smisaki NXGE_DEBUG_MSG((nxgep, MAC_CTL, 677152ccf843Smisaki "Unsupported neptune type 12")); 677252ccf843Smisaki goto error_exit; 677352ccf843Smisaki } 67742e59129aSraghus 677552ccf843Smisaki /* 677652ccf843Smisaki * Check the first phy port address against 677752ccf843Smisaki * the known phy start addresses to determine 677852ccf843Smisaki * the platform type. 677952ccf843Smisaki */ 678052ccf843Smisaki switch (phy_fd_arr[0]) { 678152ccf843Smisaki case MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE: 678252ccf843Smisaki hw_p->platform_type = 678352ccf843Smisaki P_NEPTUNE_MARAMBA_P0; 678452ccf843Smisaki break; 678552ccf843Smisaki case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE: 678652ccf843Smisaki hw_p->platform_type = 678752ccf843Smisaki P_NEPTUNE_MARAMBA_P1; 678852ccf843Smisaki break; 678952ccf843Smisaki default: 679052ccf843Smisaki NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 679152ccf843Smisaki "Unknown port %d...Cannot " 679252ccf843Smisaki "determine platform type 10 - 2", 679352ccf843Smisaki i)); 679452ccf843Smisaki goto error_exit; 679552ccf843Smisaki } 679652ccf843Smisaki 679752ccf843Smisaki /* 679852ccf843Smisaki * Check the clause45 address to determine 679952ccf843Smisaki * if XAUI is in port 0 or port 1. 680052ccf843Smisaki */ 680152ccf843Smisaki switch (port_fd_arr[0]) { 680252ccf843Smisaki case MARAMBA_CLAUSE45_PORT_ADDR_BASE: 680352ccf843Smisaki if (port_pcs_dev_id[0] 680452ccf843Smisaki == PHY_BCM8704_FAMILY || 680552ccf843Smisaki port_pma_pmd_dev_id[0] 680652ccf843Smisaki == PHY_BCM8704_FAMILY) { 680752ccf843Smisaki hw_p->niu_type 680852ccf843Smisaki = NEPTUNE_1_10GF_3_1GC; 680952ccf843Smisaki } else { 681052ccf843Smisaki hw_p->niu_type 681152ccf843Smisaki = NEPTUNE_1_TN1010_3_1GC; 681259ac0c16Sdavemq } 681352ccf843Smisaki hw_p->xcvr_addr[0] = port_fd_arr[0]; 681452ccf843Smisaki for (i = 1; i < NXGE_MAX_PORTS; i++) { 681552ccf843Smisaki hw_p->xcvr_addr[i] = 681652ccf843Smisaki phy_fd_arr[i]; 681752ccf843Smisaki } 681852ccf843Smisaki break; 681952ccf843Smisaki case (MARAMBA_CLAUSE45_PORT_ADDR_BASE + 1): 682052ccf843Smisaki if (port_pcs_dev_id[0] 682152ccf843Smisaki == PHY_BCM8704_FAMILY || 682252ccf843Smisaki port_pma_pmd_dev_id[0] 682352ccf843Smisaki == PHY_BCM8704_FAMILY) { 682452ccf843Smisaki hw_p->niu_type = 682552ccf843Smisaki NEPTUNE_1_1GC_1_10GF_2_1GC; 682652ccf843Smisaki } else { 682752ccf843Smisaki hw_p->niu_type = 682852ccf843Smisaki NEPTUNE_1_1GC_1_TN1010_2_1GC; 682952ccf843Smisaki } 683052ccf843Smisaki hw_p->xcvr_addr[0] = phy_fd_arr[0]; 683152ccf843Smisaki hw_p->xcvr_addr[1] = port_fd_arr[0]; 683252ccf843Smisaki hw_p->xcvr_addr[2] = phy_fd_arr[2]; 683352ccf843Smisaki hw_p->xcvr_addr[3] = phy_fd_arr[3]; 683452ccf843Smisaki break; 683552ccf843Smisaki default: 683659ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 683752ccf843Smisaki "Unsupported neptune type 11")); 683859ac0c16Sdavemq goto error_exit; 683959ac0c16Sdavemq } 684052ccf843Smisaki NXGE_DEBUG_MSG((nxgep, MAC_CTL, 684152ccf843Smisaki "Maramba with 1 XAUI (fiber or copper)")); 684259ac0c16Sdavemq break; 684359ac0c16Sdavemq default: 684459ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 684559ac0c16Sdavemq "Unsupported neptune type 13")); 684659ac0c16Sdavemq goto error_exit; 684759ac0c16Sdavemq } 684859ac0c16Sdavemq break; 684900161856Syc case 0: /* 4 ports Neptune based NIC */ 685059ac0c16Sdavemq switch (total_phy_fd) { 685159ac0c16Sdavemq case 4: 685230505775Ssbehera if ((port_phy_id[0] == PHY_BCM5464R_FAMILY) && 685330505775Ssbehera (port_phy_id[1] == PHY_BCM5464R_FAMILY) && 685430505775Ssbehera (port_phy_id[2] == PHY_BCM5464R_FAMILY) && 685530505775Ssbehera (port_phy_id[3] == PHY_BCM5464R_FAMILY)) { 685659ac0c16Sdavemq 685759ac0c16Sdavemq /* 685859ac0c16Sdavemq * Check the first phy port address against 685959ac0c16Sdavemq * the known phy start addresses to determine 686059ac0c16Sdavemq * the platform type. 686159ac0c16Sdavemq */ 68622d17280bSsbehera switch (phy_fd_arr[0]) { 686300161856Syc case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE: 686459ac0c16Sdavemq hw_p->platform_type = 686559ac0c16Sdavemq P_NEPTUNE_MARAMBA_P1; 68662d17280bSsbehera break; 686700161856Syc case NEPTUNE_CLAUSE22_PORT_ADDR_BASE: 68682e59129aSraghus hw_p->platform_type = 68692e59129aSraghus P_NEPTUNE_ATLAS_4PORT; 68702d17280bSsbehera break; 68712d17280bSsbehera default: 68722e59129aSraghus NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 68732e59129aSraghus "Unknown port %d...Cannot " 68742e59129aSraghus "determine platform type", i)); 68752e59129aSraghus goto error_exit; 687659ac0c16Sdavemq } 68772e59129aSraghus hw_p->niu_type = NEPTUNE_4_1GC; 68782d17280bSsbehera for (i = 0; i < NXGE_MAX_PORTS; i++) { 68792d17280bSsbehera hw_p->xcvr_addr[i] = phy_fd_arr[i]; 68802d17280bSsbehera } 688159ac0c16Sdavemq } else { 688259ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 688359ac0c16Sdavemq "Unsupported neptune type 14")); 688459ac0c16Sdavemq goto error_exit; 688559ac0c16Sdavemq } 688659ac0c16Sdavemq break; 688759ac0c16Sdavemq case 3: 688859ac0c16Sdavemq /* TODO 3 1G mode */ 688959ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 689059ac0c16Sdavemq "Unsupported neptune type 15")); 689159ac0c16Sdavemq goto error_exit; 689259ac0c16Sdavemq case 2: 689359ac0c16Sdavemq /* TODO 2 1G mode */ 689459a835ddSjoycey if ((port_phy_id[0] == PHY_BCM5482_FAMILY) && 689559a835ddSjoycey (port_phy_id[1] == PHY_BCM5482_FAMILY)) { 689659a835ddSjoycey hw_p->platform_type = P_NEPTUNE_GENERIC; 689759a835ddSjoycey hw_p->niu_type = NEPTUNE_2_1GRF; 689859a835ddSjoycey hw_p->xcvr_addr[2] = phy_fd_arr[0]; 689959a835ddSjoycey hw_p->xcvr_addr[3] = phy_fd_arr[1]; 690059a835ddSjoycey } else { 690159a835ddSjoycey NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 690259a835ddSjoycey "Unsupported neptune type 16")); 690359a835ddSjoycey goto error_exit; 690459a835ddSjoycey } 690559ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 690659a835ddSjoycey "2 RGMII Fiber ports - RTM")); 690759a835ddSjoycey break; 690859a835ddSjoycey 690959ac0c16Sdavemq case 1: 691059ac0c16Sdavemq /* TODO 1 1G mode */ 691159ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 691259ac0c16Sdavemq "Unsupported neptune type 17")); 691359ac0c16Sdavemq goto error_exit; 691459ac0c16Sdavemq default: 691559ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, 691659ac0c16Sdavemq "Unsupported neptune type 18, total phy fd %d", 691759ac0c16Sdavemq total_phy_fd)); 691859ac0c16Sdavemq goto error_exit; 691959ac0c16Sdavemq } 692059ac0c16Sdavemq break; 692159ac0c16Sdavemq default: 692256d930aeSspeer NXGE_DEBUG_MSG((nxgep, MAC_CTL, 692359ac0c16Sdavemq "Unsupported neptune type 19")); 692459ac0c16Sdavemq goto error_exit; 692544961713Sgirish } 692644961713Sgirish 692759ac0c16Sdavemq scan_exit: 692844961713Sgirish 692959ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_scan_ports_phy, " 693059ac0c16Sdavemq "niu type [0x%x]\n", hw_p->niu_type)); 693159ac0c16Sdavemq return (status); 693244961713Sgirish 693359ac0c16Sdavemq error_exit: 693459ac0c16Sdavemq return (NXGE_ERROR); 693544961713Sgirish } 693656d930aeSspeer 693756d930aeSspeer boolean_t 693856d930aeSspeer nxge_is_valid_local_mac(ether_addr_st mac_addr) 693956d930aeSspeer { 694056d930aeSspeer if ((mac_addr.ether_addr_octet[0] & 0x01) || 694156d930aeSspeer (ether_cmp(&mac_addr, ðerbroadcastaddr) == 0) || 694256d930aeSspeer (ether_cmp(&mac_addr, ðerzeroaddr) == 0)) 694356d930aeSspeer return (B_FALSE); 694456d930aeSspeer else 694556d930aeSspeer return (B_TRUE); 694656d930aeSspeer } 694759ac0c16Sdavemq 694859ac0c16Sdavemq static void 694959ac0c16Sdavemq nxge_bcm5464_link_led_off(p_nxge_t nxgep) { 695059ac0c16Sdavemq 695159ac0c16Sdavemq npi_status_t rs = NPI_SUCCESS; 695259ac0c16Sdavemq uint8_t xcvr_portn; 695359ac0c16Sdavemq uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 695459ac0c16Sdavemq 695559ac0c16Sdavemq NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_bcm5464_link_led_off")); 695659ac0c16Sdavemq 695759ac0c16Sdavemq if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P1) { 695800161856Syc xcvr_portn = MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE; 695959ac0c16Sdavemq } else if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P0) { 696000161856Syc xcvr_portn = MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE; 696159ac0c16Sdavemq } 696259ac0c16Sdavemq /* 696359ac0c16Sdavemq * For Altas 4-1G copper, Xcvr port numbers are 696459ac0c16Sdavemq * swapped with ethernet port number. This is 696559ac0c16Sdavemq * designed for better signal integrity in routing. 696659ac0c16Sdavemq */ 696759ac0c16Sdavemq switch (portn) { 696859ac0c16Sdavemq case 0: 696959ac0c16Sdavemq xcvr_portn += 3; 697059ac0c16Sdavemq break; 697159ac0c16Sdavemq case 1: 697259ac0c16Sdavemq xcvr_portn += 2; 697359ac0c16Sdavemq break; 697459ac0c16Sdavemq case 2: 697559ac0c16Sdavemq xcvr_portn += 1; 697659ac0c16Sdavemq break; 697759ac0c16Sdavemq case 3: 697859ac0c16Sdavemq default: 697959ac0c16Sdavemq break; 698059ac0c16Sdavemq } 698159ac0c16Sdavemq 6982321febdeSsbehera MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 698359ac0c16Sdavemq rs = npi_mac_mif_mii_write(nxgep->npi_handle, 698459ac0c16Sdavemq xcvr_portn, BCM5464R_MISC, 0xb4ee); 698559ac0c16Sdavemq if (rs != NPI_SUCCESS) { 698659ac0c16Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 698759ac0c16Sdavemq "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write " 698859ac0c16Sdavemq "returned error 0x[%x]", rs)); 6989321febdeSsbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 699059ac0c16Sdavemq return; 699159ac0c16Sdavemq } 699259ac0c16Sdavemq 699359ac0c16Sdavemq rs = npi_mac_mif_mii_write(nxgep->npi_handle, 699459ac0c16Sdavemq xcvr_portn, BCM5464R_MISC, 0xb8ee); 699559ac0c16Sdavemq if (rs != NPI_SUCCESS) { 699659ac0c16Sdavemq NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 699759ac0c16Sdavemq "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write " 699859ac0c16Sdavemq "returned error 0x[%x]", rs)); 699959ac0c16Sdavemq } 700059ac0c16Sdavemq 7001321febdeSsbehera MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 700259ac0c16Sdavemq } 7003d81011f0Ssbehera 7004d81011f0Ssbehera static nxge_status_t 7005d81011f0Ssbehera nxge_mii_get_link_mode(p_nxge_t nxgep) 7006d81011f0Ssbehera { 7007d81011f0Ssbehera p_nxge_stats_t statsp; 7008d81011f0Ssbehera uint8_t xcvr_portn; 7009d81011f0Ssbehera p_mii_regs_t mii_regs; 7010d81011f0Ssbehera mii_mode_control_stat_t mode; 7011d81011f0Ssbehera int status = NXGE_OK; 7012d81011f0Ssbehera 7013d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_get_link_mode")); 7014d81011f0Ssbehera 7015d81011f0Ssbehera statsp = nxgep->statsp; 7016d81011f0Ssbehera xcvr_portn = statsp->mac_stats.xcvr_portn; 7017d81011f0Ssbehera mii_regs = NULL; 7018d81011f0Ssbehera mode.value = 0; 70196b438925Ssbehera mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG; 7020d81011f0Ssbehera #if defined(__i386) 7021d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 7022d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->shadow), 7023d81011f0Ssbehera mode.value)) != NXGE_OK) { 7024d81011f0Ssbehera goto fail; 7025d81011f0Ssbehera #else 7026d81011f0Ssbehera if ((status = nxge_mii_write(nxgep, xcvr_portn, 7027d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->shadow), 7028d81011f0Ssbehera mode.value)) != NXGE_OK) { 7029d81011f0Ssbehera goto fail; 7030d81011f0Ssbehera #endif 7031d81011f0Ssbehera } 7032d81011f0Ssbehera #if defined(__i386) 7033d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 7034d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->shadow), 7035d81011f0Ssbehera &mode.value)) != NXGE_OK) { 7036d81011f0Ssbehera goto fail; 7037d81011f0Ssbehera } 7038d81011f0Ssbehera #else 7039d81011f0Ssbehera if ((status = nxge_mii_read(nxgep, xcvr_portn, 7040d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->shadow), 7041d81011f0Ssbehera &mode.value)) != NXGE_OK) { 7042d81011f0Ssbehera goto fail; 7043d81011f0Ssbehera } 7044d81011f0Ssbehera #endif 7045d81011f0Ssbehera 7046d81011f0Ssbehera if (mode.bits.mode == NXGE_MODE_SELECT_FIBER) { 7047d81011f0Ssbehera nxgep->mac.portmode = PORT_1G_RGMII_FIBER; 7048d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7049d81011f0Ssbehera "nxge_mii_get_link_mode: fiber mode")); 7050d81011f0Ssbehera } 7051d81011f0Ssbehera 7052d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7053d81011f0Ssbehera "nxge_mii_get_link_mode: " 7054d81011f0Ssbehera "(address 0x%x) port 0x%x mode value 0x%x link mode 0x%x", 70556b438925Ssbehera NXGE_MII_MODE_CONTROL_REG, xcvr_portn, 7056d81011f0Ssbehera mode.value, nxgep->mac.portmode)); 7057d81011f0Ssbehera 7058d81011f0Ssbehera NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7059d81011f0Ssbehera "<== nxge_mii_get_link_mode")); 7060d81011f0Ssbehera return (status); 7061d81011f0Ssbehera fail: 7062d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7063d81011f0Ssbehera "<== nxge_mii_get_link_mode (failed)")); 7064d81011f0Ssbehera return (NXGE_ERROR); 7065d81011f0Ssbehera } 7066d81011f0Ssbehera 70671bd6825cSml nxge_status_t 70681bd6825cSml nxge_mac_set_framesize(p_nxge_t nxgep) 70691bd6825cSml { 70701bd6825cSml npi_attr_t ap; 70711bd6825cSml uint8_t portn; 70721bd6825cSml npi_handle_t handle; 70731bd6825cSml npi_status_t rs = NPI_SUCCESS; 70741bd6825cSml 70751bd6825cSml NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_set_framesize")); 70761bd6825cSml 70771bd6825cSml portn = NXGE_GET_PORT_NUM(nxgep->function_num); 70781bd6825cSml handle = nxgep->npi_handle; 70791bd6825cSml 70801bd6825cSml NXGE_DEBUG_MSG((nxgep, MAC_CTL, 70811bd6825cSml "==> nxge_mac_sec_framesize: port<%d> " 70821bd6825cSml "min framesize %d max framesize %d ", 70831bd6825cSml portn, 70841bd6825cSml nxgep->mac.minframesize, 70851bd6825cSml nxgep->mac.maxframesize)); 70861bd6825cSml 70871bd6825cSml SET_MAC_ATTR2(handle, ap, portn, 70881bd6825cSml MAC_PORT_FRAME_SIZE, 70891bd6825cSml nxgep->mac.minframesize, 70901bd6825cSml nxgep->mac.maxframesize, 70911bd6825cSml rs); 70921bd6825cSml if (rs != NPI_SUCCESS) { 70931bd6825cSml NXGE_DEBUG_MSG((nxgep, MAC_CTL, 70941bd6825cSml "<== nxge_mac_set_framesize: failed to configure " 70951bd6825cSml "max/min frame size port %d", portn)); 70961bd6825cSml 70971bd6825cSml return (NXGE_ERROR | rs); 70981bd6825cSml } 70991bd6825cSml 71001bd6825cSml NXGE_DEBUG_MSG((nxgep, MAC_CTL, 71011bd6825cSml "<== nxge_mac_set_framesize: port<%d>", portn)); 71021bd6825cSml 71031bd6825cSml return (NXGE_OK); 71041bd6825cSml } 71051bd6825cSml 710600161856Syc static nxge_status_t 710700161856Syc nxge_get_num_of_xaui(uint32_t *port_pma_pmd_dev_id, 710800161856Syc uint32_t *port_pcs_dev_id, uint32_t *port_phy_id, uint8_t *num_xaui) 710900161856Syc { 711000161856Syc uint8_t i; 711100161856Syc 711200161856Syc for (i = 0; i < 4; i++) { 711300161856Syc if (port_phy_id[i] != PHY_BCM5464R_FAMILY) 711400161856Syc return (NXGE_ERROR); 711500161856Syc } 711600161856Syc 711700161856Syc *num_xaui = 0; 711800161856Syc if ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY && 711900161856Syc port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) || 712000161856Syc (((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK) 712100161856Syc == TN1010_DEV_ID) && 712200161856Syc ((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 712300161856Syc == TN1010_DEV_ID))) { 712400161856Syc (*num_xaui) ++; 712500161856Syc } 712600161856Syc if ((port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY && 712700161856Syc port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) || 712800161856Syc (((port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK) 712900161856Syc == TN1010_DEV_ID) && 713000161856Syc ((port_pcs_dev_id[1] & TN1010_DEV_ID_MASK) 713100161856Syc == TN1010_DEV_ID))) { 713200161856Syc (*num_xaui) ++; 713300161856Syc } 713400161856Syc return (NXGE_OK); 713500161856Syc } 713600161856Syc 713700161856Syc /* 713800161856Syc * Instruction from Teranetics: Once you detect link is up, go 713900161856Syc * read Reg 30.1.4 for link speed: '1' for 1G and '0' for 10G. You 714000161856Syc * may want to qualify it by first checking Register 30.1.7:6 and 714100161856Syc * making sure it reads "01" (Auto-Neg Complete). 714200161856Syc * 714300161856Syc * If this function is called when the link is down or before auto- 714400161856Syc * negotiation has completed, then the speed of the PHY is not certain. 714500161856Syc * In such cases, this function returns 1G as the default speed with 714600161856Syc * NXGE_OK status instead of NXGE_ERROR. It is OK to initialize the 714700161856Syc * driver based on a default speed because this function will be called 714800161856Syc * again when the link comes up. Returning NXGE_ERROR, which may 714900161856Syc * cause brutal chain reaction in caller functions, is not necessary. 715000161856Syc */ 715100161856Syc static nxge_status_t 715200161856Syc nxge_get_tn1010_speed(p_nxge_t nxgep, uint16_t *speed) 715300161856Syc { 715400161856Syc uint8_t phy_port_addr, autoneg_stat, link_up; 715500161856Syc nxge_status_t status = NXGE_OK; 715600161856Syc uint16_t val; 715700161856Syc uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 715800161856Syc 715900161856Syc /* Set default speed to 10G */ 716000161856Syc *speed = TN1010_SPEED_10G; 716100161856Syc 716200161856Syc /* Set Clause 45 */ 716300161856Syc npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE); 716400161856Syc 716500161856Syc phy_port_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 716600161856Syc 716700161856Syc /* Check Device 1 Register 0xA bit0 for link up status */ 716800161856Syc status = nxge_mdio_read(nxgep, phy_port_addr, 716900161856Syc TN1010_AUTONEG_DEV_ADDR, TN1010_AUTONEG_STATUS_REG, &val); 717000161856Syc if (status != NXGE_OK) 717100161856Syc goto fail; 717200161856Syc 717300161856Syc link_up = ((val & TN1010_AN_LINK_STAT_BIT) 717400161856Syc ? B_TRUE : B_FALSE); 717500161856Syc if (link_up == B_FALSE) { 717600161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 717700161856Syc "nxge_get_tn1010_speed: link is down")); 717800161856Syc goto nxge_get_tn1010_speed_exit; 717900161856Syc } 718000161856Syc 718100161856Syc if ((status = nxge_mdio_read(nxgep, phy_port_addr, 718200161856Syc TN1010_VENDOR_MMD1_DEV_ADDR, TN1010_VENDOR_MMD1_STATUS_REG, 718300161856Syc &val)) != NXGE_OK) { 718400161856Syc goto fail; 718500161856Syc } 718600161856Syc autoneg_stat = (val & TN1010_VENDOR_MMD1_AN_STAT_BITS) >> 718700161856Syc TN1010_VENDOR_MMD1_AN_STAT_SHIFT; 718800161856Syc 718900161856Syc /* 719000161856Syc * Return NXGE_OK even when we can not get a settled speed. In 719100161856Syc * such case, the speed reported should not be trusted but that 719200161856Syc * is OK, we will call this function periodically and will get 719300161856Syc * the correct speed after the link is up. 719400161856Syc */ 719500161856Syc switch (autoneg_stat) { 719600161856Syc case TN1010_AN_IN_PROG: 719700161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 719800161856Syc "nxge_get_tn1010_speed: Auto-negotiation in progress")); 719900161856Syc break; 720000161856Syc case TN1010_AN_COMPLETE: 720100161856Syc if ((status = nxge_mdio_read(nxgep, phy_port_addr, 720200161856Syc TN1010_VENDOR_MMD1_DEV_ADDR, 720300161856Syc TN1010_VENDOR_MMD1_STATUS_REG, 720400161856Syc &val)) != NXGE_OK) { 720500161856Syc goto fail; 720600161856Syc } 720700161856Syc *speed = (val & TN1010_VENDOR_MMD1_AN_SPEED_BIT) >> 720800161856Syc TN1010_VENDOR_MMD1_AN_SPEED_SHIFT; 720900161856Syc break; 721000161856Syc case TN1010_AN_RSVD: 721100161856Syc NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 721200161856Syc "nxge_get_tn1010_speed: Autoneg status undefined")); 721300161856Syc break; 721400161856Syc case TN1010_AN_FAILED: 721500161856Syc NXGE_DEBUG_MSG((nxgep, MAC_CTL, 721600161856Syc "nxge_get_tn1010_speed: Auto-negotiation failed")); 721700161856Syc break; 721800161856Syc default: 721900161856Syc break; 722000161856Syc } 722100161856Syc nxge_get_tn1010_speed_exit: 722200161856Syc return (NXGE_OK); 722300161856Syc fail: 722400161856Syc return (status); 722500161856Syc } 722600161856Syc 722700161856Syc 722800161856Syc /* 722900161856Syc * Teranetics TN1010 PHY chip supports both 1G and 10G modes, this function 723000161856Syc * figures out the speed of the PHY determined by the autonegotiation 723100161856Syc * process and sets the following 3 parameters, 723200161856Syc * nxgep->mac.portmode 723300161856Syc * nxgep->statsp->mac_stats.link_speed 723400161856Syc * nxgep->statsp->mac_stats.xcvr_inuse 723500161856Syc */ 723600161856Syc static nxge_status_t 723700161856Syc nxge_set_tn1010_param(p_nxge_t nxgep) 723800161856Syc { 723900161856Syc uint16_t speed; 724000161856Syc 724100161856Syc if (nxge_get_tn1010_speed(nxgep, &speed) != NXGE_OK) { 724200161856Syc NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 724300161856Syc "nxge_set_tn1010_param: " 724400161856Syc "Failed to get TN1010 speed")); 724500161856Syc return (NXGE_ERROR); 724600161856Syc } 724700161856Syc if (speed == TN1010_SPEED_1G) { 724800161856Syc nxgep->mac.portmode = PORT_1G_TN1010; 724900161856Syc nxgep->statsp->mac_stats.link_speed = 1000; 725000161856Syc nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 725100161856Syc } else { 725200161856Syc nxgep->mac.portmode = PORT_10G_TN1010; 725300161856Syc nxgep->statsp->mac_stats.link_speed = 10000; 725400161856Syc nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 725500161856Syc } 725600161856Syc return (NXGE_OK); 725700161856Syc } 725800161856Syc 7259d81011f0Ssbehera #ifdef NXGE_DEBUG 7260d81011f0Ssbehera static void 7261d81011f0Ssbehera nxge_mii_dump(p_nxge_t nxgep) 7262d81011f0Ssbehera { 7263d81011f0Ssbehera p_nxge_stats_t statsp; 7264d81011f0Ssbehera uint8_t xcvr_portn; 7265d81011f0Ssbehera p_mii_regs_t mii_regs; 7266d81011f0Ssbehera mii_bmcr_t bmcr; 7267d81011f0Ssbehera mii_bmsr_t bmsr; 7268d81011f0Ssbehera mii_idr1_t idr1; 7269d81011f0Ssbehera mii_idr2_t idr2; 7270d81011f0Ssbehera mii_mode_control_stat_t mode; 7271678453a8Sspeer p_nxge_param_t param_arr; 7272d81011f0Ssbehera 7273d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "==> nxge_mii_dump")); 7274d81011f0Ssbehera 7275d81011f0Ssbehera statsp = nxgep->statsp; 7276d81011f0Ssbehera xcvr_portn = statsp->mac_stats.xcvr_portn; 7277d81011f0Ssbehera 7278d81011f0Ssbehera mii_regs = NULL; 7279d81011f0Ssbehera 7280d81011f0Ssbehera #if defined(__i386) 7281d81011f0Ssbehera (void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn, 7282d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value); 7283d81011f0Ssbehera #else 7284d81011f0Ssbehera (void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn, 7285d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value); 7286d81011f0Ssbehera #endif 7287d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7288d81011f0Ssbehera "nxge_mii_dump: bmcr (0) xcvr 0x%x value 0x%x", 7289d81011f0Ssbehera xcvr_portn, bmcr.value)); 7290d81011f0Ssbehera 7291d81011f0Ssbehera #if defined(__i386) 7292d81011f0Ssbehera (void) nxge_mii_read(nxgep, 7293d81011f0Ssbehera nxgep->statsp->mac_stats.xcvr_portn, 7294d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->bmsr), &bmsr.value); 7295d81011f0Ssbehera #else 7296d81011f0Ssbehera (void) nxge_mii_read(nxgep, 7297d81011f0Ssbehera nxgep->statsp->mac_stats.xcvr_portn, 7298d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value); 7299d81011f0Ssbehera #endif 7300d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7301d81011f0Ssbehera "nxge_mii_dump: bmsr (1) xcvr 0x%x value 0x%x", 7302d81011f0Ssbehera xcvr_portn, bmsr.value)); 7303d81011f0Ssbehera 7304d81011f0Ssbehera #if defined(__i386) 7305d81011f0Ssbehera (void) nxge_mii_read(nxgep, 7306d81011f0Ssbehera nxgep->statsp->mac_stats.xcvr_portn, 7307d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->idr1), &idr1.value); 7308d81011f0Ssbehera #else 7309d81011f0Ssbehera (void) nxge_mii_read(nxgep, 7310d81011f0Ssbehera nxgep->statsp->mac_stats.xcvr_portn, 7311d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->idr1), &idr1.value); 7312d81011f0Ssbehera #endif 7313d81011f0Ssbehera 7314d81011f0Ssbehera 7315d81011f0Ssbehera #if defined(__i386) 7316d81011f0Ssbehera (void) nxge_mii_read(nxgep, 7317d81011f0Ssbehera nxgep->statsp->mac_stats.xcvr_portn, 7318d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->idr2), &idr2.value); 7319d81011f0Ssbehera #else 7320d81011f0Ssbehera (void) nxge_mii_read(nxgep, 7321d81011f0Ssbehera nxgep->statsp->mac_stats.xcvr_portn, 7322d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->idr2), &idr2.value); 7323d81011f0Ssbehera #endif 7324d81011f0Ssbehera 7325d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7326d81011f0Ssbehera "nxge_mii_dump: idr1 (2) xcvr 0x%x value 0x%x", 7327d81011f0Ssbehera xcvr_portn, idr1.value)); 7328d81011f0Ssbehera 7329d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7330d81011f0Ssbehera "nxge_mii_dump: idr2 (3) xcvr 0x%x value 0x%x", 7331d81011f0Ssbehera xcvr_portn, idr2.value)); 7332d81011f0Ssbehera 7333d81011f0Ssbehera mode.value = 0; 73346b438925Ssbehera mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG; 7335d81011f0Ssbehera 7336d81011f0Ssbehera #if defined(__i386) 7337d81011f0Ssbehera (void) nxge_mii_write(nxgep, xcvr_portn, 7338d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->shadow), mode.value); 7339d81011f0Ssbehera 7340d81011f0Ssbehera (void) nxge_mii_read(nxgep, xcvr_portn, 7341d81011f0Ssbehera (uint8_t)(uint32_t)(&mii_regs->shadow), &mode.value); 7342d81011f0Ssbehera #else 7343d81011f0Ssbehera (void) nxge_mii_write(nxgep, xcvr_portn, 7344d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->shadow), mode.value); 7345d81011f0Ssbehera 7346d81011f0Ssbehera (void) nxge_mii_read(nxgep, xcvr_portn, 7347d81011f0Ssbehera (uint8_t)(uint64_t)(&mii_regs->shadow), &mode.value); 7348d81011f0Ssbehera #endif 7349d81011f0Ssbehera 7350d81011f0Ssbehera NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7351d81011f0Ssbehera "nxge_mii_dump: mode control xcvr 0x%x value 0x%x", 7352d81011f0Ssbehera xcvr_portn, mode.value)); 7353d81011f0Ssbehera } 7354d81011f0Ssbehera #endif 7355