1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25 #include <sys/nxge/nxge_impl.h> 26 #include <sys/nxge/nxge_mac.h> 27 #include <sys/nxge/nxge_hio.h> 28 29 #define LINK_MONITOR_PERIOD (1000 * 1000) 30 #define LM_WAIT_MULTIPLIER 8 31 32 #define SERDES_RDY_WT_INTERVAL 50 33 #define MAX_SERDES_RDY_RETRIES 10 34 35 #define TN1010_SPEED_1G 1 36 #define TN1010_SPEED_10G 0 37 #define TN1010_AN_IN_PROG 0 /* Auto negotiation in progress */ 38 #define TN1010_AN_COMPLETE 1 39 #define TN1010_AN_RSVD 2 40 #define TN1010_AN_FAILED 3 41 42 extern uint32_t nxge_no_link_notify; 43 extern boolean_t nxge_no_msg; 44 extern uint32_t nxge_lb_dbg; 45 extern uint32_t nxge_jumbo_mtu; 46 47 typedef enum { 48 CHECK_LINK_RESCHEDULE, 49 CHECK_LINK_STOP 50 } check_link_state_t; 51 52 static check_link_state_t nxge_check_link_stop(nxge_t *); 53 54 /* 55 * Ethernet broadcast address definition. 56 */ 57 static ether_addr_st etherbroadcastaddr = 58 {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}; 59 /* 60 * Ethernet zero address definition. 61 */ 62 static ether_addr_st etherzeroaddr = 63 {{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; 64 /* 65 * Supported chip types 66 */ 67 static uint32_t nxge_supported_cl45_ids[] = { 68 BCM8704_DEV_ID, 69 MARVELL_88X_201X_DEV_ID, 70 BCM8706_DEV_ID, 71 TN1010_DEV_ID 72 }; 73 74 static uint32_t nxge_supported_cl22_ids[] = { 75 BCM5464R_PHY_ID, 76 BCM5482_PHY_ID 77 }; 78 79 #define NUM_CLAUSE_45_IDS (sizeof (nxge_supported_cl45_ids) / \ 80 sizeof (uint32_t)) 81 #define NUM_CLAUSE_22_IDS (sizeof (nxge_supported_cl22_ids) / \ 82 sizeof (uint32_t)) 83 /* 84 * static functions 85 */ 86 static uint32_t nxge_get_cl45_pma_pmd_id(p_nxge_t, int); 87 static uint32_t nxge_get_cl45_pcs_id(p_nxge_t, int); 88 static uint32_t nxge_get_cl22_phy_id(p_nxge_t, int); 89 static boolean_t nxge_is_supported_phy(uint32_t, uint8_t); 90 static boolean_t nxge_hswap_phy_present(p_nxge_t, uint8_t); 91 static boolean_t nxge_is_phy_present(p_nxge_t, int, uint32_t, uint32_t); 92 static nxge_status_t nxge_n2_serdes_init(p_nxge_t); 93 static nxge_status_t nxge_n2_kt_serdes_init(p_nxge_t); 94 static nxge_status_t nxge_neptune_10G_serdes_init(p_nxge_t); 95 static nxge_status_t nxge_1G_serdes_init(p_nxge_t); 96 static nxge_status_t nxge_10G_link_intr_stop(p_nxge_t); 97 static nxge_status_t nxge_10G_link_intr_start(p_nxge_t); 98 static nxge_status_t nxge_1G_copper_link_intr_stop(p_nxge_t); 99 static nxge_status_t nxge_1G_copper_link_intr_start(p_nxge_t); 100 static nxge_status_t nxge_1G_fiber_link_intr_stop(p_nxge_t); 101 static nxge_status_t nxge_1G_fiber_link_intr_start(p_nxge_t); 102 static nxge_status_t nxge_check_mii_link(p_nxge_t); 103 static nxge_status_t nxge_check_10g_link(p_nxge_t); 104 static nxge_status_t nxge_10G_xcvr_init(p_nxge_t); 105 static nxge_status_t nxge_BCM8704_xcvr_init(p_nxge_t); 106 static nxge_status_t nxge_BCM8706_xcvr_init(p_nxge_t); 107 static nxge_status_t nxge_1G_xcvr_init(p_nxge_t); 108 static void nxge_bcm5464_link_led_off(p_nxge_t); 109 static nxge_status_t nxge_check_mrvl88x2011_link(p_nxge_t, boolean_t *); 110 static nxge_status_t nxge_mrvl88x2011_xcvr_init(p_nxge_t); 111 static nxge_status_t nxge_check_nlp2020_link(p_nxge_t, boolean_t *); 112 static nxge_status_t nxge_nlp2020_xcvr_init(p_nxge_t); 113 static int nxge_nlp2020_i2c_read(p_nxge_t, uint8_t, uint16_t, uint16_t, 114 uint8_t *); 115 static boolean_t nxge_is_nlp2020_phy(p_nxge_t); 116 static uint8_t nxge_get_nlp2020_connector_type(p_nxge_t); 117 static nxge_status_t nxge_set_nlp2020_param(p_nxge_t); 118 static nxge_status_t nxge_get_num_of_xaui(uint32_t *port_pma_pmd_dev_id, 119 uint32_t *port_pcs_dev_id, uint32_t *port_phy_id, uint8_t *num_xaui); 120 static nxge_status_t nxge_get_tn1010_speed(p_nxge_t nxgep, uint16_t *speed); 121 static nxge_status_t nxge_set_tn1010_param(p_nxge_t nxgep); 122 static nxge_status_t nxge_tn1010_check(p_nxge_t nxgep, 123 nxge_link_state_t *link_up); 124 static boolean_t nxge_is_tn1010_phy(p_nxge_t nxgep); 125 static nxge_status_t nxge_tn1010_xcvr_init(p_nxge_t nxgep); 126 127 nxge_status_t nxge_mac_init(p_nxge_t); 128 static nxge_status_t nxge_mii_get_link_mode(p_nxge_t); 129 130 #ifdef NXGE_DEBUG 131 static void nxge_mii_dump(p_nxge_t); 132 static nxge_status_t nxge_tn1010_reset(p_nxge_t nxgep); 133 static void nxge_dump_tn1010_status_regs(p_nxge_t nxgep); 134 #endif 135 136 /* 137 * xcvr tables for supported transceivers 138 */ 139 140 /* 141 * nxge_n2_10G_table is for 10G fiber or serdes on N2-NIU systems. 142 * The Teranetics TN1010 based copper XAUI card can also be used 143 * on N2-NIU systems in 10G mode, but it uses its own table 144 * nxge_n2_10G_tn1010_table below. 145 */ 146 static nxge_xcvr_table_t nxge_n2_10G_table = { 147 nxge_n2_serdes_init, 148 nxge_10G_xcvr_init, 149 nxge_10G_link_intr_stop, 150 nxge_10G_link_intr_start, 151 nxge_check_10g_link, 152 PCS_XCVR 153 }; 154 155 /* 156 * For the Teranetics TN1010 based copper XAUI card 157 */ 158 static nxge_xcvr_table_t nxge_n2_10G_tn1010_table = { 159 nxge_n2_serdes_init, /* Handle both 1G and 10G */ 160 nxge_tn1010_xcvr_init, /* Handle both 1G and 10G */ 161 nxge_10G_link_intr_stop, 162 nxge_10G_link_intr_start, 163 nxge_check_tn1010_link, /* Will figure out speed */ 164 XPCS_XCVR 165 }; 166 167 static nxge_xcvr_table_t nxge_n2_1G_table = { 168 nxge_n2_serdes_init, 169 nxge_1G_xcvr_init, 170 nxge_1G_fiber_link_intr_stop, 171 nxge_1G_fiber_link_intr_start, 172 nxge_check_mii_link, 173 PCS_XCVR 174 }; 175 176 static nxge_xcvr_table_t nxge_n2_1G_tn1010_table = { 177 nxge_n2_serdes_init, 178 nxge_tn1010_xcvr_init, 179 nxge_1G_fiber_link_intr_stop, /* TN1010 is a Cu PHY, but it uses */ 180 nxge_1G_fiber_link_intr_start, /* PCS for 1G, so call fiber func */ 181 nxge_check_tn1010_link, 182 PCS_XCVR 183 }; 184 185 static nxge_xcvr_table_t nxge_10G_tn1010_table = { 186 nxge_neptune_10G_serdes_init, 187 nxge_tn1010_xcvr_init, 188 nxge_10G_link_intr_stop, 189 nxge_10G_link_intr_start, 190 nxge_check_tn1010_link, 191 XPCS_XCVR 192 }; 193 194 static nxge_xcvr_table_t nxge_1G_tn1010_table = { 195 nxge_1G_serdes_init, 196 nxge_tn1010_xcvr_init, 197 nxge_1G_fiber_link_intr_stop, 198 nxge_1G_fiber_link_intr_start, 199 nxge_check_tn1010_link, 200 PCS_XCVR 201 }; 202 203 static nxge_xcvr_table_t nxge_10G_fiber_table = { 204 nxge_neptune_10G_serdes_init, 205 nxge_10G_xcvr_init, 206 nxge_10G_link_intr_stop, 207 nxge_10G_link_intr_start, 208 nxge_check_10g_link, 209 PCS_XCVR 210 }; 211 212 static nxge_xcvr_table_t nxge_1G_copper_table = { 213 NULL, 214 nxge_1G_xcvr_init, 215 nxge_1G_copper_link_intr_stop, 216 nxge_1G_copper_link_intr_start, 217 nxge_check_mii_link, 218 INT_MII_XCVR 219 }; 220 221 /* This table is for Neptune portmode == PORT_1G_SERDES cases */ 222 static nxge_xcvr_table_t nxge_1G_fiber_table = { 223 nxge_1G_serdes_init, 224 nxge_1G_xcvr_init, 225 nxge_1G_fiber_link_intr_stop, 226 nxge_1G_fiber_link_intr_start, 227 nxge_check_mii_link, 228 PCS_XCVR 229 }; 230 231 static nxge_xcvr_table_t nxge_10G_copper_table = { 232 nxge_neptune_10G_serdes_init, 233 NULL, 234 NULL, 235 NULL, 236 NULL, 237 PCS_XCVR 238 }; 239 240 /* 241 * NXGE_PORT_TN1010 is defined as, 242 * NXGE_PORT_SPD_NONE | (NXGE_PHY_TN1010 << NXGE_PHY_SHIFT) 243 * = 0 | 5 << 16 = 0x50000 244 * 245 * So NEPTUNE_2_TN1010 = 246 * (NXGE_PORT_TN1010 | 247 * (NXGE_PORT_TN1010 << 4) | 248 * (NXGE_PORT_NONE << 8) | 249 * (NXGE_PORT_NONE << 12)), 250 * = 0x50000 | (0x50000 << 4) 251 * = 0x550000 252 * 253 * This function partitions nxgep->nxge_hw_p->niu_type (which may have 254 * value NEPTUNE_2_TN1010) and checks if a port has type = NXGE_PORT_TN1010 255 * = 0x50000 256 */ 257 static boolean_t nxge_is_tn1010_phy(p_nxge_t nxgep) 258 { 259 uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 260 261 if (((nxgep->nxge_hw_p->niu_type >> (NXGE_PORT_TYPE_SHIFT * portn)) 262 & NXGE_PHY_MASK) == NXGE_PORT_TN1010) { 263 return (B_TRUE); 264 } else { 265 return (B_FALSE); 266 } 267 } 268 269 270 /* 271 * Figure out nxgep->mac.portmode from nxge.conf, OBP's device properties, 272 * serial EEPROM or VPD if possible. Note that not all systems could get 273 * the portmode information by calling this function. For example, the 274 * Maramba system figures out the portmode information by calling function 275 * nxge_setup_xcvr_table. 276 */ 277 nxge_status_t 278 nxge_get_xcvr_type(p_nxge_t nxgep) 279 { 280 nxge_status_t status = NXGE_OK; 281 char *phy_type; 282 char *prop_val; 283 uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 284 uint32_t val; 285 npi_status_t rs; 286 287 /* For Opus NEM, skip xcvr checking if 10G Serdes link is up */ 288 if (nxgep->mac.portmode == PORT_10G_SERDES && 289 nxgep->statsp->mac_stats.link_up) { 290 nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 291 return (status); 292 } 293 294 nxgep->mac.portmode = 0; 295 nxgep->xcvr_addr = 0; 296 297 /* 298 * First check for hot swappable phy property. 299 */ 300 if (nxgep->hot_swappable_phy == B_TRUE) { 301 nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR; 302 nxgep->mac.portmode = PORT_HSP_MODE; 303 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Other: Hot Swappable")); 304 } else if (ddi_prop_exists(DDI_DEV_T_ANY, nxgep->dip, 305 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 306 "hot-swappable-phy") == 1) { 307 nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR; 308 nxgep->mac.portmode = PORT_HSP_MODE; 309 NXGE_DEBUG_MSG((nxgep, MAC_CTL, ".conf: Hot Swappable")); 310 } else if (nxgep->niu_type == N2_NIU && 311 ddi_prop_exists(DDI_DEV_T_ANY, nxgep->dip, 0, 312 "hot-swappable-phy") == 1) { 313 nxgep->statsp->mac_stats.xcvr_inuse = HSP_XCVR; 314 nxgep->mac.portmode = PORT_HSP_MODE; 315 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "OBP: Hot Swappable")); 316 } 317 318 /* 319 * MDIO polling support for Monza RTM card, Goa NEM card 320 */ 321 if (nxgep->mac.portmode == PORT_HSP_MODE) { 322 nxgep->hot_swappable_phy = B_TRUE; 323 if (portn > 1) { 324 return (NXGE_ERROR); 325 } 326 327 if (nxge_hswap_phy_present(nxgep, portn)) 328 goto found_phy; 329 330 nxgep->phy_absent = B_TRUE; 331 332 /* Check Serdes link to detect Opus NEM */ 333 rs = npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 334 XPCS_REG_STATUS, &val); 335 336 if (rs == 0 && val & XPCS_STATUS_LANE_ALIGN) { 337 nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 338 nxgep->mac.portmode = PORT_10G_SERDES; 339 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 340 "HSP 10G Serdes FOUND!!")); 341 } 342 goto check_phy_done; 343 found_phy: 344 nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 345 nxgep->mac.portmode = PORT_10G_FIBER; 346 nxgep->phy_absent = B_FALSE; 347 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Fiber Xcvr " 348 "found for hot swappable phy")); 349 check_phy_done: 350 return (status); 351 } 352 353 /* Get phy-type property (May have been set by nxge.conf) */ 354 if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip, 355 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 356 "phy-type", &prop_val)) == DDI_PROP_SUCCESS) { 357 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 358 "found conf file: phy-type %s", prop_val)); 359 if (strcmp("xgsd", prop_val) == 0) { 360 nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 361 nxgep->mac.portmode = PORT_10G_SERDES; 362 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 363 "found: 10G Serdes")); 364 } else if (strcmp("gsd", prop_val) == 0) { 365 nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 366 nxgep->mac.portmode = PORT_1G_SERDES; 367 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Serdes")); 368 } else if (strcmp("mif", prop_val) == 0) { 369 nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR; 370 nxgep->mac.portmode = PORT_1G_COPPER; 371 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Copper Xcvr")); 372 } else if (strcmp("pcs", prop_val) == 0) { 373 nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 374 nxgep->mac.portmode = PORT_1G_FIBER; 375 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G FIBER Xcvr")); 376 } else if (strcmp("xgf", prop_val) == 0) { 377 /* 378 * Before OBP supports new phy-type property 379 * value "xgc", the 10G copper XAUI may carry 380 * "xgf" instead of "xgc". If the OBP is 381 * upgraded to a newer version which supports 382 * "xgc", then the TN1010 related code in this 383 * "xgf" case will not be used anymore. 384 */ 385 if (nxge_is_tn1010_phy(nxgep)) { 386 if ((status = nxge_set_tn1010_param(nxgep)) 387 != NXGE_OK) { 388 return (status); 389 } 390 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "TN1010 Xcvr")); 391 } else { /* For Fiber XAUI */ 392 nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 393 nxgep->mac.portmode = PORT_10G_FIBER; 394 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 395 "10G Fiber Xcvr")); 396 } 397 } else if (strcmp("xgc", prop_val) == 0) { 398 if ((status = nxge_set_tn1010_param(nxgep)) != NXGE_OK) 399 return (status); 400 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "TN1010 Xcvr")); 401 } 402 403 (void) ddi_prop_update_string(DDI_DEV_T_NONE, nxgep->dip, 404 "phy-type", prop_val); 405 ddi_prop_free(prop_val); 406 407 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: " 408 "Got phy type [0x%x] from conf file", 409 nxgep->mac.portmode)); 410 411 return (NXGE_OK); 412 } 413 414 /* Get phy-type property from OBP */ 415 if (nxgep->niu_type == N2_NIU) { 416 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip, 0, 417 "phy-type", &prop_val) == DDI_PROP_SUCCESS) { 418 if (strcmp("xgf", prop_val) == 0) { 419 /* 420 * Before OBP supports new phy-type property 421 * value "xgc", the 10G copper XAUI may carry 422 * "xgf" instead of "xgc". If the OBP is 423 * upgraded to a newer version which supports 424 * "xgc", then the TN1010 related code in this 425 * "xgf" case will not be used anymore. 426 */ 427 if (nxge_is_tn1010_phy(nxgep)) { 428 if ((status = 429 nxge_set_tn1010_param(nxgep)) 430 != NXGE_OK) { 431 return (status); 432 } 433 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 434 "TN1010 Xcvr")); 435 } else if (nxge_is_nlp2020_phy(nxgep)) { 436 if ((status = 437 nxge_set_nlp2020_param(nxgep)) 438 != NXGE_OK) { 439 return (status); 440 } 441 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 442 "NLP2020 Xcvr")); 443 } else { /* For Fiber XAUI */ 444 nxgep->statsp->mac_stats.xcvr_inuse 445 = XPCS_XCVR; 446 nxgep->mac.portmode = PORT_10G_FIBER; 447 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 448 "10G Fiber Xcvr")); 449 } 450 } else if (strcmp("mif", prop_val) == 0) { 451 nxgep->statsp->mac_stats.xcvr_inuse = 452 INT_MII_XCVR; 453 nxgep->mac.portmode = PORT_1G_COPPER; 454 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 455 "1G Copper Xcvr")); 456 } else if (strcmp("pcs", prop_val) == 0) { 457 nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 458 nxgep->mac.portmode = PORT_1G_FIBER; 459 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 460 "1G Fiber Xcvr")); 461 } else if (strcmp("xgc", prop_val) == 0) { 462 status = nxge_set_tn1010_param(nxgep); 463 if (status != NXGE_OK) 464 return (status); 465 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "TN1010 Xcvr")); 466 } else if (strcmp("xgsd", prop_val) == 0) { 467 nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 468 nxgep->mac.portmode = PORT_10G_SERDES; 469 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 470 "OBP: 10G Serdes")); 471 } else if (strcmp("gsd", prop_val) == 0) { 472 nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 473 nxgep->mac.portmode = PORT_1G_SERDES; 474 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 475 "OBP: 1G Serdes")); 476 } else { 477 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 478 "Unknown phy-type: %s", prop_val)); 479 ddi_prop_free(prop_val); 480 return (NXGE_ERROR); 481 } 482 status = NXGE_OK; 483 (void) ddi_prop_update_string(DDI_DEV_T_NONE, 484 nxgep->dip, "phy-type", prop_val); 485 ddi_prop_free(prop_val); 486 487 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: " 488 "Got phy type [0x%x] from OBP", 489 nxgep->mac.portmode)); 490 491 return (status); 492 } else { 493 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 494 "Exiting...phy-type property not found")); 495 return (NXGE_ERROR); 496 } 497 } 498 499 500 if (!nxgep->vpd_info.present) { 501 return (NXGE_OK); 502 } 503 504 if (!nxgep->vpd_info.ver_valid) { 505 goto read_seeprom; 506 } 507 508 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 509 "Reading phy type from expansion ROM")); 510 /* 511 * Try to read the phy type from the vpd data read off the 512 * expansion ROM. 513 */ 514 phy_type = nxgep->vpd_info.phy_type; 515 516 if (strncmp(phy_type, "mif", 3) == 0) { 517 nxgep->mac.portmode = PORT_1G_COPPER; 518 nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR; 519 } else if (strncmp(phy_type, "xgf", 3) == 0) { 520 nxgep->mac.portmode = PORT_10G_FIBER; 521 nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 522 } else if (strncmp(phy_type, "pcs", 3) == 0) { 523 nxgep->mac.portmode = PORT_1G_FIBER; 524 nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 525 } else if (strncmp(phy_type, "xgc", 3) == 0) { 526 status = nxge_set_tn1010_param(nxgep); 527 if (status != NXGE_OK) { 528 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 529 "nxge_get_xcvr_type: Failed to set TN1010 param")); 530 goto read_seeprom; 531 } 532 } else if (strncmp(phy_type, "xgsd", 4) == 0) { 533 nxgep->mac.portmode = PORT_10G_SERDES; 534 nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 535 } else if (strncmp(phy_type, "gsd", 3) == 0) { 536 nxgep->mac.portmode = PORT_1G_SERDES; 537 nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 538 } else { 539 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 540 "nxge_get_xcvr_type: Unknown phy type [%c%c%c] in EEPROM", 541 phy_type[0], phy_type[1], phy_type[2])); 542 goto read_seeprom; 543 } 544 545 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: " 546 "Got phy type [0x%x] from VPD", nxgep->mac.portmode)); 547 548 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_get_xcvr_type")); 549 return (status); 550 551 read_seeprom: 552 /* 553 * read the phy type from the SEEPROM - NCR registers 554 */ 555 status = nxge_espc_phy_type_get(nxgep); 556 if (status != NXGE_OK) { 557 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 558 "Failed to get phy type")); 559 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "EEPROM version " 560 "[%s] invalid...please update", nxgep->vpd_info.ver)); 561 } 562 563 return (status); 564 565 } 566 567 /* Set up the PHY specific values. */ 568 569 nxge_status_t 570 nxge_setup_xcvr_table(p_nxge_t nxgep) 571 { 572 nxge_status_t status = NXGE_OK; 573 uint32_t port_type; 574 uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 575 uint32_t pcs_id = 0; 576 uint32_t pma_pmd_id = 0; 577 uint32_t phy_id = 0; 578 uint16_t chip_id = 0; 579 580 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_setup_xcvr_table: port<%d>", 581 portn)); 582 583 switch (nxgep->niu_type) { 584 case N2_NIU: 585 switch (nxgep->mac.portmode) { 586 case PORT_1G_FIBER: 587 case PORT_1G_SERDES: 588 nxgep->xcvr = nxge_n2_1G_table; 589 nxgep->xcvr_addr = portn; 590 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 1G %s Xcvr", 591 (nxgep->mac.portmode == PORT_1G_FIBER) ? "Fiber" : 592 "Serdes")); 593 break; 594 case PORT_10G_FIBER: 595 case PORT_10G_COPPER: 596 case PORT_10G_SERDES: 597 nxgep->xcvr = nxge_n2_10G_table; 598 if (nxgep->nxge_hw_p->xcvr_addr[portn]) { 599 nxgep->xcvr_addr = 600 nxgep->nxge_hw_p->xcvr_addr[portn]; 601 } 602 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 10G %s Xcvr", 603 (nxgep->mac.portmode == PORT_10G_FIBER) ? "Fiber" : 604 ((nxgep->mac.portmode == PORT_10G_COPPER) ? 605 "Copper" : "Serdes"))); 606 break; 607 case PORT_1G_TN1010: 608 nxgep->xcvr = nxge_n2_1G_tn1010_table; 609 nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 610 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 611 "TN1010 Copper Xcvr in 1G")); 612 break; 613 case PORT_10G_TN1010: 614 nxgep->xcvr = nxge_n2_10G_tn1010_table; 615 nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 616 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 617 "TN1010 Copper Xcvr in 10G")); 618 break; 619 case PORT_HSP_MODE: 620 nxgep->xcvr = nxge_n2_10G_table; 621 nxgep->xcvr.xcvr_inuse = HSP_XCVR; 622 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 10G Hot " 623 "Swappable Xcvr (not present)")); 624 break; 625 default: 626 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 627 "<== nxge_setup_xcvr_table: " 628 "Unable to determine NIU portmode")); 629 return (NXGE_ERROR); 630 } 631 break; 632 default: 633 if (nxgep->mac.portmode == 0) { 634 /* 635 * Would be the case for platforms like Maramba 636 * in which the phy type could not be got from conf 637 * file, OBP, VPD or Serial PROM. 638 */ 639 if (!NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) { 640 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 641 "<== nxge_setup_xcvr_table:" 642 " Invalid Neptune type [0x%x]", 643 nxgep->niu_type)); 644 return (NXGE_ERROR); 645 } 646 647 port_type = nxgep->niu_type >> 648 (NXGE_PORT_TYPE_SHIFT * portn); 649 port_type = port_type & (NXGE_PORT_TYPE_MASK); 650 651 switch (port_type) { 652 653 case NXGE_PORT_1G_COPPER: 654 nxgep->mac.portmode = PORT_1G_COPPER; 655 break; 656 case NXGE_PORT_10G_COPPER: 657 nxgep->mac.portmode = PORT_10G_COPPER; 658 break; 659 case NXGE_PORT_1G_FIBRE: 660 nxgep->mac.portmode = PORT_1G_FIBER; 661 break; 662 case NXGE_PORT_10G_FIBRE: 663 nxgep->mac.portmode = PORT_10G_FIBER; 664 break; 665 case NXGE_PORT_1G_SERDES: 666 nxgep->mac.portmode = PORT_1G_SERDES; 667 break; 668 case NXGE_PORT_10G_SERDES: 669 nxgep->mac.portmode = PORT_10G_SERDES; 670 break; 671 /* Ports 2 and 3 of Alonso or ARTM */ 672 case NXGE_PORT_1G_RGMII_FIBER: 673 nxgep->mac.portmode = PORT_1G_RGMII_FIBER; 674 break; 675 case NXGE_PORT_TN1010: 676 /* 677 * If this port uses the TN1010 copper 678 * PHY, then its speed is not known yet 679 * because nxge_scan_ports_phy could only 680 * figure out the vendor of the PHY but 681 * not its speed. nxge_set_tn1010_param 682 * will read the PHY speed and set 683 * portmode accordingly. 684 */ 685 if ((status = nxge_set_tn1010_param(nxgep)) 686 != NXGE_OK) { 687 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 688 "nxge_set_tn1010_param failed")); 689 return (status); 690 } 691 break; 692 default: 693 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 694 "<== nxge_setup_xcvr_table: " 695 "Unknown port-type: 0x%x", port_type)); 696 return (NXGE_ERROR); 697 } 698 } 699 700 /* 701 * Above switch has figured out nxge->mac.portmode, now set 702 * nxgep->xcvr (the table) and nxgep->xcvr_addr according 703 * to portmode. 704 */ 705 switch (nxgep->mac.portmode) { 706 case PORT_1G_COPPER: 707 case PORT_1G_RGMII_FIBER: 708 nxgep->xcvr = nxge_1G_copper_table; 709 nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 710 /* 711 * For Altas 4-1G copper, Xcvr port numbers are 712 * swapped with ethernet port number. This is 713 * designed for better signal integrity in 714 * routing. This is also the case for the 715 * on-board Neptune copper ports on the Maramba 716 * platform. 717 */ 718 switch (nxgep->platform_type) { 719 case P_NEPTUNE_ATLAS_4PORT: 720 case P_NEPTUNE_MARAMBA_P0: 721 case P_NEPTUNE_MARAMBA_P1: 722 switch (portn) { 723 case 0: 724 nxgep->xcvr_addr += 3; 725 break; 726 case 1: 727 nxgep->xcvr_addr += 1; 728 break; 729 case 2: 730 nxgep->xcvr_addr -= 1; 731 break; 732 case 3: 733 nxgep->xcvr_addr -= 3; 734 break; 735 default: 736 return (NXGE_ERROR); 737 } 738 break; 739 default: 740 break; 741 } 742 743 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G %s Xcvr", 744 (nxgep->mac.portmode == PORT_1G_COPPER) ? 745 "Copper" : "RGMII Fiber")); 746 break; 747 748 case PORT_10G_COPPER: 749 nxgep->xcvr = nxge_10G_copper_table; 750 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Copper Xcvr")); 751 break; 752 753 case PORT_1G_TN1010: 754 nxgep->xcvr = nxge_1G_tn1010_table; 755 nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 756 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 757 "1G TN1010 copper Xcvr")); 758 break; 759 760 case PORT_10G_TN1010: 761 nxgep->xcvr = nxge_10G_tn1010_table; 762 nxgep->xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 763 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 764 "10G TN1010 copper Xcvr")); 765 break; 766 767 case PORT_1G_FIBER: 768 case PORT_1G_SERDES: 769 nxgep->xcvr = nxge_1G_fiber_table; 770 nxgep->xcvr_addr = portn; 771 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G %s Xcvr", 772 (nxgep->mac.portmode == PORT_1G_FIBER) ? 773 "Fiber" : "Serdes")); 774 break; 775 case PORT_10G_FIBER: 776 case PORT_10G_SERDES: 777 nxgep->xcvr = nxge_10G_fiber_table; 778 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G xcvr " 779 "nxgep->nxge_hw_p->xcvr_addr[portn] = [%d] " 780 "nxgep->xcvr_addr = [%d]", 781 nxgep->nxge_hw_p->xcvr_addr[portn], 782 nxgep->xcvr_addr)); 783 if (nxgep->nxge_hw_p->xcvr_addr[portn]) { 784 nxgep->xcvr_addr = 785 nxgep->nxge_hw_p->xcvr_addr[portn]; 786 } 787 switch (nxgep->platform_type) { 788 case P_NEPTUNE_MARAMBA_P0: 789 case P_NEPTUNE_MARAMBA_P1: 790 /* 791 * Switch off LED for corresponding copper 792 * port 793 */ 794 nxge_bcm5464_link_led_off(nxgep); 795 break; 796 default: 797 break; 798 } 799 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G %s Xcvr", 800 (nxgep->mac.portmode == PORT_10G_FIBER) ? 801 "Fiber" : "Serdes")); 802 break; 803 804 case PORT_HSP_MODE: 805 nxgep->xcvr = nxge_10G_fiber_table; 806 nxgep->xcvr.xcvr_inuse = HSP_XCVR; 807 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Neptune 10G Hot " 808 "Swappable Xcvr (not present)")); 809 break; 810 default: 811 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 812 "Unknown port-type: 0x%x", port_type)); 813 return (NXGE_ERROR); 814 } 815 } 816 817 if (nxgep->mac.portmode == PORT_10G_FIBER || 818 nxgep->mac.portmode == PORT_10G_COPPER) { 819 uint32_t pma_pmd_id; 820 pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, 821 nxgep->xcvr_addr); 822 if ((pma_pmd_id & BCM_PHY_ID_MASK) == MARVELL_88X201X_PHY_ID) { 823 chip_id = MRVL88X201X_CHIP_ID; 824 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 825 "nxge_setup_xcvr_table: " 826 "Chip ID MARVELL [0x%x] for 10G xcvr", chip_id)); 827 } else if ((pma_pmd_id & NLP2020_DEV_ID_MASK) == 828 NLP2020_DEV_ID) { 829 chip_id = NLP2020_CHIP_ID; 830 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 831 "nxge_setup_xcvr_table: " 832 "Chip ID AEL2020 [0x%x] for 10G xcvr", chip_id)); 833 } else if ((status = nxge_mdio_read(nxgep, nxgep->xcvr_addr, 834 BCM8704_PCS_DEV_ADDR, BCM8704_CHIP_ID_REG, 835 &chip_id)) == NXGE_OK) { 836 837 switch (chip_id) { 838 case BCM8704_CHIP_ID: 839 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 840 "nxge_setup_xcvr_table: " 841 "Chip ID 8704 [0x%x] for 10G xcvr", 842 chip_id)); 843 break; 844 case BCM8706_CHIP_ID: 845 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 846 "nxge_setup_xcvr_table: " 847 "Chip ID 8706 [0x%x] for 10G xcvr", 848 chip_id)); 849 break; 850 default: 851 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 852 "nxge_setup_xcvr_table: " 853 "Unknown Chip ID [0x%x] for 10G xcvr", 854 chip_id)); 855 break; 856 } 857 } 858 } 859 860 nxgep->statsp->mac_stats.xcvr_inuse = nxgep->xcvr.xcvr_inuse; 861 nxgep->statsp->mac_stats.xcvr_portn = nxgep->xcvr_addr; 862 nxgep->chip_id = chip_id; 863 864 /* 865 * Get the actual device ID value returned by MDIO read. 866 */ 867 nxgep->statsp->mac_stats.xcvr_id = 0; 868 869 pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, nxgep->xcvr_addr); 870 if (nxge_is_supported_phy(pma_pmd_id, CLAUSE_45_TYPE)) { 871 nxgep->statsp->mac_stats.xcvr_id = pma_pmd_id; 872 } else { 873 pcs_id = nxge_get_cl45_pcs_id(nxgep, nxgep->xcvr_addr); 874 if (nxge_is_supported_phy(pcs_id, CLAUSE_45_TYPE)) { 875 nxgep->statsp->mac_stats.xcvr_id = pcs_id; 876 } else { 877 phy_id = nxge_get_cl22_phy_id(nxgep, 878 nxgep->xcvr_addr); 879 if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) { 880 nxgep->statsp->mac_stats.xcvr_id = phy_id; 881 } 882 } 883 } 884 885 nxgep->mac.linkchkmode = LINKCHK_TIMER; 886 887 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_setup_xcvr_table: niu_type" 888 "[0x%x] platform type[0x%x] xcvr_addr[%d]", nxgep->niu_type, 889 nxgep->platform_type, nxgep->xcvr_addr)); 890 891 return (status); 892 } 893 894 /* Initialize the entire MAC and physical layer */ 895 896 nxge_status_t 897 nxge_mac_init(p_nxge_t nxgep) 898 { 899 uint8_t portn; 900 nxge_status_t status = NXGE_OK; 901 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 902 903 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_init: port<%d>", portn)); 904 905 nxgep->mac.portnum = portn; 906 nxgep->mac.porttype = PORT_TYPE_XMAC; 907 908 if ((portn == BMAC_PORT_0) || (portn == BMAC_PORT_1)) 909 nxgep->mac.porttype = PORT_TYPE_BMAC; 910 911 912 /* Initialize XIF to configure a network mode */ 913 if ((status = nxge_xif_init(nxgep)) != NXGE_OK) { 914 goto fail; 915 } 916 917 if ((status = nxge_pcs_init(nxgep)) != NXGE_OK) { 918 goto fail; 919 } 920 921 /* Initialize TX and RX MACs */ 922 /* 923 * Always perform XIF init first, before TX and RX MAC init 924 */ 925 if ((status = nxge_tx_mac_reset(nxgep)) != NXGE_OK) 926 goto fail; 927 928 if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK) 929 goto fail; 930 931 if ((status = nxge_rx_mac_reset(nxgep)) != NXGE_OK) 932 goto fail; 933 934 if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK) 935 goto fail; 936 937 if ((status = nxge_tx_mac_enable(nxgep)) != NXGE_OK) 938 goto fail; 939 940 if (nxgep->nxge_mac_state == NXGE_MAC_STARTED) { 941 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 942 goto fail; 943 } 944 945 /* Initialize MAC control configuration */ 946 if ((status = nxge_mac_ctrl_init(nxgep)) != NXGE_OK) { 947 goto fail; 948 } 949 950 nxgep->statsp->mac_stats.mac_mtu = nxgep->mac.maxframesize; 951 952 /* The Neptune Serdes needs to be reinitialized again */ 953 if ((NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) && 954 ((nxgep->mac.portmode == PORT_1G_SERDES) || 955 (nxgep->mac.portmode == PORT_1G_TN1010) || 956 (nxgep->mac.portmode == PORT_1G_FIBER)) && 957 ((portn == 0) || (portn == 1))) { 958 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 959 "nxge_mac_init: reinit Neptune 1G Serdes ")); 960 if ((status = nxge_1G_serdes_init(nxgep)) != NXGE_OK) { 961 goto fail; 962 } 963 } 964 965 966 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_init: port<%d>", portn)); 967 968 return (NXGE_OK); 969 fail: 970 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 971 "nxge_mac_init: failed to initialize MAC port<%d>", portn)); 972 return (status); 973 } 974 975 /* Initialize the Ethernet Link */ 976 977 nxge_status_t 978 nxge_link_init(p_nxge_t nxgep) 979 { 980 nxge_status_t status = NXGE_OK; 981 nxge_port_mode_t portmode; 982 #ifdef NXGE_DEBUG 983 uint8_t portn; 984 985 portn = nxgep->mac.portnum; 986 987 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_init: port<%d>", portn)); 988 #endif 989 /* For Opus NEM, Serdes always needs to be initialized */ 990 991 portmode = nxgep->mac.portmode; 992 993 /* 994 * Workaround to get link up in both NIU ports. Some portmodes require 995 * that the xcvr be initialized twice, the first time before calling 996 * nxge_serdes_init. 997 */ 998 if (nxgep->niu_type == N2_NIU && (portmode != PORT_10G_SERDES) && 999 (portmode != PORT_10G_TN1010) && 1000 (portmode != PORT_1G_TN1010) && 1001 (portmode != PORT_1G_SERDES)) { 1002 if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK) { 1003 goto fail; 1004 } 1005 } 1006 1007 NXGE_DELAY(200000); 1008 /* Initialize internal serdes */ 1009 if ((status = nxge_serdes_init(nxgep)) != NXGE_OK) 1010 goto fail; 1011 NXGE_DELAY(200000); 1012 if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK) 1013 goto fail; 1014 1015 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_init: port<%d>", portn)); 1016 1017 return (NXGE_OK); 1018 1019 fail: 1020 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_link_init: ", 1021 "failed to initialize Ethernet link on port<%d>", portn)); 1022 1023 return (status); 1024 } 1025 1026 1027 /* Initialize the XIF sub-block within the MAC */ 1028 1029 nxge_status_t 1030 nxge_xif_init(p_nxge_t nxgep) 1031 { 1032 uint32_t xif_cfg = 0; 1033 npi_attr_t ap; 1034 uint8_t portn; 1035 nxge_port_t portt; 1036 nxge_port_mode_t portmode; 1037 p_nxge_stats_t statsp; 1038 npi_status_t rs = NPI_SUCCESS; 1039 npi_handle_t handle; 1040 1041 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 1042 1043 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xif_init: port<%d>", portn)); 1044 1045 handle = nxgep->npi_handle; 1046 portmode = nxgep->mac.portmode; 1047 portt = nxgep->mac.porttype; 1048 statsp = nxgep->statsp; 1049 1050 if ((NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) && 1051 ((nxgep->mac.portmode == PORT_1G_SERDES) || 1052 (nxgep->mac.portmode == PORT_1G_TN1010) || 1053 (nxgep->mac.portmode == PORT_1G_FIBER)) && 1054 ((portn == 0) || (portn == 1))) { 1055 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1056 "nxge_xcvr_init: set ATCA mode")); 1057 npi_mac_mif_set_atca_mode(nxgep->npi_handle, B_TRUE); 1058 } 1059 1060 if (portt == PORT_TYPE_XMAC) { 1061 1062 /* Setup XIF Configuration for XMAC */ 1063 1064 if ((portmode == PORT_10G_FIBER) || 1065 (portmode == PORT_10G_COPPER) || 1066 (portmode == PORT_10G_TN1010) || 1067 (portmode == PORT_HSP_MODE) || 1068 (portmode == PORT_10G_SERDES)) 1069 xif_cfg |= CFG_XMAC_XIF_LFS; 1070 1071 /* Bypass PCS so that RGMII will be used */ 1072 if (portmode == PORT_1G_COPPER) { 1073 xif_cfg |= CFG_XMAC_XIF_1G_PCS_BYPASS; 1074 } 1075 1076 /* Set MAC Internal Loopback if necessary */ 1077 if (statsp->port_stats.lb_mode == nxge_lb_mac1000) 1078 xif_cfg |= CFG_XMAC_XIF_LOOPBACK; 1079 1080 if (statsp->mac_stats.link_speed == 100) 1081 xif_cfg |= CFG_XMAC_XIF_SEL_CLK_25MHZ; 1082 1083 xif_cfg |= CFG_XMAC_XIF_TX_OUTPUT; 1084 1085 if ((portmode == PORT_10G_FIBER) || 1086 (portmode == PORT_10G_COPPER) || 1087 (portmode == PORT_10G_TN1010) || 1088 (portmode == PORT_1G_TN1010) || 1089 (portmode == PORT_HSP_MODE) || 1090 (portmode == PORT_10G_SERDES)) { 1091 /* Assume LED same for 1G and 10G */ 1092 if (statsp->mac_stats.link_up) { 1093 xif_cfg |= CFG_XMAC_XIF_LED_POLARITY; 1094 } else { 1095 xif_cfg |= CFG_XMAC_XIF_LED_FORCE; 1096 } 1097 } 1098 1099 rs = npi_xmac_xif_config(handle, INIT, portn, xif_cfg); 1100 if (rs != NPI_SUCCESS) 1101 goto fail; 1102 1103 nxgep->mac.xif_config = xif_cfg; 1104 1105 /* Set Port Mode */ 1106 if ((portmode == PORT_10G_FIBER) || 1107 (portmode == PORT_10G_COPPER) || 1108 (portmode == PORT_10G_TN1010) || 1109 (portmode == PORT_HSP_MODE) || 1110 (portmode == PORT_10G_SERDES)) { 1111 SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE, 1112 MAC_XGMII_MODE, rs); 1113 if (rs != NPI_SUCCESS) 1114 goto fail; 1115 if (statsp->mac_stats.link_up) { 1116 if (nxge_10g_link_led_on(nxgep) != NXGE_OK) 1117 goto fail; 1118 } else { 1119 if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 1120 goto fail; 1121 } 1122 } else if ((portmode == PORT_1G_FIBER) || 1123 (portmode == PORT_1G_COPPER) || 1124 (portmode == PORT_1G_SERDES) || 1125 (portmode == PORT_1G_TN1010) || 1126 (portmode == PORT_1G_RGMII_FIBER)) { 1127 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1128 "nxge_xif_init: Port[%d] Mode[%d] Speed[%d]", 1129 portn, portmode, statsp->mac_stats.link_speed)); 1130 if (statsp->mac_stats.link_speed == 1000) { 1131 SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE, 1132 MAC_GMII_MODE, rs); 1133 } else { 1134 SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE, 1135 MAC_MII_MODE, rs); 1136 } 1137 if (rs != NPI_SUCCESS) 1138 goto fail; 1139 } else { 1140 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1141 "nxge_xif_init: Unknown port mode (%d)" 1142 " for port<%d>", portmode, portn)); 1143 goto fail; 1144 } 1145 1146 /* Enable ATCA mode */ 1147 1148 } else if (portt == PORT_TYPE_BMAC) { 1149 1150 /* Setup XIF Configuration for BMAC */ 1151 1152 if ((portmode == PORT_1G_COPPER) || 1153 (portmode == PORT_1G_RGMII_FIBER)) { 1154 if (statsp->mac_stats.link_speed == 100) 1155 xif_cfg |= CFG_BMAC_XIF_SEL_CLK_25MHZ; 1156 } 1157 1158 if (statsp->port_stats.lb_mode == nxge_lb_mac1000) 1159 xif_cfg |= CFG_BMAC_XIF_LOOPBACK; 1160 1161 if (statsp->mac_stats.link_speed == 1000) 1162 xif_cfg |= CFG_BMAC_XIF_GMII_MODE; 1163 1164 xif_cfg |= CFG_BMAC_XIF_TX_OUTPUT; 1165 1166 rs = npi_bmac_xif_config(handle, INIT, portn, xif_cfg); 1167 if (rs != NPI_SUCCESS) 1168 goto fail; 1169 nxgep->mac.xif_config = xif_cfg; 1170 } 1171 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xif_init: port<%d>", portn)); 1172 return (NXGE_OK); 1173 fail: 1174 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1175 "nxge_xif_init: Failed to initialize XIF port<%d>", portn)); 1176 return (NXGE_ERROR | rs); 1177 } 1178 1179 1180 /* 1181 * Initialize the PCS sub-block in the MAC. Note that PCS does not 1182 * support loopback like XPCS. 1183 */ 1184 nxge_status_t 1185 nxge_pcs_init(p_nxge_t nxgep) 1186 { 1187 pcs_cfg_t pcs_cfg; 1188 uint32_t val; 1189 uint8_t portn; 1190 nxge_port_mode_t portmode; 1191 npi_handle_t handle; 1192 p_nxge_stats_t statsp; 1193 pcs_ctrl_t pcs_ctrl; 1194 npi_status_t rs = NPI_SUCCESS; 1195 uint8_t i; 1196 1197 handle = nxgep->npi_handle; 1198 portmode = nxgep->mac.portmode; 1199 portn = nxgep->mac.portnum; 1200 statsp = nxgep->statsp; 1201 1202 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_init: port<%d>", portn)); 1203 1204 if (portmode == PORT_1G_FIBER || 1205 portmode == PORT_1G_TN1010 || 1206 portmode == PORT_1G_SERDES) { 1207 if (portmode == PORT_1G_TN1010) { 1208 /* Reset PCS multiple time in PORT_1G_TN1010 mode */ 1209 for (i = 0; i < 6; i ++) { 1210 if ((rs = npi_mac_pcs_reset(handle, portn)) 1211 != NPI_SUCCESS) { 1212 goto fail; 1213 } 1214 } 1215 } else { 1216 if ((rs = npi_mac_pcs_reset(handle, portn)) 1217 != NPI_SUCCESS) 1218 goto fail; 1219 } 1220 1221 /* Initialize port's PCS */ 1222 pcs_cfg.value = 0; 1223 pcs_cfg.bits.w0.enable = 1; 1224 pcs_cfg.bits.w0.mask = 1; 1225 PCS_REG_WR(handle, portn, PCS_CONFIG_REG, pcs_cfg.value); 1226 PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG, 0); 1227 1228 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1229 "==> nxge_pcs_init: (1G) port<%d> write config 0x%llx", 1230 portn, pcs_cfg.value)); 1231 1232 if (portmode == PORT_1G_TN1010) { 1233 /* 1234 * Must disable PCS auto-negotiation when the the driver 1235 * is driving the TN1010 based XAUI card Otherwise the 1236 * autonegotiation between the PCS and the TN1010 PCS 1237 * will never complete and the Neptune/NIU will not work 1238 */ 1239 pcs_ctrl.value = 0; 1240 PCS_REG_WR(handle, portn, PCS_MII_CTRL_REG, 1241 pcs_ctrl.value); 1242 } 1243 } else if (portmode == PORT_10G_FIBER || 1244 portmode == PORT_10G_COPPER || 1245 portmode == PORT_10G_TN1010 || 1246 portmode == PORT_HSP_MODE || 1247 portmode == PORT_10G_SERDES) { 1248 /* Use internal XPCS, bypass 1G PCS */ 1249 XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val); 1250 val &= ~XMAC_XIF_XPCS_BYPASS; 1251 XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val); 1252 1253 if ((rs = npi_xmac_xpcs_reset(handle, portn)) != NPI_SUCCESS) 1254 goto fail; 1255 1256 /* Set XPCS Internal Loopback if necessary */ 1257 if ((rs = npi_xmac_xpcs_read(handle, portn, 1258 XPCS_REG_CONTROL1, &val)) != NPI_SUCCESS) 1259 goto fail; 1260 1261 if ((statsp->port_stats.lb_mode == nxge_lb_mac10g) || 1262 (statsp->port_stats.lb_mode == nxge_lb_mac1000)) 1263 val |= XPCS_CTRL1_LOOPBK; 1264 else 1265 val &= ~XPCS_CTRL1_LOOPBK; 1266 if ((rs = npi_xmac_xpcs_write(handle, portn, 1267 XPCS_REG_CONTROL1, val)) != NPI_SUCCESS) 1268 goto fail; 1269 1270 /* Clear descw errors */ 1271 if ((rs = npi_xmac_xpcs_write(handle, portn, 1272 XPCS_REG_DESCWERR_COUNTER, 0)) != NPI_SUCCESS) 1273 goto fail; 1274 /* Clear symbol errors */ 1275 if ((rs = npi_xmac_xpcs_read(handle, portn, 1276 XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val)) != NPI_SUCCESS) 1277 goto fail; 1278 if ((rs = npi_xmac_xpcs_read(handle, portn, 1279 XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val)) != NPI_SUCCESS) 1280 goto fail; 1281 1282 } else if ((portmode == PORT_1G_COPPER) || 1283 (portmode == PORT_1G_RGMII_FIBER)) { 1284 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1285 "==> nxge_pcs_init: (1G) copper port<%d>", portn)); 1286 if (portn < 4) { 1287 PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG, 1288 PCS_DATAPATH_MODE_MII); 1289 } 1290 if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS) 1291 goto fail; 1292 1293 } else { 1294 goto fail; 1295 } 1296 pass: 1297 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_init: port<%d>", portn)); 1298 return (NXGE_OK); 1299 fail: 1300 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1301 "nxge_pcs_init: Failed to initialize PCS port<%d>", portn)); 1302 return (NXGE_ERROR | rs); 1303 } 1304 1305 /* 1306 * Initialize the MAC CTRL sub-block within the MAC 1307 * Only the receive-pause-cap is supported. 1308 */ 1309 nxge_status_t 1310 nxge_mac_ctrl_init(p_nxge_t nxgep) 1311 { 1312 uint8_t portn; 1313 nxge_port_t portt; 1314 p_nxge_stats_t statsp; 1315 npi_handle_t handle; 1316 uint32_t val; 1317 1318 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 1319 1320 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_ctrl_init: port<%d>", 1321 portn)); 1322 1323 handle = nxgep->npi_handle; 1324 portt = nxgep->mac.porttype; 1325 statsp = nxgep->statsp; 1326 1327 if (portt == PORT_TYPE_XMAC) { 1328 /* Reading the current XMAC Config Register for XMAC */ 1329 XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val); 1330 1331 /* 1332 * Setup XMAC Configuration for XMAC 1333 * XMAC only supports receive-pause 1334 */ 1335 if (statsp->mac_stats.adv_cap_asmpause) { 1336 if (!statsp->mac_stats.adv_cap_pause) { 1337 /* 1338 * If adv_cap_asmpause is 1 and adv_cap_pause 1339 * is 0, enable receive pause. 1340 */ 1341 val |= XMAC_RX_CFG_RX_PAUSE_EN; 1342 } else { 1343 /* 1344 * If adv_cap_asmpause is 1 and adv_cap_pause 1345 * is 1, disable receive pause. Send pause is 1346 * not supported. 1347 */ 1348 val &= ~XMAC_RX_CFG_RX_PAUSE_EN; 1349 } 1350 } else { 1351 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1352 "==> nxge_mac_ctrl_init: port<%d>: pause", 1353 portn)); 1354 if (statsp->mac_stats.adv_cap_pause) { 1355 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1356 "==> nxge_mac_ctrl_init: port<%d>: " 1357 "enable pause", portn)); 1358 /* 1359 * If adv_cap_asmpause is 0 and adv_cap_pause 1360 * is 1, enable receive pause. 1361 */ 1362 val |= XMAC_RX_CFG_RX_PAUSE_EN; 1363 } else { 1364 /* 1365 * If adv_cap_asmpause is 0 and adv_cap_pause 1366 * is 0, disable receive pause. Send pause is 1367 * not supported 1368 */ 1369 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1370 "==> nxge_mac_ctrl_init: port<%d>: " 1371 "disable pause", portn)); 1372 val &= ~XMAC_RX_CFG_RX_PAUSE_EN; 1373 } 1374 } 1375 XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val); 1376 } else if (portt == PORT_TYPE_BMAC) { 1377 /* Reading the current MAC CTRL Config Register for BMAC */ 1378 BMAC_REG_RD(handle, portn, MAC_CTRL_CONFIG_REG, &val); 1379 1380 /* Setup MAC CTRL Configuration for BMAC */ 1381 if (statsp->mac_stats.adv_cap_asmpause) { 1382 if (statsp->mac_stats.adv_cap_pause) { 1383 /* 1384 * If adv_cap_asmpause is 1 and adv_cap_pause 1385 * is 1, disable receive pause. Send pause 1386 * is not supported 1387 */ 1388 val &= ~MAC_CTRL_CFG_RECV_PAUSE_EN; 1389 } else { 1390 /* 1391 * If adv_cap_asmpause is 1 and adv_cap_pause 1392 * is 0, enable receive pause and disable 1393 * send pause. 1394 */ 1395 val |= MAC_CTRL_CFG_RECV_PAUSE_EN; 1396 val &= ~MAC_CTRL_CFG_SEND_PAUSE_EN; 1397 } 1398 } else { 1399 if (statsp->mac_stats.adv_cap_pause) { 1400 /* 1401 * If adv_cap_asmpause is 0 and adv_cap_pause 1402 * is 1, enable receive pause. Send pause is 1403 * not supported. 1404 */ 1405 val |= MAC_CTRL_CFG_RECV_PAUSE_EN; 1406 } else { 1407 /* 1408 * If adv_cap_asmpause is 0 and adv_cap_pause 1409 * is 0, pause capability is not available in 1410 * either direction. 1411 */ 1412 val &= (~MAC_CTRL_CFG_SEND_PAUSE_EN & 1413 ~MAC_CTRL_CFG_RECV_PAUSE_EN); 1414 } 1415 } 1416 BMAC_REG_WR(handle, portn, MAC_CTRL_CONFIG_REG, val); 1417 } 1418 1419 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_ctrl_init: port<%d>", 1420 portn)); 1421 1422 return (NXGE_OK); 1423 } 1424 1425 /* Initialize the Internal Serdes */ 1426 1427 nxge_status_t 1428 nxge_serdes_init(p_nxge_t nxgep) 1429 { 1430 p_nxge_stats_t statsp; 1431 #ifdef NXGE_DEBUG 1432 uint8_t portn; 1433 #endif 1434 nxge_status_t status = NXGE_OK; 1435 1436 #ifdef NXGE_DEBUG 1437 portn = nxgep->mac.portnum; 1438 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1439 "==> nxge_serdes_init port<%d>", portn)); 1440 #endif 1441 1442 if (nxgep->xcvr.serdes_init) { 1443 statsp = nxgep->statsp; 1444 status = nxgep->xcvr.serdes_init(nxgep); 1445 if (status != NXGE_OK) 1446 goto fail; 1447 statsp->mac_stats.serdes_inits++; 1448 } 1449 1450 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_serdes_init port<%d>", 1451 portn)); 1452 1453 return (NXGE_OK); 1454 1455 fail: 1456 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1457 "nxge_serdes_init: Failed to initialize serdes for port<%d>", 1458 portn)); 1459 1460 return (status); 1461 } 1462 1463 /* Initialize the TI Hedwig Internal Serdes (N2-NIU only) */ 1464 1465 static nxge_status_t 1466 nxge_n2_serdes_init(p_nxge_t nxgep) 1467 { 1468 uint8_t portn; 1469 int chan; 1470 esr_ti_cfgpll_l_t pll_cfg_l; 1471 esr_ti_cfgpll_l_t pll_sts_l; 1472 esr_ti_cfgrx_l_t rx_cfg_l; 1473 esr_ti_cfgrx_h_t rx_cfg_h; 1474 esr_ti_cfgtx_l_t tx_cfg_l; 1475 esr_ti_cfgtx_h_t tx_cfg_h; 1476 #ifdef NXGE_DEBUG 1477 esr_ti_testcfg_t cfg; 1478 #endif 1479 esr_ti_testcfg_t test_cfg; 1480 nxge_status_t status = NXGE_OK; 1481 1482 portn = nxgep->mac.portnum; 1483 1484 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_n2_serdes_init port<%d>", 1485 portn)); 1486 if (nxgep->niu_hw_type == NIU_HW_TYPE_RF) { 1487 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1488 "==> nxge_n2_serdes_init port<%d>: KT-NIU", portn)); 1489 return (nxge_n2_kt_serdes_init(nxgep)); 1490 } 1491 1492 tx_cfg_l.value = 0; 1493 tx_cfg_h.value = 0; 1494 rx_cfg_l.value = 0; 1495 rx_cfg_h.value = 0; 1496 pll_cfg_l.value = 0; 1497 pll_sts_l.value = 0; 1498 test_cfg.value = 0; 1499 1500 /* 1501 * If the nxge driver has been plumbed without a link, then it will 1502 * detect a link up when a cable connecting to an anto-negotiation 1503 * partner is plugged into the port. Because the TN1010 PHY supports 1504 * both 1G and 10G speeds, the driver must re-configure the 1505 * Neptune/NIU according to the negotiated speed. nxge_n2_serdes_init 1506 * is called at the post-link-up reconfiguration time. Here it calls 1507 * nxge_set_tn1010_param to set portmode before re-initializing 1508 * the serdes. 1509 */ 1510 if (nxgep->mac.portmode == PORT_1G_TN1010 || 1511 nxgep->mac.portmode == PORT_10G_TN1010) { 1512 if (nxge_set_tn1010_param(nxgep) != NXGE_OK) { 1513 goto fail; 1514 } 1515 } 1516 1517 if (nxgep->mac.portmode == PORT_10G_FIBER || 1518 nxgep->mac.portmode == PORT_10G_COPPER || 1519 nxgep->mac.portmode == PORT_10G_TN1010 || 1520 nxgep->mac.portmode == PORT_HSP_MODE || 1521 nxgep->mac.portmode == PORT_10G_SERDES) { 1522 /* 0x0E01 */ 1523 tx_cfg_l.bits.entx = 1; 1524 tx_cfg_l.bits.swing = CFGTX_SWING_1375MV; 1525 1526 /* 0x9101 */ 1527 rx_cfg_l.bits.enrx = 1; 1528 rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT; 1529 rx_cfg_l.bits.align = CFGRX_ALIGN_EN; 1530 rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES; 1531 1532 /* 0x0008 */ 1533 rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF; 1534 1535 /* Set loopback mode if necessary */ 1536 if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) { 1537 tx_cfg_l.bits.entest = 1; 1538 rx_cfg_l.bits.entest = 1; 1539 test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK; 1540 if ((status = nxge_mdio_write(nxgep, portn, 1541 ESR_N2_DEV_ADDR, 1542 ESR_N2_TEST_CFG_REG, test_cfg.value)) != NXGE_OK) 1543 goto fail; 1544 } 1545 1546 /* Initialize PLL for 10G */ 1547 pll_cfg_l.bits.mpy = CFGPLL_MPY_10X; 1548 pll_cfg_l.bits.enpll = 1; 1549 pll_sts_l.bits.enpll = 1; 1550 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 1551 ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value)) != NXGE_OK) 1552 goto fail; 1553 1554 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 1555 ESR_N2_PLL_STS_L_REG, pll_sts_l.value)) != NXGE_OK) 1556 goto fail; 1557 1558 #ifdef NXGE_DEBUG 1559 nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR, 1560 ESR_N2_PLL_CFG_L_REG, &cfg.value); 1561 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1562 "==> nxge_n2_serdes_init port<%d>: PLL cfg.l 0x%x (0x%x)", 1563 portn, pll_cfg_l.value, cfg.value)); 1564 1565 nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR, 1566 ESR_N2_PLL_STS_L_REG, &cfg.value); 1567 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1568 "==> nxge_n2_serdes_init port<%d>: PLL sts.l 0x%x (0x%x)", 1569 portn, pll_sts_l.value, cfg.value)); 1570 #endif 1571 } else if (nxgep->mac.portmode == PORT_1G_FIBER || 1572 nxgep->mac.portmode == PORT_1G_TN1010 || 1573 nxgep->mac.portmode == PORT_1G_SERDES) { 1574 /* 0x0E21 */ 1575 tx_cfg_l.bits.entx = 1; 1576 tx_cfg_l.bits.rate = CFGTX_RATE_HALF; 1577 tx_cfg_l.bits.swing = CFGTX_SWING_1375MV; 1578 1579 /* 0x9121 */ 1580 rx_cfg_l.bits.enrx = 1; 1581 rx_cfg_l.bits.rate = CFGRX_RATE_HALF; 1582 rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT; 1583 rx_cfg_l.bits.align = CFGRX_ALIGN_EN; 1584 rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES; 1585 1586 if (portn == 0) { 1587 /* 0x8 */ 1588 rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF; 1589 } 1590 1591 /* Initialize PLL for 1G */ 1592 pll_cfg_l.bits.mpy = CFGPLL_MPY_8X; 1593 pll_cfg_l.bits.enpll = 1; 1594 pll_sts_l.bits.enpll = 1; 1595 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 1596 ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value)) != NXGE_OK) 1597 goto fail; 1598 1599 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 1600 ESR_N2_PLL_STS_L_REG, pll_sts_l.value)) != NXGE_OK) 1601 goto fail; 1602 1603 #ifdef NXGE_DEBUG 1604 nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR, 1605 ESR_N2_PLL_CFG_L_REG, &cfg.value); 1606 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1607 "==> nxge_n2_serdes_init port<%d>: PLL cfg.l 0x%x (0x%x)", 1608 portn, pll_cfg_l.value, cfg.value)); 1609 1610 nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR, 1611 ESR_N2_PLL_STS_L_REG, &cfg.value); 1612 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1613 "==> nxge_n2_serdes_init port<%d>: PLL sts.l 0x%x (0x%x)", 1614 portn, pll_sts_l.value, cfg.value)); 1615 #endif 1616 1617 /* Set loopback mode if necessary */ 1618 if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) { 1619 tx_cfg_l.bits.entest = 1; 1620 rx_cfg_l.bits.entest = 1; 1621 test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK; 1622 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1623 "==> nxge_n2_serdes_init port<%d>: loopback 0x%x", 1624 portn, test_cfg.value)); 1625 if ((status = nxge_mdio_write(nxgep, portn, 1626 ESR_N2_DEV_ADDR, 1627 ESR_N2_TEST_CFG_REG, test_cfg.value)) != NXGE_OK) { 1628 goto fail; 1629 } 1630 } 1631 } else { 1632 goto fail; 1633 } 1634 1635 /* MIF_REG_WR(handle, MIF_MASK_REG, ~mask); */ 1636 1637 NXGE_DELAY(20); 1638 1639 /* init TX channels */ 1640 for (chan = 0; chan < 4; chan++) { 1641 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 1642 ESR_N2_TX_CFG_L_REG_ADDR(chan), tx_cfg_l.value)) != NXGE_OK) 1643 goto fail; 1644 1645 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 1646 ESR_N2_TX_CFG_H_REG_ADDR(chan), tx_cfg_h.value)) != NXGE_OK) 1647 goto fail; 1648 1649 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1650 "==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_l 0x%x", 1651 portn, chan, tx_cfg_l.value)); 1652 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1653 "==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_h 0x%x", 1654 portn, chan, tx_cfg_h.value)); 1655 } 1656 1657 /* init RX channels */ 1658 for (chan = 0; chan < 4; chan++) { 1659 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 1660 ESR_N2_RX_CFG_L_REG_ADDR(chan), rx_cfg_l.value)) != NXGE_OK) 1661 goto fail; 1662 1663 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 1664 ESR_N2_RX_CFG_H_REG_ADDR(chan), rx_cfg_h.value)) != NXGE_OK) 1665 goto fail; 1666 1667 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1668 "==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_l 0x%x", 1669 portn, chan, rx_cfg_l.value)); 1670 1671 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1672 "==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_h 0x%x", 1673 portn, chan, rx_cfg_h.value)); 1674 } 1675 1676 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_n2_serdes_init port<%d>", 1677 portn)); 1678 1679 return (NXGE_OK); 1680 fail: 1681 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1682 "nxge_n2_serdes_init: Failed to initialize N2 serdes for port<%d>", 1683 portn)); 1684 1685 return (status); 1686 1687 } 1688 1689 /* Initialize the TI Hedwig Internal Serdes (N2-KT-NIU only) */ 1690 1691 static nxge_status_t 1692 nxge_n2_kt_serdes_init(p_nxge_t nxgep) 1693 { 1694 uint8_t portn; 1695 int chan, i; 1696 k_esr_ti_cfgpll_l_t pll_cfg_l; 1697 k_esr_ti_cfgrx_l_t rx_cfg_l; 1698 k_esr_ti_cfgrx_h_t rx_cfg_h; 1699 k_esr_ti_cfgtx_l_t tx_cfg_l; 1700 k_esr_ti_cfgtx_h_t tx_cfg_h; 1701 #ifdef NXGE_DEBUG 1702 k_esr_ti_testcfg_t cfg; 1703 #endif 1704 k_esr_ti_testcfg_t test_cfg; 1705 nxge_status_t status = NXGE_OK; 1706 boolean_t mode_1g = B_FALSE; 1707 uint64_t val; 1708 npi_handle_t handle; 1709 1710 portn = nxgep->mac.portnum; 1711 1712 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1713 "==> nxge_n2_kt_serdes_init port<%d>", portn)); 1714 handle = nxgep->npi_handle; 1715 1716 tx_cfg_l.value = 0; 1717 tx_cfg_h.value = 0; 1718 rx_cfg_l.value = 0; 1719 rx_cfg_h.value = 0; 1720 pll_cfg_l.value = 0; 1721 test_cfg.value = 0; 1722 1723 /* 1724 * The following setting assumes the reference clock frquency 1725 * is 156.25 MHz. 1726 */ 1727 /* 1728 * If the nxge driver has been plumbed without a link, then it will 1729 * detect a link up when a cable connecting to an anto-negotiation 1730 * partner is plugged into the port. Because the TN1010 PHY supports 1731 * both 1G and 10G speeds, the driver must re-configure the 1732 * Neptune/NIU according to the negotiated speed. nxge_n2_serdes_init 1733 * is called at the post-link-up reconfiguration time. Here it calls 1734 * nxge_set_tn1010_param to set portmode before re-initializing 1735 * the serdes. 1736 */ 1737 if (nxgep->mac.portmode == PORT_1G_TN1010 || 1738 nxgep->mac.portmode == PORT_10G_TN1010) { 1739 if (nxge_set_tn1010_param(nxgep) != NXGE_OK) { 1740 goto fail; 1741 } 1742 } 1743 if (nxgep->mac.portmode == PORT_10G_FIBER || 1744 nxgep->mac.portmode == PORT_10G_COPPER || 1745 nxgep->mac.portmode == PORT_10G_TN1010 || 1746 nxgep->mac.portmode == PORT_10G_SERDES) { 1747 1748 /* Take tunables from OBP if present, otherwise use defaults */ 1749 if (nxgep->srds_prop.prop_set & NXGE_SRDS_TXCFGL) { 1750 tx_cfg_l.value = nxgep->srds_prop.tx_cfg_l; 1751 } else { 1752 tx_cfg_l.bits.entx = K_CFGTX_ENABLE_TX; 1753 /* 0x1e21 */ 1754 tx_cfg_l.bits.swing = K_CFGTX_SWING_2000MV; 1755 tx_cfg_l.bits.rate = K_CFGTX_RATE_HALF; 1756 } 1757 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1758 "==> nxge_n2_kt_serdes_init port<%d> tx_cfg_l 0x%x", 1759 portn, tx_cfg_l.value)); 1760 1761 if (nxgep->srds_prop.prop_set & NXGE_SRDS_TXCFGH) { 1762 tx_cfg_h.value = nxgep->srds_prop.tx_cfg_h; 1763 } else { 1764 /* channel 0: enable syn. master */ 1765 /* 0x40 */ 1766 tx_cfg_h.bits.msync = K_CFGTX_ENABLE_MSYNC; 1767 } 1768 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1769 "==> nxge_n2_kt_serdes_init port<%d> tx_cfg_h 0x%x", 1770 portn, tx_cfg_h.value)); 1771 1772 if (nxgep->srds_prop.prop_set & NXGE_SRDS_RXCFGL) { 1773 rx_cfg_l.value = nxgep->srds_prop.rx_cfg_l; 1774 } else { 1775 /* 0x4821 */ 1776 rx_cfg_l.bits.enrx = K_CFGRX_ENABLE_RX; 1777 rx_cfg_l.bits.rate = K_CFGRX_RATE_HALF; 1778 rx_cfg_l.bits.align = K_CFGRX_ALIGN_EN; 1779 rx_cfg_l.bits.los = K_CFGRX_LOS_ENABLE; 1780 } 1781 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1782 "==> nxge_n2_kt_serdes_init port<%d> rx_cfg_l 0x%x", 1783 portn, rx_cfg_l.value)); 1784 1785 if (nxgep->srds_prop.prop_set & NXGE_SRDS_RXCFGH) { 1786 rx_cfg_h.value = nxgep->srds_prop.rx_cfg_h; 1787 } else { 1788 /* 0x0008 */ 1789 rx_cfg_h.bits.eq = K_CFGRX_EQ_ADAPTIVE; 1790 } 1791 1792 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1793 "==> nxge_n2_kt_serdes_init port<%d> rx_cfg_h 0x%x", 1794 portn, rx_cfg_h.value)); 1795 1796 if (nxgep->srds_prop.prop_set & NXGE_SRDS_PLLCFGL) { 1797 pll_cfg_l.value = nxgep->srds_prop.pll_cfg_l; 1798 } else { 1799 /* 0xa1: Initialize PLL for 10G */ 1800 pll_cfg_l.bits.mpy = K_CFGPLL_MPY_20X; 1801 pll_cfg_l.bits.enpll = K_CFGPLL_ENABLE_PLL; 1802 } 1803 1804 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1805 "==> nxge_n2_kt_serdes_init port<%d> pll_cfg_l 0x%x", 1806 portn, pll_cfg_l.value)); 1807 1808 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 1809 ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value)) != NXGE_OK) 1810 goto fail; 1811 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1812 "==> nxge_n2_kt_serdes_init port<%d> pll_cfg_l 0x%x", 1813 portn, pll_cfg_l.value)); 1814 1815 /* Set loopback mode if necessary */ 1816 if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) { 1817 tx_cfg_h.bits.loopback = K_CFGTX_INNER_CML_ENA_LOOPBACK; 1818 rx_cfg_h.bits.loopback = K_CFGTX_INNER_CML_ENA_LOOPBACK; 1819 rx_cfg_l.bits.los = 0; 1820 1821 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1822 "==> nxge_n2_kt_serdes_init port<%d>: " 1823 "loopback 0x%x", portn, tx_cfg_h.value)); 1824 } 1825 #ifdef NXGE_DEBUG 1826 nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR, 1827 ESR_N2_PLL_CFG_L_REG, &cfg.value); 1828 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1829 "==> nxge_n2_kt_serdes_init port<%d>: " 1830 "PLL cfg.l 0x%x (0x%x)", 1831 portn, pll_cfg_l.value, cfg.value)); 1832 1833 nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR, 1834 ESR_N2_PLL_STS_L_REG, &cfg.value); 1835 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1836 "==> nxge_n2_kt_serdes_init port<%d>: (0x%x)", 1837 portn, cfg.value)); 1838 #endif 1839 } else if (nxgep->mac.portmode == PORT_1G_FIBER || 1840 nxgep->mac.portmode == PORT_1G_TN1010 || 1841 nxgep->mac.portmode == PORT_1G_SERDES) { 1842 mode_1g = B_TRUE; 1843 /* 0x1e41 */ 1844 tx_cfg_l.bits.entx = 1; 1845 tx_cfg_l.bits.rate = K_CFGTX_RATE_HALF; 1846 tx_cfg_l.bits.swing = K_CFGTX_SWING_2000MV; 1847 1848 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1849 "==> nxge_n2_kt_serdes_init port<%d> tx_cfg_l 0x%x", 1850 portn, tx_cfg_l.value)); 1851 1852 1853 /* channel 0: enable syn. master */ 1854 tx_cfg_h.bits.msync = K_CFGTX_ENABLE_MSYNC; 1855 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1856 "==> nxge_n2_kt_serdes_init port<%d> tx_cfg_h 0x%x", 1857 portn, tx_cfg_h.value)); 1858 1859 1860 /* 0x4841 */ 1861 rx_cfg_l.bits.enrx = 1; 1862 rx_cfg_l.bits.rate = K_CFGRX_RATE_HALF; 1863 rx_cfg_l.bits.align = K_CFGRX_ALIGN_EN; 1864 rx_cfg_l.bits.los = K_CFGRX_LOS_ENABLE; 1865 1866 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1867 "==> nxge_n2_kt_serdes_init port<%d> rx_cfg_l 0x%x", 1868 portn, rx_cfg_l.value)); 1869 1870 /* 0x0008 */ 1871 rx_cfg_h.bits.eq = K_CFGRX_EQ_ADAPTIVE_LF_365MHZ_ZF; 1872 1873 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1874 "==> nxge_n2_kt_serdes_init port<%d> tx_cfg_h 0x%x", 1875 portn, rx_cfg_h.value)); 1876 1877 /* 0xa1: Initialize PLL for 1G */ 1878 pll_cfg_l.bits.mpy = K_CFGPLL_MPY_20X; 1879 pll_cfg_l.bits.enpll = K_CFGPLL_ENABLE_PLL; 1880 1881 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1882 "==> nxge_n2_kt_serdes_init port<%d> pll_cfg_l 0x%x", 1883 portn, pll_cfg_l.value)); 1884 1885 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 1886 ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value)) 1887 != NXGE_OK) 1888 goto fail; 1889 1890 1891 #ifdef NXGE_DEBUG 1892 nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR, 1893 ESR_N2_PLL_CFG_L_REG, &cfg.value); 1894 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1895 "==> nxge_n2_serdes_init port<%d>: PLL cfg.l 0x%x (0x%x)", 1896 portn, pll_cfg_l.value, cfg.value)); 1897 1898 nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR, 1899 ESR_N2_PLL_STS_L_REG, &cfg.value); 1900 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1901 "==> nxge_n2_kt_serdes_init port<%d>: (0x%x)", 1902 portn, cfg.value)); 1903 #endif 1904 1905 /* Set loopback mode if necessary */ 1906 if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) { 1907 tx_cfg_h.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK; 1908 1909 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1910 "==> nxge_n2_kt_serdes_init port<%d>: " 1911 "loopback 0x%x", portn, test_cfg.value)); 1912 if ((status = nxge_mdio_write(nxgep, portn, 1913 ESR_N2_DEV_ADDR, 1914 ESR_N2_TX_CFG_L_REG_ADDR(0), 1915 tx_cfg_h.value)) != NXGE_OK) { 1916 goto fail; 1917 } 1918 } 1919 } else { 1920 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1921 "nxge_n2_kt_serdes_init:port<%d> - " 1922 "unsupported port mode %d", 1923 portn, nxgep->mac.portmode)); 1924 goto fail; 1925 } 1926 1927 NXGE_DELAY(20); 1928 /* Clear the test register (offset 0x8004) */ 1929 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 1930 ESR_N2_TEST_CFG_REG, test_cfg.value)) != NXGE_OK) { 1931 goto fail; 1932 } 1933 NXGE_DELAY(20); 1934 1935 /* init TX channels */ 1936 for (chan = 0; chan < 4; chan++) { 1937 if (mode_1g) 1938 tx_cfg_l.value = 0; 1939 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 1940 ESR_N2_TX_CFG_L_REG_ADDR(chan), tx_cfg_l.value)) != NXGE_OK) 1941 goto fail; 1942 1943 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 1944 ESR_N2_TX_CFG_H_REG_ADDR(chan), tx_cfg_h.value)) != NXGE_OK) 1945 goto fail; 1946 1947 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1948 "==> nxge_n2_kt_serdes_init port<%d>: " 1949 "chan %d tx_cfg_l 0x%x", portn, chan, tx_cfg_l.value)); 1950 1951 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1952 "==> nxge_n2_kt_serdes_init port<%d>: " 1953 "chan %d tx_cfg_h 0x%x", portn, chan, tx_cfg_h.value)); 1954 } 1955 1956 /* init RX channels */ 1957 /* 1G mode only write to the first channel */ 1958 for (chan = 0; chan < 4; chan++) { 1959 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 1960 ESR_N2_RX_CFG_L_REG_ADDR(chan), rx_cfg_l.value)) 1961 != NXGE_OK) 1962 goto fail; 1963 1964 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 1965 ESR_N2_RX_CFG_H_REG_ADDR(chan), rx_cfg_h.value)) 1966 != NXGE_OK) 1967 goto fail; 1968 1969 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1970 "==> nxge_n2_kt_serdes_init port<%d>: " 1971 "chan %d rx_cfg_l 0x%x", portn, chan, rx_cfg_l.value)); 1972 1973 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1974 "==> nxge_n2_kt_serdes_init port<%d>: " 1975 "chan %d rx_cfg_h 0x%x", portn, chan, rx_cfg_h.value)); 1976 } 1977 1978 if (portn == 0) { 1979 /* Wait for serdes to be ready */ 1980 for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) { 1981 ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val); 1982 if ((val & ESR_SIG_P0_BITS_MASK) != 1983 (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0 | 1984 ESR_SIG_XSERDES_RDY_P0 | 1985 ESR_SIG_XDETECT_P0_CH3 | 1986 ESR_SIG_XDETECT_P0_CH2 | 1987 ESR_SIG_XDETECT_P0_CH1 | 1988 ESR_SIG_XDETECT_P0_CH0)) 1989 1990 NXGE_DELAY(SERDES_RDY_WT_INTERVAL); 1991 else 1992 break; 1993 } 1994 1995 if (i == MAX_SERDES_RDY_RETRIES) { 1996 /* 1997 * RDY signal stays low may due to the absent of the 1998 * external PHY, it is not an error condition. 1999 * But still print the message for the debugging 2000 * purpose when link stays down 2001 */ 2002 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2003 "nxge_n2_kt_serdes_init: " 2004 "Serdes/signal for port<%d> not ready", portn)); 2005 goto done; 2006 } 2007 } else if (portn == 1) { 2008 /* Wait for serdes to be ready */ 2009 for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) { 2010 ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val); 2011 if ((val & ESR_SIG_P1_BITS_MASK) != 2012 (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1 | 2013 ESR_SIG_XSERDES_RDY_P1 | 2014 ESR_SIG_XDETECT_P1_CH3 | 2015 ESR_SIG_XDETECT_P1_CH2 | 2016 ESR_SIG_XDETECT_P1_CH1 | 2017 ESR_SIG_XDETECT_P1_CH0)) 2018 2019 NXGE_DELAY(SERDES_RDY_WT_INTERVAL); 2020 else 2021 break; 2022 } 2023 2024 if (i == MAX_SERDES_RDY_RETRIES) { 2025 /* 2026 * RDY signal stays low may due to the absent of the 2027 * external PHY, it is not an error condition. 2028 * But still print the message for the debugging 2029 * purpose when link stays down 2030 */ 2031 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2032 "nxge_n2_kt_serdes_init: " 2033 "Serdes/signal for port<%d> not ready", portn)); 2034 goto done; 2035 } 2036 } 2037 done: 2038 2039 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2040 "<== nxge_n2_kt_serdes_init port<%d>", portn)); 2041 2042 return (NXGE_OK); 2043 fail: 2044 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2045 "nxge_n2_serdes_init: Failed to initialize N2 serdes for port<%d>", 2046 portn)); 2047 2048 return (status); 2049 } 2050 2051 /* Initialize the Neptune Internal Serdes for 10G (Neptune only) */ 2052 2053 static nxge_status_t 2054 nxge_neptune_10G_serdes_init(p_nxge_t nxgep) 2055 { 2056 npi_handle_t handle; 2057 uint8_t portn; 2058 int chan, i; 2059 sr_rx_tx_ctrl_l_t rx_tx_ctrl_l; 2060 sr_rx_tx_ctrl_h_t rx_tx_ctrl_h; 2061 sr_glue_ctrl0_l_t glue_ctrl0_l; 2062 sr_glue_ctrl0_h_t glue_ctrl0_h; 2063 uint64_t val; 2064 uint16_t val16l; 2065 uint16_t val16h; 2066 nxge_status_t status = NXGE_OK; 2067 2068 portn = nxgep->mac.portnum; 2069 2070 if ((portn != 0) && (portn != 1)) 2071 return (NXGE_OK); 2072 2073 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2074 "==> nxge_neptune_10G_serdes_init port<%d>", portn)); 2075 handle = nxgep->npi_handle; 2076 switch (portn) { 2077 case 0: 2078 /* Reset Serdes */ 2079 ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0); 2080 NXGE_DELAY(20); 2081 ESR_REG_WR(handle, ESR_RESET_REG, 0x0); 2082 NXGE_DELAY(2000); 2083 2084 /* Configure Serdes to 10G mode */ 2085 ESR_REG_WR(handle, ESR_0_PLL_CONFIG_REG, 2086 ESR_PLL_CFG_10G_SERDES); 2087 2088 ESR_REG_WR(handle, ESR_0_CONTROL_REG, 2089 ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 | 2090 ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 | 2091 (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) | 2092 (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) | 2093 (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) | 2094 (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 2095 (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 2096 (0x1 << ESR_CTL_LOSADJ_0_SHIFT) | 2097 (0x1 << ESR_CTL_LOSADJ_1_SHIFT) | 2098 (0x1 << ESR_CTL_LOSADJ_2_SHIFT) | 2099 (0x1 << ESR_CTL_LOSADJ_3_SHIFT)); 2100 2101 /* Set Serdes0 Internal Loopback if necessary */ 2102 if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) { 2103 ESR_REG_WR(handle, 2104 ESR_0_TEST_CONFIG_REG, 2105 ESR_PAD_LOOPBACK_CH3 | 2106 ESR_PAD_LOOPBACK_CH2 | 2107 ESR_PAD_LOOPBACK_CH1 | 2108 ESR_PAD_LOOPBACK_CH0); 2109 } else { 2110 ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0); 2111 } 2112 break; 2113 case 1: 2114 /* Reset Serdes */ 2115 ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_1); 2116 NXGE_DELAY(20); 2117 ESR_REG_WR(handle, ESR_RESET_REG, 0x0); 2118 NXGE_DELAY(2000); 2119 2120 /* Configure Serdes to 10G mode */ 2121 ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG, 2122 ESR_PLL_CFG_10G_SERDES); 2123 2124 ESR_REG_WR(handle, ESR_1_CONTROL_REG, 2125 ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 | 2126 ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 | 2127 (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) | 2128 (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) | 2129 (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) | 2130 (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 2131 (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 2132 (0x1 << ESR_CTL_LOSADJ_0_SHIFT) | 2133 (0x1 << ESR_CTL_LOSADJ_1_SHIFT) | 2134 (0x1 << ESR_CTL_LOSADJ_2_SHIFT) | 2135 (0x1 << ESR_CTL_LOSADJ_3_SHIFT)); 2136 2137 /* Set Serdes1 Internal Loopback if necessary */ 2138 if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) { 2139 ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 2140 ESR_PAD_LOOPBACK_CH3 | ESR_PAD_LOOPBACK_CH2 | 2141 ESR_PAD_LOOPBACK_CH1 | ESR_PAD_LOOPBACK_CH0); 2142 } else { 2143 ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0); 2144 } 2145 break; 2146 default: 2147 /* Nothing to do here */ 2148 goto done; 2149 } 2150 2151 /* init TX RX channels */ 2152 for (chan = 0; chan < 4; chan++) { 2153 if ((status = nxge_mdio_read(nxgep, portn, 2154 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 2155 &rx_tx_ctrl_l.value)) != NXGE_OK) 2156 goto fail; 2157 if ((status = nxge_mdio_read(nxgep, portn, 2158 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 2159 &rx_tx_ctrl_h.value)) != NXGE_OK) 2160 goto fail; 2161 if ((status = nxge_mdio_read(nxgep, portn, 2162 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 2163 &glue_ctrl0_l.value)) != NXGE_OK) 2164 goto fail; 2165 if ((status = nxge_mdio_read(nxgep, portn, 2166 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 2167 &glue_ctrl0_h.value)) != NXGE_OK) 2168 goto fail; 2169 rx_tx_ctrl_l.bits.enstretch = 1; 2170 rx_tx_ctrl_h.bits.vmuxlo = 2; 2171 rx_tx_ctrl_h.bits.vpulselo = 2; 2172 glue_ctrl0_l.bits.rxlosenable = 1; 2173 glue_ctrl0_l.bits.samplerate = 0xF; 2174 glue_ctrl0_l.bits.thresholdcount = 0xFF; 2175 glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES; 2176 if ((status = nxge_mdio_write(nxgep, portn, 2177 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 2178 rx_tx_ctrl_l.value)) != NXGE_OK) 2179 goto fail; 2180 if ((status = nxge_mdio_write(nxgep, portn, 2181 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 2182 rx_tx_ctrl_h.value)) != NXGE_OK) 2183 goto fail; 2184 if ((status = nxge_mdio_write(nxgep, portn, 2185 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 2186 glue_ctrl0_l.value)) != NXGE_OK) 2187 goto fail; 2188 if ((status = nxge_mdio_write(nxgep, portn, 2189 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 2190 glue_ctrl0_h.value)) != NXGE_OK) 2191 goto fail; 2192 } 2193 2194 /* Apply Tx core reset */ 2195 if ((status = nxge_mdio_write(nxgep, portn, 2196 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), 2197 (uint16_t)0)) != NXGE_OK) 2198 goto fail; 2199 2200 if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2201 ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) != 2202 NXGE_OK) 2203 goto fail; 2204 2205 NXGE_DELAY(200); 2206 2207 /* Apply Rx core reset */ 2208 if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2209 ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) != 2210 NXGE_OK) 2211 goto fail; 2212 2213 NXGE_DELAY(200); 2214 if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2215 ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK) 2216 goto fail; 2217 2218 NXGE_DELAY(200); 2219 if ((status = nxge_mdio_read(nxgep, portn, 2220 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), 2221 &val16l)) != NXGE_OK) 2222 goto fail; 2223 if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2224 ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK) 2225 goto fail; 2226 if ((val16l != 0) || (val16h != 0)) { 2227 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2228 "Failed to reset port<%d> XAUI Serdes " 2229 "(val16l 0x%x val16h 0x%x)", 2230 portn, val16l, val16h)); 2231 } 2232 2233 if (portn == 0) { 2234 /* Wait for serdes to be ready */ 2235 for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) { 2236 ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val); 2237 if ((val & ESR_SIG_P0_BITS_MASK) != 2238 (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0 | 2239 ESR_SIG_XSERDES_RDY_P0 | 2240 ESR_SIG_XDETECT_P0_CH3 | 2241 ESR_SIG_XDETECT_P0_CH2 | 2242 ESR_SIG_XDETECT_P0_CH1 | 2243 ESR_SIG_XDETECT_P0_CH0)) 2244 2245 NXGE_DELAY(SERDES_RDY_WT_INTERVAL); 2246 else 2247 break; 2248 } 2249 2250 if (i == MAX_SERDES_RDY_RETRIES) { 2251 /* 2252 * RDY signal stays low may due to the absent of the 2253 * external PHY, it is not an error condition. But still 2254 * print the message for the debugging purpose when link 2255 * stays down 2256 */ 2257 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2258 "nxge_neptune_10G_serdes_init: " 2259 "Serdes/signal for port<%d> not ready", portn)); 2260 goto done; 2261 } 2262 } else if (portn == 1) { 2263 /* Wait for serdes to be ready */ 2264 for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) { 2265 ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val); 2266 if ((val & ESR_SIG_P1_BITS_MASK) != 2267 (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1 | 2268 ESR_SIG_XSERDES_RDY_P1 | 2269 ESR_SIG_XDETECT_P1_CH3 | 2270 ESR_SIG_XDETECT_P1_CH2 | 2271 ESR_SIG_XDETECT_P1_CH1 | 2272 ESR_SIG_XDETECT_P1_CH0)) 2273 2274 NXGE_DELAY(SERDES_RDY_WT_INTERVAL); 2275 else 2276 break; 2277 } 2278 2279 if (i == MAX_SERDES_RDY_RETRIES) { 2280 /* 2281 * RDY signal stays low may due to the absent of the 2282 * external PHY, it is not an error condition. But still 2283 * print the message for the debugging purpose when link 2284 * stays down 2285 */ 2286 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2287 "nxge_neptune_10G_serdes_init: " 2288 "Serdes/signal for port<%d> not ready", portn)); 2289 goto done; 2290 } 2291 } 2292 2293 done: 2294 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2295 "<== nxge_neptune_10G_serdes_init port<%d>", portn)); 2296 2297 return (NXGE_OK); 2298 fail: 2299 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2300 "nxge_neptune_10G_serdes_init: " 2301 "Failed to initialize Neptune serdes for port<%d>", portn)); 2302 2303 return (status); 2304 } 2305 2306 /* Initialize Neptune Internal Serdes for 1G (Neptune only) */ 2307 2308 static nxge_status_t 2309 nxge_1G_serdes_init(p_nxge_t nxgep) 2310 { 2311 npi_handle_t handle; 2312 uint8_t portn; 2313 int chan; 2314 sr_rx_tx_ctrl_l_t rx_tx_ctrl_l; 2315 sr_rx_tx_ctrl_h_t rx_tx_ctrl_h; 2316 sr_glue_ctrl0_l_t glue_ctrl0_l; 2317 sr_glue_ctrl0_h_t glue_ctrl0_h; 2318 uint64_t val; 2319 uint16_t val16l; 2320 uint16_t val16h; 2321 nxge_status_t status = NXGE_OK; 2322 2323 portn = nxgep->mac.portnum; 2324 2325 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2326 "==> nxge_1G_serdes_init port<%d>", portn)); 2327 2328 handle = nxgep->npi_handle; 2329 2330 switch (portn) { 2331 case 0: 2332 /* Assert the reset register */ 2333 ESR_REG_RD(handle, ESR_RESET_REG, &val); 2334 val |= ESR_RESET_0; 2335 ESR_REG_WR(handle, ESR_RESET_REG, val); 2336 2337 /* Set the PLL register to 0x79 */ 2338 ESR_REG_WR(handle, ESR_0_PLL_CONFIG_REG, 2339 ESR_PLL_CFG_1G_SERDES); 2340 2341 /* Set the control register to 0x249249f */ 2342 ESR_REG_WR(handle, ESR_0_CONTROL_REG, ESR_CTL_1G_SERDES); 2343 2344 /* Set Serdes0 Internal Loopback if necessary */ 2345 if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) { 2346 /* Set pad loopback modes 0xaa */ 2347 ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 2348 ESR_TSTCFG_LBTEST_PAD); 2349 } else { 2350 ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0); 2351 } 2352 2353 /* Deassert the reset register */ 2354 ESR_REG_RD(handle, ESR_RESET_REG, &val); 2355 val &= ~ESR_RESET_0; 2356 ESR_REG_WR(handle, ESR_RESET_REG, val); 2357 break; 2358 2359 case 1: 2360 /* Assert the reset register */ 2361 ESR_REG_RD(handle, ESR_RESET_REG, &val); 2362 val |= ESR_RESET_1; 2363 ESR_REG_WR(handle, ESR_RESET_REG, val); 2364 2365 /* Set PLL register to 0x79 */ 2366 ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG, 2367 ESR_PLL_CFG_1G_SERDES); 2368 2369 /* Set the control register to 0x249249f */ 2370 ESR_REG_WR(handle, ESR_1_CONTROL_REG, ESR_CTL_1G_SERDES); 2371 2372 /* Set Serdes1 Internal Loopback if necessary */ 2373 if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) { 2374 /* Set pad loopback mode 0xaa */ 2375 ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 2376 ESR_TSTCFG_LBTEST_PAD); 2377 } else { 2378 ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0); 2379 } 2380 2381 /* Deassert the reset register */ 2382 ESR_REG_RD(handle, ESR_RESET_REG, &val); 2383 val &= ~ESR_RESET_1; 2384 ESR_REG_WR(handle, ESR_RESET_REG, val); 2385 break; 2386 2387 default: 2388 /* Nothing to do here */ 2389 goto done; 2390 } 2391 2392 /* init TX RX channels */ 2393 for (chan = 0; chan < 4; chan++) { 2394 if ((status = nxge_mdio_read(nxgep, portn, 2395 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 2396 &rx_tx_ctrl_l.value)) != NXGE_OK) { 2397 goto fail; 2398 } 2399 if ((status = nxge_mdio_read(nxgep, portn, 2400 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 2401 &rx_tx_ctrl_h.value)) != NXGE_OK) { 2402 goto fail; 2403 } 2404 if ((status = nxge_mdio_read(nxgep, portn, 2405 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 2406 &glue_ctrl0_l.value)) != NXGE_OK) { 2407 goto fail; 2408 } 2409 if ((status = nxge_mdio_read(nxgep, portn, 2410 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 2411 &glue_ctrl0_h.value)) != NXGE_OK) { 2412 goto fail; 2413 } 2414 2415 rx_tx_ctrl_l.bits.enstretch = 1; 2416 rx_tx_ctrl_h.bits.vmuxlo = 2; 2417 rx_tx_ctrl_h.bits.vpulselo = 2; 2418 glue_ctrl0_l.bits.rxlosenable = 1; 2419 glue_ctrl0_l.bits.samplerate = 0xF; 2420 glue_ctrl0_l.bits.thresholdcount = 0xFF; 2421 glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES; 2422 if ((status = nxge_mdio_write(nxgep, portn, 2423 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 2424 rx_tx_ctrl_l.value)) != NXGE_OK) { 2425 goto fail; 2426 } 2427 if ((status = nxge_mdio_write(nxgep, portn, 2428 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 2429 rx_tx_ctrl_h.value)) != NXGE_OK) { 2430 goto fail; 2431 } 2432 if ((status = nxge_mdio_write(nxgep, portn, 2433 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 2434 glue_ctrl0_l.value)) != NXGE_OK) { 2435 goto fail; 2436 } 2437 if ((status = nxge_mdio_write(nxgep, portn, 2438 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 2439 glue_ctrl0_h.value)) != NXGE_OK) { 2440 goto fail; 2441 } 2442 } 2443 2444 if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2445 ESR_NEP_RX_POWER_CONTROL_L_ADDR(), 0xfff)) != NXGE_OK) { 2446 goto fail; 2447 } 2448 if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2449 ESR_NEP_RX_POWER_CONTROL_H_ADDR(), 0xfff)) != NXGE_OK) { 2450 goto fail; 2451 } 2452 if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2453 ESR_NEP_TX_POWER_CONTROL_L_ADDR(), 0x70)) != NXGE_OK) { 2454 goto fail; 2455 } 2456 if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2457 ESR_NEP_TX_POWER_CONTROL_H_ADDR(), 0xfff)) != NXGE_OK) { 2458 goto fail; 2459 } 2460 2461 /* Apply Tx core reset */ 2462 if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2463 ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0)) != NXGE_OK) { 2464 goto fail; 2465 } 2466 2467 if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2468 ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) != 2469 NXGE_OK) { 2470 goto fail; 2471 } 2472 2473 NXGE_DELAY(200); 2474 2475 /* Apply Rx core reset */ 2476 if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2477 ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) != 2478 NXGE_OK) { 2479 goto fail; 2480 } 2481 2482 NXGE_DELAY(200); 2483 if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2484 ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK) { 2485 goto fail; 2486 } 2487 2488 NXGE_DELAY(200); 2489 if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2490 ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), &val16l)) != NXGE_OK) { 2491 goto fail; 2492 } 2493 if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2494 ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK) { 2495 goto fail; 2496 } 2497 if ((val16l != 0) || (val16h != 0)) { 2498 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2499 "Failed to reset port<%d> XAUI Serdes " 2500 "(val16l 0x%x val16h 0x%x)", portn, val16l, val16h)); 2501 status = NXGE_ERROR; 2502 goto fail; 2503 } 2504 2505 NXGE_DELAY(200); 2506 ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val); 2507 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2508 "nxge_neptune_serdes_init: read internal signal reg port<%d> " 2509 "val 0x%x", portn, val)); 2510 if (portn == 0) { 2511 if ((val & ESR_SIG_P0_BITS_MASK_1G) != 2512 (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0)) { 2513 /* 2514 * RDY signal stays low may due to the absent of the 2515 * external PHY, it is not an error condition. But still 2516 * print the message for the debugging purpose when link 2517 * stays down 2518 */ 2519 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2520 "nxge_neptune_1G_serdes_init: " 2521 "Serdes/signal for port<%d> not ready", portn)); 2522 goto done; 2523 } 2524 } else if (portn == 1) { 2525 if ((val & ESR_SIG_P1_BITS_MASK_1G) != 2526 (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1)) { 2527 /* 2528 * RDY signal stays low may due to the absent of the 2529 * external PHY, it is not an error condition. But still 2530 * print the message for the debugging purpose when link 2531 * stays down 2532 */ 2533 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2534 "nxge_neptune_1G_serdes_init: " 2535 "Serdes/signal for port<%d> not ready", portn)); 2536 goto done; 2537 2538 } 2539 } 2540 done: 2541 2542 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2543 "<== nxge_1G_serdes_init port<%d>", portn)); 2544 return (NXGE_OK); 2545 fail: 2546 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2547 "nxge_1G_serdes_init: " 2548 "Failed to initialize Neptune serdes for port<%d>", 2549 portn)); 2550 2551 return (status); 2552 } 2553 2554 #define NXGE_SET_PHY_TUNABLES(nxgep, phy_port, stat) \ 2555 { \ 2556 int i; \ 2557 \ 2558 if (nxgep->phy_prop.cnt > 0) { \ 2559 for (i = 0; i < nxgep->phy_prop.cnt; i++) { \ 2560 if ((stat = nxge_mdio_write(nxgep, phy_port, \ 2561 nxgep->phy_prop.arr[i].dev, \ 2562 nxgep->phy_prop.arr[i].reg, \ 2563 nxgep->phy_prop.arr[i].val)) != NXGE_OK) { \ 2564 break; \ 2565 } \ 2566 NXGE_DEBUG_MSG((nxgep, MAC_CTL, \ 2567 "From OBP, write<dev.reg.val> = " \ 2568 "<0x%x.0x%x.0x%x>", \ 2569 nxgep->phy_prop.arr[i].dev, \ 2570 nxgep->phy_prop.arr[i].reg, \ 2571 nxgep->phy_prop.arr[i].val)); \ 2572 } \ 2573 } \ 2574 } 2575 2576 /* Initialize the BCM 8704 xcvr */ 2577 2578 static nxge_status_t 2579 nxge_BCM8704_xcvr_init(p_nxge_t nxgep) 2580 { 2581 uint16_t val; 2582 #ifdef NXGE_DEBUG 2583 uint8_t portn; 2584 uint16_t val1; 2585 #endif 2586 uint8_t phy_port_addr; 2587 pmd_tx_control_t tx_ctl; 2588 control_t ctl; 2589 phyxs_control_t phyxs_ctl; 2590 pcs_control_t pcs_ctl; 2591 uint32_t delay = 0; 2592 optics_dcntr_t op_ctr; 2593 nxge_status_t status = NXGE_OK; 2594 #ifdef NXGE_DEBUG 2595 portn = nxgep->mac.portnum; 2596 #endif 2597 2598 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8704_xcvr_init: port<%d>", 2599 portn)); 2600 2601 phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn; 2602 2603 /* Reset the transceiver */ 2604 if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 2605 BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK) 2606 goto fail; 2607 2608 phyxs_ctl.bits.reset = 1; 2609 if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 2610 BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK) 2611 goto fail; 2612 2613 do { 2614 drv_usecwait(500); 2615 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 2616 BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG, 2617 &phyxs_ctl.value)) != NXGE_OK) 2618 goto fail; 2619 delay++; 2620 } while ((phyxs_ctl.bits.reset) && (delay < 100)); 2621 if (delay == 100) { 2622 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: " 2623 "failed to reset Transceiver on port<%d>", portn)); 2624 status = NXGE_ERROR; 2625 goto fail; 2626 } 2627 2628 /* Set to 0x7FBF */ 2629 ctl.value = 0; 2630 ctl.bits.res1 = 0x3F; 2631 ctl.bits.optxon_lvl = 1; 2632 ctl.bits.oprxflt_lvl = 1; 2633 ctl.bits.optrxlos_lvl = 1; 2634 ctl.bits.optxflt_lvl = 1; 2635 ctl.bits.opprflt_lvl = 1; 2636 ctl.bits.obtmpflt_lvl = 1; 2637 ctl.bits.opbiasflt_lvl = 1; 2638 ctl.bits.optxrst_lvl = 1; 2639 if ((status = nxge_mdio_write(nxgep, phy_port_addr, 2640 BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, ctl.value)) 2641 != NXGE_OK) 2642 goto fail; 2643 2644 /* Set to 0x164 */ 2645 tx_ctl.value = 0; 2646 tx_ctl.bits.tsck_lpwren = 1; 2647 tx_ctl.bits.tx_dac_txck = 0x2; 2648 tx_ctl.bits.tx_dac_txd = 0x1; 2649 tx_ctl.bits.xfp_clken = 1; 2650 if ((status = nxge_mdio_write(nxgep, phy_port_addr, 2651 BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, 2652 tx_ctl.value)) != NXGE_OK) 2653 goto fail; 2654 /* 2655 * According to Broadcom's instruction, SW needs to read 2656 * back these registers twice after written. 2657 */ 2658 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 2659 BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val)) 2660 != NXGE_OK) 2661 goto fail; 2662 2663 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 2664 BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val)) 2665 != NXGE_OK) 2666 goto fail; 2667 2668 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 2669 BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val)) 2670 != NXGE_OK) 2671 goto fail; 2672 2673 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 2674 BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val)) 2675 != NXGE_OK) 2676 goto fail; 2677 2678 /* Enable Tx and Rx LEDs to be driven by traffic */ 2679 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 2680 BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 2681 &op_ctr.value)) != NXGE_OK) 2682 goto fail; 2683 if (NXGE_IS_XAUI_PLATFORM(nxgep)) { 2684 op_ctr.bits.gpio_sel = 0x1; 2685 } else { 2686 op_ctr.bits.gpio_sel = 0x3; 2687 } 2688 if ((status = nxge_mdio_write(nxgep, phy_port_addr, 2689 BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 2690 op_ctr.value)) != NXGE_OK) 2691 goto fail; 2692 2693 NXGE_DELAY(1000000); 2694 2695 /* 2696 * Set XAUI link tunables from OBP if present. 2697 */ 2698 NXGE_SET_PHY_TUNABLES(nxgep, phy_port_addr, status); 2699 if (status != NXGE_OK) { 2700 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2701 "nxge_BCM8704_xcvr_init: Failed setting PHY tunables")); 2702 goto fail; 2703 } 2704 2705 /* Set BCM8704 Internal Loopback mode if necessary */ 2706 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 2707 BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value)) 2708 != NXGE_OK) 2709 goto fail; 2710 if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g) 2711 pcs_ctl.bits.loopback = 1; 2712 else 2713 pcs_ctl.bits.loopback = 0; 2714 if ((status = nxge_mdio_write(nxgep, phy_port_addr, 2715 BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value)) 2716 != NXGE_OK) 2717 goto fail; 2718 2719 status = nxge_mdio_read(nxgep, phy_port_addr, 0x1, 0xA, &val); 2720 if (status != NXGE_OK) 2721 goto fail; 2722 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2723 "BCM8704 port<%d> Dev 1 Reg 0xA = 0x%x\n", portn, val)); 2724 status = nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0x20, &val); 2725 if (status != NXGE_OK) 2726 goto fail; 2727 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2728 "BCM8704 port<%d> Dev 3 Reg 0x20 = 0x%x\n", portn, val)); 2729 status = nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, &val); 2730 if (status != NXGE_OK) 2731 goto fail; 2732 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2733 "BCM8704 port<%d> Dev 4 Reg 0x18 = 0x%x\n", portn, val)); 2734 2735 #ifdef NXGE_DEBUG 2736 /* Diagnose link issue if link is not up */ 2737 status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_USER_DEV3_ADDR, 2738 BCM8704_USER_ANALOG_STATUS0_REG, 2739 &val); 2740 if (status != NXGE_OK) 2741 goto fail; 2742 2743 status = nxge_mdio_read(nxgep, phy_port_addr, 2744 BCM8704_USER_DEV3_ADDR, BCM8704_USER_ANALOG_STATUS0_REG, &val); 2745 if (status != NXGE_OK) 2746 goto fail; 2747 2748 status = nxge_mdio_read(nxgep, phy_port_addr, 2749 BCM8704_USER_DEV3_ADDR, BCM8704_USER_TX_ALARM_STATUS_REG, &val1); 2750 if (status != NXGE_OK) 2751 goto fail; 2752 2753 status = nxge_mdio_read(nxgep, phy_port_addr, 2754 BCM8704_USER_DEV3_ADDR, BCM8704_USER_TX_ALARM_STATUS_REG, &val1); 2755 if (status != NXGE_OK) 2756 goto fail; 2757 2758 if (val != 0x3FC) { 2759 if ((val == 0x43BC) && (val1 != 0)) { 2760 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2761 "Cable not connected to peer or bad" 2762 " cable on port<%d>\n", portn)); 2763 } else if (val == 0x639C) { 2764 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2765 "Optical module (XFP) is bad or absent" 2766 " on port<%d>\n", portn)); 2767 } 2768 } 2769 #endif 2770 2771 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8704_xcvr_init: port<%d>", 2772 portn)); 2773 return (NXGE_OK); 2774 2775 fail: 2776 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2777 "nxge_BCM8704_xcvr_init: failed to initialize transceiver for " 2778 "port<%d>", nxgep->mac.portnum)); 2779 return (NXGE_ERROR); 2780 } 2781 2782 /* Initialize the BCM 8706 Transceiver */ 2783 2784 static nxge_status_t 2785 nxge_BCM8706_xcvr_init(p_nxge_t nxgep) 2786 { 2787 uint8_t phy_port_addr; 2788 phyxs_control_t phyxs_ctl; 2789 pcs_control_t pcs_ctl; 2790 uint32_t delay = 0; 2791 optics_dcntr_t op_ctr; 2792 nxge_status_t status = NXGE_OK; 2793 #ifdef NXGE_DEBUG 2794 uint8_t portn = nxgep->mac.portnum; 2795 #endif 2796 2797 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8706_xcvr_init: port<%d>", 2798 portn)); 2799 2800 phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn; 2801 2802 /* Reset the transceiver */ 2803 if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 2804 BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK) 2805 goto fail; 2806 2807 phyxs_ctl.bits.reset = 1; 2808 if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 2809 BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK) 2810 goto fail; 2811 do { 2812 drv_usecwait(500); 2813 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 2814 BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG, 2815 &phyxs_ctl.value)) != NXGE_OK) 2816 goto fail; 2817 delay++; 2818 } while ((phyxs_ctl.bits.reset) && (delay < 100)); 2819 2820 if (delay == 100) { 2821 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: " 2822 "failed to reset Transceiver on port<%d>", portn)); 2823 status = NXGE_ERROR; 2824 goto fail; 2825 } 2826 2827 NXGE_DELAY(1000000); 2828 2829 /* 2830 * Set XAUI link tunables from OBP if present. 2831 */ 2832 NXGE_SET_PHY_TUNABLES(nxgep, phy_port_addr, status); 2833 if (status != NXGE_OK) { 2834 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2835 "nxge_BCM8706_xcvr_init: Failed setting PHY tunables")); 2836 goto fail; 2837 } 2838 2839 /* Set BCM8706 Internal Loopback mode if necessary */ 2840 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 2841 BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value)) 2842 != NXGE_OK) 2843 goto fail; 2844 if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g) 2845 pcs_ctl.bits.loopback = 1; 2846 else 2847 pcs_ctl.bits.loopback = 0; 2848 if ((status = nxge_mdio_write(nxgep, phy_port_addr, 2849 BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value)) 2850 != NXGE_OK) 2851 goto fail; 2852 2853 /* Enable Tx and Rx LEDs to be driven by traffic */ 2854 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 2855 BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 2856 &op_ctr.value)) != NXGE_OK) 2857 goto fail; 2858 op_ctr.bits.gpio_sel = 0x3; 2859 op_ctr.bits.res2 = 0x1; 2860 2861 if ((status = nxge_mdio_write(nxgep, phy_port_addr, 2862 BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 2863 op_ctr.value)) != NXGE_OK) 2864 goto fail; 2865 2866 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8706_xcvr_init: port<%d>", 2867 portn)); 2868 return (NXGE_OK); 2869 2870 fail: 2871 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2872 "nxge_BCM8706_xcvr_init: failed to initialize transceiver for " 2873 "port<%d>", nxgep->mac.portnum)); 2874 return (status); 2875 } 2876 2877 static int 2878 nxge_nlp2020_i2c_read(p_nxge_t nxgep, uint8_t ctrl_port, uint16_t address, 2879 uint16_t reg, uint8_t *data) 2880 { 2881 int phy_dev, phy_reg; 2882 uint16_t phy_data = 0; 2883 uint16_t stat; 2884 uint8_t count = 100; 2885 2886 /* 2887 * NLP2020_I2C_SNOOP_ADDR_REG [15:9][1] - Address 2888 * NLP2020_I2C_SNOOP_ADDR_REG[7:0] - register in the xcvr's i2c 2889 */ 2890 phy_dev = NLP2020_I2C_SNOOP_DEV_ADDR; 2891 phy_reg = NLP2020_I2C_SNOOP_ADDR_REG; 2892 phy_data = ((address + 1) << NLP2020_XCVR_I2C_ADDR_SH) | reg; 2893 if (nxge_mdio_write(nxgep, ctrl_port, 2894 phy_dev, phy_reg, phy_data) != NXGE_OK) 2895 goto fail; 2896 2897 phy_reg = NLP2020_I2C_SNOOP_STAT_REG; 2898 (void) nxge_mdio_read(nxgep, ctrl_port, phy_dev, phy_reg, &stat); 2899 while ((stat != 0x01) && (count-- > 0)) { 2900 (void) nxge_mdio_read(nxgep, ctrl_port, phy_dev, phy_reg, 2901 &stat); 2902 } 2903 if (count) { 2904 phy_reg = NLP2020_I2C_SNOOP_DATA_REG; 2905 (void) nxge_mdio_read(nxgep, ctrl_port, phy_dev, phy_reg, 2906 &phy_data); 2907 *data = (phy_data >> 8); 2908 return (0); 2909 } 2910 fail: 2911 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2912 "nxge_nlp2020_i2c_read: FAILED")); 2913 return (1); 2914 2915 } 2916 2917 /* Initialize the Netlogic AEL2020 Transceiver */ 2918 2919 #define NLP_INI_WAIT 1 2920 #define NLP_INI_STOP 0 2921 2922 static nxge_nlp_initseq_t nlp2020_revC_fiber_init[] = { 2923 {0x1C003, 0x3101}, 2924 {0x1CC01, 0x488a}, 2925 {0x1CB1B, 0x0200}, 2926 {0x1CB1C, 0x00f0}, 2927 {0x1CC06, 0x00e0}, 2928 {NLP_INI_STOP, 0}, 2929 }; 2930 2931 static nxge_nlp_initseq_t nlp2020_revC_copper_init[] = { 2932 2933 {0x1C003, 0x3101}, 2934 {0x1CD40, 0x0001}, 2935 2936 {0x1CA12, 0x0100}, 2937 {0x1CA22, 0x0100}, 2938 {0x1CA42, 0x0100}, 2939 {0x1C20D, 0x0002}, 2940 {NLP_INI_WAIT, 100}, 2941 2942 {0x1ff28, 0x4001}, 2943 {0x1ff2A, 0x004A}, 2944 {NLP_INI_WAIT, 500}, 2945 2946 {0x1d000, 0x5200}, 2947 {NLP_INI_WAIT, 500}, 2948 2949 {0x1d800, 0x4009}, 2950 {0x1d801, 0x2fff}, 2951 {0x1d802, 0x300f}, 2952 {0x1d803, 0x40aa}, 2953 {0x1d804, 0x401c}, 2954 {0x1d805, 0x401e}, 2955 {0x1d806, 0x20c5}, 2956 {0x1d807, 0x3c05}, 2957 {0x1d808, 0x6536}, 2958 {0x1d809, 0x2fe4}, 2959 {0x1d80a, 0x3dc4}, 2960 {0x1d80b, 0x6624}, 2961 {0x1d80c, 0x2ff4}, 2962 {0x1d80d, 0x3dc4}, 2963 {0x1d80e, 0x2035}, 2964 {0x1d80f, 0x30a5}, 2965 {0x1d810, 0x6524}, 2966 {0x1d811, 0x2ca2}, 2967 {0x1d812, 0x3012}, 2968 {0x1d813, 0x1002}, 2969 {0x1d814, 0x2882}, 2970 {0x1d815, 0x3022}, 2971 {0x1d816, 0x1002}, 2972 {0x1d817, 0x2972}, 2973 {0x1d818, 0x3022}, 2974 {0x1d819, 0x1002}, 2975 {0x1d81a, 0x2892}, 2976 {0x1d81b, 0x3012}, 2977 {0x1d81c, 0x1002}, 2978 {0x1d81d, 0x24e2}, 2979 {0x1d81e, 0x3022}, 2980 {0x1d81f, 0x1002}, 2981 {0x1d820, 0x27e2}, 2982 {0x1d821, 0x3012}, 2983 {0x1d822, 0x1002}, 2984 {0x1d823, 0x2422}, 2985 {0x1d824, 0x3022}, 2986 {0x1d825, 0x1002}, 2987 {0x1d826, 0x22cd}, 2988 {0x1d827, 0x301d}, 2989 {0x1d828, 0x2992}, 2990 {0x1d829, 0x3022}, 2991 {0x1d82a, 0x1002}, 2992 {0x1d82b, 0x5553}, 2993 {0x1d82c, 0x0307}, 2994 {0x1d82d, 0x2572}, 2995 {0x1d82e, 0x3022}, 2996 {0x1d82f, 0x1002}, 2997 {0x1d830, 0x21a2}, 2998 {0x1d831, 0x3012}, 2999 {0x1d832, 0x1002}, 3000 {0x1d833, 0x4016}, 3001 {0x1d834, 0x5e63}, 3002 {0x1d835, 0x0344}, 3003 {0x1d836, 0x21a2}, 3004 {0x1d837, 0x3012}, 3005 {0x1d838, 0x1002}, 3006 {0x1d839, 0x400e}, 3007 {0x1d83a, 0x2572}, 3008 {0x1d83b, 0x3022}, 3009 {0x1d83c, 0x1002}, 3010 {0x1d83d, 0x2b22}, 3011 {0x1d83e, 0x3012}, 3012 {0x1d83f, 0x1002}, 3013 {0x1d840, 0x28e2}, 3014 {0x1d841, 0x3022}, 3015 {0x1d842, 0x1002}, 3016 {0x1d843, 0x2782}, 3017 {0x1d844, 0x3022}, 3018 {0x1d845, 0x1002}, 3019 {0x1d846, 0x2fa4}, 3020 {0x1d847, 0x3dc4}, 3021 {0x1d848, 0x6624}, 3022 {0x1d849, 0x2e8b}, 3023 {0x1d84a, 0x303b}, 3024 {0x1d84b, 0x56b3}, 3025 {0x1d84c, 0x03c6}, 3026 {0x1d84d, 0x866b}, 3027 {0x1d84e, 0x400c}, 3028 {0x1d84f, 0x2782}, 3029 {0x1d850, 0x3012}, 3030 {0x1d851, 0x1002}, 3031 {0x1d852, 0x2c4b}, 3032 {0x1d853, 0x309b}, 3033 {0x1d854, 0x56b3}, 3034 {0x1d855, 0x03c3}, 3035 {0x1d856, 0x866b}, 3036 {0x1d857, 0x400c}, 3037 {0x1d858, 0x22a2}, 3038 {0x1d859, 0x3022}, 3039 {0x1d85a, 0x1002}, 3040 {0x1d85b, 0x28e2}, 3041 {0x1d85c, 0x3022}, 3042 {0x1d85d, 0x1002}, 3043 {0x1d85e, 0x2782}, 3044 {0x1d85f, 0x3022}, 3045 {0x1d860, 0x1002}, 3046 {0x1d861, 0x2fb4}, 3047 {0x1d862, 0x3dc4}, 3048 {0x1d863, 0x6624}, 3049 {0x1d864, 0x56b3}, 3050 {0x1d865, 0x03c3}, 3051 {0x1d866, 0x866b}, 3052 {0x1d867, 0x401c}, 3053 {0x1d868, 0x2c45}, 3054 {0x1d869, 0x3095}, 3055 {0x1d86a, 0x5b53}, 3056 {0x1d86b, 0x23d2}, 3057 {0x1d86c, 0x3012}, 3058 {0x1d86d, 0x13c2}, 3059 {0x1d86e, 0x5cc3}, 3060 {0x1d86f, 0x2782}, 3061 {0x1d870, 0x3012}, 3062 {0x1d871, 0x1312}, 3063 {0x1d872, 0x2b22}, 3064 {0x1d873, 0x3012}, 3065 {0x1d874, 0x1002}, 3066 {0x1d875, 0x28e2}, 3067 {0x1d876, 0x3022}, 3068 {0x1d877, 0x1002}, 3069 {0x1d878, 0x2672}, 3070 {0x1d879, 0x3022}, 3071 {0x1d87a, 0x1002}, 3072 {0x1d87b, 0x21a2}, 3073 {0x1d87c, 0x3012}, 3074 {0x1d87d, 0x1002}, 3075 {0x1d87e, 0x628f}, 3076 {0x1d87f, 0x2985}, 3077 {0x1d880, 0x33a5}, 3078 {0x1d881, 0x2782}, 3079 {0x1d882, 0x3022}, 3080 {0x1d883, 0x1002}, 3081 {0x1d884, 0x5653}, 3082 {0x1d885, 0x03d2}, 3083 {0x1d886, 0x401e}, 3084 {0x1d887, 0x6f72}, 3085 {0x1d888, 0x1002}, 3086 {0x1d889, 0x628f}, 3087 {0x1d88a, 0x2304}, 3088 {0x1d88b, 0x3c84}, 3089 {0x1d88c, 0x6436}, 3090 {0x1d88d, 0xdff4}, 3091 {0x1d88e, 0x6436}, 3092 {0x1d88f, 0x2ff5}, 3093 {0x1d890, 0x3005}, 3094 {0x1d891, 0x8656}, 3095 {0x1d892, 0xdfba}, 3096 {0x1d893, 0x56a3}, 3097 {0x1d894, 0xd05a}, 3098 {0x1d895, 0x29e2}, 3099 {0x1d896, 0x3012}, 3100 {0x1d897, 0x1392}, 3101 {0x1d898, 0xd05a}, 3102 {0x1d899, 0x56a3}, 3103 {0x1d89a, 0xdfba}, 3104 {0x1d89b, 0x0383}, 3105 {0x1d89c, 0x6f72}, 3106 {0x1d89d, 0x1002}, 3107 {0x1d89e, 0x2a64}, 3108 {0x1d89f, 0x3014}, 3109 {0x1d8a0, 0x2005}, 3110 {0x1d8a1, 0x3d75}, 3111 {0x1d8a2, 0xc451}, 3112 {0x1d8a3, 0x2a42}, 3113 {0x1d8a4, 0x3022}, 3114 {0x1d8a5, 0x1002}, 3115 {0x1d8a6, 0x178c}, 3116 {0x1d8a7, 0x1898}, 3117 {0x1d8a8, 0x19a4}, 3118 {0x1d8a9, 0x1ab0}, 3119 {0x1d8aa, 0x1bbc}, 3120 {0x1d8ab, 0x1cc8}, 3121 {0x1d8ac, 0x1dd3}, 3122 {0x1d8ad, 0x1ede}, 3123 {0x1d8ae, 0x1fe9}, 3124 {0x1d8af, 0x20f4}, 3125 {0x1d8b0, 0x21ff}, 3126 {0x1d8b1, 0x0000}, 3127 {0x1d8b2, 0x27e1}, 3128 {0x1d8b3, 0x3021}, 3129 {0x1d8b4, 0x1001}, 3130 {0x1d8b5, 0xc620}, 3131 {0x1d8b6, 0x0000}, 3132 {0x1d8b7, 0xc621}, 3133 {0x1d8b8, 0x0000}, 3134 {0x1d8b9, 0xc622}, 3135 {0x1d8ba, 0x00e2}, 3136 {0x1d8bb, 0xc623}, 3137 {0x1d8bc, 0x007f}, 3138 {0x1d8bd, 0xc624}, 3139 {0x1d8be, 0x00ce}, 3140 {0x1d8bf, 0xc625}, 3141 {0x1d8c0, 0x0000}, 3142 {0x1d8c1, 0xc627}, 3143 {0x1d8c2, 0x0000}, 3144 {0x1d8c3, 0xc628}, 3145 {0x1d8c4, 0x0000}, 3146 {0x1d8c5, 0xc90a}, 3147 {0x1d8c6, 0x3a7c}, 3148 {0x1d8c7, 0xc62c}, 3149 {0x1d8c8, 0x0000}, 3150 {0x1d8c9, 0x0000}, 3151 {0x1d8ca, 0x27e1}, 3152 {0x1d8cb, 0x3021}, 3153 {0x1d8cc, 0x1001}, 3154 {0x1d8cd, 0xc502}, 3155 {0x1d8ce, 0x53ac}, 3156 {0x1d8cf, 0xc503}, 3157 {0x1d8d0, 0x2cd3}, 3158 {0x1d8d1, 0xc600}, 3159 {0x1d8d2, 0x2a6e}, 3160 {0x1d8d3, 0xc601}, 3161 {0x1d8d4, 0x2a2c}, 3162 {0x1d8d5, 0xc605}, 3163 {0x1d8d6, 0x5557}, 3164 {0x1d8d7, 0xc60c}, 3165 {0x1d8d8, 0x5400}, 3166 {0x1d8d9, 0xc710}, 3167 {0x1d8da, 0x0700}, 3168 {0x1d8db, 0xc711}, 3169 {0x1d8dc, 0x0f06}, 3170 {0x1d8dd, 0xc718}, 3171 {0x1d8de, 0x0700}, 3172 {0x1d8df, 0xc719}, 3173 {0x1d8e0, 0x0f06}, 3174 {0x1d8e1, 0xc720}, 3175 {0x1d8e2, 0x4700}, 3176 {0x1d8e3, 0xc721}, 3177 {0x1d8e4, 0x0f06}, 3178 {0x1d8e5, 0xc728}, 3179 {0x1d8e6, 0x0700}, 3180 {0x1d8e7, 0xc729}, 3181 {0x1d8e8, 0x1207}, 3182 {0x1d8e9, 0xc801}, 3183 {0x1d8ea, 0x7f50}, 3184 {0x1d8eb, 0xc802}, 3185 {0x1d8ec, 0x7760}, 3186 {0x1d8ed, 0xc803}, 3187 {0x1d8ee, 0x7fce}, 3188 {0x1d8ef, 0xc804}, 3189 {0x1d8f0, 0x520e}, 3190 {0x1d8f1, 0xc805}, 3191 {0x1d8f2, 0x5c11}, 3192 {0x1d8f3, 0xc806}, 3193 {0x1d8f4, 0x3c51}, 3194 {0x1d8f5, 0xc807}, 3195 {0x1d8f6, 0x4061}, 3196 {0x1d8f7, 0xc808}, 3197 {0x1d8f8, 0x49c1}, 3198 {0x1d8f9, 0xc809}, 3199 {0x1d8fa, 0x3840}, 3200 {0x1d8fb, 0xc80a}, 3201 {0x1d8fc, 0x0000}, 3202 {0x1d8fd, 0xc821}, 3203 {0x1d8fe, 0x0002}, 3204 {0x1d8ff, 0xc822}, 3205 {0x1d900, 0x0046}, 3206 {0x1d901, 0xc844}, 3207 {0x1d902, 0x182f}, 3208 {0x1d903, 0xc849}, 3209 {0x1d904, 0x0400}, 3210 {0x1d905, 0xc84a}, 3211 {0x1d906, 0x0002}, 3212 {0x1d907, 0xc013}, 3213 {0x1d908, 0xf341}, 3214 {0x1d909, 0xc084}, 3215 {0x1d90a, 0x0030}, 3216 {0x1d90b, 0xc904}, 3217 {0x1d90c, 0x1401}, 3218 {0x1d90d, 0xcb0c}, 3219 {0x1d90e, 0x0004}, 3220 {0x1d90f, 0xcb0e}, 3221 {0x1d910, 0xa00a}, 3222 {0x1d911, 0xcb0f}, 3223 {0x1d912, 0xc0c0}, 3224 {0x1d913, 0xcb10}, 3225 {0x1d914, 0xc0c0}, 3226 {0x1d915, 0xcb11}, 3227 {0x1d916, 0x00a0}, 3228 {0x1d917, 0xcb12}, 3229 {0x1d918, 0x0007}, 3230 {0x1d919, 0xc241}, 3231 {0x1d91a, 0xa000}, 3232 {0x1d91b, 0xc243}, 3233 {0x1d91c, 0x7fe0}, 3234 {0x1d91d, 0xc604}, 3235 {0x1d91e, 0x000e}, 3236 {0x1d91f, 0xc609}, 3237 {0x1d920, 0x00f5}, 3238 {0x1d921, 0x0c61}, 3239 {0x1d922, 0x000e}, 3240 {0x1d923, 0xc660}, 3241 {0x1d924, 0x9600}, 3242 {0x1d925, 0xc687}, 3243 {0x1d926, 0x0004}, 3244 {0x1d927, 0xc60a}, 3245 {0x1d928, 0x04f5}, 3246 {0x1d929, 0x0000}, 3247 {0x1d92a, 0x27e1}, 3248 {0x1d92b, 0x3021}, 3249 {0x1d92c, 0x1001}, 3250 {0x1d92d, 0xc620}, 3251 {0x1d92e, 0x14e5}, 3252 {0x1d92f, 0xc621}, 3253 {0x1d930, 0xc53d}, 3254 {0x1d931, 0xc622}, 3255 {0x1d932, 0x3cbe}, 3256 {0x1d933, 0xc623}, 3257 {0x1d934, 0x4452}, 3258 {0x1d935, 0xc624}, 3259 {0x1d936, 0xc5c5}, 3260 {0x1d937, 0xc625}, 3261 {0x1d938, 0xe01e}, 3262 {0x1d939, 0xc627}, 3263 {0x1d93a, 0x0000}, 3264 {0x1d93b, 0xc628}, 3265 {0x1d93c, 0x0000}, 3266 {0x1d93d, 0xc62c}, 3267 {0x1d93e, 0x0000}, 3268 {0x1d93f, 0xc90a}, 3269 {0x1d940, 0x3a7c}, 3270 {0x1d941, 0x0000}, 3271 {0x1d942, 0x2b84}, 3272 {0x1d943, 0x3c74}, 3273 {0x1d944, 0x6435}, 3274 {0x1d945, 0xdff4}, 3275 {0x1d946, 0x6435}, 3276 {0x1d947, 0x2806}, 3277 {0x1d948, 0x3006}, 3278 {0x1d949, 0x8565}, 3279 {0x1d94a, 0x2b24}, 3280 {0x1d94b, 0x3c24}, 3281 {0x1d94c, 0x6436}, 3282 {0x1d94d, 0x1002}, 3283 {0x1d94e, 0x2b24}, 3284 {0x1d94f, 0x3c24}, 3285 {0x1d950, 0x6436}, 3286 {0x1d951, 0x4045}, 3287 {0x1d952, 0x8656}, 3288 {0x1d953, 0x5663}, 3289 {0x1d954, 0x0302}, 3290 {0x1d955, 0x401e}, 3291 {0x1d956, 0x1002}, 3292 {0x1d957, 0x2017}, 3293 {0x1d958, 0x3b17}, 3294 {0x1d959, 0x2084}, 3295 {0x1d95a, 0x3c14}, 3296 {0x1d95b, 0x6724}, 3297 {0x1d95c, 0x2807}, 3298 {0x1d95d, 0x31a7}, 3299 {0x1d95e, 0x20c4}, 3300 {0x1d95f, 0x3c24}, 3301 {0x1d960, 0x6724}, 3302 {0x1d961, 0x2ff7}, 3303 {0x1d962, 0x30f7}, 3304 {0x1d963, 0x20c4}, 3305 {0x1d964, 0x3c04}, 3306 {0x1d965, 0x6724}, 3307 {0x1d966, 0x1002}, 3308 {0x1d967, 0x2807}, 3309 {0x1d968, 0x3187}, 3310 {0x1d969, 0x20c4}, 3311 {0x1d96a, 0x3c24}, 3312 {0x1d96b, 0x6724}, 3313 {0x1d96c, 0x2fe4}, 3314 {0x1d96d, 0x3dc4}, 3315 {0x1d96e, 0x6437}, 3316 {0x1d96f, 0x20c4}, 3317 {0x1d970, 0x3c04}, 3318 {0x1d971, 0x6724}, 3319 {0x1d972, 0x2017}, 3320 {0x1d973, 0x3d17}, 3321 {0x1d974, 0x2084}, 3322 {0x1d975, 0x3c14}, 3323 {0x1d976, 0x6724}, 3324 {0x1d977, 0x1002}, 3325 {0x1d978, 0x24f4}, 3326 {0x1d979, 0x3c64}, 3327 {0x1d97a, 0x6436}, 3328 {0x1d97b, 0xdff4}, 3329 {0x1d97c, 0x6436}, 3330 {0x1d97d, 0x1002}, 3331 {0x1d97e, 0x2006}, 3332 {0x1d97f, 0x3d76}, 3333 {0x1d980, 0xc161}, 3334 {0x1d981, 0x6134}, 3335 {0x1d982, 0x6135}, 3336 {0x1d983, 0x5443}, 3337 {0x1d984, 0x0303}, 3338 {0x1d985, 0x6524}, 3339 {0x1d986, 0x00fb}, 3340 {0x1d987, 0x1002}, 3341 {0x1d988, 0x20d4}, 3342 {0x1d989, 0x3c24}, 3343 {0x1d98a, 0x2025}, 3344 {0x1d98b, 0x3005}, 3345 {0x1d98c, 0x6524}, 3346 {0x1d98d, 0x1002}, 3347 {0x1d98e, 0xd019}, 3348 {0x1d98f, 0x2104}, 3349 {0x1d990, 0x3c24}, 3350 {0x1d991, 0x2105}, 3351 {0x1d992, 0x3805}, 3352 {0x1d993, 0x6524}, 3353 {0x1d994, 0xdff4}, 3354 {0x1d995, 0x4005}, 3355 {0x1d996, 0x6524}, 3356 {0x1d997, 0x2e8d}, 3357 {0x1d998, 0x303d}, 3358 {0x1d999, 0x2408}, 3359 {0x1d99a, 0x35d8}, 3360 {0x1d99b, 0x5dd3}, 3361 {0x1d99c, 0x0307}, 3362 {0x1d99d, 0x8887}, 3363 {0x1d99e, 0x63a7}, 3364 {0x1d99f, 0x8887}, 3365 {0x1d9a0, 0x63a7}, 3366 {0x1d9a1, 0xdffd}, 3367 {0x1d9a2, 0x00f9}, 3368 {0x1d9a3, 0x1002}, 3369 {0x1d9a4, 0x866a}, 3370 {0x1d9a5, 0x6138}, 3371 {0x1d9a6, 0x5883}, 3372 {0x1d9a7, 0x2b42}, 3373 {0x1d9a8, 0x3022}, 3374 {0x1d9a9, 0x1302}, 3375 {0x1d9aa, 0x2ff7}, 3376 {0x1d9ab, 0x3007}, 3377 {0x1d9ac, 0x8785}, 3378 {0x1d9ad, 0xb887}, 3379 {0x1d9ae, 0x8786}, 3380 {0x1d9af, 0xb8c6}, 3381 {0x1d9b0, 0x5a53}, 3382 {0x1d9b1, 0x2a52}, 3383 {0x1d9b2, 0x3022}, 3384 {0x1d9b3, 0x13c2}, 3385 {0x1d9b4, 0x2474}, 3386 {0x1d9b5, 0x3c84}, 3387 {0x1d9b6, 0x64d7}, 3388 {0x1d9b7, 0x64d7}, 3389 {0x1d9b8, 0x2ff5}, 3390 {0x1d9b9, 0x3c05}, 3391 {0x1d9ba, 0x8757}, 3392 {0x1d9bb, 0xb886}, 3393 {0x1d9bc, 0x9767}, 3394 {0x1d9bd, 0x67c4}, 3395 {0x1d9be, 0x6f72}, 3396 {0x1d9bf, 0x1002}, 3397 {0x1d9c0, 0x0000}, 3398 {0x1d080, 0x0100}, 3399 {0x1d092, 0x0000}, 3400 {NLP_INI_STOP, 0}, 3401 }; 3402 3403 static nxge_status_t 3404 nxge_nlp2020_xcvr_init(p_nxge_t nxgep) 3405 { 3406 uint8_t phy_port_addr; 3407 nxge_status_t status = NXGE_OK; 3408 uint16_t ctrl_reg, rst_val, pmd_ctl, rx_los; 3409 int i = 0, count = 1000; 3410 3411 uint8_t connector = 0, len, lpm; 3412 p_nxge_nlp_initseq_t initseq; 3413 uint16_t dev, reg, val; 3414 3415 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_nlp2020_xcvr_init: " 3416 "port<%d>, phyaddr[0x%x]", nxgep->mac.portnum, 3417 nxgep->statsp->mac_stats.xcvr_portn)); 3418 3419 phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn; 3420 3421 /* Reset the transceiver */ 3422 rst_val = ctrl_reg = NLP2020_PMA_PMD_PHY_RST; 3423 if ((status = nxge_mdio_write(nxgep, phy_port_addr, 3424 NLP2020_PMA_PMD_ADDR, NLP2020_PMA_PMD_CTL_REG, rst_val)) 3425 != NXGE_OK) 3426 goto fail; 3427 while ((count--) && (ctrl_reg & rst_val)) { 3428 drv_usecwait(1000); 3429 (void) nxge_mdio_read(nxgep, phy_port_addr, 3430 NLP2020_PMA_PMD_ADDR, NLP2020_PMA_PMD_CTL_REG, &ctrl_reg); 3431 } 3432 if (count == 0) { 3433 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_nlp2020_xcvr_init: " 3434 "PMA_PMD reset failed")); 3435 goto fail; 3436 } 3437 3438 /* Set loopback mode if required */ 3439 /* Set PMA PMD system loopback */ 3440 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 3441 NLP2020_PMA_PMD_ADDR, NLP2020_PMA_PMD_CTL_REG, &pmd_ctl)) 3442 != NXGE_OK) 3443 goto fail; 3444 3445 if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g) 3446 pmd_ctl |= 0x0001; 3447 else 3448 pmd_ctl &= 0xfffe; 3449 if ((status = nxge_mdio_write(nxgep, phy_port_addr, 3450 NLP2020_PMA_PMD_ADDR, NLP2020_PMA_PMD_CTL_REG, pmd_ctl)) 3451 != NXGE_OK) 3452 goto fail; 3453 3454 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_nlp2020_xcvr_init: " 3455 "setting LB, wrote NLP2020_PMA_PMD_CTL_REG[0x%x]", pmd_ctl)); 3456 3457 /* Check connector details using I2c */ 3458 if (nxge_nlp2020_i2c_read(nxgep, phy_port_addr, NLP2020_XCVR_I2C_ADDR, 3459 QSFP_MSA_CONN_REG, &connector) == 1) { 3460 goto fail; 3461 } 3462 3463 switch (connector) { 3464 case SFPP_FIBER: 3465 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3466 "nxge_nlp2020_xcvr_init: SFPP_FIBER detected")); 3467 initseq = nlp2020_revC_fiber_init; 3468 nxgep->nlp_conn = NXGE_NLP_CONN_FIBER; 3469 break; 3470 case QSFP_FIBER: 3471 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3472 "nxge_nlp2020_xcvr_init: QSFP_FIBER detected")); 3473 initseq = nlp2020_revC_fiber_init; 3474 nxgep->nlp_conn = NXGE_NLP_CONN_FIBER; 3475 break; 3476 case QSFP_COPPER_TWINAX: 3477 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3478 "nxge_nlp2020_xcvr_init: QSFP_COPPER_TWINAX/" 3479 "SFPP_COPPER_TWINAX detected")); 3480 3481 initseq = nlp2020_revC_copper_init; 3482 nxgep->nlp_conn = NXGE_NLP_CONN_COPPER_LT_7M; 3483 break; 3484 default: 3485 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3486 "nxge_nlp2020_xcvr_init: Unknown type [0x%x] detected", 3487 "...setting to QSFP_FIBER", 3488 connector)); 3489 initseq = nlp2020_revC_fiber_init; 3490 nxgep->nlp_conn = NXGE_NLP_CONN_FIBER; 3491 break; 3492 } 3493 3494 /* Run appropriate init sequence */ 3495 for (i = 0; initseq[i].dev_reg != NLP_INI_STOP; i++) { 3496 dev = initseq[i].dev_reg >> 16; 3497 reg = initseq[i].dev_reg & 0xffff; 3498 val = initseq[i].val; 3499 3500 if (reg == NLP_INI_WAIT) { 3501 drv_usecwait(1000 * val); 3502 } else { 3503 if ((status = nxge_mdio_write(nxgep, phy_port_addr, 3504 dev, reg, val)) != NXGE_OK) 3505 goto fail; 3506 } 3507 } 3508 3509 /* rx_los inversion */ 3510 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 3511 NLP2020_PMA_PMD_ADDR, NLP2020_OPT_SET_REG, &rx_los)) != NXGE_OK) 3512 goto fail; 3513 3514 rx_los &= ~(NLP2020_RXLOS_ACT_H); 3515 3516 if ((status = nxge_mdio_write(nxgep, phy_port_addr, 3517 NLP2020_PMA_PMD_ADDR, NLP2020_OPT_SET_REG, rx_los)) != NXGE_OK) 3518 goto fail; 3519 3520 if (nxge_nlp2020_i2c_read(nxgep, phy_port_addr, NLP2020_XCVR_I2C_ADDR, 3521 QSFP_MSA_LEN_REG, &len) == 1) { 3522 goto fail; 3523 } 3524 3525 if (nxge_nlp2020_i2c_read(nxgep, phy_port_addr, NLP2020_XCVR_I2C_ADDR, 3526 QSFP_MSA_LPM_REG, &lpm) == 1) { 3527 goto fail; 3528 } 3529 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3530 "nxge_nlp2020_xcvr_init: len[0x%x] lpm[0x%x]", len, lpm)); 3531 3532 if (connector == QSFP_COPPER_TWINAX) { 3533 if (len >= 7) { 3534 nxgep->nlp_conn = NXGE_NLP_CONN_COPPER_7M_ABOVE; 3535 /* enable pre-emphasis */ 3536 (void) nxge_mdio_write(nxgep, phy_port_addr, 3537 NLP2020_PMA_PMD_ADDR, NLP2020_TX_DRV_CTL1_REG, 3538 NLP2020_TX_DRV_CTL1_PREEMP_EN); 3539 /* write emphasis value */ 3540 (void) nxge_mdio_write(nxgep, phy_port_addr, 3541 NLP2020_PMA_PMD_ADDR, NLP2020_TX_DRV_CTL2_REG, 3542 NLP2020_TX_DRV_CTL2_EMP_VAL); 3543 /* stop microcontroller */ 3544 (void) nxge_mdio_write(nxgep, phy_port_addr, 3545 NLP2020_PMA_PMD_ADDR, NLP2020_UC_CTL_REG, 3546 NLP2020_UC_CTL_STOP); 3547 /* reset program counter */ 3548 (void) nxge_mdio_write(nxgep, phy_port_addr, 3549 NLP2020_PMA_PMD_ADDR, NLP2020_UC_PC_START_REG, 3550 NLP2020_UC_PC_START_VAL); 3551 /* start microcontroller */ 3552 (void) nxge_mdio_write(nxgep, phy_port_addr, 3553 NLP2020_PMA_PMD_ADDR, NLP2020_UC_CTL_REG, 3554 NLP2020_UC_CTL_START); 3555 } 3556 } 3557 if (lpm & QSFP_MSA_LPM_HIGH) { 3558 /* enable high power mode */ 3559 (void) nxge_mdio_write(nxgep, phy_port_addr, 3560 NLP2020_GPIO_ADDR, NLP2020_GPIO_CTL_REG, 3561 NLP2020_GPIO_ACT); 3562 } else { 3563 /* revert to low power mode */ 3564 (void) nxge_mdio_write(nxgep, phy_port_addr, 3565 NLP2020_GPIO_ADDR, NLP2020_GPIO_CTL_REG, 3566 NLP2020_GPIO_INACT); 3567 } 3568 3569 /* 3570 * Set XAUI link tunables from OBP if present. 3571 */ 3572 NXGE_SET_PHY_TUNABLES(nxgep, phy_port_addr, status); 3573 if (status != NXGE_OK) { 3574 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3575 "nxge_nlp2020_xcvr_init: Failed setting PHY tunables")); 3576 goto fail; 3577 } 3578 3579 /* It takes ~2s for EDC to settle */ 3580 drv_usecwait(2000000); 3581 3582 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_nlp2020_xcvr_init: " 3583 "port<%d> phyaddr[0x%x]", nxgep->mac.portnum, phy_port_addr)); 3584 3585 return (NXGE_OK); 3586 3587 fail: 3588 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3589 "nxge_nlp2020_xcvr_init: failed to initialize transceiver for " 3590 "port<%d>", nxgep->mac.portnum)); 3591 return (status); 3592 } 3593 3594 static boolean_t nxge_is_nlp2020_phy(p_nxge_t nxgep) 3595 { 3596 uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 3597 uint32_t pcs_id = 0; 3598 uint32_t pma_pmd_id = 0; 3599 uint8_t xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 3600 3601 pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, xcvr_addr); 3602 pcs_id = nxge_get_cl45_pcs_id(nxgep, xcvr_addr); 3603 3604 if (((pma_pmd_id & NLP2020_DEV_ID_MASK) == NLP2020_DEV_ID) || 3605 ((pcs_id & NLP2020_DEV_ID_MASK) == NLP2020_DEV_ID)) { 3606 return (B_TRUE); 3607 } else { 3608 return (B_FALSE); 3609 } 3610 } 3611 3612 static uint8_t nxge_get_nlp2020_connector_type(p_nxge_t nxgep) 3613 { 3614 uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 3615 uint8_t xcvr_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 3616 uint8_t connector = 0; 3617 3618 (void) nxge_nlp2020_i2c_read(nxgep, xcvr_addr, NLP2020_XCVR_I2C_ADDR, 3619 QSFP_MSA_CONN_REG, &connector); 3620 3621 return (connector); 3622 } 3623 3624 static nxge_status_t nxge_set_nlp2020_param(p_nxge_t nxgep) 3625 { 3626 uint8_t connector = 0; 3627 3628 connector = nxge_get_nlp2020_connector_type(nxgep); 3629 3630 switch (connector) { 3631 case SFPP_FIBER: 3632 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3633 "nxge_set_nlp2020_param: SFPP_FIBER detected")); 3634 nxgep->mac.portmode = PORT_10G_FIBER; 3635 nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 3636 break; 3637 case QSFP_FIBER: 3638 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3639 "nxge_set_nlp2020_param: QSFP_FIBER detected")); 3640 nxgep->mac.portmode = PORT_10G_FIBER; 3641 nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 3642 break; 3643 case QSFP_COPPER_TWINAX: 3644 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3645 "nxge_set_nlp2020_param: QSFP_COPPER_TWINAX/" 3646 "SFPP_COPPER_TWINAX detected")); 3647 nxgep->mac.portmode = PORT_10G_COPPER; 3648 nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 3649 break; 3650 default: 3651 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3652 "nxge_set_nlp2020_param: Unknown type [0x%x] detected" 3653 "...setting to QSFP_FIBER", 3654 connector)); 3655 nxgep->mac.portmode = PORT_10G_FIBER; 3656 nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 3657 break; 3658 } 3659 3660 return (NXGE_OK); 3661 } 3662 3663 #define CHK_STAT(x) status = (x); if (status != NXGE_OK) goto fail 3664 3665 #define MRVL88X2011_RD(nxgep, port, d, r, p) \ 3666 CHK_STAT(nxge_mdio_read(nxgep, port, d, r, p)) 3667 3668 #define MRVL88X2011_WR(nxgep, port, d, r, p) \ 3669 CHK_STAT(nxge_mdio_write(nxgep, port, d, r, p)) 3670 3671 3672 static void 3673 nxge_mrvl88x2011_led_blink_rate(p_nxge_t nxgep, uint16_t rate) 3674 { 3675 uint16_t value; 3676 uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn; 3677 3678 if (nxge_mdio_read(nxgep, phy, MRVL_88X2011_USER_DEV2_ADDR, 3679 MRVL_88X2011_LED_BLINK_CTL, &value) == NXGE_OK) { 3680 value &= ~MRVL_88X2011_LED_BLK_MASK; 3681 value |= (rate << MRVL_88X2011_LED_BLK_SHIFT); 3682 (void) nxge_mdio_write(nxgep, phy, 3683 MRVL_88X2011_USER_DEV2_ADDR, MRVL_88X2011_LED_BLINK_CTL, 3684 value); 3685 } 3686 } 3687 3688 static nxge_status_t 3689 nxge_mrvl88x2011_setup_lb(p_nxge_t nxgep) 3690 { 3691 nxge_status_t status; 3692 pcs_control_t pcs_ctl; 3693 uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn; 3694 3695 MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR, 3696 MRVL_88X2011_PMA_PMD_CTL_1, &pcs_ctl.value); 3697 3698 if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g) 3699 pcs_ctl.bits.loopback = 1; 3700 else 3701 pcs_ctl.bits.loopback = 0; 3702 3703 MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR, 3704 MRVL_88X2011_PMA_PMD_CTL_1, pcs_ctl.value); 3705 3706 fail: 3707 return (status); 3708 } 3709 3710 3711 static void 3712 nxge_mrvl88x2011_led(p_nxge_t nxgep, uint16_t val) 3713 { 3714 uint16_t val2; 3715 uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn; 3716 3717 val2 = MRVL_88X2011_LED(MRVL_88X2011_LED_ACT, val); 3718 val2 &= ~MRVL_88X2011_LED(MRVL_88X2011_LED_ACT, 3719 MRVL_88X2011_LED_CTL_MASK); 3720 val2 |= MRVL_88X2011_LED(MRVL_88X2011_LED_ACT, val); 3721 3722 if (nxge_mdio_write(nxgep, phy, MRVL_88X2011_USER_DEV2_ADDR, 3723 MRVL_88X2011_LED_8_TO_11_CTL, val2) != NXGE_OK) { 3724 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3725 "nxge_mrvl88x2011_led: nxge_mdio_write failed!!")); 3726 } 3727 } 3728 3729 3730 static nxge_status_t 3731 nxge_mrvl88x2011_xcvr_init(p_nxge_t nxgep) 3732 { 3733 uint8_t phy; 3734 nxge_status_t status; 3735 uint16_t clk; 3736 3737 phy = nxgep->statsp->mac_stats.xcvr_portn; 3738 3739 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3740 "==> nxge_mrvl88x2011_xcvr_init: port<%d> addr<0x%x>", 3741 nxgep->mac.portnum, phy)); 3742 3743 /* Set LED functions */ 3744 nxge_mrvl88x2011_led_blink_rate(nxgep, MRVL_88X2011_LED_BLK134MS); 3745 /* PCS activity */ 3746 nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_ACT); 3747 3748 MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR, 3749 MRVL_88X2011_GEN_CTL, &clk); 3750 clk |= MRVL_88X2011_ENA_XFPREFCLK; 3751 MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR, 3752 MRVL_88X2011_GEN_CTL, clk); 3753 3754 /* Set internal loopback mode if necessary */ 3755 3756 CHK_STAT(nxge_mrvl88x2011_setup_lb(nxgep)); 3757 3758 /* Enable PMD */ 3759 MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR, 3760 MRVL_88X2011_10G_PMD_TX_DIS, MRVL_88X2011_ENA_PMDTX); 3761 3762 NXGE_DEBUG_MSG((nxgep, MAC_CTL, " nxge_mrvl88x2011_reset: OK")); 3763 3764 fail: 3765 return (status); 3766 } 3767 3768 3769 3770 /* Initialize the 10G Transceiver */ 3771 3772 static nxge_status_t 3773 nxge_10G_xcvr_init(p_nxge_t nxgep) 3774 { 3775 p_nxge_stats_t statsp; 3776 p_nxge_param_t param_arr = nxgep->param_arr; 3777 nxge_status_t status = NXGE_OK; 3778 #ifdef NXGE_DEBUG 3779 uint8_t portn = nxgep->mac.portnum; 3780 #endif 3781 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>", 3782 portn)); 3783 3784 statsp = nxgep->statsp; 3785 3786 /* Disable Link LEDs, with or without PHY */ 3787 if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 3788 goto done; 3789 3790 /* Skip MDIO, if PHY absent */ 3791 if (nxgep->mac.portmode == PORT_10G_SERDES || nxgep->phy_absent) { 3792 goto done; 3793 } 3794 3795 /* Set Clause 45 */ 3796 npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE); 3797 3798 switch (nxgep->chip_id) { 3799 case BCM8704_CHIP_ID: 3800 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_10G_xcvr_init: " 3801 "Chip ID 8704 [0x%x] for 10G xcvr", nxgep->chip_id)); 3802 status = nxge_BCM8704_xcvr_init(nxgep); 3803 break; 3804 case BCM8706_CHIP_ID: 3805 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_10G_xcvr_init: " 3806 "Chip ID 8706 [0x%x] for 10G xcvr", nxgep->chip_id)); 3807 status = nxge_BCM8706_xcvr_init(nxgep); 3808 break; 3809 case MRVL88X201X_CHIP_ID: 3810 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_10G_xcvr_init: " 3811 "Chip ID MRVL [0x%x] for 10G xcvr", nxgep->chip_id)); 3812 status = nxge_mrvl88x2011_xcvr_init(nxgep); 3813 break; 3814 case NLP2020_CHIP_ID: 3815 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_10G_xcvr_init: " 3816 "Chip ID NL2020 [0x%x] for 10G xcvr", nxgep->chip_id)); 3817 status = nxge_nlp2020_xcvr_init(nxgep); 3818 break; 3819 default: 3820 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_xcvr_init: " 3821 "Unknown chip ID 0x%x for 10G xcvr addr[%d]", 3822 nxgep->chip_id, nxgep->statsp->mac_stats.xcvr_portn)); 3823 goto fail; 3824 } 3825 3826 if (status != NXGE_OK) { 3827 goto fail; 3828 } 3829 done: 3830 statsp->mac_stats.cap_10gfdx = 1; 3831 statsp->mac_stats.lp_cap_10gfdx = 1; 3832 statsp->mac_stats.adv_cap_asmpause = 3833 param_arr[param_anar_asmpause].value; 3834 statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value; 3835 3836 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>", 3837 portn)); 3838 return (NXGE_OK); 3839 3840 fail: 3841 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3842 "nxge_10G_xcvr_init: failed to initialize transceiver for " 3843 "port<%d>", nxgep->mac.portnum)); 3844 return (NXGE_ERROR); 3845 } 3846 3847 /* Initialize the 1G copper (BCM 5464) Transceiver */ 3848 3849 static nxge_status_t 3850 nxge_1G_xcvr_init(p_nxge_t nxgep) 3851 { 3852 p_nxge_param_t param_arr = nxgep->param_arr; 3853 p_nxge_stats_t statsp = nxgep->statsp; 3854 nxge_status_t status = NXGE_OK; 3855 3856 if (nxgep->mac.portmode == PORT_1G_SERDES) { 3857 statsp->mac_stats.cap_1000fdx = 3858 param_arr[param_anar_1000fdx].value; 3859 goto done; 3860 } 3861 3862 /* Set Clause 22 */ 3863 npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_FALSE); 3864 3865 /* Set capability flags */ 3866 statsp->mac_stats.cap_1000fdx = param_arr[param_anar_1000fdx].value; 3867 if ((nxgep->mac.portmode == PORT_1G_COPPER) || 3868 (nxgep->mac.portmode == PORT_1G_FIBER)) { 3869 statsp->mac_stats.cap_100fdx = 3870 param_arr[param_anar_100fdx].value; 3871 statsp->mac_stats.cap_10fdx = 3872 param_arr[param_anar_10fdx].value; 3873 } 3874 3875 status = nxge_mii_xcvr_init(nxgep); 3876 done: 3877 return (status); 3878 } 3879 3880 /* 3881 * Although the Teranetics copper transceiver (TN1010) does not need 3882 * to be initialized by the driver for passing packets, this funtion 3883 * initializes the members of nxgep->statsp->mac_stats struct for 3884 * kstat based on the value of nxgep->statsp->ports_stats.lb_mode. 3885 * It also configures the TN1010 for PHY loopback to support SunVTS. 3886 * 3887 * TN1010 only has the option to disable advertisement for the 10G 3888 * mode. So we can set it to either Dual Mode or 1G Only mode but 3889 * can't set it to 10G Only mode. 3890 * 3891 * ndd -set command can set the following 6 speed/duplex related parameters. 3892 * 3893 * ---------------------------------------------------------------- 3894 * ndd -set /dev/nxgeX param n kstat nxge:X | grep param 3895 * ---------------------------------------------------------------- 3896 * adv_autoneg_cap kstat nxge:1 | grep adv_cap_autoneg 3897 * adv_10gfdx_cap 3898 * adv_1000fdx_cap kstat nxge:1 | grep adv_cap_1000fdx 3899 * adv_100fdx_cap kstat nxge:1 | grep adv_cap_100fdx 3900 * adv_10fdx_cap kstat nxge:1 | grep adv_cap_10fdx 3901 * adv_pause_cap kstat nxge:1 | grep adv_cap_pause 3902 * ---------------------------------------------------------------- 3903 */ 3904 static nxge_status_t 3905 nxge_tn1010_xcvr_init(p_nxge_t nxgep) 3906 { 3907 p_nxge_param_t param_arr; 3908 p_nxge_stats_t statsp; 3909 tn1010_pcs_ctrl_t tn1010_pcs_ctrl; 3910 uint16_t speed; 3911 uint8_t phy_port_addr; 3912 uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 3913 int status = NXGE_OK; 3914 3915 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_1G_tn1010_xcvr_init")); 3916 3917 param_arr = nxgep->param_arr; 3918 statsp = nxgep->statsp; 3919 3920 /* 3921 * Initialize the xcvr statistics which are NOT controlled by ndd 3922 */ 3923 statsp->mac_stats.cap_autoneg = 1; /* TN1010 autoneg is always on */ 3924 statsp->mac_stats.cap_100T4 = 0; 3925 3926 /* 3927 * Read the TN1010 link speed and initialize capabilities kstat. Note 3928 * that function nxge_check_tn1010_link repeatedly invoked by the 3929 * timer will update link_speed real time. 3930 */ 3931 if (nxge_get_tn1010_speed(nxgep, &speed) != NXGE_OK) { 3932 goto fail; 3933 } 3934 if (speed == TN1010_SPEED_1G) { 3935 statsp->mac_stats.cap_10gfdx = 0; 3936 } else { 3937 statsp->mac_stats.cap_10gfdx = 1; 3938 } 3939 3940 /* Whether we are in 1G or 10G mode, we always have the 1G capability */ 3941 statsp->mac_stats.cap_1000fdx = 1; 3942 3943 /* TN1010 is not able to operate in the following states */ 3944 statsp->mac_stats.cap_1000hdx = 0; 3945 statsp->mac_stats.cap_100fdx = 0; 3946 statsp->mac_stats.cap_100hdx = 0; 3947 statsp->mac_stats.cap_10fdx = 0; 3948 statsp->mac_stats.cap_10hdx = 0; 3949 3950 /* param_anar_pause can be modified by ndd -set */ 3951 statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value; 3952 3953 /* 3954 * The following 4 lines actually overwrites what ever the ndd command 3955 * has set. For example, by command 3956 * ndd -set /dev/nxge1 adv_autoneg_cap n (n = 0 or 1) 3957 * we could set param_arr[param_autoneg].value to n. However, because 3958 * here we assign constants to these parameters, whatever we set with 3959 * the "ndd -set" command will be replaced. So command 3960 * kstat nxge:X | grep param 3961 * will always show those constant values. In other words, the 3962 * "ndd -set" command can NOT change the values of these 4 parameters 3963 * even though the command appears to be successful. 3964 * 3965 * Note: TN1010 auto negotiation is always enabled. 3966 */ 3967 statsp->mac_stats.adv_cap_autoneg 3968 = param_arr[param_autoneg].value = 1; 3969 statsp->mac_stats.adv_cap_1000fdx 3970 = param_arr[param_anar_1000fdx].value = 1; 3971 statsp->mac_stats.adv_cap_100fdx 3972 = param_arr[param_anar_100fdx].value = 0; 3973 statsp->mac_stats.adv_cap_10fdx 3974 = param_arr[param_anar_10fdx].value = 0; 3975 3976 /* 3977 * The following 4 ndd params have type NXGE_PARAM_MAC_DONT_SHOW as 3978 * defined in nxge_param_arr[], therefore they are not seen by the 3979 * "ndd -get" command and can not be changed by ndd. We just set 3980 * them (both ndd param and kstat values) to constant 0 because TN1010 3981 * does not support those speeds. 3982 */ 3983 statsp->mac_stats.adv_cap_100T4 3984 = param_arr[param_anar_100T4].value = 0; 3985 statsp->mac_stats.adv_cap_1000hdx 3986 = param_arr[param_anar_1000hdx].value = 0; 3987 statsp->mac_stats.adv_cap_100hdx 3988 = param_arr[param_anar_100hdx].value = 0; 3989 statsp->mac_stats.adv_cap_10hdx 3990 = param_arr[param_anar_10hdx].value = 0; 3991 3992 /* 3993 * adv_cap_pause has type NXGE_PARAM_MAC_RW, so it can be modified 3994 * by ndd 3995 */ 3996 statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value; 3997 3998 /* 3999 * nxge_param_arr[] defines the adv_cap_asmpause with type 4000 * NXGE_PARAM_DONT_SHOW, therefore they are NOT seen by the 4001 * "ndd -get" command and can not be changed by ndd. Here we do not 4002 * assign a constant to it so the default value defined in 4003 * nxge_param_arr[] will be used to set the parameter and 4004 * will be shown by the kstat. 4005 */ 4006 statsp->mac_stats.adv_cap_asmpause 4007 = param_arr[param_anar_asmpause].value; 4008 4009 /* 4010 * Initialize the link statistics. 4011 */ 4012 statsp->mac_stats.link_T4 = 0; 4013 statsp->mac_stats.link_asmpause = 0; 4014 statsp->mac_stats.link_pause = 0; 4015 if (speed == TN1010_SPEED_1G) { 4016 statsp->mac_stats.link_speed = 1000; 4017 statsp->mac_stats.link_duplex = 2; /* Full duplex */ 4018 statsp->mac_stats.link_up = 1; 4019 } else { 4020 statsp->mac_stats.link_speed = 10000; 4021 statsp->mac_stats.link_duplex = 2; 4022 statsp->mac_stats.link_up = 1; 4023 } 4024 4025 /* 4026 * Because TN1010 does not have a link partner register, to 4027 * figure out the link partner's capabilities is tricky. Here we 4028 * just set the kstat based on our knowledge about the partner 4029 * (The partner must support auto-neg because auto-negotiation 4030 * has completed, it must support 1G or 10G because that is the 4031 * negotiated speed we are using.) 4032 * 4033 * Note: Current kstat does not show lp_cap_10gfdx and 4034 * lp_cap_10ghdx. 4035 */ 4036 if (speed == TN1010_SPEED_1G) { 4037 statsp->mac_stats.lp_cap_1000fdx = 1; 4038 statsp->mac_stats.lp_cap_10gfdx = 0; 4039 } else { 4040 statsp->mac_stats.lp_cap_1000fdx = 0; 4041 statsp->mac_stats.lp_cap_10gfdx = 1; 4042 } 4043 statsp->mac_stats.lp_cap_10ghdx = 0; 4044 statsp->mac_stats.lp_cap_1000hdx = 0; 4045 statsp->mac_stats.lp_cap_100fdx = 0; 4046 statsp->mac_stats.lp_cap_100hdx = 0; 4047 statsp->mac_stats.lp_cap_10fdx = 0; 4048 statsp->mac_stats.lp_cap_10hdx = 0; 4049 statsp->mac_stats.lp_cap_10gfdx = 0; 4050 statsp->mac_stats.lp_cap_10ghdx = 0; 4051 statsp->mac_stats.lp_cap_100T4 = 0; 4052 statsp->mac_stats.lp_cap_autoneg = 1; 4053 statsp->mac_stats.lp_cap_asmpause = 0; 4054 statsp->mac_stats.lp_cap_pause = 0; 4055 4056 /* Handle PHY loopback for SunVTS loopback test */ 4057 npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE); 4058 phy_port_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 4059 4060 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 4061 TN1010_PCS_DEV_ADDR, TN1010_PCS_CONTROL_REG, 4062 &tn1010_pcs_ctrl.value)) != NXGE_OK) { 4063 goto fail; 4064 } 4065 if ((statsp->port_stats.lb_mode == nxge_lb_phy1000) || 4066 (statsp->port_stats.lb_mode == nxge_lb_phy10g)) { 4067 tn1010_pcs_ctrl.bits.loopback = 1; 4068 } else { 4069 tn1010_pcs_ctrl.bits.loopback = 0; 4070 } 4071 if ((status = nxge_mdio_write(nxgep, phy_port_addr, 4072 TN1010_PCS_DEV_ADDR, TN1010_PCS_CONTROL_REG, 4073 tn1010_pcs_ctrl.value)) != NXGE_OK) { 4074 goto fail; 4075 } 4076 4077 statsp->mac_stats.xcvr_inits++; 4078 4079 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4080 "<== nxge_1G_tn1010_xcvr_init status 0x%x", status)); 4081 return (status); 4082 fail: 4083 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4084 "<== nxge_1G_tn1010_xcvr_init status 0x%x", status)); 4085 return (status); 4086 } 4087 4088 /* Initialize transceiver */ 4089 4090 nxge_status_t 4091 nxge_xcvr_init(p_nxge_t nxgep) 4092 { 4093 p_nxge_stats_t statsp; 4094 #ifdef NXGE_DEBUG 4095 uint8_t portn; 4096 #endif 4097 4098 nxge_status_t status = NXGE_OK; 4099 #ifdef NXGE_DEBUG 4100 portn = nxgep->mac.portnum; 4101 #endif 4102 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", portn)); 4103 statsp = nxgep->statsp; 4104 4105 /* 4106 * Initialize the xcvr statistics. nxgep->xcvr.xcvr_init will 4107 * modify mac_stats. 4108 */ 4109 statsp->mac_stats.cap_autoneg = 0; 4110 statsp->mac_stats.cap_100T4 = 0; 4111 statsp->mac_stats.cap_100fdx = 0; 4112 statsp->mac_stats.cap_100hdx = 0; 4113 statsp->mac_stats.cap_10fdx = 0; 4114 statsp->mac_stats.cap_10hdx = 0; 4115 statsp->mac_stats.cap_asmpause = 0; 4116 statsp->mac_stats.cap_pause = 0; 4117 statsp->mac_stats.cap_1000fdx = 0; 4118 statsp->mac_stats.cap_1000hdx = 0; 4119 statsp->mac_stats.cap_10gfdx = 0; 4120 statsp->mac_stats.cap_10ghdx = 0; 4121 4122 /* 4123 * Initialize the link statistics. 4124 */ 4125 statsp->mac_stats.link_T4 = 0; 4126 statsp->mac_stats.link_asmpause = 0; 4127 statsp->mac_stats.link_pause = 0; 4128 4129 if (nxgep->xcvr.xcvr_init) { 4130 status = nxgep->xcvr.xcvr_init(nxgep); 4131 if (status != NXGE_OK) 4132 goto fail; 4133 statsp->mac_stats.xcvr_inits++; 4134 } 4135 4136 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", 4137 portn)); 4138 return (NXGE_OK); 4139 4140 fail: 4141 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4142 "nxge_xcvr_init: failed to initialize transceiver for port<%d>", 4143 portn)); 4144 return (status); 4145 } 4146 4147 /* Look for transceiver type */ 4148 4149 nxge_status_t 4150 nxge_xcvr_find(p_nxge_t nxgep) 4151 { 4152 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_find: port<%d>", 4153 nxgep->mac.portnum)); 4154 4155 if (nxge_get_xcvr_type(nxgep) != NXGE_OK) 4156 return (NXGE_ERROR); 4157 4158 if (nxge_setup_xcvr_table(nxgep) != NXGE_OK) 4159 return (NXGE_ERROR); 4160 4161 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xcvr_find: xcvr_inuse = %d", 4162 nxgep->statsp->mac_stats.xcvr_inuse)); 4163 return (NXGE_OK); 4164 } 4165 4166 /* Initialize the TxMAC sub-block */ 4167 4168 nxge_status_t 4169 nxge_tx_mac_init(p_nxge_t nxgep) 4170 { 4171 npi_attr_t ap; 4172 uint8_t portn; 4173 nxge_port_mode_t portmode; 4174 nxge_port_t portt; 4175 npi_handle_t handle; 4176 npi_status_t rs = NPI_SUCCESS; 4177 4178 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 4179 portt = nxgep->mac.porttype; 4180 handle = nxgep->npi_handle; 4181 portmode = nxgep->mac.portmode; 4182 4183 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_init: port<%d>", 4184 portn)); 4185 /* Set Max and Min Frame Size */ 4186 /* 4187 * Use maxframesize to configure the hardware maxframe size 4188 * and minframesize to configure the hardware minframe size. 4189 */ 4190 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4191 "==> nxge_tx_mac_init: port<%d> " 4192 "min framesize %d max framesize %d ", 4193 nxgep->mac.minframesize, 4194 nxgep->mac.maxframesize, 4195 portn)); 4196 4197 SET_MAC_ATTR2(handle, ap, portn, 4198 MAC_PORT_FRAME_SIZE, 4199 nxgep->mac.minframesize, 4200 nxgep->mac.maxframesize, 4201 rs); 4202 if (rs != NPI_SUCCESS) 4203 goto fail; 4204 4205 if (portt == PORT_TYPE_XMAC) { 4206 if ((rs = npi_xmac_tx_iconfig(handle, INIT, portn, 4207 0)) != NPI_SUCCESS) 4208 goto fail; 4209 nxgep->mac.tx_iconfig = NXGE_XMAC_TX_INTRS; 4210 if ((portmode == PORT_10G_FIBER) || 4211 (portmode == PORT_10G_COPPER) || 4212 (portmode == PORT_10G_TN1010) || 4213 (portmode == PORT_HSP_MODE) || 4214 (portmode == PORT_10G_SERDES)) { 4215 SET_MAC_ATTR1(handle, ap, portn, XMAC_10G_PORT_IPG, 4216 XGMII_IPG_12_15, rs); 4217 if (rs != NPI_SUCCESS) 4218 goto fail; 4219 nxgep->mac.ipg[0] = XGMII_IPG_12_15; 4220 } else { 4221 SET_MAC_ATTR1(handle, ap, portn, XMAC_PORT_IPG, 4222 MII_GMII_IPG_12, rs); 4223 if (rs != NPI_SUCCESS) 4224 goto fail; 4225 nxgep->mac.ipg[0] = MII_GMII_IPG_12; 4226 } 4227 if ((rs = npi_xmac_tx_config(handle, INIT, portn, 4228 CFG_XMAC_TX_CRC | CFG_XMAC_TX)) != NPI_SUCCESS) 4229 goto fail; 4230 nxgep->mac.tx_config = CFG_XMAC_TX_CRC | CFG_XMAC_TX; 4231 nxgep->mac.maxburstsize = 0; /* not programmable */ 4232 nxgep->mac.ctrltype = 0; /* not programmable */ 4233 nxgep->mac.pa_size = 0; /* not programmable */ 4234 4235 if ((rs = npi_xmac_zap_tx_counters(handle, portn)) 4236 != NPI_SUCCESS) 4237 goto fail; 4238 4239 } else { 4240 if ((rs = npi_bmac_tx_iconfig(handle, INIT, portn, 4241 0)) != NPI_SUCCESS) 4242 goto fail; 4243 nxgep->mac.tx_iconfig = NXGE_BMAC_TX_INTRS; 4244 4245 SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_CTRL_TYPE, 0x8808, 4246 rs); 4247 if (rs != NPI_SUCCESS) 4248 goto fail; 4249 nxgep->mac.ctrltype = 0x8808; 4250 4251 SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_PA_SIZE, 0x7, rs); 4252 if (rs != NPI_SUCCESS) 4253 goto fail; 4254 nxgep->mac.pa_size = 0x7; 4255 4256 if ((rs = npi_bmac_tx_config(handle, INIT, portn, 4257 CFG_BMAC_TX_CRC | CFG_BMAC_TX)) != NPI_SUCCESS) 4258 goto fail; 4259 nxgep->mac.tx_config = CFG_BMAC_TX_CRC | CFG_BMAC_TX; 4260 } 4261 4262 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_init: port<%d>", 4263 portn)); 4264 4265 return (NXGE_OK); 4266 fail: 4267 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4268 "nxge_tx_mac_init: failed to initialize port<%d> TXMAC", portn)); 4269 4270 return (NXGE_ERROR | rs); 4271 } 4272 4273 static npi_status_t 4274 nxge_rx_mac_mcast_hash_table(p_nxge_t nxgep) 4275 { 4276 uint32_t i; 4277 uint16_t hashtab_e; 4278 p_hash_filter_t hash_filter; 4279 uint8_t portn; 4280 npi_handle_t handle; 4281 npi_status_t rs = NPI_SUCCESS; 4282 4283 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 4284 handle = nxgep->npi_handle; 4285 4286 /* 4287 * Load the multicast hash filter bits. 4288 */ 4289 hash_filter = nxgep->hash_filter; 4290 for (i = 0; i < MAC_MAX_HASH_ENTRY; i++) { 4291 if (hash_filter != NULL) { 4292 hashtab_e = (uint16_t)hash_filter->hash_filter_regs[ 4293 (NMCFILTER_REGS - 1) - i]; 4294 } else { 4295 hashtab_e = 0; 4296 } 4297 4298 if ((rs = npi_mac_hashtab_entry(handle, OP_SET, portn, i, 4299 (uint16_t *)&hashtab_e)) != NPI_SUCCESS) 4300 return (rs); 4301 } 4302 4303 return (NPI_SUCCESS); 4304 } 4305 4306 /* 4307 * Initialize the RxMAC sub-block 4308 */ 4309 nxge_status_t 4310 nxge_rx_mac_init(p_nxge_t nxgep) 4311 { 4312 npi_attr_t ap; 4313 nxge_port_t portt; 4314 uint8_t portn; 4315 npi_handle_t handle; 4316 npi_status_t rs = NPI_SUCCESS; 4317 uint16_t *addr16p; 4318 uint16_t addr0, addr1, addr2; 4319 xmac_rx_config_t xconfig; 4320 bmac_rx_config_t bconfig; 4321 4322 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 4323 4324 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_init: port<%d>\n", 4325 portn)); 4326 handle = nxgep->npi_handle; 4327 portt = nxgep->mac.porttype; 4328 4329 addr16p = (uint16_t *)nxgep->ouraddr.ether_addr_octet; 4330 addr0 = ntohs(addr16p[2]); 4331 addr1 = ntohs(addr16p[1]); 4332 addr2 = ntohs(addr16p[0]); 4333 SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR, 4334 addr0, addr1, addr2, rs); 4335 if (rs != NPI_SUCCESS) 4336 goto fail; 4337 SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR_FILTER, 0, 0, 0, rs); 4338 if (rs != NPI_SUCCESS) 4339 goto fail; 4340 SET_MAC_ATTR2(handle, ap, portn, MAC_PORT_ADDR_FILTER_MASK, 0, 0, rs); 4341 if (rs != NPI_SUCCESS) 4342 goto fail; 4343 4344 rs = nxge_rx_mac_mcast_hash_table(nxgep); 4345 if (rs != NPI_SUCCESS) 4346 goto fail; 4347 4348 if (portt == PORT_TYPE_XMAC) { 4349 if ((rs = npi_xmac_rx_iconfig(handle, INIT, portn, 4350 0)) != NPI_SUCCESS) 4351 goto fail; 4352 nxgep->mac.rx_iconfig = NXGE_XMAC_RX_INTRS; 4353 4354 (void) nxge_fflp_init_hostinfo(nxgep); 4355 4356 xconfig = CFG_XMAC_RX_ERRCHK | CFG_XMAC_RX_CRC_CHK | 4357 CFG_XMAC_RX | CFG_XMAC_RX_CODE_VIO_CHK & 4358 ~CFG_XMAC_RX_STRIP_CRC; 4359 4360 if (nxgep->filter.all_phys_cnt != 0) 4361 xconfig |= CFG_XMAC_RX_PROMISCUOUS; 4362 if (nxgep->filter.all_multicast_cnt != 0) 4363 xconfig |= CFG_XMAC_RX_PROMISCUOUSGROUP; 4364 4365 xconfig |= CFG_XMAC_RX_HASH_FILTER; 4366 4367 if ((rs = npi_xmac_rx_config(handle, INIT, 4368 portn, xconfig)) != NPI_SUCCESS) 4369 goto fail; 4370 nxgep->mac.rx_config = xconfig; 4371 4372 /* 4373 * Comparison of mac unique address is always 4374 * enabled on XMAC 4375 */ 4376 if ((rs = npi_xmac_zap_rx_counters(handle, portn)) 4377 != NPI_SUCCESS) 4378 goto fail; 4379 } else { 4380 if (npi_bmac_rx_iconfig(nxgep->npi_handle, INIT, portn, 4381 0) != NPI_SUCCESS) 4382 goto fail; 4383 4384 nxgep->mac.rx_iconfig = NXGE_BMAC_RX_INTRS; 4385 4386 (void) nxge_fflp_init_hostinfo(nxgep); 4387 4388 bconfig = CFG_BMAC_RX_DISCARD_ON_ERR | CFG_BMAC_RX & 4389 ~CFG_BMAC_RX_STRIP_CRC; 4390 4391 if (nxgep->filter.all_phys_cnt != 0) 4392 bconfig |= CFG_BMAC_RX_PROMISCUOUS; 4393 if (nxgep->filter.all_multicast_cnt != 0) 4394 bconfig |= CFG_BMAC_RX_PROMISCUOUSGROUP; 4395 4396 bconfig |= CFG_BMAC_RX_HASH_FILTER; 4397 if ((rs = npi_bmac_rx_config(handle, INIT, 4398 portn, bconfig)) != NPI_SUCCESS) 4399 goto fail; 4400 nxgep->mac.rx_config = bconfig; 4401 4402 /* 4403 * Always enable comparison of mac unique address 4404 */ 4405 if ((rs = npi_mac_altaddr_enable(handle, 4406 portn, 0)) != NPI_SUCCESS) 4407 goto fail; 4408 } 4409 4410 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_init: port<%d>\n", 4411 portn)); 4412 4413 return (NXGE_OK); 4414 4415 fail: 4416 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4417 "nxge_rx_mac_init: Failed to Initialize port<%d> RxMAC", portn)); 4418 4419 return (NXGE_ERROR | rs); 4420 } 4421 4422 /* Enable TXMAC */ 4423 4424 nxge_status_t 4425 nxge_tx_mac_enable(p_nxge_t nxgep) 4426 { 4427 npi_handle_t handle; 4428 npi_status_t rs = NPI_SUCCESS; 4429 nxge_status_t status = NXGE_OK; 4430 4431 handle = nxgep->npi_handle; 4432 4433 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_enable: port<%d>", 4434 nxgep->mac.portnum)); 4435 4436 if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK) 4437 goto fail; 4438 4439 /* based on speed */ 4440 nxgep->msg_min = ETHERMIN; 4441 4442 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 4443 if ((rs = npi_xmac_tx_config(handle, ENABLE, nxgep->mac.portnum, 4444 CFG_XMAC_TX)) != NPI_SUCCESS) 4445 goto fail; 4446 } else { 4447 if ((rs = npi_bmac_tx_config(handle, ENABLE, nxgep->mac.portnum, 4448 CFG_BMAC_TX)) != NPI_SUCCESS) 4449 goto fail; 4450 } 4451 4452 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_enable: port<%d>", 4453 nxgep->mac.portnum)); 4454 4455 return (NXGE_OK); 4456 fail: 4457 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4458 "nxgep_tx_mac_enable: Failed to enable port<%d> TxMAC", 4459 nxgep->mac.portnum)); 4460 if (rs != NPI_SUCCESS) 4461 return (NXGE_ERROR | rs); 4462 else 4463 return (status); 4464 } 4465 4466 /* Disable TXMAC */ 4467 4468 nxge_status_t 4469 nxge_tx_mac_disable(p_nxge_t nxgep) 4470 { 4471 npi_handle_t handle; 4472 npi_status_t rs = NPI_SUCCESS; 4473 4474 if (isLDOMguest(nxgep)) 4475 return (NXGE_OK); 4476 4477 handle = nxgep->npi_handle; 4478 4479 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_disable: port<%d>", 4480 nxgep->mac.portnum)); 4481 4482 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 4483 if ((rs = npi_xmac_tx_config(handle, DISABLE, 4484 nxgep->mac.portnum, CFG_XMAC_TX)) != NPI_SUCCESS) 4485 goto fail; 4486 } else { 4487 if ((rs = npi_bmac_tx_config(handle, DISABLE, 4488 nxgep->mac.portnum, CFG_BMAC_TX)) != NPI_SUCCESS) 4489 goto fail; 4490 } 4491 4492 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_disable: port<%d>", 4493 nxgep->mac.portnum)); 4494 return (NXGE_OK); 4495 fail: 4496 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4497 "nxge_tx_mac_disable: Failed to disable port<%d> TxMAC", 4498 nxgep->mac.portnum)); 4499 return (NXGE_ERROR | rs); 4500 } 4501 4502 /* Enable RXMAC */ 4503 4504 nxge_status_t 4505 nxge_rx_mac_enable(p_nxge_t nxgep) 4506 { 4507 npi_handle_t handle; 4508 uint8_t portn; 4509 npi_status_t rs = NPI_SUCCESS; 4510 nxge_status_t status = NXGE_OK; 4511 4512 /* This is a service-domain-only activity. */ 4513 if (isLDOMguest(nxgep)) 4514 return (status); 4515 4516 handle = nxgep->npi_handle; 4517 portn = nxgep->mac.portnum; 4518 4519 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_enable: port<%d>", 4520 portn)); 4521 4522 if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK) 4523 goto fail; 4524 4525 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 4526 if ((rs = npi_xmac_rx_config(handle, ENABLE, portn, 4527 CFG_XMAC_RX)) != NPI_SUCCESS) 4528 goto fail; 4529 } else { 4530 if ((rs = npi_bmac_rx_config(handle, ENABLE, portn, 4531 CFG_BMAC_RX)) != NPI_SUCCESS) 4532 goto fail; 4533 } 4534 4535 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4536 "<== nxge_rx_mac_enable: port<%d>", portn)); 4537 4538 return (NXGE_OK); 4539 fail: 4540 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4541 "nxgep_rx_mac_enable: Failed to enable port<%d> RxMAC", portn)); 4542 4543 if (rs != NPI_SUCCESS) 4544 return (NXGE_ERROR | rs); 4545 else 4546 return (status); 4547 } 4548 4549 /* Disable RXMAC */ 4550 4551 nxge_status_t 4552 nxge_rx_mac_disable(p_nxge_t nxgep) 4553 { 4554 npi_handle_t handle; 4555 uint8_t portn; 4556 npi_status_t rs = NPI_SUCCESS; 4557 4558 /* If we are a guest domain driver, don't bother. */ 4559 if (isLDOMguest(nxgep)) 4560 return (NXGE_OK); 4561 4562 handle = nxgep->npi_handle; 4563 portn = nxgep->mac.portnum; 4564 4565 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_disable: port<%d>", 4566 portn)); 4567 4568 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 4569 if ((rs = npi_xmac_rx_config(handle, DISABLE, portn, 4570 CFG_XMAC_RX)) != NPI_SUCCESS) 4571 goto fail; 4572 } else { 4573 if ((rs = npi_bmac_rx_config(handle, DISABLE, portn, 4574 CFG_BMAC_RX)) != NPI_SUCCESS) 4575 goto fail; 4576 } 4577 4578 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_disable: port<%d>", 4579 portn)); 4580 return (NXGE_OK); 4581 fail: 4582 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4583 "nxgep_rx_mac_disable: Failed to disable port<%d> RxMAC", portn)); 4584 4585 return (NXGE_ERROR | rs); 4586 } 4587 4588 /* Reset TXMAC */ 4589 4590 nxge_status_t 4591 nxge_tx_mac_reset(p_nxge_t nxgep) 4592 { 4593 npi_handle_t handle; 4594 uint8_t portn; 4595 npi_status_t rs = NPI_SUCCESS; 4596 4597 handle = nxgep->npi_handle; 4598 portn = nxgep->mac.portnum; 4599 4600 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_reset: port<%d>", 4601 portn)); 4602 4603 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 4604 if ((rs = npi_xmac_reset(handle, portn, XTX_MAC_RESET_ALL)) 4605 != NPI_SUCCESS) 4606 goto fail; 4607 } else { 4608 if ((rs = npi_bmac_reset(handle, portn, TX_MAC_RESET)) 4609 != NPI_SUCCESS) 4610 goto fail; 4611 } 4612 4613 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_reset: port<%d>", 4614 portn)); 4615 4616 return (NXGE_OK); 4617 fail: 4618 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4619 "nxge_tx_mac_reset: Failed to Reset TxMAC port<%d>", portn)); 4620 4621 return (NXGE_ERROR | rs); 4622 } 4623 4624 /* Reset RXMAC */ 4625 4626 nxge_status_t 4627 nxge_rx_mac_reset(p_nxge_t nxgep) 4628 { 4629 npi_handle_t handle; 4630 uint8_t portn; 4631 npi_status_t rs = NPI_SUCCESS; 4632 4633 handle = nxgep->npi_handle; 4634 portn = nxgep->mac.portnum; 4635 4636 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_reset: port<%d>", 4637 portn)); 4638 4639 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 4640 if ((rs = npi_xmac_reset(handle, portn, XRX_MAC_RESET_ALL)) 4641 != NPI_SUCCESS) 4642 goto fail; 4643 } else { 4644 if ((rs = npi_bmac_reset(handle, portn, RX_MAC_RESET)) 4645 != NPI_SUCCESS) 4646 goto fail; 4647 } 4648 4649 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_reset: port<%d>", 4650 portn)); 4651 4652 return (NXGE_OK); 4653 fail: 4654 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4655 "nxge_rx_mac_reset: Failed to Reset RxMAC port<%d>", portn)); 4656 return (NXGE_ERROR | rs); 4657 } 4658 4659 /* 10G fiber link interrupt start routine */ 4660 4661 static nxge_status_t 4662 nxge_10G_link_intr_start(p_nxge_t nxgep) 4663 { 4664 npi_status_t rs = NPI_SUCCESS; 4665 uint8_t portn = nxgep->mac.portnum; 4666 4667 rs = npi_xmac_xpcs_link_intr_enable(nxgep->npi_handle, portn); 4668 4669 if (rs != NPI_SUCCESS) 4670 return (NXGE_ERROR | rs); 4671 else 4672 return (NXGE_OK); 4673 } 4674 4675 /* 10G fiber link interrupt stop routine */ 4676 4677 static nxge_status_t 4678 nxge_10G_link_intr_stop(p_nxge_t nxgep) 4679 { 4680 npi_status_t rs = NPI_SUCCESS; 4681 uint8_t portn = nxgep->mac.portnum; 4682 4683 rs = npi_xmac_xpcs_link_intr_disable(nxgep->npi_handle, portn); 4684 4685 if (rs != NPI_SUCCESS) 4686 return (NXGE_ERROR | rs); 4687 else 4688 return (NXGE_OK); 4689 } 4690 4691 /* 1G fiber link interrupt start routine */ 4692 4693 static nxge_status_t 4694 nxge_1G_fiber_link_intr_start(p_nxge_t nxgep) 4695 { 4696 npi_status_t rs = NPI_SUCCESS; 4697 uint8_t portn = nxgep->mac.portnum; 4698 4699 rs = npi_mac_pcs_link_intr_enable(nxgep->npi_handle, portn); 4700 if (rs != NPI_SUCCESS) 4701 return (NXGE_ERROR | rs); 4702 else 4703 return (NXGE_OK); 4704 } 4705 4706 /* 1G fiber link interrupt stop routine */ 4707 4708 static nxge_status_t 4709 nxge_1G_fiber_link_intr_stop(p_nxge_t nxgep) 4710 { 4711 npi_status_t rs = NPI_SUCCESS; 4712 uint8_t portn = nxgep->mac.portnum; 4713 4714 rs = npi_mac_pcs_link_intr_disable(nxgep->npi_handle, portn); 4715 4716 if (rs != NPI_SUCCESS) 4717 return (NXGE_ERROR | rs); 4718 else 4719 return (NXGE_OK); 4720 } 4721 4722 /* 1G copper link interrupt start routine */ 4723 4724 static nxge_status_t 4725 nxge_1G_copper_link_intr_start(p_nxge_t nxgep) 4726 { 4727 npi_status_t rs = NPI_SUCCESS; 4728 uint8_t portn = nxgep->mac.portnum; 4729 4730 rs = npi_mac_mif_link_intr_enable(nxgep->npi_handle, portn, 4731 MII_STATUS, MII_STATUS_LINKUP); 4732 4733 if (rs != NPI_SUCCESS) 4734 return (NXGE_ERROR | rs); 4735 else 4736 return (NXGE_OK); 4737 } 4738 4739 /* 1G copper link interrupt stop routine */ 4740 4741 static nxge_status_t 4742 nxge_1G_copper_link_intr_stop(p_nxge_t nxgep) 4743 { 4744 npi_status_t rs = NPI_SUCCESS; 4745 uint8_t portn = nxgep->mac.portnum; 4746 4747 rs = npi_mac_mif_link_intr_disable(nxgep->npi_handle, portn); 4748 4749 if (rs != NPI_SUCCESS) 4750 return (NXGE_ERROR | rs); 4751 else 4752 return (NXGE_OK); 4753 } 4754 4755 /* Enable/Disable Link Status change interrupt */ 4756 4757 nxge_status_t 4758 nxge_link_intr(p_nxge_t nxgep, link_intr_enable_t enable) 4759 { 4760 uint8_t portn; 4761 nxge_status_t status = NXGE_OK; 4762 4763 portn = nxgep->mac.portnum; 4764 4765 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_intr: port<%d>", portn)); 4766 if (!nxgep->xcvr.link_intr_stop || !nxgep->xcvr.link_intr_start) 4767 return (NXGE_OK); 4768 4769 if (enable == LINK_INTR_START) 4770 status = nxgep->xcvr.link_intr_start(nxgep); 4771 else if (enable == LINK_INTR_STOP) 4772 status = nxgep->xcvr.link_intr_stop(nxgep); 4773 if (status != NXGE_OK) 4774 goto fail; 4775 4776 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_intr: port<%d>", portn)); 4777 4778 return (NXGE_OK); 4779 fail: 4780 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4781 "nxge_link_intr: Failed to set port<%d> mif intr mode", portn)); 4782 4783 return (status); 4784 } 4785 4786 /* Initialize 1G Fiber / Copper transceiver using Clause 22 */ 4787 4788 nxge_status_t 4789 nxge_mii_xcvr_init(p_nxge_t nxgep) 4790 { 4791 p_nxge_param_t param_arr; 4792 p_nxge_stats_t statsp; 4793 uint8_t xcvr_portn; 4794 p_mii_regs_t mii_regs; 4795 mii_bmcr_t bmcr; 4796 mii_bmsr_t bmsr; 4797 mii_anar_t anar; 4798 mii_gcr_t gcr; 4799 mii_esr_t esr; 4800 mii_aux_ctl_t bcm5464r_aux; 4801 int status = NXGE_OK; 4802 4803 uint_t delay; 4804 4805 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_init")); 4806 4807 param_arr = nxgep->param_arr; 4808 statsp = nxgep->statsp; 4809 xcvr_portn = statsp->mac_stats.xcvr_portn; 4810 4811 mii_regs = NULL; 4812 4813 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4814 "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value)); 4815 4816 /* 4817 * The mif phy mode may be connected to either a copper link 4818 * or fiber link. Read the mode control register to get the fiber 4819 * configuration if it is hard-wired to fiber link. 4820 */ 4821 (void) nxge_mii_get_link_mode(nxgep); 4822 if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) { 4823 return (nxge_mii_xcvr_fiber_init(nxgep)); 4824 } 4825 4826 /* 4827 * Reset the transceiver. 4828 */ 4829 delay = 0; 4830 bmcr.value = 0; 4831 bmcr.bits.reset = 1; 4832 if ((status = nxge_mii_write(nxgep, xcvr_portn, 4833 (uint8_t)(uint64_t)&mii_regs->bmcr, 4834 bmcr.value)) != NXGE_OK) 4835 goto fail; 4836 do { 4837 drv_usecwait(500); 4838 if ((status = nxge_mii_read(nxgep, xcvr_portn, 4839 (uint8_t)(uint64_t)&mii_regs->bmcr, 4840 &bmcr.value)) != NXGE_OK) 4841 goto fail; 4842 delay++; 4843 } while ((bmcr.bits.reset) && (delay < 1000)); 4844 if (delay == 1000) { 4845 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed.")); 4846 goto fail; 4847 } 4848 4849 if ((status = nxge_mii_read(nxgep, xcvr_portn, 4850 (uint8_t)(uint64_t)(&mii_regs->bmsr), 4851 &bmsr.value)) != NXGE_OK) 4852 goto fail; 4853 4854 param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able; 4855 param_arr[param_anar_100T4].value &= bmsr.bits.link_100T4; 4856 param_arr[param_anar_100fdx].value &= bmsr.bits.link_100fdx; 4857 param_arr[param_anar_100hdx].value = 0; 4858 param_arr[param_anar_10fdx].value &= bmsr.bits.link_10fdx; 4859 param_arr[param_anar_10hdx].value = 0; 4860 4861 /* 4862 * Initialize the xcvr statistics. 4863 */ 4864 statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able; 4865 statsp->mac_stats.cap_100T4 = bmsr.bits.link_100T4; 4866 statsp->mac_stats.cap_100fdx = bmsr.bits.link_100fdx; 4867 statsp->mac_stats.cap_100hdx = 0; 4868 statsp->mac_stats.cap_10fdx = bmsr.bits.link_10fdx; 4869 statsp->mac_stats.cap_10hdx = 0; 4870 statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value; 4871 statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value; 4872 4873 /* 4874 * Initialize the xcvr advertised capability statistics. 4875 */ 4876 statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value; 4877 statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 4878 statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 4879 statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value; 4880 statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value; 4881 statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value; 4882 statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value; 4883 statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value; 4884 statsp->mac_stats.adv_cap_asmpause = 4885 param_arr[param_anar_asmpause].value; 4886 statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value; 4887 4888 4889 /* 4890 * Check for extended status just in case we're 4891 * running a Gigibit phy. 4892 */ 4893 if (bmsr.bits.extend_status) { 4894 if ((status = nxge_mii_read(nxgep, xcvr_portn, 4895 (uint8_t)(uint64_t)(&mii_regs->esr), 4896 &esr.value)) != NXGE_OK) 4897 goto fail; 4898 param_arr[param_anar_1000fdx].value &= esr.bits.link_1000fdx; 4899 param_arr[param_anar_1000hdx].value = 0; 4900 4901 statsp->mac_stats.cap_1000fdx = 4902 (esr.bits.link_1000Xfdx || esr.bits.link_1000fdx); 4903 statsp->mac_stats.cap_1000hdx = 0; 4904 } else { 4905 param_arr[param_anar_1000fdx].value = 0; 4906 param_arr[param_anar_1000hdx].value = 0; 4907 } 4908 4909 /* 4910 * Initialize 1G Statistics once the capability is established. 4911 */ 4912 statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 4913 statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 4914 4915 /* 4916 * Initialize the link statistics. 4917 */ 4918 statsp->mac_stats.link_T4 = 0; 4919 statsp->mac_stats.link_asmpause = 0; 4920 statsp->mac_stats.link_pause = 0; 4921 statsp->mac_stats.link_speed = 0; 4922 statsp->mac_stats.link_duplex = 0; 4923 statsp->mac_stats.link_up = 0; 4924 4925 /* 4926 * Switch off Auto-negotiation, 100M and full duplex. 4927 */ 4928 bmcr.value = 0; 4929 if ((status = nxge_mii_write(nxgep, xcvr_portn, 4930 (uint8_t)(uint64_t)(&mii_regs->bmcr), 4931 bmcr.value)) != NXGE_OK) 4932 goto fail; 4933 4934 if ((statsp->port_stats.lb_mode == nxge_lb_phy) || 4935 (statsp->port_stats.lb_mode == nxge_lb_phy1000)) { 4936 bmcr.bits.loopback = 1; 4937 bmcr.bits.enable_autoneg = 0; 4938 if (statsp->port_stats.lb_mode == nxge_lb_phy1000) 4939 bmcr.bits.speed_1000_sel = 1; 4940 bmcr.bits.duplex_mode = 1; 4941 param_arr[param_autoneg].value = 0; 4942 } else { 4943 bmcr.bits.loopback = 0; 4944 } 4945 4946 if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) || 4947 (statsp->port_stats.lb_mode == nxge_lb_ext100) || 4948 (statsp->port_stats.lb_mode == nxge_lb_ext10)) { 4949 param_arr[param_autoneg].value = 0; 4950 bcm5464r_aux.value = 0; 4951 bcm5464r_aux.bits.ext_lb = 1; 4952 bcm5464r_aux.bits.write_1 = 1; 4953 if ((status = nxge_mii_write(nxgep, xcvr_portn, 4954 BCM5464R_AUX_CTL, bcm5464r_aux.value)) != NXGE_OK) 4955 goto fail; 4956 } 4957 4958 /* If auto-negotiation is desired */ 4959 if (param_arr[param_autoneg].value) { 4960 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4961 "Restarting Auto-negotiation.")); 4962 /* 4963 * Setup our Auto-negotiation advertisement register. 4964 */ 4965 anar.value = 0; 4966 anar.bits.selector = 1; 4967 anar.bits.cap_100T4 = param_arr[param_anar_100T4].value; 4968 anar.bits.cap_100fdx = param_arr[param_anar_100fdx].value; 4969 anar.bits.cap_100hdx = param_arr[param_anar_100hdx].value; 4970 anar.bits.cap_10fdx = param_arr[param_anar_10fdx].value; 4971 anar.bits.cap_10hdx = param_arr[param_anar_10hdx].value; 4972 anar.bits.cap_asmpause = 0; 4973 anar.bits.cap_pause = 0; 4974 if (param_arr[param_anar_1000fdx].value || 4975 param_arr[param_anar_100fdx].value || 4976 param_arr[param_anar_10fdx].value) { 4977 anar.bits.cap_asmpause = statsp->mac_stats.cap_asmpause; 4978 anar.bits.cap_pause = statsp->mac_stats.cap_pause; 4979 } 4980 4981 /* Write to the auto-negotiation advertisement register */ 4982 if ((status = nxge_mii_write(nxgep, xcvr_portn, 4983 (uint8_t)(uint64_t)(&mii_regs->anar), 4984 anar.value)) != NXGE_OK) 4985 goto fail; 4986 if (bmsr.bits.extend_status) { 4987 gcr.value = 0; 4988 gcr.bits.ms_mode_en = 4989 param_arr[param_master_cfg_enable].value; 4990 gcr.bits.master = 4991 param_arr[param_master_cfg_value].value; 4992 gcr.bits.link_1000fdx = 4993 param_arr[param_anar_1000fdx].value; 4994 gcr.bits.link_1000hdx = 4995 param_arr[param_anar_1000hdx].value; 4996 if ((status = nxge_mii_write(nxgep, xcvr_portn, 4997 (uint8_t)(uint64_t)(&mii_regs->gcr), 4998 gcr.value)) != NXGE_OK) 4999 goto fail; 5000 } 5001 5002 bmcr.bits.enable_autoneg = 1; 5003 bmcr.bits.restart_autoneg = 1; 5004 5005 } else { 5006 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode.")); 5007 bmcr.bits.speed_1000_sel = 5008 param_arr[param_anar_1000fdx].value | 5009 param_arr[param_anar_1000hdx].value; 5010 bmcr.bits.speed_sel = (~bmcr.bits.speed_1000_sel) & 5011 (param_arr[param_anar_100fdx].value | 5012 param_arr[param_anar_100hdx].value); 5013 5014 /* Force to 1G */ 5015 if (bmcr.bits.speed_1000_sel) { 5016 statsp->mac_stats.link_speed = 1000; 5017 gcr.value = 0; 5018 gcr.bits.ms_mode_en = 5019 param_arr[param_master_cfg_enable].value; 5020 gcr.bits.master = 5021 param_arr[param_master_cfg_value].value; 5022 if ((status = nxge_mii_write(nxgep, xcvr_portn, 5023 (uint8_t)(uint64_t)(&mii_regs->gcr), 5024 gcr.value)) != NXGE_OK) 5025 goto fail; 5026 if (param_arr[param_anar_1000fdx].value) { 5027 bmcr.bits.duplex_mode = 1; 5028 statsp->mac_stats.link_duplex = 2; 5029 } else 5030 statsp->mac_stats.link_duplex = 1; 5031 5032 /* Force to 100M */ 5033 } else if (bmcr.bits.speed_sel) { 5034 statsp->mac_stats.link_speed = 100; 5035 if (param_arr[param_anar_100fdx].value) { 5036 bmcr.bits.duplex_mode = 1; 5037 statsp->mac_stats.link_duplex = 2; 5038 } else 5039 statsp->mac_stats.link_duplex = 1; 5040 5041 /* Force to 10M */ 5042 } else { 5043 statsp->mac_stats.link_speed = 10; 5044 if (param_arr[param_anar_10fdx].value) { 5045 bmcr.bits.duplex_mode = 1; 5046 statsp->mac_stats.link_duplex = 2; 5047 } else 5048 statsp->mac_stats.link_duplex = 1; 5049 } 5050 if (statsp->mac_stats.link_duplex != 1) { 5051 statsp->mac_stats.link_asmpause = 5052 statsp->mac_stats.cap_asmpause; 5053 statsp->mac_stats.link_pause = 5054 statsp->mac_stats.cap_pause; 5055 } 5056 5057 if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) || 5058 (statsp->port_stats.lb_mode == nxge_lb_ext100) || 5059 (statsp->port_stats.lb_mode == nxge_lb_ext10)) { 5060 if (statsp->port_stats.lb_mode == nxge_lb_ext1000) { 5061 /* BCM5464R 1000mbps external loopback mode */ 5062 gcr.value = 0; 5063 gcr.bits.ms_mode_en = 1; 5064 gcr.bits.master = 1; 5065 if ((status = nxge_mii_write(nxgep, xcvr_portn, 5066 (uint8_t)(uint64_t)(&mii_regs->gcr), 5067 gcr.value)) != NXGE_OK) 5068 goto fail; 5069 bmcr.value = 0; 5070 bmcr.bits.speed_1000_sel = 1; 5071 statsp->mac_stats.link_speed = 1000; 5072 } else if (statsp->port_stats.lb_mode 5073 == nxge_lb_ext100) { 5074 /* BCM5464R 100mbps external loopback mode */ 5075 bmcr.value = 0; 5076 bmcr.bits.speed_sel = 1; 5077 bmcr.bits.duplex_mode = 1; 5078 statsp->mac_stats.link_speed = 100; 5079 } else if (statsp->port_stats.lb_mode 5080 == nxge_lb_ext10) { 5081 /* BCM5464R 10mbps external loopback mode */ 5082 bmcr.value = 0; 5083 bmcr.bits.duplex_mode = 1; 5084 statsp->mac_stats.link_speed = 10; 5085 } 5086 } 5087 } 5088 5089 if ((status = nxge_mii_write(nxgep, xcvr_portn, 5090 (uint8_t)(uint64_t)(&mii_regs->bmcr), 5091 bmcr.value)) != NXGE_OK) 5092 goto fail; 5093 5094 if ((status = nxge_mii_read(nxgep, xcvr_portn, 5095 (uint8_t)(uint64_t)(&mii_regs->bmcr), 5096 &bmcr.value)) != NXGE_OK) 5097 goto fail; 5098 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "bmcr = 0x%04X", bmcr.value)); 5099 5100 /* 5101 * Initialize the xcvr status kept in the context structure. 5102 */ 5103 nxgep->soft_bmsr.value = 0; 5104 5105 if ((status = nxge_mii_read(nxgep, xcvr_portn, 5106 (uint8_t)(uint64_t)(&mii_regs->bmsr), 5107 &nxgep->bmsr.value)) != NXGE_OK) 5108 goto fail; 5109 5110 statsp->mac_stats.xcvr_inits++; 5111 nxgep->bmsr.value = 0; 5112 5113 fail: 5114 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5115 "<== nxge_mii_xcvr_init status 0x%x", status)); 5116 return (status); 5117 } 5118 5119 nxge_status_t 5120 nxge_mii_xcvr_fiber_init(p_nxge_t nxgep) 5121 { 5122 p_nxge_param_t param_arr; 5123 p_nxge_stats_t statsp; 5124 uint8_t xcvr_portn; 5125 p_mii_regs_t mii_regs; 5126 mii_bmcr_t bmcr; 5127 mii_bmsr_t bmsr; 5128 mii_gcr_t gcr; 5129 mii_esr_t esr; 5130 mii_aux_ctl_t bcm5464r_aux; 5131 int status = NXGE_OK; 5132 5133 uint_t delay; 5134 5135 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_fiber_init")); 5136 5137 param_arr = nxgep->param_arr; 5138 statsp = nxgep->statsp; 5139 xcvr_portn = statsp->mac_stats.xcvr_portn; 5140 5141 mii_regs = NULL; 5142 5143 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5144 "nxge_mii_xcvr_fiber_init: " 5145 "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value)); 5146 5147 /* 5148 * Reset the transceiver. 5149 */ 5150 delay = 0; 5151 bmcr.value = 0; 5152 bmcr.bits.reset = 1; 5153 5154 if ((status = nxge_mii_write(nxgep, xcvr_portn, 5155 (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 5156 goto fail; 5157 do { 5158 drv_usecwait(500); 5159 if ((status = nxge_mii_read(nxgep, xcvr_portn, 5160 (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) 5161 != NXGE_OK) 5162 goto fail; 5163 delay++; 5164 } while ((bmcr.bits.reset) && (delay < 1000)); 5165 if (delay == 1000) { 5166 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed.")); 5167 goto fail; 5168 } 5169 5170 if ((status = nxge_mii_read(nxgep, xcvr_portn, 5171 (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK) 5172 goto fail; 5173 5174 param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able; 5175 param_arr[param_anar_100T4].value = 0; 5176 param_arr[param_anar_100fdx].value = 0; 5177 param_arr[param_anar_100hdx].value = 0; 5178 param_arr[param_anar_10fdx].value = 0; 5179 param_arr[param_anar_10hdx].value = 0; 5180 5181 /* 5182 * Initialize the xcvr statistics. 5183 */ 5184 statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able; 5185 statsp->mac_stats.cap_100T4 = 0; 5186 statsp->mac_stats.cap_100fdx = 0; 5187 statsp->mac_stats.cap_100hdx = 0; 5188 statsp->mac_stats.cap_10fdx = 0; 5189 statsp->mac_stats.cap_10hdx = 0; 5190 statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value; 5191 statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value; 5192 5193 /* 5194 * Initialize the xcvr advertised capability statistics. 5195 */ 5196 statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value; 5197 statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 5198 statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 5199 statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value; 5200 statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value; 5201 statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value; 5202 statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value; 5203 statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value; 5204 statsp->mac_stats.adv_cap_asmpause = 5205 param_arr[param_anar_asmpause].value; 5206 statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value; 5207 5208 /* 5209 * Check for extended status just in case we're 5210 * running a Gigibit phy. 5211 */ 5212 if (bmsr.bits.extend_status) { 5213 if ((status = nxge_mii_read(nxgep, xcvr_portn, 5214 (uint8_t)(uint64_t)(&mii_regs->esr), &esr.value)) != 5215 NXGE_OK) 5216 goto fail; 5217 param_arr[param_anar_1000fdx].value &= 5218 esr.bits.link_1000fdx; 5219 param_arr[param_anar_1000hdx].value = 0; 5220 5221 statsp->mac_stats.cap_1000fdx = 5222 (esr.bits.link_1000Xfdx || esr.bits.link_1000fdx); 5223 statsp->mac_stats.cap_1000hdx = 0; 5224 } else { 5225 param_arr[param_anar_1000fdx].value = 0; 5226 param_arr[param_anar_1000hdx].value = 0; 5227 } 5228 5229 /* 5230 * Initialize 1G Statistics once the capability is established. 5231 */ 5232 statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 5233 statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 5234 5235 /* 5236 * Initialize the link statistics. 5237 */ 5238 statsp->mac_stats.link_T4 = 0; 5239 statsp->mac_stats.link_asmpause = 0; 5240 statsp->mac_stats.link_pause = 0; 5241 statsp->mac_stats.link_speed = 0; 5242 statsp->mac_stats.link_duplex = 0; 5243 statsp->mac_stats.link_up = 0; 5244 5245 /* 5246 * Switch off Auto-negotiation, 100M and full duplex. 5247 */ 5248 bmcr.value = 0; 5249 if ((status = nxge_mii_write(nxgep, xcvr_portn, 5250 (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 5251 goto fail; 5252 5253 if ((statsp->port_stats.lb_mode == nxge_lb_phy) || 5254 (statsp->port_stats.lb_mode == nxge_lb_phy1000)) { 5255 bmcr.bits.loopback = 1; 5256 bmcr.bits.enable_autoneg = 0; 5257 if (statsp->port_stats.lb_mode == nxge_lb_phy1000) 5258 bmcr.bits.speed_1000_sel = 1; 5259 bmcr.bits.duplex_mode = 1; 5260 param_arr[param_autoneg].value = 0; 5261 } else { 5262 bmcr.bits.loopback = 0; 5263 } 5264 5265 if (statsp->port_stats.lb_mode == nxge_lb_ext1000) { 5266 param_arr[param_autoneg].value = 0; 5267 bcm5464r_aux.value = 0; 5268 bcm5464r_aux.bits.ext_lb = 1; 5269 bcm5464r_aux.bits.write_1 = 1; 5270 if ((status = nxge_mii_write(nxgep, xcvr_portn, 5271 BCM5464R_AUX_CTL, bcm5464r_aux.value)) != NXGE_OK) 5272 goto fail; 5273 } 5274 5275 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode.")); 5276 bmcr.bits.speed_1000_sel = 1; 5277 bmcr.bits.speed_sel = 0; 5278 bmcr.bits.duplex_mode = 1; 5279 statsp->mac_stats.link_speed = 1000; 5280 statsp->mac_stats.link_duplex = 2; 5281 5282 if ((statsp->port_stats.lb_mode == nxge_lb_ext1000)) { 5283 /* BCM5464R 1000mbps external loopback mode */ 5284 gcr.value = 0; 5285 gcr.bits.ms_mode_en = 1; 5286 gcr.bits.master = 1; 5287 if ((status = nxge_mii_write(nxgep, xcvr_portn, 5288 (uint8_t)(uint64_t)(&mii_regs->gcr), 5289 gcr.value)) != NXGE_OK) 5290 goto fail; 5291 bmcr.value = 0; 5292 bmcr.bits.speed_1000_sel = 1; 5293 statsp->mac_stats.link_speed = 1000; 5294 } 5295 5296 if ((status = nxge_mii_write(nxgep, xcvr_portn, 5297 (uint8_t)(uint64_t)(&mii_regs->bmcr), 5298 bmcr.value)) != NXGE_OK) 5299 goto fail; 5300 5301 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5302 "nxge_mii_xcvr_fiber_init: value wrote bmcr = 0x%x", 5303 bmcr.value)); 5304 5305 if ((status = nxge_mii_read(nxgep, xcvr_portn, 5306 (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK) 5307 goto fail; 5308 5309 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5310 "nxge_mii_xcvr_fiber_init: read bmcr = 0x%04X", bmcr.value)); 5311 5312 /* 5313 * Initialize the xcvr status kept in the context structure. 5314 */ 5315 nxgep->soft_bmsr.value = 0; 5316 if ((status = nxge_mii_read(nxgep, xcvr_portn, 5317 (uint8_t)(uint64_t)(&mii_regs->bmsr), 5318 &nxgep->bmsr.value)) != NXGE_OK) 5319 goto fail; 5320 5321 statsp->mac_stats.xcvr_inits++; 5322 nxgep->bmsr.value = 0; 5323 5324 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5325 "<== nxge_mii_xcvr_fiber_init status 0x%x", status)); 5326 return (status); 5327 5328 fail: 5329 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5330 "<== nxge_mii_xcvr_fiber_init status 0x%x", status)); 5331 return (status); 5332 } 5333 5334 /* Read from a MII compliant register */ 5335 5336 nxge_status_t 5337 nxge_mii_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg, 5338 uint16_t *value) 5339 { 5340 npi_status_t rs = NPI_SUCCESS; 5341 5342 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_read: xcvr_port<%d>" 5343 "xcvr_reg<%d>", xcvr_portn, xcvr_reg)); 5344 5345 MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 5346 5347 if ((nxgep->mac.portmode == PORT_1G_COPPER) || 5348 (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) { 5349 if ((rs = npi_mac_mif_mii_read(nxgep->npi_handle, 5350 xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 5351 goto fail; 5352 } else if ((nxgep->mac.portmode == PORT_1G_FIBER) || 5353 (nxgep->mac.portmode == PORT_1G_SERDES)) { 5354 if ((rs = npi_mac_pcs_mii_read(nxgep->npi_handle, 5355 xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 5356 goto fail; 5357 } else 5358 goto fail; 5359 5360 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 5361 5362 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_read: xcvr_port<%d>" 5363 "xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg, *value)); 5364 return (NXGE_OK); 5365 fail: 5366 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 5367 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5368 "nxge_mii_read: Failed to read mii on xcvr %d", xcvr_portn)); 5369 5370 return (NXGE_ERROR | rs); 5371 } 5372 5373 /* Write to a MII compliant Register */ 5374 5375 nxge_status_t 5376 nxge_mii_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg, 5377 uint16_t value) 5378 { 5379 npi_status_t rs = NPI_SUCCESS; 5380 5381 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_write: xcvr_port<%d>" 5382 "xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg, value)); 5383 5384 MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 5385 5386 if ((nxgep->mac.portmode == PORT_1G_COPPER) || 5387 (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) { 5388 if ((rs = npi_mac_mif_mii_write(nxgep->npi_handle, 5389 xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 5390 goto fail; 5391 } else if ((nxgep->mac.portmode == PORT_1G_FIBER) || 5392 (nxgep->mac.portmode == PORT_1G_SERDES)) { 5393 if ((rs = npi_mac_pcs_mii_write(nxgep->npi_handle, 5394 xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 5395 goto fail; 5396 } else 5397 goto fail; 5398 5399 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 5400 5401 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_write: xcvr_port<%d>" 5402 "xcvr_reg<%d>", xcvr_portn, xcvr_reg)); 5403 return (NXGE_OK); 5404 fail: 5405 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 5406 5407 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5408 "nxge_mii_write: Failed to write mii on xcvr %d", xcvr_portn)); 5409 5410 return (NXGE_ERROR | rs); 5411 } 5412 5413 /* 5414 * Perform write to Clause45 serdes / transceiver device 5415 * Arguments: 5416 * xcvr_portn: The IEEE 802.3 Clause45 PHYAD, it is the same as port 5417 * number if nxge_mdio_write is used for accessing the 5418 * internal LSIL serdes. Otherwise PHYAD is different 5419 * for different platforms. 5420 * device: With each PHYAD, the driver can use MDIO to control 5421 * multiple devices inside the PHY, here "device" is an 5422 * MMD (MDIO managable device). 5423 * xcvr_reg: Each device has multiple registers. xcvr_reg specifies 5424 * the register which the driver will write value to. 5425 * value: The register value will be filled in. 5426 */ 5427 nxge_status_t 5428 nxge_mdio_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device, 5429 uint16_t xcvr_reg, uint16_t *value) 5430 { 5431 npi_status_t rs = NPI_SUCCESS; 5432 5433 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_read: xcvr_port<%d>", 5434 xcvr_portn)); 5435 5436 MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 5437 5438 if ((rs = npi_mac_mif_mdio_read(nxgep->npi_handle, 5439 xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS) 5440 goto fail; 5441 5442 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 5443 5444 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_read: xcvr_port<%d>", 5445 xcvr_portn)); 5446 return (NXGE_OK); 5447 fail: 5448 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 5449 5450 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5451 "nxge_mdio_read: Failed to read mdio on xcvr %d", xcvr_portn)); 5452 5453 return (NXGE_ERROR | rs); 5454 } 5455 5456 /* Perform write to Clause45 serdes / transceiver device */ 5457 5458 nxge_status_t 5459 nxge_mdio_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device, 5460 uint16_t xcvr_reg, uint16_t value) 5461 { 5462 npi_status_t rs = NPI_SUCCESS; 5463 5464 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_write: xcvr_port<%d>", 5465 xcvr_portn)); 5466 5467 MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 5468 5469 if ((rs = npi_mac_mif_mdio_write(nxgep->npi_handle, 5470 xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS) 5471 goto fail; 5472 5473 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 5474 5475 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_write: xcvr_port<%d>", 5476 xcvr_portn)); 5477 return (NXGE_OK); 5478 fail: 5479 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 5480 5481 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5482 "nxge_mdio_write: Failed to write mdio on xcvr %d", xcvr_portn)); 5483 5484 return (NXGE_ERROR | rs); 5485 } 5486 5487 5488 /* Check MII to see if there is any link status change */ 5489 5490 nxge_status_t 5491 nxge_mii_check(p_nxge_t nxgep, mii_bmsr_t bmsr, mii_bmsr_t bmsr_ints, 5492 nxge_link_state_t *link_up) 5493 { 5494 p_nxge_param_t param_arr; 5495 p_nxge_stats_t statsp; 5496 p_mii_regs_t mii_regs; 5497 p_mii_bmsr_t soft_bmsr; 5498 mii_anar_t anar; 5499 mii_anlpar_t anlpar; 5500 mii_anar_t an_common; 5501 mii_aner_t aner; 5502 mii_gsr_t gsr; 5503 nxge_status_t status = NXGE_OK; 5504 5505 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_check")); 5506 5507 mii_regs = NULL; 5508 param_arr = nxgep->param_arr; 5509 statsp = nxgep->statsp; 5510 soft_bmsr = &nxgep->soft_bmsr; 5511 *link_up = LINK_NO_CHANGE; 5512 5513 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5514 "==> nxge_mii_check bmsr 0x%x bmsr_int 0x%x", 5515 bmsr.value, bmsr_ints.value)); 5516 5517 if (bmsr_ints.bits.link_status) { 5518 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5519 "==> nxge_mii_check (link up) bmsr 0x%x bmsr_int 0x%x", 5520 bmsr.value, bmsr_ints.value)); 5521 if (bmsr.bits.link_status) { 5522 soft_bmsr->bits.link_status = 1; 5523 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5524 "==> nxge_mii_check (link up) soft bmsr 0x%x bmsr_int " 5525 "0x%x", bmsr.value, bmsr_ints.value)); 5526 } else { 5527 /* Only status change will update *link_up */ 5528 if (statsp->mac_stats.link_up == 1) { 5529 *link_up = LINK_IS_DOWN; 5530 /* Will notify, turn off further msg */ 5531 nxgep->link_notify = B_FALSE; 5532 } 5533 statsp->mac_stats.link_up = 0; 5534 soft_bmsr->bits.link_status = 0; 5535 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5536 "Link down cable problem")); 5537 } 5538 } 5539 5540 if (nxgep->mac.portmode == PORT_1G_COPPER && 5541 param_arr[param_autoneg].value) { 5542 if (bmsr_ints.bits.auto_neg_complete) { 5543 if (bmsr.bits.auto_neg_complete) 5544 soft_bmsr->bits.auto_neg_complete = 1; 5545 else 5546 soft_bmsr->bits.auto_neg_complete = 0; 5547 } 5548 if (soft_bmsr->bits.link_status == 0) { 5549 statsp->mac_stats.link_T4 = 0; 5550 statsp->mac_stats.link_speed = 0; 5551 statsp->mac_stats.link_duplex = 0; 5552 statsp->mac_stats.link_asmpause = 0; 5553 statsp->mac_stats.link_pause = 0; 5554 statsp->mac_stats.lp_cap_autoneg = 0; 5555 statsp->mac_stats.lp_cap_100T4 = 0; 5556 statsp->mac_stats.lp_cap_1000fdx = 0; 5557 statsp->mac_stats.lp_cap_1000hdx = 0; 5558 statsp->mac_stats.lp_cap_100fdx = 0; 5559 statsp->mac_stats.lp_cap_100hdx = 0; 5560 statsp->mac_stats.lp_cap_10fdx = 0; 5561 statsp->mac_stats.lp_cap_10hdx = 0; 5562 statsp->mac_stats.lp_cap_10gfdx = 0; 5563 statsp->mac_stats.lp_cap_10ghdx = 0; 5564 statsp->mac_stats.lp_cap_asmpause = 0; 5565 statsp->mac_stats.lp_cap_pause = 0; 5566 } 5567 } else 5568 soft_bmsr->bits.auto_neg_complete = 1; 5569 5570 if ((bmsr_ints.bits.link_status || 5571 bmsr_ints.bits.auto_neg_complete) && 5572 soft_bmsr->bits.link_status && 5573 soft_bmsr->bits.auto_neg_complete) { 5574 if (statsp->mac_stats.link_up == 0) { 5575 *link_up = LINK_IS_UP; 5576 nxgep->link_notify = B_FALSE; 5577 } 5578 statsp->mac_stats.link_up = 1; 5579 5580 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5581 "==> nxge_mii_check " 5582 "(auto negotiation complete or link up) " 5583 "soft bmsr 0x%x bmsr_int 0x%x", 5584 bmsr.value, bmsr_ints.value)); 5585 5586 if (nxgep->mac.portmode == PORT_1G_COPPER && 5587 param_arr[param_autoneg].value) { 5588 if ((status = nxge_mii_read(nxgep, 5589 statsp->mac_stats.xcvr_portn, 5590 (uint8_t)(uint64_t)(&mii_regs->anar), 5591 &anar.value)) != NXGE_OK) 5592 goto fail; 5593 if ((status = nxge_mii_read(nxgep, 5594 statsp->mac_stats.xcvr_portn, 5595 (uint8_t)(uint64_t)(&mii_regs->anlpar), 5596 &anlpar.value)) != NXGE_OK) 5597 goto fail; 5598 if ((status = nxge_mii_read(nxgep, 5599 statsp->mac_stats.xcvr_portn, 5600 (uint8_t)(uint64_t)(&mii_regs->aner), 5601 &aner.value)) != NXGE_OK) 5602 goto fail; 5603 statsp->mac_stats.lp_cap_autoneg = aner.bits.lp_an_able; 5604 statsp->mac_stats.lp_cap_100T4 = anlpar.bits.cap_100T4; 5605 statsp->mac_stats.lp_cap_100fdx = 5606 anlpar.bits.cap_100fdx; 5607 statsp->mac_stats.lp_cap_100hdx = 5608 anlpar.bits.cap_100hdx; 5609 statsp->mac_stats.lp_cap_10fdx = anlpar.bits.cap_10fdx; 5610 statsp->mac_stats.lp_cap_10hdx = anlpar.bits.cap_10hdx; 5611 statsp->mac_stats.lp_cap_asmpause = 5612 anlpar.bits.cap_asmpause; 5613 statsp->mac_stats.lp_cap_pause = anlpar.bits.cap_pause; 5614 an_common.value = anar.value & anlpar.value; 5615 if (param_arr[param_anar_1000fdx].value || 5616 param_arr[param_anar_1000hdx].value) { 5617 if ((status = nxge_mii_read(nxgep, 5618 statsp->mac_stats.xcvr_portn, 5619 (uint8_t)(uint64_t)(&mii_regs->gsr), 5620 &gsr.value)) != NXGE_OK) 5621 goto fail; 5622 statsp->mac_stats.lp_cap_1000fdx = 5623 gsr.bits.link_1000fdx; 5624 statsp->mac_stats.lp_cap_1000hdx = 5625 gsr.bits.link_1000hdx; 5626 if (param_arr[param_anar_1000fdx].value && 5627 gsr.bits.link_1000fdx) { 5628 statsp->mac_stats.link_speed = 1000; 5629 statsp->mac_stats.link_duplex = 2; 5630 } else if ( 5631 param_arr[param_anar_1000hdx].value && 5632 gsr.bits.link_1000hdx) { 5633 statsp->mac_stats.link_speed = 1000; 5634 statsp->mac_stats.link_duplex = 1; 5635 } 5636 } 5637 if ((an_common.value != 0) && 5638 !(statsp->mac_stats.link_speed)) { 5639 if (an_common.bits.cap_100T4) { 5640 statsp->mac_stats.link_T4 = 1; 5641 statsp->mac_stats.link_speed = 100; 5642 statsp->mac_stats.link_duplex = 1; 5643 } else if (an_common.bits.cap_100fdx) { 5644 statsp->mac_stats.link_speed = 100; 5645 statsp->mac_stats.link_duplex = 2; 5646 } else if (an_common.bits.cap_100hdx) { 5647 statsp->mac_stats.link_speed = 100; 5648 statsp->mac_stats.link_duplex = 1; 5649 } else if (an_common.bits.cap_10fdx) { 5650 statsp->mac_stats.link_speed = 10; 5651 statsp->mac_stats.link_duplex = 2; 5652 } else if (an_common.bits.cap_10hdx) { 5653 statsp->mac_stats.link_speed = 10; 5654 statsp->mac_stats.link_duplex = 1; 5655 } else { 5656 goto fail; 5657 } 5658 } 5659 if (statsp->mac_stats.link_duplex != 1) { 5660 int link_pause; 5661 int cp, lcp; 5662 5663 statsp->mac_stats.link_asmpause = 5664 an_common.bits.cap_asmpause; 5665 cp = statsp->mac_stats.cap_pause; 5666 lcp = statsp->mac_stats.lp_cap_pause; 5667 if (statsp->mac_stats.link_asmpause) { 5668 if ((cp == 0) && (lcp == 1)) { 5669 link_pause = 0; 5670 } else { 5671 link_pause = 1; 5672 } 5673 } else { 5674 link_pause = an_common.bits.cap_pause; 5675 } 5676 statsp->mac_stats.link_pause = link_pause; 5677 } 5678 } else if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) { 5679 statsp->mac_stats.link_speed = 1000; 5680 statsp->mac_stats.link_duplex = 2; 5681 } 5682 } 5683 /* Initial link_notify, delay link down msg */ 5684 if (nxgep->link_notify && nxgep->nxge_mac_state == NXGE_MAC_STARTED && 5685 (statsp->mac_stats.link_up == 1 || nxgep->link_check_count > 3)) { 5686 *link_up = ((statsp->mac_stats.link_up) ? LINK_IS_UP : 5687 LINK_IS_DOWN); 5688 nxgep->link_notify = B_FALSE; 5689 } 5690 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mii_check")); 5691 return (NXGE_OK); 5692 fail: 5693 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5694 "nxge_mii_check: Unable to check MII")); 5695 return (status); 5696 } 5697 5698 /* 5699 * Check PCS to see if there is any link status change. 5700 * This function is called by PORT_1G_SERDES only. 5701 */ 5702 void 5703 nxge_pcs_check(p_nxge_t nxgep, uint8_t portn, nxge_link_state_t *link_up) 5704 { 5705 p_nxge_stats_t statsp; 5706 boolean_t linkup; 5707 5708 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_check")); 5709 5710 statsp = nxgep->statsp; 5711 *link_up = LINK_NO_CHANGE; 5712 5713 (void) npi_mac_get_link_status(nxgep->npi_handle, portn, &linkup); 5714 if (linkup) { 5715 if ((nxgep->link_notify && 5716 nxgep->nxge_mac_state == NXGE_MAC_STARTED) || 5717 nxgep->statsp->mac_stats.link_up == 0) { 5718 statsp->mac_stats.link_up = 1; 5719 statsp->mac_stats.link_speed = 1000; 5720 statsp->mac_stats.link_duplex = 2; 5721 *link_up = LINK_IS_UP; 5722 nxgep->link_notify = B_FALSE; 5723 } 5724 } else { 5725 if ((nxgep->link_notify && nxgep->link_check_count > 3 && 5726 nxgep->nxge_mac_state == NXGE_MAC_STARTED) || 5727 nxgep->statsp->mac_stats.link_up == 1) { 5728 statsp->mac_stats.link_up = 0; 5729 statsp->mac_stats.link_speed = 0; 5730 statsp->mac_stats.link_duplex = 0; 5731 *link_up = LINK_IS_DOWN; 5732 nxgep->link_notify = B_FALSE; 5733 } 5734 } 5735 5736 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_check")); 5737 } 5738 5739 /* Add a multicast address entry into the HW hash table */ 5740 5741 nxge_status_t 5742 nxge_add_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp) 5743 { 5744 uint32_t mchash; 5745 p_hash_filter_t hash_filter; 5746 uint16_t hash_bit; 5747 uint_t j; 5748 nxge_status_t status = NXGE_OK; 5749 npi_status_t rs; 5750 5751 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_add_mcast_addr")); 5752 5753 RW_ENTER_WRITER(&nxgep->filter_lock); 5754 mchash = crc32_mchash(addrp); 5755 if (nxgep->hash_filter == NULL) { 5756 NXGE_DEBUG_MSG((NULL, STR_CTL, 5757 "Allocating hash filter storage.")); 5758 nxgep->hash_filter = KMEM_ZALLOC(sizeof (hash_filter_t), 5759 KM_SLEEP); 5760 } 5761 5762 hash_filter = nxgep->hash_filter; 5763 j = mchash / HASH_REG_WIDTH; 5764 hash_bit = (1 << (mchash % HASH_REG_WIDTH)); 5765 hash_filter->hash_filter_regs[j] |= hash_bit; 5766 hash_filter->hash_bit_ref_cnt[mchash]++; 5767 if (hash_filter->hash_bit_ref_cnt[mchash] == 1) { 5768 hash_filter->hash_ref_cnt++; 5769 } 5770 5771 rs = nxge_rx_mac_mcast_hash_table(nxgep); 5772 if (rs != NPI_SUCCESS) 5773 goto fail; 5774 5775 RW_EXIT(&nxgep->filter_lock); 5776 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_add_mcast_addr")); 5777 return (NXGE_OK); 5778 fail: 5779 RW_EXIT(&nxgep->filter_lock); 5780 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_add_mcast_addr: " 5781 "Unable to add multicast address")); 5782 return (status); 5783 } 5784 5785 /* Remove a multicast address entry from the HW hash table */ 5786 5787 nxge_status_t 5788 nxge_del_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp) 5789 { 5790 uint32_t mchash; 5791 p_hash_filter_t hash_filter; 5792 uint16_t hash_bit; 5793 uint_t j; 5794 nxge_status_t status = NXGE_OK; 5795 npi_status_t rs; 5796 5797 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_del_mcast_addr")); 5798 RW_ENTER_WRITER(&nxgep->filter_lock); 5799 mchash = crc32_mchash(addrp); 5800 if (nxgep->hash_filter == NULL) { 5801 NXGE_DEBUG_MSG((NULL, STR_CTL, 5802 "Hash filter already de_allocated.")); 5803 RW_EXIT(&nxgep->filter_lock); 5804 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr")); 5805 return (NXGE_OK); 5806 } 5807 hash_filter = nxgep->hash_filter; 5808 hash_filter->hash_bit_ref_cnt[mchash]--; 5809 if (hash_filter->hash_bit_ref_cnt[mchash] == 0) { 5810 j = mchash / HASH_REG_WIDTH; 5811 hash_bit = (1 << (mchash % HASH_REG_WIDTH)); 5812 hash_filter->hash_filter_regs[j] &= ~hash_bit; 5813 hash_filter->hash_ref_cnt--; 5814 } 5815 5816 if (hash_filter->hash_ref_cnt == 0) { 5817 NXGE_DEBUG_MSG((NULL, STR_CTL, 5818 "De-allocating hash filter storage.")); 5819 KMEM_FREE(hash_filter, sizeof (hash_filter_t)); 5820 nxgep->hash_filter = NULL; 5821 } 5822 5823 rs = nxge_rx_mac_mcast_hash_table(nxgep); 5824 if (rs != NPI_SUCCESS) 5825 goto fail; 5826 5827 RW_EXIT(&nxgep->filter_lock); 5828 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr")); 5829 5830 return (NXGE_OK); 5831 fail: 5832 RW_EXIT(&nxgep->filter_lock); 5833 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_del_mcast_addr: " 5834 "Unable to remove multicast address")); 5835 5836 return (status); 5837 } 5838 5839 /* Set MAC address into MAC address HW registers */ 5840 5841 nxge_status_t 5842 nxge_set_mac_addr(p_nxge_t nxgep, struct ether_addr *addrp) 5843 { 5844 nxge_status_t status = NXGE_OK; 5845 5846 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_mac_addr")); 5847 5848 MUTEX_ENTER(&nxgep->ouraddr_lock); 5849 /* 5850 * Exit if the address is same as ouraddr or multicast or broadcast 5851 */ 5852 if (((addrp->ether_addr_octet[0] & 01) == 1) || 5853 (ether_cmp(addrp, ðerbroadcastaddr) == 0) || 5854 (ether_cmp(addrp, &nxgep->ouraddr) == 0)) { 5855 goto nxge_set_mac_addr_exit; 5856 } 5857 nxgep->ouraddr = *addrp; 5858 /* 5859 * Set new interface local address and re-init device. 5860 * This is destructive to any other streams attached 5861 * to this device. 5862 */ 5863 RW_ENTER_WRITER(&nxgep->filter_lock); 5864 if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 5865 goto fail; 5866 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 5867 goto fail; 5868 5869 RW_EXIT(&nxgep->filter_lock); 5870 MUTEX_EXIT(&nxgep->ouraddr_lock); 5871 goto nxge_set_mac_addr_end; 5872 nxge_set_mac_addr_exit: 5873 MUTEX_EXIT(&nxgep->ouraddr_lock); 5874 nxge_set_mac_addr_end: 5875 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_mac_addr")); 5876 5877 return (NXGE_OK); 5878 fail: 5879 MUTEX_EXIT(&nxgep->ouraddr_lock); 5880 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_mac_addr: " 5881 "Unable to set mac address")); 5882 return (status); 5883 } 5884 5885 static 5886 check_link_state_t 5887 nxge_check_link_stop(nxge_t *nxge) 5888 { 5889 /* If the poll has been cancelled, return STOP. */ 5890 MUTEX_ENTER(&nxge->poll_lock); 5891 if (nxge->suspended || nxge->poll_state == LINK_MONITOR_STOPPING) { 5892 nxge->poll_state = LINK_MONITOR_STOP; 5893 nxge->nxge_link_poll_timerid = 0; 5894 cv_broadcast(&nxge->poll_cv); 5895 MUTEX_EXIT(&nxge->poll_lock); 5896 5897 NXGE_DEBUG_MSG((nxge, MAC_CTL, 5898 "nxge_check_%s_link(port<%d>) stopped.", 5899 nxge->mac.portmode == PORT_10G_FIBER ? "10g" : "mii", 5900 nxge->mac.portnum)); 5901 return (CHECK_LINK_STOP); 5902 } 5903 MUTEX_EXIT(&nxge->poll_lock); 5904 5905 return (CHECK_LINK_RESCHEDULE); 5906 } 5907 5908 /* 5909 * Check status of MII (MIF or PCS) link. 5910 * This function is called once per second, that is because this function 5911 * calls nxge_link_monitor with LINK_MONITOR_START, which starts a timer to 5912 * call this function recursively. 5913 */ 5914 static nxge_status_t 5915 nxge_check_mii_link(p_nxge_t nxgep) 5916 { 5917 mii_bmsr_t bmsr_ints, bmsr_data; 5918 mii_anlpar_t anlpar; 5919 mii_gsr_t gsr; 5920 p_mii_regs_t mii_regs; 5921 nxge_status_t status = NXGE_OK; 5922 uint8_t portn; 5923 nxge_link_state_t link_up; 5924 5925 if (nxgep->nxge_magic != NXGE_MAGIC) 5926 return (NXGE_ERROR); 5927 5928 if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 5929 return (NXGE_OK); 5930 5931 portn = nxgep->mac.portnum; 5932 5933 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_mii_link port<%d>", 5934 portn)); 5935 5936 mii_regs = NULL; 5937 5938 RW_ENTER_WRITER(&nxgep->filter_lock); 5939 5940 if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10) 5941 goto nxge_check_mii_link_exit; 5942 5943 switch (nxgep->mac.portmode) { 5944 default: 5945 bmsr_data.value = 0; 5946 if ((status = nxge_mii_read(nxgep, 5947 nxgep->statsp->mac_stats.xcvr_portn, 5948 (uint8_t)(uint64_t)(&mii_regs->bmsr), 5949 &bmsr_data.value)) != NXGE_OK) { 5950 goto fail; 5951 } 5952 5953 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5954 "==> nxge_check_mii_link port<0x%x> " 5955 "RIGHT AFTER READ bmsr_data 0x%x (nxgep->bmsr 0x%x ", 5956 portn, bmsr_data.value, nxgep->bmsr.value)); 5957 5958 if (nxgep->param_arr[param_autoneg].value) { 5959 if ((status = nxge_mii_read(nxgep, 5960 nxgep->statsp->mac_stats.xcvr_portn, 5961 (uint8_t)(uint64_t)(&mii_regs->gsr), 5962 &gsr.value)) != NXGE_OK) 5963 goto fail; 5964 if ((status = nxge_mii_read(nxgep, 5965 nxgep->statsp->mac_stats.xcvr_portn, 5966 (uint8_t)(uint64_t)(&mii_regs->anlpar), 5967 &anlpar.value)) != NXGE_OK) 5968 goto fail; 5969 if (nxgep->mac.portmode != PORT_1G_RGMII_FIBER) { 5970 5971 if (nxgep->statsp->mac_stats.link_up && 5972 ((nxgep->statsp->mac_stats.lp_cap_1000fdx ^ 5973 gsr.bits.link_1000fdx) || 5974 (nxgep->statsp->mac_stats.lp_cap_1000hdx ^ 5975 gsr.bits.link_1000hdx) || 5976 (nxgep->statsp->mac_stats.lp_cap_100T4 ^ 5977 anlpar.bits.cap_100T4) || 5978 (nxgep->statsp->mac_stats.lp_cap_100fdx ^ 5979 anlpar.bits.cap_100fdx) || 5980 (nxgep->statsp->mac_stats.lp_cap_100hdx ^ 5981 anlpar.bits.cap_100hdx) || 5982 (nxgep->statsp->mac_stats.lp_cap_10fdx ^ 5983 anlpar.bits.cap_10fdx) || 5984 (nxgep->statsp->mac_stats.lp_cap_10hdx ^ 5985 anlpar.bits.cap_10hdx))) { 5986 bmsr_data.bits.link_status = 0; 5987 } 5988 } 5989 } 5990 5991 /* Workaround for link down issue */ 5992 if (bmsr_data.value == 0) { 5993 cmn_err(CE_NOTE, "!LINK DEBUG: Read zero bmsr\n"); 5994 goto nxge_check_mii_link_exit; 5995 } 5996 5997 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5998 "==> nxge_check_mii_link port<0x%x> :" 5999 "BEFORE BMSR ^ nxgep->bmsr 0x%x bmsr_data 0x%x", 6000 portn, nxgep->bmsr.value, bmsr_data.value)); 6001 6002 bmsr_ints.value = nxgep->bmsr.value ^ bmsr_data.value; 6003 nxgep->bmsr.value = bmsr_data.value; 6004 6005 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6006 "==> nxge_check_mii_link port<0x%x> CALLING " 6007 "bmsr_data 0x%x bmsr_ints.value 0x%x", 6008 portn, bmsr_data.value, bmsr_ints.value)); 6009 6010 if ((status = nxge_mii_check(nxgep, bmsr_data, bmsr_ints, 6011 &link_up)) != NXGE_OK) { 6012 goto fail; 6013 } 6014 break; 6015 6016 case PORT_1G_SERDES: 6017 /* 6018 * Above default is for all cases except PORT_1G_SERDES. 6019 * The default case gets information from the PHY, but a 6020 * nxge whose portmode equals PORT_1G_SERDES does not 6021 * have a PHY. 6022 */ 6023 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6024 "==> nxge_check_mii_link port<%d> (SERDES)", portn)); 6025 nxge_pcs_check(nxgep, portn, &link_up); 6026 break; 6027 } 6028 6029 nxge_check_mii_link_exit: 6030 RW_EXIT(&nxgep->filter_lock); 6031 if (link_up == LINK_IS_UP) { 6032 nxge_link_is_up(nxgep); 6033 } else if (link_up == LINK_IS_DOWN) { 6034 nxge_link_is_down(nxgep); 6035 } 6036 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 6037 6038 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_mii_link port<%d>", 6039 portn)); 6040 return (NXGE_OK); 6041 6042 fail: 6043 RW_EXIT(&nxgep->filter_lock); 6044 6045 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 6046 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6047 "nxge_check_mii_link: Failed to check link port<%d>", portn)); 6048 return (status); 6049 } 6050 6051 /*ARGSUSED*/ 6052 static nxge_status_t 6053 nxge_check_10g_link(p_nxge_t nxgep) 6054 { 6055 uint8_t portn; 6056 nxge_status_t status = NXGE_OK; 6057 boolean_t link_up; 6058 uint32_t val; 6059 npi_status_t rs; 6060 6061 if (nxgep->nxge_magic != NXGE_MAGIC) 6062 return (NXGE_ERROR); 6063 6064 if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 6065 return (NXGE_OK); 6066 6067 portn = nxgep->mac.portnum; 6068 val = 0; 6069 rs = NPI_SUCCESS; 6070 6071 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_10g_link port<%d>", 6072 portn)); 6073 6074 switch (nxgep->mac.portmode) { 6075 default: 6076 /* 6077 * Check if the phy is present in case of hot swappable phy 6078 */ 6079 if (nxgep->hot_swappable_phy) { 6080 boolean_t phy_present_now = B_FALSE; 6081 6082 if (nxge_hswap_phy_present(nxgep, portn)) 6083 phy_present_now = B_TRUE; 6084 6085 /* Check back-to-back XAUI connect to detect Opus NEM */ 6086 rs = npi_xmac_xpcs_read(nxgep->npi_handle, 6087 nxgep->mac.portnum, XPCS_REG_STATUS, &val); 6088 if (rs != 0) 6089 goto fail; 6090 6091 link_up = B_FALSE; 6092 if (val & XPCS_STATUS_LANE_ALIGN) { 6093 link_up = B_TRUE; 6094 } 6095 6096 if (nxgep->phy_absent) { 6097 if (phy_present_now) { 6098 /* 6099 * Detect, Initialize phy and do link up 6100 * set xcvr vals, link_init, nxge_init 6101 */ 6102 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6103 "Hot swappable phy DETECTED!!")); 6104 nxgep->phy_absent = B_FALSE; 6105 (void) nxge_xcvr_find(nxgep); 6106 (void) nxge_link_init(nxgep); 6107 if (!(nxgep->drv_state & 6108 STATE_HW_INITIALIZED)) { 6109 status = nxge_init(nxgep); 6110 if (status != NXGE_OK) { 6111 NXGE_ERROR_MSG((nxgep, 6112 NXGE_ERR_CTL, 6113 "Hot swappable " 6114 "phy present, but" 6115 " driver init" 6116 " failed...")); 6117 goto fail; 6118 } 6119 } 6120 } else if (link_up) { /* XAUI linkup, no PHY */ 6121 /* 6122 * This is the back-to-back XAUI 6123 * connect case for Opus NEM. 6124 */ 6125 nxgep->statsp->mac_stats.xcvr_inuse = 6126 XPCS_XCVR; 6127 nxgep->mac.portmode = PORT_10G_SERDES; 6128 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6129 "HSP 10G Serdes DETECTED!!")); 6130 break; 6131 } 6132 6133 if (nxgep->link_notify && 6134 nxgep->link_check_count > 3 && 6135 nxgep->nxge_mac_state == NXGE_MAC_STARTED || 6136 nxgep->statsp->mac_stats.link_up == 1) { 6137 nxgep->statsp->mac_stats.link_up = 0; 6138 nxgep->statsp->mac_stats.link_speed = 0; 6139 nxgep->statsp->mac_stats.link_duplex = 6140 0; 6141 6142 nxge_link_is_down(nxgep); 6143 nxgep->link_notify = B_FALSE; 6144 } 6145 6146 goto start_link_check; 6147 6148 } else if (!phy_present_now) { 6149 /* 6150 * Phy gone, bring link down reset xcvr vals 6151 */ 6152 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6153 "Hot swappable phy REMOVED!!")); 6154 nxgep->phy_absent = B_TRUE; 6155 nxgep->statsp->mac_stats.link_up = 0; 6156 nxgep->statsp->mac_stats.link_speed = 0; 6157 nxgep->statsp->mac_stats.link_duplex = 0; 6158 nxge_link_is_down(nxgep); 6159 nxgep->link_notify = B_FALSE; 6160 6161 (void) nxge_xcvr_find(nxgep); 6162 6163 goto start_link_check; 6164 6165 } 6166 } 6167 6168 switch (nxgep->chip_id) { 6169 case MRVL88X201X_CHIP_ID: 6170 status = nxge_check_mrvl88x2011_link(nxgep, &link_up); 6171 break; 6172 case NLP2020_CHIP_ID: 6173 status = nxge_check_nlp2020_link(nxgep, &link_up); 6174 break; 6175 default: 6176 status = nxge_check_bcm8704_link(nxgep, &link_up); 6177 break; 6178 } 6179 6180 if (status != NXGE_OK) 6181 goto fail; 6182 break; 6183 case PORT_10G_SERDES: 6184 rs = npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 6185 XPCS_REG_STATUS, &val); 6186 if (rs != 0) 6187 goto fail; 6188 6189 link_up = B_FALSE; 6190 if (val & XPCS_STATUS_LANE_ALIGN) { 6191 link_up = B_TRUE; 6192 } 6193 6194 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6195 "==> nxge_check_10g_link port<%d> " 6196 "XPCS_REG_STATUS2 0x%x link_up %d", 6197 portn, val, link_up)); 6198 6199 break; 6200 } 6201 6202 if (link_up) { 6203 if ((nxgep->link_notify && 6204 nxgep->nxge_mac_state == NXGE_MAC_STARTED) || 6205 nxgep->statsp->mac_stats.link_up == 0) { 6206 if (nxge_10g_link_led_on(nxgep) != NXGE_OK) 6207 goto fail; 6208 nxgep->statsp->mac_stats.link_up = 1; 6209 nxgep->statsp->mac_stats.link_speed = 10000; 6210 nxgep->statsp->mac_stats.link_duplex = 2; 6211 6212 nxge_link_is_up(nxgep); 6213 nxgep->link_notify = B_FALSE; 6214 } 6215 } else { 6216 if ((nxgep->link_notify && nxgep->link_check_count > 3 && 6217 nxgep->nxge_mac_state == NXGE_MAC_STARTED) || 6218 nxgep->statsp->mac_stats.link_up == 1) { 6219 if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 6220 goto fail; 6221 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6222 "Link down cable problem")); 6223 nxgep->statsp->mac_stats.link_up = 0; 6224 nxgep->statsp->mac_stats.link_speed = 0; 6225 nxgep->statsp->mac_stats.link_duplex = 0; 6226 6227 nxge_link_is_down(nxgep); 6228 nxgep->link_notify = B_FALSE; 6229 6230 if (nxgep->mac.portmode == PORT_10G_SERDES) { 6231 /* 6232 * NEM was unplugged, set up xcvr table 6233 * to find another xcvr in the future. 6234 */ 6235 (void) nxge_xcvr_find(nxgep); 6236 } 6237 } 6238 } 6239 6240 start_link_check: 6241 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 6242 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_10g_link port<%d>", 6243 portn)); 6244 return (NXGE_OK); 6245 6246 fail: 6247 (void) nxge_check_link_stop(nxgep); 6248 6249 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6250 "nxge_check_10g_link: Failed to check link port<%d>", 6251 portn)); 6252 return (status); 6253 } 6254 6255 6256 /* Declare link down */ 6257 6258 void 6259 nxge_link_is_down(p_nxge_t nxgep) 6260 { 6261 p_nxge_stats_t statsp; 6262 char link_stat_msg[64]; 6263 6264 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_down")); 6265 6266 statsp = nxgep->statsp; 6267 (void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is down", 6268 statsp->mac_stats.xcvr_portn); 6269 6270 if (nxge_no_msg == B_FALSE) { 6271 NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg)); 6272 } 6273 6274 mac_link_update(nxgep->mach, LINK_STATE_DOWN); 6275 6276 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_down")); 6277 } 6278 6279 /* Declare link up */ 6280 6281 void 6282 nxge_link_is_up(p_nxge_t nxgep) 6283 { 6284 p_nxge_stats_t statsp; 6285 char link_stat_msg[64]; 6286 uint32_t val; 6287 6288 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_up")); 6289 6290 statsp = nxgep->statsp; 6291 (void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is up %d Mbps ", 6292 statsp->mac_stats.xcvr_portn, 6293 statsp->mac_stats.link_speed); 6294 6295 if (statsp->mac_stats.link_T4) 6296 (void) strcat(link_stat_msg, "T4"); 6297 else if (statsp->mac_stats.link_duplex == 2) 6298 (void) strcat(link_stat_msg, "full duplex"); 6299 else 6300 (void) strcat(link_stat_msg, "half duplex"); 6301 6302 6303 /* Clean up symbol errors incurred during link transition */ 6304 if ((nxgep->mac.portmode == PORT_10G_FIBER) || 6305 (nxgep->mac.portmode == PORT_10G_COPPER) || 6306 (nxgep->mac.portmode == PORT_10G_SERDES)) { 6307 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 6308 XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val); 6309 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 6310 XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val); 6311 } 6312 6313 /* 6314 * If the driver was plumbed without a link (therefore auto-negotiation 6315 * could not complete), the driver will detect a link up when a cable 6316 * conneting to a link partner is plugged into the port. By the time 6317 * link-up is detected, auto-negotiation should have completed (The 6318 * TN1010 tries to contact a link partner every 8~24ms). Here we re- 6319 * configure the Neptune/NIU according to the newly negotiated speed. 6320 * This is necessary only for the TN1010 basad device because only the 6321 * TN1010 supports dual speeds. 6322 */ 6323 if (nxgep->mac.portmode == PORT_1G_TN1010 || 6324 nxgep->mac.portmode == PORT_10G_TN1010) { 6325 6326 (void) nxge_set_tn1010_param(nxgep); 6327 6328 /* 6329 * nxge_xcvr_find calls nxge_get_xcvr_type (which sets 6330 * nxgep->portmode) and nxge_setup_xcvr_table (which sets 6331 * the nxgep->xcvr to the proper nxge_xcvr_table_t struct). 6332 */ 6333 if (nxge_xcvr_find(nxgep) != NXGE_OK) { 6334 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6335 "nxge_link_is_up: nxge_xcvr_find failed")); 6336 } 6337 6338 /* nxge_link_init calls nxge_xcvr_init and nxge_serdes_init */ 6339 if (nxge_link_init(nxgep) != NXGE_OK) { 6340 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6341 "nxge_link_is_up: nxge_link_init failed")); 6342 } 6343 6344 /* 6345 * nxge_mac_init calls many subroutines including 6346 * nxge_xif_init which sets XGMII or GMII mode 6347 */ 6348 if (nxge_mac_init(nxgep) != NXGE_OK) { 6349 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6350 "nxge_link_is_up: nxge_mac_init failed")); 6351 } 6352 } else { 6353 (void) nxge_xif_init(nxgep); 6354 } 6355 6356 if (nxge_no_msg == B_FALSE) { 6357 NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg)); 6358 } 6359 6360 mac_link_update(nxgep->mach, LINK_STATE_UP); 6361 6362 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_up")); 6363 } 6364 6365 #ifdef NXGE_DEBUG 6366 /* Dump all TN1010 Status registers */ 6367 static void 6368 nxge_dump_tn1010_status_regs(p_nxge_t nxgep) 6369 { 6370 uint16_t val; 6371 6372 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 6373 TN1010_PMA_PMD_DEV_ADDR, 1, &val); 6374 cmn_err(CE_NOTE, "PMA status1 = 0x%x", val); 6375 6376 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 6377 TN1010_PMA_PMD_DEV_ADDR, 8, &val); 6378 cmn_err(CE_NOTE, "PMA status2 = 0x%x", val); 6379 6380 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 6381 TN1010_PMA_PMD_DEV_ADDR, 129, &val); 6382 cmn_err(CE_NOTE, "10BASET-T status = 0x%x", val); 6383 6384 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 6385 TN1010_PCS_DEV_ADDR, 1, &val); 6386 cmn_err(CE_NOTE, "PCS status1 = 0x%x", val); 6387 6388 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 6389 TN1010_PCS_DEV_ADDR, 8, &val); 6390 cmn_err(CE_NOTE, "PCS status2 = 0x%x", val); 6391 6392 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 6393 TN1010_PCS_DEV_ADDR, 32, &val); 6394 cmn_err(CE_NOTE, "10GBASE-R status1 = 0x%x", val); 6395 6396 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 6397 TN1010_PCS_DEV_ADDR, 33, &val); 6398 cmn_err(CE_NOTE, "10GBASE-R Status2 = 0x%x", val); 6399 6400 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 6401 TN1010_PHYXS_DEV_ADDR, 1, &val); 6402 cmn_err(CE_NOTE, "PHYXS status1 = 0x%x", val); 6403 6404 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 6405 TN1010_PHYXS_DEV_ADDR, 8, &val); 6406 cmn_err(CE_NOTE, "PHYXS status2 = 0x%x", val); 6407 6408 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 6409 TN1010_PHYXS_DEV_ADDR, 24, &val); 6410 cmn_err(CE_NOTE, "XGXS Lane status = 0x%x", val); 6411 6412 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 6413 TN1010_AUTONEG_DEV_ADDR, 1, &val); 6414 cmn_err(CE_NOTE, "Autoneg status = 0x%x", val); 6415 6416 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 6417 TN1010_AUTONEG_DEV_ADDR, 33, &val); 6418 cmn_err(CE_NOTE, "10Gbase-T An status = 0x%x", val); 6419 6420 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 6421 TN1010_VENDOR_MMD1_DEV_ADDR, 1, &val); 6422 cmn_err(CE_NOTE, "TN1010 status = 0x%x", val); 6423 6424 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 6425 TN1010_VENDOR_MMD1_DEV_ADDR, 8, &val); 6426 cmn_err(CE_NOTE, "Device status = 0x%x", val); 6427 6428 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 6429 TN1010_VENDOR_MMD1_DEV_ADDR, 16, &val); 6430 cmn_err(CE_NOTE, "DDR status = 0x%x", val); 6431 6432 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 6433 TN1010_VENDOR_MMD1_DEV_ADDR, 17, &val); 6434 cmn_err(CE_NOTE, "DDR fault status = 0x%x", val); 6435 6436 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 6437 TN1010_VENDOR_MMD1_DEV_ADDR, 11, &val); 6438 cmn_err(CE_NOTE, "Firmware Revision = 0x%x Major = 0x%x Minor = 0x%x", 6439 val, (val & 0xFF00) >> 8, val & 0x00FF); 6440 } 6441 #endif 6442 6443 /* 6444 * Calculate the bit in the multicast address filter 6445 * that selects the given * address. 6446 * Note: For GEM, the last 8-bits are used. 6447 */ 6448 uint32_t 6449 crc32_mchash(p_ether_addr_t addr) 6450 { 6451 uint8_t *cp; 6452 uint32_t crc; 6453 uint32_t c; 6454 int byte; 6455 int bit; 6456 6457 cp = (uint8_t *)addr; 6458 crc = (uint32_t)0xffffffff; 6459 for (byte = 0; byte < 6; byte++) { 6460 c = (uint32_t)cp[byte]; 6461 for (bit = 0; bit < 8; bit++) { 6462 if ((c & 0x1) ^ (crc & 0x1)) 6463 crc = (crc >> 1)^0xedb88320; 6464 else 6465 crc = (crc >> 1); 6466 c >>= 1; 6467 } 6468 } 6469 return ((~crc) >> (32 - HASH_BITS)); 6470 } 6471 6472 /* Reset serdes */ 6473 6474 nxge_status_t 6475 nxge_serdes_reset(p_nxge_t nxgep) 6476 { 6477 npi_handle_t handle; 6478 6479 handle = nxgep->npi_handle; 6480 6481 ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0 | ESR_RESET_1); 6482 drv_usecwait(500); 6483 ESR_REG_WR(handle, ESR_CONFIG_REG, 0); 6484 6485 return (NXGE_OK); 6486 } 6487 6488 /* 6489 * This function monitors link status using interrupt or polling. 6490 * It calls nxgep->xcvr.check_link, a member function of 6491 * nxge_xcvr_table_t. But nxgep->xcvr.check_link calls this 6492 * function back, that is why the check_link routine is 6493 * executed periodically. 6494 */ 6495 nxge_status_t 6496 nxge_link_monitor(p_nxge_t nxgep, link_mon_enable_t enable) 6497 { 6498 nxge_status_t status = NXGE_OK; 6499 6500 /* If we are a guest domain driver, don't bother. */ 6501 if (isLDOMguest(nxgep)) 6502 return (status); 6503 6504 /* 6505 * Return immediately if this is an imaginary XMAC port. 6506 * (At least, we don't have 4-port XMAC cards yet.) 6507 */ 6508 if ((nxgep->mac.portmode == PORT_10G_FIBER || 6509 nxgep->mac.portmode == PORT_10G_COPPER || 6510 nxgep->mac.portmode == PORT_10G_SERDES) && 6511 (nxgep->mac.portnum > 1)) 6512 return (NXGE_OK); 6513 6514 if (nxgep->statsp == NULL) { 6515 /* stats has not been allocated. */ 6516 return (NXGE_OK); 6517 } 6518 /* Don't check link if we're in internal loopback mode */ 6519 if (nxgep->statsp->port_stats.lb_mode >= nxge_lb_serdes10g) 6520 return (NXGE_OK); 6521 6522 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6523 "==> nxge_link_monitor port<%d> enable=%d", 6524 nxgep->mac.portnum, enable)); 6525 if (enable == LINK_MONITOR_START) { 6526 if (nxgep->mac.linkchkmode == LINKCHK_INTR) { 6527 if ((status = nxge_link_intr(nxgep, LINK_INTR_START)) 6528 != NXGE_OK) 6529 goto fail; 6530 } else { 6531 timeout_id_t timerid; 6532 /* 6533 * check_link_stop means "Stop the link check", so 6534 * we return without starting the timer. 6535 */ 6536 if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 6537 return (NXGE_OK); 6538 6539 /* 6540 * Otherwise fire the timer for the nxge to check 6541 * the link using the check_link function 6542 * of the nxge_xcvr_table and pass "nxgep" as the 6543 * argument to the check_link function. 6544 */ 6545 if (nxgep->xcvr.check_link) { 6546 timerid = timeout((fptrv_t)(uintptr_t) 6547 (nxgep->xcvr.check_link), 6548 nxgep, 6549 drv_usectohz(LINK_MONITOR_PERIOD)); 6550 MUTEX_ENTER(&nxgep->poll_lock); 6551 nxgep->nxge_link_poll_timerid = timerid; 6552 MUTEX_EXIT(&nxgep->poll_lock); 6553 nxgep->link_check_count ++; 6554 } else { 6555 return (NXGE_ERROR); 6556 } 6557 } 6558 } else { 6559 if (nxgep->mac.linkchkmode == LINKCHK_INTR) { 6560 if ((status = nxge_link_intr(nxgep, LINK_INTR_STOP)) 6561 != NXGE_OK) 6562 goto fail; 6563 } else { 6564 clock_t rv; 6565 6566 MUTEX_ENTER(&nxgep->poll_lock); 6567 6568 /* If <timerid> == 0, the link monitor has */ 6569 /* never been started, or just now stopped. */ 6570 if (nxgep->nxge_link_poll_timerid == 0) { 6571 MUTEX_EXIT(&nxgep->poll_lock); 6572 return (NXGE_OK); 6573 } 6574 6575 nxgep->poll_state = LINK_MONITOR_STOPPING; 6576 rv = cv_reltimedwait(&nxgep->poll_cv, &nxgep->poll_lock, 6577 drv_usectohz(LM_WAIT_MULTIPLIER * 6578 LINK_MONITOR_PERIOD), TR_CLOCK_TICK); 6579 if (rv == -1) { 6580 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6581 "==> stopping port %d: " 6582 "cv_timedwait(%d) timed out", 6583 nxgep->mac.portnum, nxgep->poll_state)); 6584 nxgep->poll_state = LINK_MONITOR_STOP; 6585 nxgep->nxge_link_poll_timerid = 0; 6586 } 6587 6588 MUTEX_EXIT(&nxgep->poll_lock); 6589 } 6590 } 6591 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6592 "<== nxge_link_monitor port<%d> enable=%d", 6593 nxgep->mac.portnum, enable)); 6594 6595 return (NXGE_OK); 6596 fail: 6597 return (status); 6598 6599 } 6600 6601 nxge_status_t 6602 nxge_check_tn1010_link(p_nxge_t nxgep) 6603 { 6604 nxge_status_t status = NXGE_OK; 6605 nxge_link_state_t link_up; 6606 6607 if (nxgep->nxge_magic != NXGE_MAGIC) { 6608 /* magic is 0 if driver is not attached */ 6609 return (NXGE_ERROR); 6610 } 6611 6612 /* Link has been stopped, no need to continue */ 6613 if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) { 6614 return (NXGE_OK); 6615 } 6616 6617 if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10) 6618 goto nxge_check_tn1010_link_exit; 6619 6620 if ((status = nxge_tn1010_check(nxgep, &link_up)) != NXGE_OK) 6621 goto fail; 6622 6623 nxge_check_tn1010_link_exit: 6624 if (link_up == LINK_IS_UP) 6625 nxge_link_is_up(nxgep); 6626 else if (link_up == LINK_IS_DOWN) 6627 nxge_link_is_down(nxgep); 6628 6629 /* 6630 * nxge_link_monitor will call (nxgep->xcvr.check_link) 6631 * which could be THIS function. 6632 */ 6633 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 6634 6635 return (NXGE_OK); 6636 6637 fail: 6638 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 6639 6640 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6641 "nxge_check_tn1010_link: Failed to check link")); 6642 return (status); 6643 } 6644 6645 6646 /* 6647 * Fill variable "link_up" with either LINK_IS_UP or LINK_IS_DOWN. 6648 */ 6649 static nxge_status_t 6650 nxge_tn1010_check(p_nxge_t nxgep, nxge_link_state_t *link_up) 6651 { 6652 nxge_status_t status = NXGE_OK; 6653 p_nxge_stats_t statsp; 6654 uint8_t phy_port_addr, portn; 6655 uint16_t val; 6656 6657 *link_up = LINK_NO_CHANGE; 6658 6659 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 6660 phy_port_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 6661 statsp = nxgep->statsp; 6662 6663 /* Check if link is up */ 6664 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 6665 TN1010_AUTONEG_DEV_ADDR, TN1010_AUTONEG_STATUS_REG, &val)) 6666 != NXGE_OK) { 6667 goto fail; 6668 } 6669 /* 6670 * nxge_link_is_up has called nxge_set_tn1010_param and set 6671 * portmode and link_speed 6672 */ 6673 if (val & TN1010_AN_LINK_STAT_BIT) { 6674 if ((nxgep->link_notify && 6675 nxgep->nxge_mac_state == NXGE_MAC_STARTED) || 6676 nxgep->statsp->mac_stats.link_up == 0) { 6677 statsp->mac_stats.link_up = 1; 6678 statsp->mac_stats.link_duplex = 2; 6679 *link_up = LINK_IS_UP; 6680 nxgep->link_notify = B_FALSE; 6681 } 6682 } else { 6683 if ((nxgep->link_notify && nxgep->link_check_count > 3 && 6684 nxgep->nxge_mac_state == NXGE_MAC_STARTED) || 6685 nxgep->statsp->mac_stats.link_up == 1) { 6686 statsp->mac_stats.link_up = 0; 6687 statsp->mac_stats.link_speed = 0; 6688 statsp->mac_stats.link_duplex = 0; 6689 *link_up = LINK_IS_DOWN; 6690 nxgep->link_notify = B_FALSE; 6691 } 6692 } 6693 return (NXGE_OK); 6694 6695 fail: 6696 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6697 "nxge_tn1010_check: Unable to check TN1010")); 6698 return (status); 6699 } 6700 6701 6702 /* Set promiscous mode */ 6703 6704 nxge_status_t 6705 nxge_set_promisc(p_nxge_t nxgep, boolean_t on) 6706 { 6707 nxge_status_t status = NXGE_OK; 6708 6709 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_promisc: on %d", on)); 6710 6711 nxgep->filter.all_phys_cnt = ((on) ? 1 : 0); 6712 6713 RW_ENTER_WRITER(&nxgep->filter_lock); 6714 6715 if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) { 6716 goto fail; 6717 } 6718 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) { 6719 goto fail; 6720 } 6721 6722 RW_EXIT(&nxgep->filter_lock); 6723 6724 if (on) 6725 nxgep->statsp->mac_stats.promisc = B_TRUE; 6726 else 6727 nxgep->statsp->mac_stats.promisc = B_FALSE; 6728 6729 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_promisc")); 6730 6731 return (NXGE_OK); 6732 fail: 6733 RW_EXIT(&nxgep->filter_lock); 6734 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_promisc: " 6735 "Unable to set promisc (%d)", on)); 6736 6737 return (status); 6738 } 6739 6740 /*ARGSUSED*/ 6741 uint_t 6742 nxge_mif_intr(void *arg1, void *arg2) 6743 { 6744 #ifdef NXGE_DEBUG 6745 p_nxge_t nxgep = (p_nxge_t)arg2; 6746 #endif 6747 #if NXGE_MIF 6748 p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1; 6749 uint32_t status; 6750 npi_handle_t handle; 6751 uint8_t portn; 6752 p_nxge_stats_t statsp; 6753 #endif 6754 6755 #ifdef NXGE_MIF 6756 if (arg2 == NULL || (void *)ldvp->nxgep != arg2) { 6757 nxgep = ldvp->nxgep; 6758 } 6759 nxgep = ldvp->nxgep; 6760 #endif 6761 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mif_intr")); 6762 6763 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr")); 6764 return (DDI_INTR_CLAIMED); 6765 6766 mif_intr_fail: 6767 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr")); 6768 return (DDI_INTR_UNCLAIMED); 6769 } 6770 6771 /*ARGSUSED*/ 6772 uint_t 6773 nxge_mac_intr(void *arg1, void *arg2) 6774 { 6775 p_nxge_t nxgep = (p_nxge_t)arg2; 6776 p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1; 6777 p_nxge_ldg_t ldgp; 6778 uint32_t status; 6779 npi_handle_t handle; 6780 uint8_t portn; 6781 p_nxge_stats_t statsp; 6782 npi_status_t rs = NPI_SUCCESS; 6783 6784 if (arg2 == NULL || (void *)ldvp->nxgep != arg2) { 6785 nxgep = ldvp->nxgep; 6786 } 6787 6788 ldgp = ldvp->ldgp; 6789 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mac_intr: " 6790 "group %d", ldgp->ldg)); 6791 6792 handle = NXGE_DEV_NPI_HANDLE(nxgep); 6793 /* 6794 * This interrupt handler is for a specific 6795 * mac port. 6796 */ 6797 statsp = (p_nxge_stats_t)nxgep->statsp; 6798 portn = nxgep->mac.portnum; 6799 6800 NXGE_DEBUG_MSG((nxgep, INT_CTL, 6801 "==> nxge_mac_intr: reading mac stats: port<%d>", portn)); 6802 6803 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 6804 rs = npi_xmac_tx_get_istatus(handle, portn, 6805 (xmac_tx_iconfig_t *)&status); 6806 if (rs != NPI_SUCCESS) 6807 goto npi_fail; 6808 if (status & ICFG_XMAC_TX_ALL) { 6809 if (status & ICFG_XMAC_TX_UNDERRUN) { 6810 statsp->xmac_stats.tx_underflow_err++; 6811 NXGE_FM_REPORT_ERROR(nxgep, portn, 0, 6812 NXGE_FM_EREPORT_TXMAC_UNDERFLOW); 6813 } 6814 if (status & ICFG_XMAC_TX_MAX_PACKET_ERR) { 6815 statsp->xmac_stats.tx_maxpktsize_err++; 6816 /* 6817 * Do not send FMA ereport because this 6818 * error does not indicate HW failure. 6819 */ 6820 } 6821 if (status & ICFG_XMAC_TX_OVERFLOW) { 6822 statsp->xmac_stats.tx_overflow_err++; 6823 NXGE_FM_REPORT_ERROR(nxgep, portn, 0, 6824 NXGE_FM_EREPORT_TXMAC_OVERFLOW); 6825 } 6826 if (status & ICFG_XMAC_TX_FIFO_XFR_ERR) { 6827 statsp->xmac_stats.tx_fifo_xfr_err++; 6828 NXGE_FM_REPORT_ERROR(nxgep, portn, 0, 6829 NXGE_FM_EREPORT_TXMAC_TXFIFO_XFR_ERR); 6830 } 6831 if (status & ICFG_XMAC_TX_BYTE_CNT_EXP) { 6832 statsp->xmac_stats.tx_byte_cnt += 6833 XTXMAC_BYTE_CNT_MASK; 6834 } 6835 if (status & ICFG_XMAC_TX_FRAME_CNT_EXP) { 6836 statsp->xmac_stats.tx_frame_cnt += 6837 XTXMAC_FRM_CNT_MASK; 6838 } 6839 } 6840 6841 rs = npi_xmac_rx_get_istatus(handle, portn, 6842 (xmac_rx_iconfig_t *)&status); 6843 if (rs != NPI_SUCCESS) 6844 goto npi_fail; 6845 if (status & ICFG_XMAC_RX_ALL) { 6846 if (status & ICFG_XMAC_RX_OVERFLOW) 6847 statsp->xmac_stats.rx_overflow_err++; 6848 if (status & ICFG_XMAC_RX_UNDERFLOW) { 6849 statsp->xmac_stats.rx_underflow_err++; 6850 NXGE_FM_REPORT_ERROR(nxgep, portn, 0, 6851 NXGE_FM_EREPORT_RXMAC_UNDERFLOW); 6852 } 6853 /* 6854 * Do not send FMA ereport for the following 3 errors 6855 * because they do not indicate HW failures. 6856 */ 6857 if (status & ICFG_XMAC_RX_CRC_ERR_CNT_EXP) { 6858 statsp->xmac_stats.rx_crc_err_cnt += 6859 XRXMAC_CRC_ER_CNT_MASK; 6860 } 6861 if (status & ICFG_XMAC_RX_LEN_ERR_CNT_EXP) { 6862 statsp->xmac_stats.rx_len_err_cnt += 6863 MAC_LEN_ER_CNT_MASK; 6864 } 6865 if (status & ICFG_XMAC_RX_VIOL_ERR_CNT_EXP) { 6866 statsp->xmac_stats.rx_viol_err_cnt += 6867 XRXMAC_CD_VIO_CNT_MASK; 6868 } 6869 if (status & ICFG_XMAC_RX_OCT_CNT_EXP) { 6870 statsp->xmac_stats.rx_byte_cnt += 6871 XRXMAC_BT_CNT_MASK; 6872 } 6873 if (status & ICFG_XMAC_RX_HST_CNT1_EXP) { 6874 statsp->xmac_stats.rx_hist1_cnt += 6875 XRXMAC_HIST_CNT1_MASK; 6876 } 6877 if (status & ICFG_XMAC_RX_HST_CNT2_EXP) { 6878 statsp->xmac_stats.rx_hist2_cnt += 6879 XRXMAC_HIST_CNT2_MASK; 6880 } 6881 if (status & ICFG_XMAC_RX_HST_CNT3_EXP) { 6882 statsp->xmac_stats.rx_hist3_cnt += 6883 XRXMAC_HIST_CNT3_MASK; 6884 } 6885 if (status & ICFG_XMAC_RX_HST_CNT4_EXP) { 6886 statsp->xmac_stats.rx_hist4_cnt += 6887 XRXMAC_HIST_CNT4_MASK; 6888 } 6889 if (status & ICFG_XMAC_RX_HST_CNT5_EXP) { 6890 statsp->xmac_stats.rx_hist5_cnt += 6891 XRXMAC_HIST_CNT5_MASK; 6892 } 6893 if (status & ICFG_XMAC_RX_HST_CNT6_EXP) { 6894 statsp->xmac_stats.rx_hist6_cnt += 6895 XRXMAC_HIST_CNT6_MASK; 6896 } 6897 if (status & ICFG_XMAC_RX_BCAST_CNT_EXP) { 6898 statsp->xmac_stats.rx_broadcast_cnt += 6899 XRXMAC_BC_FRM_CNT_MASK; 6900 } 6901 if (status & ICFG_XMAC_RX_MCAST_CNT_EXP) { 6902 statsp->xmac_stats.rx_mult_cnt += 6903 XRXMAC_MC_FRM_CNT_MASK; 6904 } 6905 /* 6906 * Do not send FMA ereport for the following 3 errors 6907 * because they do not indicate HW failures. 6908 */ 6909 if (status & ICFG_XMAC_RX_FRAG_CNT_EXP) { 6910 statsp->xmac_stats.rx_frag_cnt += 6911 XRXMAC_FRAG_CNT_MASK; 6912 } 6913 if (status & ICFG_XMAC_RX_ALIGNERR_CNT_EXP) { 6914 statsp->xmac_stats.rx_frame_align_err_cnt += 6915 XRXMAC_AL_ER_CNT_MASK; 6916 } 6917 if (status & ICFG_XMAC_RX_LINK_FLT_CNT_EXP) { 6918 statsp->xmac_stats.rx_linkfault_err_cnt += 6919 XMAC_LINK_FLT_CNT_MASK; 6920 } 6921 if (status & ICFG_XMAC_RX_REMOTE_FLT_DET) { 6922 statsp->xmac_stats.rx_remotefault_err++; 6923 } 6924 if (status & ICFG_XMAC_RX_LOCAL_FLT_DET) { 6925 statsp->xmac_stats.rx_localfault_err++; 6926 } 6927 } 6928 6929 rs = npi_xmac_ctl_get_istatus(handle, portn, 6930 (xmac_ctl_iconfig_t *)&status); 6931 if (rs != NPI_SUCCESS) 6932 goto npi_fail; 6933 if (status & ICFG_XMAC_CTRL_ALL) { 6934 if (status & ICFG_XMAC_CTRL_PAUSE_RCVD) 6935 statsp->xmac_stats.rx_pause_cnt++; 6936 if (status & ICFG_XMAC_CTRL_PAUSE_STATE) 6937 statsp->xmac_stats.tx_pause_state++; 6938 if (status & ICFG_XMAC_CTRL_NOPAUSE_STATE) 6939 statsp->xmac_stats.tx_nopause_state++; 6940 } 6941 } else if (nxgep->mac.porttype == PORT_TYPE_BMAC) { 6942 rs = npi_bmac_tx_get_istatus(handle, portn, 6943 (bmac_tx_iconfig_t *)&status); 6944 if (rs != NPI_SUCCESS) 6945 goto npi_fail; 6946 if (status & ICFG_BMAC_TX_ALL) { 6947 if (status & ICFG_BMAC_TX_UNDERFLOW) { 6948 statsp->bmac_stats.tx_underrun_err++; 6949 NXGE_FM_REPORT_ERROR(nxgep, portn, 0, 6950 NXGE_FM_EREPORT_TXMAC_UNDERFLOW); 6951 } 6952 if (status & ICFG_BMAC_TX_MAXPKTSZ_ERR) { 6953 statsp->bmac_stats.tx_max_pkt_err++; 6954 NXGE_FM_REPORT_ERROR(nxgep, portn, 0, 6955 NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR); 6956 } 6957 if (status & ICFG_BMAC_TX_BYTE_CNT_EXP) { 6958 statsp->bmac_stats.tx_byte_cnt += 6959 BTXMAC_BYTE_CNT_MASK; 6960 } 6961 if (status & ICFG_BMAC_TX_FRAME_CNT_EXP) { 6962 statsp->bmac_stats.tx_frame_cnt += 6963 BTXMAC_FRM_CNT_MASK; 6964 } 6965 } 6966 6967 rs = npi_bmac_rx_get_istatus(handle, portn, 6968 (bmac_rx_iconfig_t *)&status); 6969 if (rs != NPI_SUCCESS) 6970 goto npi_fail; 6971 if (status & ICFG_BMAC_RX_ALL) { 6972 if (status & ICFG_BMAC_RX_OVERFLOW) { 6973 statsp->bmac_stats.rx_overflow_err++; 6974 } 6975 if (status & ICFG_BMAC_RX_FRAME_CNT_EXP) { 6976 statsp->bmac_stats.rx_frame_cnt += 6977 RXMAC_FRM_CNT_MASK; 6978 } 6979 if (status & ICFG_BMAC_RX_CRC_ERR_CNT_EXP) { 6980 statsp->bmac_stats.rx_crc_err_cnt += 6981 BMAC_CRC_ER_CNT_MASK; 6982 NXGE_FM_REPORT_ERROR(nxgep, portn, 0, 6983 NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP); 6984 } 6985 if (status & ICFG_BMAC_RX_LEN_ERR_CNT_EXP) { 6986 statsp->bmac_stats.rx_len_err_cnt += 6987 MAC_LEN_ER_CNT_MASK; 6988 NXGE_FM_REPORT_ERROR(nxgep, portn, 0, 6989 NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP); 6990 } 6991 if (status & ICFG_BMAC_RX_VIOL_ERR_CNT_EXP) { 6992 statsp->bmac_stats.rx_viol_err_cnt += 6993 BMAC_CD_VIO_CNT_MASK; 6994 NXGE_FM_REPORT_ERROR(nxgep, portn, 0, 6995 NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP); 6996 } 6997 if (status & ICFG_BMAC_RX_BYTE_CNT_EXP) { 6998 statsp->bmac_stats.rx_byte_cnt += 6999 BRXMAC_BYTE_CNT_MASK; 7000 } 7001 if (status & ICFG_BMAC_RX_ALIGNERR_CNT_EXP) { 7002 statsp->bmac_stats.rx_align_err_cnt += 7003 BMAC_AL_ER_CNT_MASK; 7004 NXGE_FM_REPORT_ERROR(nxgep, portn, 0, 7005 NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP); 7006 } 7007 7008 rs = npi_bmac_ctl_get_istatus(handle, portn, 7009 (bmac_ctl_iconfig_t *)&status); 7010 if (rs != NPI_SUCCESS) 7011 goto npi_fail; 7012 7013 if (status & ICFG_BMAC_CTL_ALL) { 7014 if (status & ICFG_BMAC_CTL_RCVPAUSE) 7015 statsp->bmac_stats.rx_pause_cnt++; 7016 if (status & ICFG_BMAC_CTL_INPAUSE_ST) 7017 statsp->bmac_stats.tx_pause_state++; 7018 if (status & ICFG_BMAC_CTL_INNOTPAUSE_ST) 7019 statsp->bmac_stats.tx_nopause_state++; 7020 } 7021 } 7022 } 7023 7024 if (ldgp->nldvs == 1) { 7025 (void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg, 7026 B_TRUE, ldgp->ldg_timer); 7027 } 7028 7029 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mac_intr")); 7030 return (DDI_INTR_CLAIMED); 7031 7032 npi_fail: 7033 NXGE_ERROR_MSG((nxgep, INT_CTL, "<== nxge_mac_intr")); 7034 return (DDI_INTR_UNCLAIMED); 7035 } 7036 7037 nxge_status_t 7038 nxge_check_bcm8704_link(p_nxge_t nxgep, boolean_t *link_up) 7039 { 7040 uint8_t phy_port_addr; 7041 nxge_status_t status = NXGE_OK; 7042 boolean_t rx_sig_ok; 7043 boolean_t pcs_blk_lock; 7044 boolean_t link_align; 7045 uint16_t val1, val2, val3; 7046 #ifdef NXGE_DEBUG_SYMBOL_ERR 7047 uint16_t val_debug; 7048 uint32_t val; 7049 #endif 7050 7051 phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn; 7052 7053 #ifdef NXGE_DEBUG_SYMBOL_ERR 7054 /* Check Device 3 Register Device 3 0xC809 */ 7055 (void) nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0xC809, &val_debug); 7056 if ((val_debug & ~0x200) != 0) { 7057 cmn_err(CE_NOTE, "!Port%d BCM8704 Dev3 Reg 0xc809 = 0x%x\n", 7058 nxgep->mac.portnum, val_debug); 7059 (void) nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, 7060 &val_debug); 7061 cmn_err(CE_NOTE, "!Port%d BCM8704 Dev4 Reg 0x18 = 0x%x\n", 7062 nxgep->mac.portnum, val_debug); 7063 } 7064 7065 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 7066 XPCS_REG_DESCWERR_COUNTER, &val); 7067 if (val != 0) 7068 cmn_err(CE_NOTE, "!XPCS DESCWERR = 0x%x\n", val); 7069 7070 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 7071 XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val); 7072 if (val != 0) 7073 cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L0_1 = 0x%x\n", val); 7074 7075 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 7076 XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val); 7077 if (val != 0) 7078 cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L2_3 = 0x%x\n", val); 7079 #endif 7080 7081 /* Check from BCM8704 if 10G link is up or down */ 7082 7083 /* Check Device 1 Register 0xA bit0 */ 7084 status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PMA_PMD_DEV_ADDR, 7085 BCM8704_PMD_RECEIVE_SIG_DETECT, &val1); 7086 if (status != NXGE_OK) 7087 goto fail; 7088 rx_sig_ok = ((val1 & GLOB_PMD_RX_SIG_OK) ? B_TRUE : B_FALSE); 7089 7090 /* Check Device 3 Register 0x20 bit0 */ 7091 if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PCS_DEV_ADDR, 7092 BCM8704_10GBASE_R_PCS_STATUS_REG, &val2)) != NPI_SUCCESS) 7093 goto fail; 7094 pcs_blk_lock = ((val2 & PCS_10GBASE_R_PCS_BLK_LOCK) ? B_TRUE : B_FALSE); 7095 7096 /* Check Device 4 Register 0x18 bit12 */ 7097 status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 7098 BCM8704_PHYXS_XGXS_LANE_STATUS_REG, &val3); 7099 if (status != NXGE_OK) 7100 goto fail; 7101 7102 switch (nxgep->chip_id) { 7103 case BCM8704_CHIP_ID: 7104 link_align = (val3 == (XGXS_LANE_ALIGN_STATUS | 7105 XGXS_LANE3_SYNC | XGXS_LANE2_SYNC | XGXS_LANE1_SYNC | 7106 XGXS_LANE0_SYNC | 0x400)) ? B_TRUE : B_FALSE; 7107 break; 7108 case BCM8706_CHIP_ID: 7109 link_align = ((val3 & XGXS_LANE_ALIGN_STATUS) && 7110 (val3 & XGXS_LANE3_SYNC) && (val3 & XGXS_LANE2_SYNC) && 7111 (val3 & XGXS_LANE1_SYNC) && (val3 & XGXS_LANE0_SYNC)) ? 7112 B_TRUE : B_FALSE; 7113 break; 7114 default: 7115 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_check_bcm8704_link:" 7116 "Unknown chip ID [0x%x]", nxgep->chip_id)); 7117 goto fail; 7118 } 7119 7120 #ifdef NXGE_DEBUG_ALIGN_ERR 7121 /* Temp workaround for link down issue */ 7122 if (pcs_blk_lock == B_FALSE) { 7123 if (val2 != 0x4) { 7124 pcs_blk_lock = B_TRUE; 7125 cmn_err(CE_NOTE, "!LINK DEBUG: port%d PHY Dev3 " 7126 "Reg 0x20 = 0x%x\n", nxgep->mac.portnum, val2); 7127 } 7128 } 7129 7130 if (link_align == B_FALSE) { 7131 if (val3 != 0x140f) { 7132 link_align = B_TRUE; 7133 cmn_err(CE_NOTE, "!LINK DEBUG: port%d PHY Dev4 " 7134 "Reg 0x18 = 0x%x\n", nxgep->mac.portnum, val3); 7135 } 7136 } 7137 7138 if (rx_sig_ok == B_FALSE) { 7139 if ((val2 == 0) || (val3 == 0)) { 7140 rx_sig_ok = B_TRUE; 7141 cmn_err(CE_NOTE, 7142 "!LINK DEBUG: port %d Dev3 or Dev4 read zero\n", 7143 nxgep->mac.portnum); 7144 } 7145 } 7146 #endif 7147 7148 *link_up = ((rx_sig_ok == B_TRUE) && (pcs_blk_lock == B_TRUE) && 7149 (link_align == B_TRUE)) ? B_TRUE : B_FALSE; 7150 7151 return (NXGE_OK); 7152 fail: 7153 return (status); 7154 } 7155 7156 static nxge_status_t 7157 nxge_check_mrvl88x2011_link(p_nxge_t nxgep, boolean_t *link_up) 7158 { 7159 uint8_t phy; 7160 nxge_status_t status = NXGE_OK; 7161 boolean_t pma_status; 7162 boolean_t pcs_status; 7163 boolean_t xgxs_status; 7164 uint16_t val; 7165 7166 phy = nxgep->statsp->mac_stats.xcvr_portn; 7167 7168 MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR, 7169 MRVL_88X2011_10G_PMD_STAT_2, &val); 7170 7171 *link_up = B_FALSE; 7172 7173 /* Check from Marvell 88X2011 if 10G link is up or down */ 7174 7175 /* Check PMA/PMD Register: 1.0001.2 == 1 */ 7176 MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR, 7177 MRVL_88X2011_PMA_PMD_STAT_1, &val); 7178 7179 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7180 "nxge_check_mrvl88x2011_link: pmd=0x%x", val)); 7181 7182 pma_status = ((val & MRVL_88X2011_LNK_STATUS_OK) ? B_TRUE : B_FALSE); 7183 7184 /* Check PMC Register : 3.0001.2 == 1: read twice */ 7185 MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR, 7186 MRVL_88X2011_PMA_PMD_STAT_1, &val); 7187 MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR, 7188 MRVL_88X2011_PMA_PMD_STAT_1, &val); 7189 7190 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7191 "nxge_check_mrvl88x2011_link: pcs=0x%x", val)); 7192 7193 pcs_status = ((val & MRVL_88X2011_LNK_STATUS_OK) ? B_TRUE : B_FALSE); 7194 7195 /* Check XGXS Register : 4.0018.[0-3,12] */ 7196 MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV4_ADDR, 7197 MRVL_88X2011_10G_XGXS_LANE_STAT, &val); 7198 7199 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7200 "nxge_check_mrvl88x2011_link: xgxs=0x%x", val)); 7201 7202 xgxs_status = (val == (XGXS_LANE_ALIGN_STATUS | XGXS_LANE3_SYNC | 7203 XGXS_LANE2_SYNC | XGXS_LANE1_SYNC | 7204 XGXS_LANE0_SYNC | XGXS_PATTERN_TEST_ABILITY | 7205 XGXS_LANE_STAT_MAGIC)) ? B_TRUE : B_FALSE; 7206 7207 *link_up = (pma_status && pcs_status && xgxs_status) ? 7208 B_TRUE : B_FALSE; 7209 7210 fail: 7211 7212 if (*link_up == B_FALSE) { 7213 /* PCS OFF */ 7214 nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_CTL_OFF); 7215 } else { 7216 /* PCS Activity */ 7217 nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_CTL_PCS_ACT); 7218 } 7219 7220 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7221 " <== nxge_check_mrvl88x2011_link: up=%d", *link_up)); 7222 7223 return (status); 7224 } 7225 7226 static nxge_status_t 7227 nxge_check_nlp2020_link(p_nxge_t nxgep, boolean_t *link_up) 7228 { 7229 uint8_t phy; 7230 nxge_status_t status = NXGE_OK; 7231 uint16_t pmd_rx_sig, pcs_10gbr_stat1, phy_xs_ln_stat; 7232 uint8_t connector = 0; 7233 7234 phy = nxgep->statsp->mac_stats.xcvr_portn; 7235 *link_up = B_FALSE; 7236 7237 /* Check from Netlogic AEL2020 if 10G link is up or down */ 7238 7239 status = nxge_mdio_read(nxgep, phy, NLP2020_PMA_PMD_ADDR, 7240 NLP2020_PMA_PMD_RX_SIG_DET_REG, &pmd_rx_sig); 7241 if (status != NXGE_OK) 7242 goto fail; 7243 7244 status = nxge_mdio_read(nxgep, phy, NLP2020_PHY_PCS_ADDR, 7245 NLP2020_PHY_PCS_10GBR_STAT1_REG, &pcs_10gbr_stat1); 7246 if (status != NXGE_OK) 7247 goto fail; 7248 7249 status = nxge_mdio_read(nxgep, phy, NLP2020_PHY_XS_ADDR, 7250 NLP2020_PHY_XS_LN_ST_REG, &phy_xs_ln_stat); 7251 if (status != NXGE_OK) 7252 goto fail; 7253 7254 if ((pmd_rx_sig & NLP2020_PMA_PMD_RX_SIG_ON) && 7255 (pcs_10gbr_stat1 & NLP2020_PHY_PCS_10GBR_RX_LINK_UP) && 7256 (phy_xs_ln_stat & NLP2020_PHY_XS_LN_ALIGN_SYNC)) 7257 *link_up = B_TRUE; 7258 /* 7259 * If previously link was down, check the connector type as 7260 * it might have been changed. 7261 */ 7262 if (nxgep->statsp->mac_stats.link_up == 0) { 7263 (void) nxge_nlp2020_i2c_read(nxgep, phy, 7264 NLP2020_XCVR_I2C_ADDR, QSFP_MSA_CONN_REG, &connector); 7265 7266 switch (connector) { 7267 case SFPP_FIBER: 7268 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7269 "nxge_check_nlp2020_link: SFPP_FIBER")); 7270 if (nxgep->mac.portmode != PORT_10G_FIBER) { 7271 nxgep->mac.portmode = PORT_10G_FIBER; 7272 (void) nxge_nlp2020_xcvr_init(nxgep); 7273 } 7274 break; 7275 case QSFP_FIBER: 7276 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7277 "nxge_check_nlp2020_link: QSFP_FIBER")); 7278 if (nxgep->mac.portmode != PORT_10G_FIBER) { 7279 nxgep->mac.portmode = PORT_10G_FIBER; 7280 (void) nxge_nlp2020_xcvr_init(nxgep); 7281 } 7282 break; 7283 case QSFP_COPPER_TWINAX: 7284 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7285 "nxge_check_nlp2020_link: " 7286 "QSFP_COPPER_TWINAX/" 7287 "SFPP_COPPER_TWINAX")); 7288 if (nxgep->mac.portmode != PORT_10G_COPPER) { 7289 nxgep->mac.portmode = PORT_10G_COPPER; 7290 (void) nxge_nlp2020_xcvr_init(nxgep); 7291 } else { 7292 uint8_t len = 0; 7293 (void) nxge_nlp2020_i2c_read(nxgep, phy, 7294 NLP2020_XCVR_I2C_ADDR, QSFP_MSA_LEN_REG, 7295 &len); 7296 if (((len < 7) && 7297 (nxgep->nlp_conn == 7298 NXGE_NLP_CONN_COPPER_7M_ABOVE)) || 7299 ((len >= 7) && 7300 (nxgep->nlp_conn == 7301 NXGE_NLP_CONN_COPPER_LT_7M))) { 7302 (void) nxge_nlp2020_xcvr_init(nxgep); 7303 } 7304 } 7305 break; 7306 default: 7307 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7308 "nxge_check_nlp2020_link: Unknown type [0x%x] " 7309 "detected...setting to QSFP_FIBER", 7310 connector)); 7311 if (nxgep->mac.portmode != PORT_10G_FIBER) { 7312 nxgep->mac.portmode = PORT_10G_FIBER; 7313 (void) nxge_nlp2020_xcvr_init(nxgep); 7314 } 7315 break; 7316 } 7317 } 7318 fail: 7319 if (*link_up == B_FALSE && nxgep->statsp->mac_stats.link_up == 1) { 7320 /* Turn link LED OFF */ 7321 (void) nxge_mdio_write(nxgep, phy, 7322 NLP2020_GPIO_ADDR, NLP2020_GPIO_CTL_REG, 0xb000); 7323 (void) nxge_mdio_write(nxgep, phy, 7324 NLP2020_GPIO_ADDR, NLP2020_GPIO_PT3_CFG_REG, 0x0); 7325 } else if (*link_up == B_TRUE && 7326 nxgep->statsp->mac_stats.link_up == 0) { 7327 /* Turn link LED ON */ 7328 (void) nxge_mdio_write(nxgep, phy, 7329 NLP2020_GPIO_ADDR, NLP2020_GPIO_CTL_REG, 0xd000); 7330 (void) nxge_mdio_write(nxgep, phy, 7331 NLP2020_GPIO_ADDR, NLP2020_GPIO_PT3_CFG_REG, 0xfbff); 7332 (void) nxge_mdio_write(nxgep, phy, 7333 NLP2020_GPIO_ADDR, 0xff2a, 0x004a); 7334 } 7335 7336 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7337 " <== nxge_check_nlp2020_link: up=%d", *link_up)); 7338 return (status); 7339 } 7340 7341 7342 nxge_status_t 7343 nxge_10g_link_led_on(p_nxge_t nxgep) 7344 { 7345 if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_TRUE) 7346 != NPI_SUCCESS) 7347 return (NXGE_ERROR); 7348 else 7349 return (NXGE_OK); 7350 } 7351 7352 nxge_status_t 7353 nxge_10g_link_led_off(p_nxge_t nxgep) 7354 { 7355 if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_FALSE) 7356 != NPI_SUCCESS) 7357 return (NXGE_ERROR); 7358 else 7359 return (NXGE_OK); 7360 } 7361 7362 static boolean_t 7363 nxge_hswap_phy_present(p_nxge_t nxgep, uint8_t portn) 7364 { 7365 /* 7366 * check for BCM PHY (GOA NEM) 7367 */ 7368 /* 7369 * If this is the 2nd NIU port, then check 2 addresses 7370 * to take care of the Goa NEM card. Port 1 can have addr 17 7371 * (in the eval board) or 20 (in the P0 board). 7372 */ 7373 if (portn == 1) { 7374 if (nxge_is_phy_present(nxgep, ALT_GOA_CLAUSE45_PORT1_ADDR, 7375 BCM8706_DEV_ID, BCM_PHY_ID_MASK)) { 7376 nxgep->xcvr_addr = ALT_GOA_CLAUSE45_PORT1_ADDR; 7377 goto found_phy; 7378 } 7379 } 7380 if (nxge_is_phy_present(nxgep, GOA_CLAUSE45_PORT_ADDR_BASE + portn, 7381 BCM8706_DEV_ID, BCM_PHY_ID_MASK)) { 7382 nxgep->xcvr_addr = GOA_CLAUSE45_PORT_ADDR_BASE + portn; 7383 goto found_phy; 7384 } 7385 7386 /* 7387 * check for NLP2020 PHY on C4 NEM 7388 */ 7389 switch (portn) { 7390 case 0: 7391 if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT0_ADDR0, 7392 NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) { 7393 nxgep->xcvr_addr = NLP2020_CL45_PORT0_ADDR0; 7394 goto found_phy; 7395 } else if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT0_ADDR1, 7396 NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) { 7397 nxgep->xcvr_addr = NLP2020_CL45_PORT0_ADDR1; 7398 goto found_phy; 7399 } else if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT0_ADDR2, 7400 NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) { 7401 nxgep->xcvr_addr = NLP2020_CL45_PORT0_ADDR2; 7402 goto found_phy; 7403 } else if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT0_ADDR3, 7404 NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) { 7405 nxgep->xcvr_addr = NLP2020_CL45_PORT0_ADDR3; 7406 goto found_phy; 7407 } 7408 break; 7409 7410 case 1: 7411 if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT1_ADDR0, 7412 NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) { 7413 nxgep->xcvr_addr = NLP2020_CL45_PORT1_ADDR0; 7414 goto found_phy; 7415 } else if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT1_ADDR1, 7416 NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) { 7417 nxgep->xcvr_addr = NLP2020_CL45_PORT1_ADDR1; 7418 goto found_phy; 7419 } else if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT1_ADDR2, 7420 NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) { 7421 nxgep->xcvr_addr = NLP2020_CL45_PORT1_ADDR2; 7422 goto found_phy; 7423 } else if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT1_ADDR3, 7424 NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) { 7425 nxgep->xcvr_addr = NLP2020_CL45_PORT1_ADDR3; 7426 goto found_phy; 7427 } 7428 break; 7429 default: 7430 break; 7431 } 7432 7433 return (B_FALSE); 7434 found_phy: 7435 return (B_TRUE); 7436 7437 } 7438 7439 static boolean_t 7440 nxge_is_phy_present(p_nxge_t nxgep, int addr, uint32_t id, uint32_t mask) 7441 { 7442 uint32_t pma_pmd_id = 0; 7443 uint32_t pcs_id = 0; 7444 uint32_t phy_id = 0; 7445 7446 pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, addr); 7447 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7448 "nxge_is_phy_present: pma_pmd_id[0x%x]", pma_pmd_id)); 7449 if ((pma_pmd_id & mask) == (id & mask)) 7450 goto found_phy; 7451 pcs_id = nxge_get_cl45_pcs_id(nxgep, addr); 7452 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7453 "nxge_is_phy_present: pcs_id[0x%x]", pcs_id)); 7454 if ((pcs_id & mask) == (id & mask)) 7455 goto found_phy; 7456 phy_id = nxge_get_cl22_phy_id(nxgep, addr); 7457 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7458 "nxge_is_phy_present: phy_id[0x%x]", phy_id)); 7459 if ((phy_id & mask) == (id & mask)) 7460 goto found_phy; 7461 7462 return (B_FALSE); 7463 7464 found_phy: 7465 return (B_TRUE); 7466 } 7467 7468 /* Check if the given id read using the given MDIO Clause is supported */ 7469 7470 static boolean_t 7471 nxge_is_supported_phy(uint32_t id, uint8_t type) 7472 { 7473 int i; 7474 boolean_t found = B_FALSE; 7475 7476 switch (type) { 7477 case CLAUSE_45_TYPE: 7478 for (i = 0; i < NUM_CLAUSE_45_IDS; i++) { 7479 if (((nxge_supported_cl45_ids[i] & BCM_PHY_ID_MASK) == 7480 (id & BCM_PHY_ID_MASK)) || 7481 (TN1010_DEV_ID == (id & TN1010_DEV_ID_MASK)) || 7482 (NLP2020_DEV_ID == (id & NLP2020_DEV_ID_MASK))) { 7483 found = B_TRUE; 7484 break; 7485 } 7486 } 7487 break; 7488 case CLAUSE_22_TYPE: 7489 for (i = 0; i < NUM_CLAUSE_22_IDS; i++) { 7490 if ((nxge_supported_cl22_ids[i] & BCM_PHY_ID_MASK) == 7491 (id & BCM_PHY_ID_MASK)) { 7492 found = B_TRUE; 7493 break; 7494 } 7495 } 7496 break; 7497 default: 7498 break; 7499 } 7500 7501 return (found); 7502 } 7503 7504 static uint32_t 7505 nxge_get_cl45_pma_pmd_id(p_nxge_t nxgep, int phy_port) 7506 { 7507 uint16_t val1 = 0; 7508 uint16_t val2 = 0; 7509 uint32_t pma_pmd_dev_id = 0; 7510 npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep); 7511 7512 MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 7513 (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR, 7514 NXGE_DEV_ID_REG_1, &val1); 7515 (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR, 7516 NXGE_DEV_ID_REG_2, &val2); 7517 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 7518 7519 /* Concatenate the Device ID stored in two registers. */ 7520 pma_pmd_dev_id = val1; 7521 pma_pmd_dev_id = (pma_pmd_dev_id << 16); 7522 pma_pmd_dev_id |= val2; 7523 7524 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PMA/PMD " 7525 "devid[0x%llx]", phy_port, pma_pmd_dev_id)); 7526 7527 return (pma_pmd_dev_id); 7528 } 7529 7530 static uint32_t 7531 nxge_get_cl45_pcs_id(p_nxge_t nxgep, int phy_port) 7532 { 7533 uint16_t val1 = 0; 7534 uint16_t val2 = 0; 7535 uint32_t pcs_dev_id = 0; 7536 npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep); 7537 7538 MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 7539 (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR, 7540 NXGE_DEV_ID_REG_1, &val1); 7541 (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR, 7542 NXGE_DEV_ID_REG_2, &val2); 7543 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 7544 7545 pcs_dev_id = val1; 7546 pcs_dev_id = (pcs_dev_id << 16); 7547 pcs_dev_id |= val2; 7548 7549 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS " 7550 "devid[0x%llx]", phy_port, pcs_dev_id)); 7551 7552 return (pcs_dev_id); 7553 } 7554 7555 static uint32_t 7556 nxge_get_cl22_phy_id(p_nxge_t nxgep, int phy_port) 7557 { 7558 uint16_t val1 = 0; 7559 uint16_t val2 = 0; 7560 uint32_t phy_id = 0; 7561 npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep); 7562 npi_status_t npi_status = NPI_SUCCESS; 7563 7564 MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 7565 npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_1, 7566 &val1); 7567 if (npi_status != NPI_SUCCESS) { 7568 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] " 7569 "clause 22 read to reg 2 failed!!!")); 7570 goto exit; 7571 } 7572 npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_2, 7573 &val2); 7574 if (npi_status != 0) { 7575 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] " 7576 "clause 22 read to reg 3 failed!!!")); 7577 goto exit; 7578 } 7579 phy_id = val1; 7580 phy_id = (phy_id << 16); 7581 phy_id |= val2; 7582 7583 exit: 7584 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 7585 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID [0x%llx]", 7586 phy_port, phy_id)); 7587 7588 return (phy_id); 7589 } 7590 7591 /* 7592 * Scan the PHY ports 0 through 31 to get the PHY ID using Clause 22 MDIO 7593 * read and the PMA/PMD device ID and the PCS device ID using Clause 45 MDIO 7594 * read. Then use the values obtained to determine the phy type of each port 7595 * and the Neptune type. 7596 * 7597 * This function sets hw_p->xcvr_addr[i] for future MDIO access and set 7598 * hw_p->niu_type for each nxge instance to figure out nxgep->mac.portmode 7599 * in case the portmode information is not available via OBP, nxge.conf, 7600 * VPD or SEEPROM. 7601 */ 7602 nxge_status_t 7603 nxge_scan_ports_phy(p_nxge_t nxgep, p_nxge_hw_list_t hw_p) 7604 { 7605 int i, j, l; 7606 uint32_t pma_pmd_dev_id = 0; 7607 uint32_t pcs_dev_id = 0; 7608 uint32_t phy_id = 0; 7609 uint32_t port_pma_pmd_dev_id[NXGE_PORTS_NEPTUNE]; 7610 uint32_t port_pcs_dev_id[NXGE_PORTS_NEPTUNE]; 7611 uint32_t port_phy_id[NXGE_PORTS_NEPTUNE]; 7612 uint8_t pma_pmd_dev_fd[NXGE_MAX_PHY_PORTS]; 7613 uint8_t pcs_dev_fd[NXGE_MAX_PHY_PORTS]; 7614 uint8_t phy_fd_arr[NXGE_MAX_PHY_PORTS]; 7615 uint8_t port_fd_arr[NXGE_MAX_PHY_PORTS]; 7616 uint8_t total_port_fd, total_phy_fd; 7617 uint8_t num_xaui; 7618 nxge_status_t status = NXGE_OK; 7619 7620 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_scan_ports_phy: ")); 7621 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7622 "==> nxge_scan_ports_phy: nxge niu_type[0x%x]", 7623 nxgep->niu_type)); 7624 7625 if (isLDOMguest(nxgep)) { 7626 hw_p->niu_type = NIU_TYPE_NONE; 7627 hw_p->platform_type = P_NEPTUNE_NONE; 7628 return (NXGE_OK); 7629 } 7630 7631 j = l = 0; 7632 total_port_fd = total_phy_fd = 0; 7633 /* 7634 * Clause 45 and Clause 22 port/phy addresses 0 through 5 are reserved 7635 * for on chip serdes usages. "i" in the following for loop starts at 6. 7636 */ 7637 for (i = NXGE_EXT_PHY_PORT_ST; i < NXGE_MAX_PHY_PORTS; i++) { 7638 7639 pma_pmd_dev_id = nxge_get_cl45_pma_pmd_id(nxgep, i); 7640 7641 if (nxge_is_supported_phy(pma_pmd_dev_id, CLAUSE_45_TYPE)) { 7642 pma_pmd_dev_fd[i] = 1; 7643 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] " 7644 "PMA/PMD dev %x found", i, pma_pmd_dev_id)); 7645 if (j < NXGE_PORTS_NEPTUNE) { 7646 if ((pma_pmd_dev_id & TN1010_DEV_ID_MASK) 7647 == TN1010_DEV_ID) { 7648 port_pma_pmd_dev_id[j] = TN1010_DEV_ID; 7649 } else if ((pma_pmd_dev_id & 7650 NLP2020_DEV_ID_MASK) == NLP2020_DEV_ID) { 7651 port_pma_pmd_dev_id[j] = 7652 NLP2020_DEV_ID; 7653 } else { 7654 port_pma_pmd_dev_id[j] = 7655 pma_pmd_dev_id & BCM_PHY_ID_MASK; 7656 } 7657 port_fd_arr[j] = (uint8_t)i; 7658 j++; 7659 } 7660 } else { 7661 pma_pmd_dev_fd[i] = 0; 7662 } 7663 7664 pcs_dev_id = nxge_get_cl45_pcs_id(nxgep, i); 7665 7666 if (nxge_is_supported_phy(pcs_dev_id, CLAUSE_45_TYPE)) { 7667 pcs_dev_fd[i] = 1; 7668 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS " 7669 "dev %x found", i, pcs_dev_id)); 7670 if (pma_pmd_dev_fd[i] == 1) { 7671 if ((pcs_dev_id & TN1010_DEV_ID_MASK) 7672 == TN1010_DEV_ID) { 7673 port_pcs_dev_id[j - 1] = 7674 TN1010_DEV_ID; 7675 } else if ((pcs_dev_id & NLP2020_DEV_ID_MASK) 7676 == NLP2020_DEV_ID) { 7677 port_pcs_dev_id[j - 1] = 7678 NLP2020_DEV_ID; 7679 } else { 7680 port_pcs_dev_id[j - 1] = 7681 pcs_dev_id & 7682 BCM_PHY_ID_MASK; 7683 } 7684 } else { 7685 if (j < NXGE_PORTS_NEPTUNE) { 7686 if ((pcs_dev_id & TN1010_DEV_ID_MASK) 7687 == TN1010_DEV_ID) { 7688 port_pcs_dev_id[j] = 7689 TN1010_DEV_ID; 7690 } else if ((pcs_dev_id & 7691 NLP2020_DEV_ID_MASK) 7692 == NLP2020_DEV_ID) { 7693 port_pcs_dev_id[j] = 7694 NLP2020_DEV_ID; 7695 } else { 7696 port_pcs_dev_id[j] = 7697 pcs_dev_id & 7698 BCM_PHY_ID_MASK; 7699 } 7700 port_fd_arr[j] = (uint8_t)i; 7701 j++; 7702 } 7703 } 7704 } else { 7705 pcs_dev_fd[i] = 0; 7706 } 7707 7708 if (pcs_dev_fd[i] || pma_pmd_dev_fd[i]) { 7709 total_port_fd ++; 7710 } 7711 7712 phy_id = nxge_get_cl22_phy_id(nxgep, i); 7713 if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) { 7714 total_phy_fd ++; 7715 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID" 7716 "%x found", i, phy_id)); 7717 if (l < NXGE_PORTS_NEPTUNE) { 7718 if ((phy_id & TN1010_DEV_ID_MASK) 7719 == TN1010_DEV_ID) { 7720 port_phy_id[l] = TN1010_DEV_ID; 7721 } else { 7722 port_phy_id[l] 7723 = phy_id & BCM_PHY_ID_MASK; 7724 } 7725 phy_fd_arr[l] = (uint8_t)i; 7726 l++; 7727 } 7728 } 7729 } 7730 7731 switch (total_port_fd) { 7732 case 2: 7733 switch (total_phy_fd) { 7734 case 2: 7735 /* 2 10G, 2 1G RGMII Fiber / copper */ 7736 if ((((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) && 7737 (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) || 7738 ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) && 7739 (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) && 7740 ((port_phy_id[0] == PHY_BCM5482_FAMILY) && 7741 (port_phy_id[1] == PHY_BCM5482_FAMILY))) { 7742 7743 switch (hw_p->platform_type) { 7744 case P_NEPTUNE_ROCK: 7745 hw_p->niu_type = NEPTUNE_2_10GF_2_1GC; 7746 /* 7747 * ROCK platform has assigned a lower 7748 * addr to port 1. (port 0 = 0x9 and 7749 * port 1 = 0x8). 7750 */ 7751 hw_p->xcvr_addr[1] = port_fd_arr[0]; 7752 hw_p->xcvr_addr[0] = port_fd_arr[1]; 7753 7754 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7755 "Rock with 2 10G, 2 1GC")); 7756 break; 7757 7758 case P_NEPTUNE_NONE: 7759 default: 7760 hw_p->platform_type = 7761 P_NEPTUNE_GENERIC; 7762 hw_p->niu_type = NEPTUNE_2_10GF_2_1GRF; 7763 7764 hw_p->xcvr_addr[0] = port_fd_arr[0]; 7765 hw_p->xcvr_addr[1] = port_fd_arr[1]; 7766 7767 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7768 "ARTM card with 2 10G, 2 1GF")); 7769 break; 7770 } 7771 7772 hw_p->xcvr_addr[2] = phy_fd_arr[0]; 7773 hw_p->xcvr_addr[3] = phy_fd_arr[1]; 7774 7775 } else { 7776 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7777 "Unsupported neptune type 1")); 7778 goto error_exit; 7779 } 7780 break; 7781 7782 case 1: 7783 /* TODO - 2 10G, 1 1G */ 7784 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7785 "Unsupported neptune type 2 10G, 1 1G")); 7786 goto error_exit; 7787 case 0: 7788 /* 7789 * 2 10G: 2XGF NIC, Marvell, Goa, Huron with 2 XAUI 7790 * cards, etc. 7791 */ 7792 if (((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) && 7793 (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) || 7794 ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) && 7795 (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY)) || 7796 ((port_pcs_dev_id[0] == MARVELL_88X201X_PHY_ID) && 7797 (port_pcs_dev_id[1] == MARVELL_88X201X_PHY_ID)) || 7798 ((port_pma_pmd_dev_id[0] == 7799 MARVELL_88X201X_PHY_ID) && 7800 (port_pma_pmd_dev_id[1] == 7801 MARVELL_88X201X_PHY_ID))) { 7802 7803 /* 7804 * Check the first phy port address against 7805 * the known phy start addresses to determine 7806 * the platform type. 7807 */ 7808 7809 switch (port_fd_arr[0]) { 7810 case NEPTUNE_CLAUSE45_PORT_ADDR_BASE: 7811 /* 7812 * The Marvell case also falls into 7813 * this case as 7814 * MRVL88X2011_NEPTUNE_PORT_ADDR_BASE 7815 * == NEPTUNE_CLAUSE45_PORT_ADDR_BASE. 7816 * This is OK for the 2 10G case. 7817 */ 7818 hw_p->niu_type = NEPTUNE_2_10GF; 7819 hw_p->platform_type = 7820 P_NEPTUNE_ATLAS_2PORT; 7821 break; 7822 case GOA_CLAUSE45_PORT_ADDR_BASE: 7823 if (hw_p->platform_type != 7824 P_NEPTUNE_NIU) { 7825 hw_p->platform_type = 7826 P_NEPTUNE_GENERIC; 7827 hw_p->niu_type = 7828 NEPTUNE_2_10GF; 7829 } 7830 break; 7831 default: 7832 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7833 "Unsupported neptune type 2 - 1")); 7834 goto error_exit; 7835 } 7836 7837 for (i = 0; i < 2; i++) { 7838 hw_p->xcvr_addr[i] = port_fd_arr[i]; 7839 } 7840 7841 /* 2 10G optical Netlogic AEL2020 ports */ 7842 } else if (((port_pcs_dev_id[0] == NLP2020_DEV_ID) && 7843 (port_pcs_dev_id[1] == NLP2020_DEV_ID)) || 7844 ((port_pma_pmd_dev_id[0] == NLP2020_DEV_ID) && 7845 (port_pma_pmd_dev_id[1] == NLP2020_DEV_ID))) { 7846 if (hw_p->platform_type != P_NEPTUNE_NIU) { 7847 hw_p->platform_type = 7848 P_NEPTUNE_GENERIC; 7849 hw_p->niu_type = 7850 NEPTUNE_2_10GF; 7851 } 7852 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7853 "Found 2 NL PHYs at addrs 0x%x and 0x%x", 7854 port_fd_arr[0], port_fd_arr[1])); 7855 hw_p->xcvr_addr[0] = port_fd_arr[0]; 7856 hw_p->xcvr_addr[1] = port_fd_arr[1]; 7857 7858 /* Both XAUI slots have copper XAUI cards */ 7859 } else if ((((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 7860 == TN1010_DEV_ID) && 7861 ((port_pcs_dev_id[1] & TN1010_DEV_ID_MASK) 7862 == TN1010_DEV_ID)) || 7863 (((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK) 7864 == TN1010_DEV_ID) && 7865 ((port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK) 7866 == TN1010_DEV_ID))) { 7867 hw_p->niu_type = NEPTUNE_2_TN1010; 7868 hw_p->xcvr_addr[0] = port_fd_arr[0]; 7869 hw_p->xcvr_addr[1] = port_fd_arr[1]; 7870 7871 /* Slot0 has fiber XAUI, slot1 has copper XAUI */ 7872 } else if ((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY && 7873 (port_pcs_dev_id[1] & TN1010_DEV_ID_MASK) 7874 == TN1010_DEV_ID) || 7875 (port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY && 7876 (port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK) == 7877 TN1010_DEV_ID)) { 7878 hw_p->niu_type = NEPTUNE_1_10GF_1_TN1010; 7879 hw_p->xcvr_addr[0] = port_fd_arr[0]; 7880 hw_p->xcvr_addr[1] = port_fd_arr[1]; 7881 7882 /* Slot0 has copper XAUI, slot1 has fiber XAUI */ 7883 } else if ((port_pcs_dev_id[1] == PHY_BCM8704_FAMILY && 7884 (port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 7885 == TN1010_DEV_ID) || 7886 (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY && 7887 (port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK) 7888 == TN1010_DEV_ID)) { 7889 hw_p->niu_type = NEPTUNE_1_TN1010_1_10GF; 7890 hw_p->xcvr_addr[0] = port_fd_arr[0]; 7891 hw_p->xcvr_addr[1] = port_fd_arr[1]; 7892 7893 } else { 7894 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7895 "Unsupported neptune type 2")); 7896 goto error_exit; 7897 } 7898 break; 7899 7900 case 4: 7901 if (nxge_get_num_of_xaui( 7902 port_pma_pmd_dev_id, port_pcs_dev_id, 7903 port_phy_id, &num_xaui) == NXGE_ERROR) { 7904 goto error_exit; 7905 } 7906 if (num_xaui != 2) 7907 goto error_exit; 7908 7909 /* 7910 * Maramba with 2 XAUIs (either fiber or copper) 7911 * 7912 * Check the first phy port address against 7913 * the known phy start addresses to determine 7914 * the platform type. 7915 */ 7916 switch (phy_fd_arr[0]) { 7917 case MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE: 7918 hw_p->platform_type = 7919 P_NEPTUNE_MARAMBA_P0; 7920 break; 7921 case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE: 7922 hw_p->platform_type = 7923 P_NEPTUNE_MARAMBA_P1; 7924 break; 7925 default: 7926 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7927 "Unknown port %d...Cannot " 7928 "determine platform type", i)); 7929 goto error_exit; 7930 } 7931 7932 hw_p->xcvr_addr[0] = port_fd_arr[0]; 7933 hw_p->xcvr_addr[1] = port_fd_arr[1]; 7934 hw_p->xcvr_addr[2] = phy_fd_arr[2]; 7935 hw_p->xcvr_addr[3] = phy_fd_arr[3]; 7936 7937 /* slot0 has fiber XAUI, slot1 has Cu XAUI */ 7938 if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY && 7939 (port_pcs_dev_id[1] & TN1010_DEV_ID_MASK) 7940 == TN1010_DEV_ID) { 7941 hw_p->niu_type = NEPTUNE_1_10GF_1_TN1010_2_1GC; 7942 7943 /* slot0 has Cu XAUI, slot1 has fiber XAUI */ 7944 } else if (((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 7945 == TN1010_DEV_ID) && 7946 port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) { 7947 hw_p->niu_type = NEPTUNE_1_TN1010_1_10GF_2_1GC; 7948 7949 /* Both slots have fiber XAUI */ 7950 } else if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY && 7951 port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) { 7952 hw_p->niu_type = NEPTUNE_2_10GF_2_1GC; 7953 7954 /* Both slots have copper XAUI */ 7955 } else if (((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 7956 == TN1010_DEV_ID) && 7957 (port_pcs_dev_id[1] & TN1010_DEV_ID_MASK) 7958 == TN1010_DEV_ID) { 7959 hw_p->niu_type = NEPTUNE_2_TN1010_2_1GC; 7960 7961 } else { 7962 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7963 "Unsupported neptune type 3")); 7964 goto error_exit; 7965 } 7966 break; 7967 default: 7968 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7969 "Unsupported neptune type 5")); 7970 goto error_exit; 7971 } 7972 break; 7973 case 1: /* Only one clause45 port */ 7974 switch (total_phy_fd) { /* Number of clause22 ports */ 7975 case 3: 7976 /* 7977 * TODO 3 1G, 1 10G mode. 7978 * Differentiate between 1_1G_1_10G_2_1G and 7979 * 1_10G_3_1G 7980 */ 7981 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7982 "Unsupported neptune type 7")); 7983 goto error_exit; 7984 case 2: 7985 /* 7986 * TODO 2 1G, 1 10G mode. 7987 * Differentiate between 1_1G_1_10G_1_1G and 7988 * 1_10G_2_1G 7989 */ 7990 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7991 "Unsupported neptune type 8")); 7992 goto error_exit; 7993 case 1: 7994 /* 7995 * TODO 1 1G, 1 10G mode. 7996 * Differentiate between 1_1G_1_10G and 7997 * 1_10G_1_1G 7998 */ 7999 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8000 "Unsupported neptune type 9")); 8001 goto error_exit; 8002 case 0: /* N2 with 1 XAUI (fiber or copper) */ 8003 /* Fiber XAUI */ 8004 if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY || 8005 port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) { 8006 8007 /* 8008 * Check the first phy port address against 8009 * the known phy start addresses to determine 8010 * the platform type. 8011 */ 8012 8013 switch (port_fd_arr[0]) { 8014 case N2_CLAUSE45_PORT_ADDR_BASE: 8015 case (N2_CLAUSE45_PORT_ADDR_BASE + 1): 8016 case ALT_GOA_CLAUSE45_PORT1_ADDR: 8017 /* 8018 * If hw_p->platform_type == 8019 * P_NEPTUNE_NIU, then portmode 8020 * is already known, so there is 8021 * no need to figure out hw_p-> 8022 * platform_type because 8023 * platform_type is only for 8024 * figuring out portmode. 8025 */ 8026 if (hw_p->platform_type != 8027 P_NEPTUNE_NIU) { 8028 hw_p->platform_type = 8029 P_NEPTUNE_GENERIC; 8030 hw_p->niu_type = 8031 NEPTUNE_2_10GF; 8032 } 8033 break; 8034 default: 8035 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 8036 "Unsupported neptune type 10")); 8037 goto error_exit; 8038 } 8039 /* 8040 * For GOA, which is a hot swappable PHY, the 8041 * phy address to function number mapping 8042 * should be preserved, i.e., addr 16 is 8043 * assigned to function 0 and 20 to function 1 8044 * But for Huron XAUI, the assignment should 8045 * be by function number, i.e., whichever 8046 * function number attaches should be 8047 * assigned the available PHY (this is required 8048 * primarily to support pre-production Huron 8049 * boards where function 0 is mapped to addr 17 8050 */ 8051 if (port_fd_arr[0] == 8052 ALT_GOA_CLAUSE45_PORT1_ADDR) { 8053 hw_p->xcvr_addr[1] = port_fd_arr[0]; 8054 } else { 8055 hw_p->xcvr_addr[nxgep->function_num] = 8056 port_fd_arr[0]; 8057 } 8058 } else if (port_pcs_dev_id[0] == NLP2020_DEV_ID || 8059 port_pma_pmd_dev_id[0] == NLP2020_DEV_ID) { 8060 /* A 10G NLP2020 PHY in slot0 or slot1 */ 8061 switch (port_fd_arr[0]) { 8062 case NLP2020_CL45_PORT0_ADDR0: 8063 case NLP2020_CL45_PORT0_ADDR1: 8064 case NLP2020_CL45_PORT0_ADDR2: 8065 case NLP2020_CL45_PORT0_ADDR3: 8066 case NLP2020_CL45_PORT1_ADDR0: 8067 case NLP2020_CL45_PORT1_ADDR1: 8068 case NLP2020_CL45_PORT1_ADDR2: 8069 case NLP2020_CL45_PORT1_ADDR3: 8070 /* 8071 * If hw_p->platform_type == 8072 * P_NEPTUNE_NIU, then portmode 8073 * is already known, so there is 8074 * no need to figure out hw_p-> 8075 * platform_type because 8076 * platform_type is only for 8077 * figuring out portmode. 8078 */ 8079 if (hw_p->platform_type != 8080 P_NEPTUNE_NIU) { 8081 hw_p->platform_type = 8082 P_NEPTUNE_GENERIC; 8083 hw_p->niu_type = 8084 NEPTUNE_2_10GF; 8085 } 8086 break; 8087 default: 8088 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 8089 "Unsupported neptune type 10-1")); 8090 goto error_exit; 8091 } 8092 switch (port_fd_arr[0]) { 8093 case NLP2020_CL45_PORT0_ADDR0: 8094 case NLP2020_CL45_PORT0_ADDR1: 8095 case NLP2020_CL45_PORT0_ADDR2: 8096 case NLP2020_CL45_PORT0_ADDR3: 8097 hw_p->xcvr_addr[0] = port_fd_arr[0]; 8098 break; 8099 case NLP2020_CL45_PORT1_ADDR0: 8100 case NLP2020_CL45_PORT1_ADDR1: 8101 case NLP2020_CL45_PORT1_ADDR2: 8102 case NLP2020_CL45_PORT1_ADDR3: 8103 hw_p->xcvr_addr[1] = port_fd_arr[0]; 8104 break; 8105 default: 8106 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 8107 "Unsupported neptune type 10-11")); 8108 goto error_exit; 8109 } 8110 8111 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8112 "Found 1 NL PHYs at addr 0x%x", 8113 port_fd_arr[0])); 8114 8115 /* A 10G copper XAUI in either slot0 or slot1 */ 8116 } else if ((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 8117 == TN1010_DEV_ID || 8118 (port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK) 8119 == TN1010_DEV_ID) { 8120 switch (port_fd_arr[0]) { 8121 /* The XAUI is in slot0 */ 8122 case N2_CLAUSE45_PORT_ADDR_BASE: 8123 hw_p->niu_type = NEPTUNE_1_TN1010; 8124 break; 8125 8126 /* The XAUI is in slot1 */ 8127 case (N2_CLAUSE45_PORT_ADDR_BASE + 1): 8128 hw_p->niu_type 8129 = NEPTUNE_1_NONE_1_TN1010; 8130 break; 8131 default: 8132 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 8133 "Unsupported XAUI port address")); 8134 goto error_exit; 8135 } 8136 hw_p->xcvr_addr[nxgep->function_num] 8137 = port_fd_arr[0]; 8138 8139 } else { 8140 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8141 "Unsupported PHY type")); 8142 goto error_exit; 8143 } 8144 break; 8145 case 4: /* Maramba always have 4 clause 45 ports */ 8146 8147 /* Maramba with 1 XAUI */ 8148 if ((port_pcs_dev_id[0] != PHY_BCM8704_FAMILY) && 8149 (port_pma_pmd_dev_id[0] != PHY_BCM8704_FAMILY) && 8150 ((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 8151 != TN1010_DEV_ID) && 8152 ((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK) 8153 != TN1010_DEV_ID)) { 8154 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8155 "Unsupported neptune type 12")); 8156 goto error_exit; 8157 } 8158 8159 /* 8160 * Check the first phy port address against 8161 * the known phy start addresses to determine 8162 * the platform type. 8163 */ 8164 switch (phy_fd_arr[0]) { 8165 case MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE: 8166 hw_p->platform_type = 8167 P_NEPTUNE_MARAMBA_P0; 8168 break; 8169 case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE: 8170 hw_p->platform_type = 8171 P_NEPTUNE_MARAMBA_P1; 8172 break; 8173 default: 8174 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 8175 "Unknown port %d...Cannot " 8176 "determine platform type 10 - 2", 8177 i)); 8178 goto error_exit; 8179 } 8180 8181 /* 8182 * Check the clause45 address to determine 8183 * if XAUI is in port 0 or port 1. 8184 */ 8185 switch (port_fd_arr[0]) { 8186 case MARAMBA_CLAUSE45_PORT_ADDR_BASE: 8187 if (port_pcs_dev_id[0] 8188 == PHY_BCM8704_FAMILY || 8189 port_pma_pmd_dev_id[0] 8190 == PHY_BCM8704_FAMILY) { 8191 hw_p->niu_type 8192 = NEPTUNE_1_10GF_3_1GC; 8193 } else { 8194 hw_p->niu_type 8195 = NEPTUNE_1_TN1010_3_1GC; 8196 } 8197 hw_p->xcvr_addr[0] = port_fd_arr[0]; 8198 for (i = 1; i < NXGE_MAX_PORTS; i++) { 8199 hw_p->xcvr_addr[i] = 8200 phy_fd_arr[i]; 8201 } 8202 break; 8203 case (MARAMBA_CLAUSE45_PORT_ADDR_BASE + 1): 8204 if (port_pcs_dev_id[0] 8205 == PHY_BCM8704_FAMILY || 8206 port_pma_pmd_dev_id[0] 8207 == PHY_BCM8704_FAMILY) { 8208 hw_p->niu_type = 8209 NEPTUNE_1_1GC_1_10GF_2_1GC; 8210 } else { 8211 hw_p->niu_type = 8212 NEPTUNE_1_1GC_1_TN1010_2_1GC; 8213 } 8214 hw_p->xcvr_addr[0] = phy_fd_arr[0]; 8215 hw_p->xcvr_addr[1] = port_fd_arr[0]; 8216 hw_p->xcvr_addr[2] = phy_fd_arr[2]; 8217 hw_p->xcvr_addr[3] = phy_fd_arr[3]; 8218 break; 8219 default: 8220 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8221 "Unsupported neptune type 11")); 8222 goto error_exit; 8223 } 8224 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8225 "Maramba with 1 XAUI (fiber or copper)")); 8226 break; 8227 default: 8228 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8229 "Unsupported neptune type 13")); 8230 goto error_exit; 8231 } 8232 break; 8233 case 0: /* 4 ports Neptune based NIC */ 8234 switch (total_phy_fd) { 8235 case 4: 8236 if ((port_phy_id[0] == PHY_BCM5464R_FAMILY) && 8237 (port_phy_id[1] == PHY_BCM5464R_FAMILY) && 8238 (port_phy_id[2] == PHY_BCM5464R_FAMILY) && 8239 (port_phy_id[3] == PHY_BCM5464R_FAMILY)) { 8240 8241 /* 8242 * Check the first phy port address against 8243 * the known phy start addresses to determine 8244 * the platform type. 8245 */ 8246 switch (phy_fd_arr[0]) { 8247 case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE: 8248 hw_p->platform_type = 8249 P_NEPTUNE_MARAMBA_P1; 8250 break; 8251 case NEPTUNE_CLAUSE22_PORT_ADDR_BASE: 8252 hw_p->platform_type = 8253 P_NEPTUNE_ATLAS_4PORT; 8254 break; 8255 default: 8256 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 8257 "Unknown port %d...Cannot " 8258 "determine platform type", i)); 8259 goto error_exit; 8260 } 8261 hw_p->niu_type = NEPTUNE_4_1GC; 8262 for (i = 0; i < NXGE_MAX_PORTS; i++) { 8263 hw_p->xcvr_addr[i] = phy_fd_arr[i]; 8264 } 8265 } else { 8266 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8267 "Unsupported neptune type 14")); 8268 goto error_exit; 8269 } 8270 break; 8271 case 3: 8272 /* TODO 3 1G mode */ 8273 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8274 "Unsupported neptune type 15")); 8275 goto error_exit; 8276 case 2: 8277 /* TODO 2 1G mode */ 8278 if ((port_phy_id[0] == PHY_BCM5482_FAMILY) && 8279 (port_phy_id[1] == PHY_BCM5482_FAMILY)) { 8280 hw_p->platform_type = P_NEPTUNE_GENERIC; 8281 hw_p->niu_type = NEPTUNE_2_1GRF; 8282 hw_p->xcvr_addr[2] = phy_fd_arr[0]; 8283 hw_p->xcvr_addr[3] = phy_fd_arr[1]; 8284 } else { 8285 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 8286 "Unsupported neptune type 16")); 8287 goto error_exit; 8288 } 8289 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8290 "2 RGMII Fiber ports - RTM")); 8291 break; 8292 8293 case 1: 8294 /* TODO 1 1G mode */ 8295 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8296 "Unsupported neptune type 17")); 8297 goto error_exit; 8298 default: 8299 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8300 "Unsupported neptune type 18, total phy fd %d", 8301 total_phy_fd)); 8302 goto error_exit; 8303 } 8304 break; 8305 default: 8306 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8307 "Unsupported neptune type 19")); 8308 goto error_exit; 8309 } 8310 8311 scan_exit: 8312 8313 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_scan_ports_phy, " 8314 "niu type [0x%x]\n", hw_p->niu_type)); 8315 return (status); 8316 8317 error_exit: 8318 return (NXGE_ERROR); 8319 } 8320 8321 boolean_t 8322 nxge_is_valid_local_mac(ether_addr_st mac_addr) 8323 { 8324 if ((mac_addr.ether_addr_octet[0] & 0x01) || 8325 (ether_cmp(&mac_addr, ðerbroadcastaddr) == 0) || 8326 (ether_cmp(&mac_addr, ðerzeroaddr) == 0)) 8327 return (B_FALSE); 8328 else 8329 return (B_TRUE); 8330 } 8331 8332 static void 8333 nxge_bcm5464_link_led_off(p_nxge_t nxgep) 8334 { 8335 8336 npi_status_t rs = NPI_SUCCESS; 8337 uint8_t xcvr_portn; 8338 uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 8339 8340 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_bcm5464_link_led_off")); 8341 8342 switch (nxgep->nxge_hw_p->platform_type) { 8343 case P_NEPTUNE_MARAMBA_P1: 8344 xcvr_portn = MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE; 8345 break; 8346 case P_NEPTUNE_MARAMBA_P0: 8347 xcvr_portn = MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE; 8348 break; 8349 default: 8350 xcvr_portn = 0; 8351 break; 8352 } 8353 /* 8354 * For Altas 4-1G copper, Xcvr port numbers are 8355 * swapped with ethernet port number. This is 8356 * designed for better signal integrity in routing. 8357 */ 8358 switch (portn) { 8359 case 0: 8360 xcvr_portn += 3; 8361 break; 8362 case 1: 8363 xcvr_portn += 2; 8364 break; 8365 case 2: 8366 xcvr_portn += 1; 8367 break; 8368 case 3: 8369 default: 8370 break; 8371 } 8372 8373 MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 8374 rs = npi_mac_mif_mii_write(nxgep->npi_handle, 8375 xcvr_portn, BCM5464R_MISC, 0xb4ee); 8376 if (rs != NPI_SUCCESS) { 8377 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 8378 "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write " 8379 "returned error 0x[%x]", rs)); 8380 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 8381 return; 8382 } 8383 8384 rs = npi_mac_mif_mii_write(nxgep->npi_handle, 8385 xcvr_portn, BCM5464R_MISC, 0xb8ee); 8386 if (rs != NPI_SUCCESS) { 8387 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 8388 "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write " 8389 "returned error 0x[%x]", rs)); 8390 } 8391 8392 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 8393 } 8394 8395 static nxge_status_t 8396 nxge_mii_get_link_mode(p_nxge_t nxgep) 8397 { 8398 p_nxge_stats_t statsp; 8399 uint8_t xcvr_portn; 8400 p_mii_regs_t mii_regs; 8401 mii_mode_control_stat_t mode; 8402 int status = NXGE_OK; 8403 8404 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_get_link_mode")); 8405 8406 statsp = nxgep->statsp; 8407 xcvr_portn = statsp->mac_stats.xcvr_portn; 8408 mii_regs = NULL; 8409 mode.value = 0; 8410 mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG; 8411 if ((status = nxge_mii_write(nxgep, xcvr_portn, 8412 (uint8_t)(uint64_t)(&mii_regs->shadow), 8413 mode.value)) != NXGE_OK) { 8414 goto fail; 8415 } 8416 if ((status = nxge_mii_read(nxgep, xcvr_portn, 8417 (uint8_t)(uint64_t)(&mii_regs->shadow), 8418 &mode.value)) != NXGE_OK) { 8419 goto fail; 8420 } 8421 8422 if (mode.bits.mode == NXGE_MODE_SELECT_FIBER) { 8423 nxgep->mac.portmode = PORT_1G_RGMII_FIBER; 8424 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8425 "nxge_mii_get_link_mode: fiber mode")); 8426 } 8427 8428 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8429 "nxge_mii_get_link_mode: " 8430 "(address 0x%x) port 0x%x mode value 0x%x link mode 0x%x", 8431 NXGE_MII_MODE_CONTROL_REG, xcvr_portn, 8432 mode.value, nxgep->mac.portmode)); 8433 8434 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8435 "<== nxge_mii_get_link_mode")); 8436 return (status); 8437 fail: 8438 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 8439 "<== nxge_mii_get_link_mode (failed)")); 8440 return (NXGE_ERROR); 8441 } 8442 8443 nxge_status_t 8444 nxge_mac_set_framesize(p_nxge_t nxgep) 8445 { 8446 npi_attr_t ap; 8447 uint8_t portn; 8448 npi_handle_t handle; 8449 npi_status_t rs = NPI_SUCCESS; 8450 8451 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_set_framesize")); 8452 8453 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 8454 handle = nxgep->npi_handle; 8455 8456 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8457 "==> nxge_mac_sec_framesize: port<%d> " 8458 "min framesize %d max framesize %d ", 8459 portn, 8460 nxgep->mac.minframesize, 8461 nxgep->mac.maxframesize)); 8462 8463 SET_MAC_ATTR2(handle, ap, portn, 8464 MAC_PORT_FRAME_SIZE, 8465 nxgep->mac.minframesize, 8466 nxgep->mac.maxframesize, 8467 rs); 8468 if (rs != NPI_SUCCESS) { 8469 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8470 "<== nxge_mac_set_framesize: failed to configure " 8471 "max/min frame size port %d", portn)); 8472 8473 return (NXGE_ERROR | rs); 8474 } 8475 8476 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8477 "<== nxge_mac_set_framesize: port<%d>", portn)); 8478 8479 return (NXGE_OK); 8480 } 8481 8482 static nxge_status_t 8483 nxge_get_num_of_xaui(uint32_t *port_pma_pmd_dev_id, 8484 uint32_t *port_pcs_dev_id, uint32_t *port_phy_id, uint8_t *num_xaui) 8485 { 8486 uint8_t i; 8487 8488 for (i = 0; i < 4; i++) { 8489 if (port_phy_id[i] != PHY_BCM5464R_FAMILY) 8490 return (NXGE_ERROR); 8491 } 8492 8493 *num_xaui = 0; 8494 if ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY && 8495 port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) || 8496 (((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK) 8497 == TN1010_DEV_ID) && 8498 ((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 8499 == TN1010_DEV_ID))) { 8500 (*num_xaui) ++; 8501 } 8502 if ((port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY && 8503 port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) || 8504 (((port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK) 8505 == TN1010_DEV_ID) && 8506 ((port_pcs_dev_id[1] & TN1010_DEV_ID_MASK) 8507 == TN1010_DEV_ID))) { 8508 (*num_xaui) ++; 8509 } 8510 return (NXGE_OK); 8511 } 8512 8513 /* 8514 * Instruction from Teranetics: Once you detect link is up, go 8515 * read Reg 30.1.4 for link speed: '1' for 1G and '0' for 10G. You 8516 * may want to qualify it by first checking Register 30.1.7:6 and 8517 * making sure it reads "01" (Auto-Neg Complete). 8518 * 8519 * If this function is called when the link is down or before auto- 8520 * negotiation has completed, then the speed of the PHY is not certain. 8521 * In such cases, this function returns 1G as the default speed with 8522 * NXGE_OK status instead of NXGE_ERROR. It is OK to initialize the 8523 * driver based on a default speed because this function will be called 8524 * again when the link comes up. Returning NXGE_ERROR, which may 8525 * cause brutal chain reaction in caller functions, is not necessary. 8526 */ 8527 static nxge_status_t 8528 nxge_get_tn1010_speed(p_nxge_t nxgep, uint16_t *speed) 8529 { 8530 uint8_t phy_port_addr, autoneg_stat, link_up; 8531 nxge_status_t status = NXGE_OK; 8532 uint16_t val; 8533 uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 8534 8535 /* Set default speed to 10G */ 8536 *speed = TN1010_SPEED_10G; 8537 8538 /* Set Clause 45 */ 8539 npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE); 8540 8541 phy_port_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 8542 8543 /* Check Device 1 Register 0xA bit0 for link up status */ 8544 status = nxge_mdio_read(nxgep, phy_port_addr, 8545 TN1010_AUTONEG_DEV_ADDR, TN1010_AUTONEG_STATUS_REG, &val); 8546 if (status != NXGE_OK) 8547 goto fail; 8548 8549 link_up = ((val & TN1010_AN_LINK_STAT_BIT) 8550 ? B_TRUE : B_FALSE); 8551 if (link_up == B_FALSE) { 8552 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8553 "nxge_get_tn1010_speed: link is down")); 8554 goto nxge_get_tn1010_speed_exit; 8555 } 8556 8557 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 8558 TN1010_VENDOR_MMD1_DEV_ADDR, TN1010_VENDOR_MMD1_STATUS_REG, 8559 &val)) != NXGE_OK) { 8560 goto fail; 8561 } 8562 autoneg_stat = (val & TN1010_VENDOR_MMD1_AN_STAT_BITS) >> 8563 TN1010_VENDOR_MMD1_AN_STAT_SHIFT; 8564 8565 /* 8566 * Return NXGE_OK even when we can not get a settled speed. In 8567 * such case, the speed reported should not be trusted but that 8568 * is OK, we will call this function periodically and will get 8569 * the correct speed after the link is up. 8570 */ 8571 switch (autoneg_stat) { 8572 case TN1010_AN_IN_PROG: 8573 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8574 "nxge_get_tn1010_speed: Auto-negotiation in progress")); 8575 break; 8576 case TN1010_AN_COMPLETE: 8577 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 8578 TN1010_VENDOR_MMD1_DEV_ADDR, 8579 TN1010_VENDOR_MMD1_STATUS_REG, 8580 &val)) != NXGE_OK) { 8581 goto fail; 8582 } 8583 *speed = (val & TN1010_VENDOR_MMD1_AN_SPEED_BIT) >> 8584 TN1010_VENDOR_MMD1_AN_SPEED_SHIFT; 8585 break; 8586 case TN1010_AN_RSVD: 8587 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 8588 "nxge_get_tn1010_speed: Autoneg status undefined")); 8589 break; 8590 case TN1010_AN_FAILED: 8591 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8592 "nxge_get_tn1010_speed: Auto-negotiation failed")); 8593 break; 8594 default: 8595 break; 8596 } 8597 nxge_get_tn1010_speed_exit: 8598 return (NXGE_OK); 8599 fail: 8600 return (status); 8601 } 8602 8603 8604 /* 8605 * Teranetics TN1010 PHY chip supports both 1G and 10G modes, this function 8606 * figures out the speed of the PHY determined by the autonegotiation 8607 * process and sets the following 3 parameters, 8608 * nxgep->mac.portmode 8609 * nxgep->statsp->mac_stats.link_speed 8610 * nxgep->statsp->mac_stats.xcvr_inuse 8611 */ 8612 static nxge_status_t 8613 nxge_set_tn1010_param(p_nxge_t nxgep) 8614 { 8615 uint16_t speed; 8616 8617 if (nxge_get_tn1010_speed(nxgep, &speed) != NXGE_OK) { 8618 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 8619 "nxge_set_tn1010_param: " 8620 "Failed to get TN1010 speed")); 8621 return (NXGE_ERROR); 8622 } 8623 if (speed == TN1010_SPEED_1G) { 8624 nxgep->mac.portmode = PORT_1G_TN1010; 8625 nxgep->statsp->mac_stats.link_speed = 1000; 8626 nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 8627 } else { 8628 nxgep->mac.portmode = PORT_10G_TN1010; 8629 nxgep->statsp->mac_stats.link_speed = 10000; 8630 nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 8631 } 8632 return (NXGE_OK); 8633 } 8634 8635 #ifdef NXGE_DEBUG 8636 static void 8637 nxge_mii_dump(p_nxge_t nxgep) 8638 { 8639 p_nxge_stats_t statsp; 8640 uint8_t xcvr_portn; 8641 p_mii_regs_t mii_regs; 8642 mii_bmcr_t bmcr; 8643 mii_bmsr_t bmsr; 8644 mii_idr1_t idr1; 8645 mii_idr2_t idr2; 8646 mii_mode_control_stat_t mode; 8647 p_nxge_param_t param_arr; 8648 8649 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "==> nxge_mii_dump")); 8650 8651 statsp = nxgep->statsp; 8652 xcvr_portn = statsp->mac_stats.xcvr_portn; 8653 8654 mii_regs = NULL; 8655 8656 (void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn, 8657 (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value); 8658 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 8659 "nxge_mii_dump: bmcr (0) xcvr 0x%x value 0x%x", 8660 xcvr_portn, bmcr.value)); 8661 8662 (void) nxge_mii_read(nxgep, 8663 nxgep->statsp->mac_stats.xcvr_portn, 8664 (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value); 8665 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 8666 "nxge_mii_dump: bmsr (1) xcvr 0x%x value 0x%x", 8667 xcvr_portn, bmsr.value)); 8668 8669 (void) nxge_mii_read(nxgep, 8670 nxgep->statsp->mac_stats.xcvr_portn, 8671 (uint8_t)(uint64_t)(&mii_regs->idr1), &idr1.value); 8672 8673 8674 (void) nxge_mii_read(nxgep, 8675 nxgep->statsp->mac_stats.xcvr_portn, 8676 (uint8_t)(uint64_t)(&mii_regs->idr2), &idr2.value); 8677 8678 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 8679 "nxge_mii_dump: idr1 (2) xcvr 0x%x value 0x%x", 8680 xcvr_portn, idr1.value)); 8681 8682 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 8683 "nxge_mii_dump: idr2 (3) xcvr 0x%x value 0x%x", 8684 xcvr_portn, idr2.value)); 8685 8686 mode.value = 0; 8687 mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG; 8688 8689 (void) nxge_mii_write(nxgep, xcvr_portn, 8690 (uint8_t)(uint64_t)(&mii_regs->shadow), mode.value); 8691 8692 (void) nxge_mii_read(nxgep, xcvr_portn, 8693 (uint8_t)(uint64_t)(&mii_regs->shadow), &mode.value); 8694 8695 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 8696 "nxge_mii_dump: mode control xcvr 0x%x value 0x%x", 8697 xcvr_portn, mode.value)); 8698 } 8699 #endif 8700