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 #if defined(__i386) 4834 (uint8_t)(uint32_t)&mii_regs->bmcr, 4835 #else 4836 (uint8_t)(uint64_t)&mii_regs->bmcr, 4837 #endif 4838 bmcr.value)) != NXGE_OK) 4839 goto fail; 4840 do { 4841 drv_usecwait(500); 4842 if ((status = nxge_mii_read(nxgep, xcvr_portn, 4843 #if defined(__i386) 4844 (uint8_t)(uint32_t)&mii_regs->bmcr, 4845 #else 4846 (uint8_t)(uint64_t)&mii_regs->bmcr, 4847 #endif 4848 &bmcr.value)) != NXGE_OK) 4849 goto fail; 4850 delay++; 4851 } while ((bmcr.bits.reset) && (delay < 1000)); 4852 if (delay == 1000) { 4853 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed.")); 4854 goto fail; 4855 } 4856 4857 if ((status = nxge_mii_read(nxgep, xcvr_portn, 4858 #if defined(__i386) 4859 (uint8_t)(uint32_t)(&mii_regs->bmsr), 4860 #else 4861 (uint8_t)(uint64_t)(&mii_regs->bmsr), 4862 #endif 4863 &bmsr.value)) != NXGE_OK) 4864 goto fail; 4865 4866 param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able; 4867 param_arr[param_anar_100T4].value &= bmsr.bits.link_100T4; 4868 param_arr[param_anar_100fdx].value &= bmsr.bits.link_100fdx; 4869 param_arr[param_anar_100hdx].value = 0; 4870 param_arr[param_anar_10fdx].value &= bmsr.bits.link_10fdx; 4871 param_arr[param_anar_10hdx].value = 0; 4872 4873 /* 4874 * Initialize the xcvr statistics. 4875 */ 4876 statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able; 4877 statsp->mac_stats.cap_100T4 = bmsr.bits.link_100T4; 4878 statsp->mac_stats.cap_100fdx = bmsr.bits.link_100fdx; 4879 statsp->mac_stats.cap_100hdx = 0; 4880 statsp->mac_stats.cap_10fdx = bmsr.bits.link_10fdx; 4881 statsp->mac_stats.cap_10hdx = 0; 4882 statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value; 4883 statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value; 4884 4885 /* 4886 * Initialize the xcvr advertised capability statistics. 4887 */ 4888 statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value; 4889 statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 4890 statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 4891 statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value; 4892 statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value; 4893 statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value; 4894 statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value; 4895 statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value; 4896 statsp->mac_stats.adv_cap_asmpause = 4897 param_arr[param_anar_asmpause].value; 4898 statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value; 4899 4900 4901 /* 4902 * Check for extended status just in case we're 4903 * running a Gigibit phy. 4904 */ 4905 if (bmsr.bits.extend_status) { 4906 if ((status = nxge_mii_read(nxgep, xcvr_portn, 4907 #if defined(__i386) 4908 (uint8_t)(uint32_t)(&mii_regs->esr), 4909 #else 4910 (uint8_t)(uint64_t)(&mii_regs->esr), 4911 #endif 4912 &esr.value)) != NXGE_OK) 4913 goto fail; 4914 param_arr[param_anar_1000fdx].value &= esr.bits.link_1000fdx; 4915 param_arr[param_anar_1000hdx].value = 0; 4916 4917 statsp->mac_stats.cap_1000fdx = 4918 (esr.bits.link_1000Xfdx || esr.bits.link_1000fdx); 4919 statsp->mac_stats.cap_1000hdx = 0; 4920 } else { 4921 param_arr[param_anar_1000fdx].value = 0; 4922 param_arr[param_anar_1000hdx].value = 0; 4923 } 4924 4925 /* 4926 * Initialize 1G Statistics once the capability is established. 4927 */ 4928 statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 4929 statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 4930 4931 /* 4932 * Initialize the link statistics. 4933 */ 4934 statsp->mac_stats.link_T4 = 0; 4935 statsp->mac_stats.link_asmpause = 0; 4936 statsp->mac_stats.link_pause = 0; 4937 statsp->mac_stats.link_speed = 0; 4938 statsp->mac_stats.link_duplex = 0; 4939 statsp->mac_stats.link_up = 0; 4940 4941 /* 4942 * Switch off Auto-negotiation, 100M and full duplex. 4943 */ 4944 bmcr.value = 0; 4945 if ((status = nxge_mii_write(nxgep, xcvr_portn, 4946 #if defined(__i386) 4947 (uint8_t)(uint32_t)(&mii_regs->bmcr), 4948 #else 4949 (uint8_t)(uint64_t)(&mii_regs->bmcr), 4950 #endif 4951 bmcr.value)) != NXGE_OK) 4952 goto fail; 4953 4954 if ((statsp->port_stats.lb_mode == nxge_lb_phy) || 4955 (statsp->port_stats.lb_mode == nxge_lb_phy1000)) { 4956 bmcr.bits.loopback = 1; 4957 bmcr.bits.enable_autoneg = 0; 4958 if (statsp->port_stats.lb_mode == nxge_lb_phy1000) 4959 bmcr.bits.speed_1000_sel = 1; 4960 bmcr.bits.duplex_mode = 1; 4961 param_arr[param_autoneg].value = 0; 4962 } else { 4963 bmcr.bits.loopback = 0; 4964 } 4965 4966 if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) || 4967 (statsp->port_stats.lb_mode == nxge_lb_ext100) || 4968 (statsp->port_stats.lb_mode == nxge_lb_ext10)) { 4969 param_arr[param_autoneg].value = 0; 4970 bcm5464r_aux.value = 0; 4971 bcm5464r_aux.bits.ext_lb = 1; 4972 bcm5464r_aux.bits.write_1 = 1; 4973 if ((status = nxge_mii_write(nxgep, xcvr_portn, 4974 BCM5464R_AUX_CTL, bcm5464r_aux.value)) != NXGE_OK) 4975 goto fail; 4976 } 4977 4978 /* If auto-negotiation is desired */ 4979 if (param_arr[param_autoneg].value) { 4980 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4981 "Restarting Auto-negotiation.")); 4982 /* 4983 * Setup our Auto-negotiation advertisement register. 4984 */ 4985 anar.value = 0; 4986 anar.bits.selector = 1; 4987 anar.bits.cap_100T4 = param_arr[param_anar_100T4].value; 4988 anar.bits.cap_100fdx = param_arr[param_anar_100fdx].value; 4989 anar.bits.cap_100hdx = param_arr[param_anar_100hdx].value; 4990 anar.bits.cap_10fdx = param_arr[param_anar_10fdx].value; 4991 anar.bits.cap_10hdx = param_arr[param_anar_10hdx].value; 4992 anar.bits.cap_asmpause = 0; 4993 anar.bits.cap_pause = 0; 4994 if (param_arr[param_anar_1000fdx].value || 4995 param_arr[param_anar_100fdx].value || 4996 param_arr[param_anar_10fdx].value) { 4997 anar.bits.cap_asmpause = statsp->mac_stats.cap_asmpause; 4998 anar.bits.cap_pause = statsp->mac_stats.cap_pause; 4999 } 5000 5001 /* Write to the auto-negotiation advertisement register */ 5002 if ((status = nxge_mii_write(nxgep, xcvr_portn, 5003 #if defined(__i386) 5004 (uint8_t)(uint32_t)(&mii_regs->anar), 5005 #else 5006 (uint8_t)(uint64_t)(&mii_regs->anar), 5007 #endif 5008 anar.value)) != NXGE_OK) 5009 goto fail; 5010 if (bmsr.bits.extend_status) { 5011 gcr.value = 0; 5012 gcr.bits.ms_mode_en = 5013 param_arr[param_master_cfg_enable].value; 5014 gcr.bits.master = 5015 param_arr[param_master_cfg_value].value; 5016 gcr.bits.link_1000fdx = 5017 param_arr[param_anar_1000fdx].value; 5018 gcr.bits.link_1000hdx = 5019 param_arr[param_anar_1000hdx].value; 5020 if ((status = nxge_mii_write(nxgep, xcvr_portn, 5021 #if defined(__i386) 5022 (uint8_t)(uint32_t)(&mii_regs->gcr), 5023 #else 5024 (uint8_t)(uint64_t)(&mii_regs->gcr), 5025 #endif 5026 gcr.value)) != NXGE_OK) 5027 goto fail; 5028 } 5029 5030 bmcr.bits.enable_autoneg = 1; 5031 bmcr.bits.restart_autoneg = 1; 5032 5033 } else { 5034 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode.")); 5035 bmcr.bits.speed_1000_sel = 5036 param_arr[param_anar_1000fdx].value | 5037 param_arr[param_anar_1000hdx].value; 5038 bmcr.bits.speed_sel = (~bmcr.bits.speed_1000_sel) & 5039 (param_arr[param_anar_100fdx].value | 5040 param_arr[param_anar_100hdx].value); 5041 5042 /* Force to 1G */ 5043 if (bmcr.bits.speed_1000_sel) { 5044 statsp->mac_stats.link_speed = 1000; 5045 gcr.value = 0; 5046 gcr.bits.ms_mode_en = 5047 param_arr[param_master_cfg_enable].value; 5048 gcr.bits.master = 5049 param_arr[param_master_cfg_value].value; 5050 if ((status = nxge_mii_write(nxgep, xcvr_portn, 5051 #if defined(__i386) 5052 (uint8_t)(uint32_t)(&mii_regs->gcr), 5053 #else 5054 (uint8_t)(uint64_t)(&mii_regs->gcr), 5055 #endif 5056 gcr.value)) != NXGE_OK) 5057 goto fail; 5058 if (param_arr[param_anar_1000fdx].value) { 5059 bmcr.bits.duplex_mode = 1; 5060 statsp->mac_stats.link_duplex = 2; 5061 } else 5062 statsp->mac_stats.link_duplex = 1; 5063 5064 /* Force to 100M */ 5065 } else if (bmcr.bits.speed_sel) { 5066 statsp->mac_stats.link_speed = 100; 5067 if (param_arr[param_anar_100fdx].value) { 5068 bmcr.bits.duplex_mode = 1; 5069 statsp->mac_stats.link_duplex = 2; 5070 } else 5071 statsp->mac_stats.link_duplex = 1; 5072 5073 /* Force to 10M */ 5074 } else { 5075 statsp->mac_stats.link_speed = 10; 5076 if (param_arr[param_anar_10fdx].value) { 5077 bmcr.bits.duplex_mode = 1; 5078 statsp->mac_stats.link_duplex = 2; 5079 } else 5080 statsp->mac_stats.link_duplex = 1; 5081 } 5082 if (statsp->mac_stats.link_duplex != 1) { 5083 statsp->mac_stats.link_asmpause = 5084 statsp->mac_stats.cap_asmpause; 5085 statsp->mac_stats.link_pause = 5086 statsp->mac_stats.cap_pause; 5087 } 5088 5089 if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) || 5090 (statsp->port_stats.lb_mode == nxge_lb_ext100) || 5091 (statsp->port_stats.lb_mode == nxge_lb_ext10)) { 5092 if (statsp->port_stats.lb_mode == nxge_lb_ext1000) { 5093 /* BCM5464R 1000mbps external loopback mode */ 5094 gcr.value = 0; 5095 gcr.bits.ms_mode_en = 1; 5096 gcr.bits.master = 1; 5097 if ((status = nxge_mii_write(nxgep, xcvr_portn, 5098 #if defined(__i386) 5099 (uint8_t)(uint32_t)(&mii_regs->gcr), 5100 #else 5101 (uint8_t)(uint64_t)(&mii_regs->gcr), 5102 #endif 5103 gcr.value)) != NXGE_OK) 5104 goto fail; 5105 bmcr.value = 0; 5106 bmcr.bits.speed_1000_sel = 1; 5107 statsp->mac_stats.link_speed = 1000; 5108 } else if (statsp->port_stats.lb_mode 5109 == nxge_lb_ext100) { 5110 /* BCM5464R 100mbps external loopback mode */ 5111 bmcr.value = 0; 5112 bmcr.bits.speed_sel = 1; 5113 bmcr.bits.duplex_mode = 1; 5114 statsp->mac_stats.link_speed = 100; 5115 } else if (statsp->port_stats.lb_mode 5116 == nxge_lb_ext10) { 5117 /* BCM5464R 10mbps external loopback mode */ 5118 bmcr.value = 0; 5119 bmcr.bits.duplex_mode = 1; 5120 statsp->mac_stats.link_speed = 10; 5121 } 5122 } 5123 } 5124 5125 if ((status = nxge_mii_write(nxgep, xcvr_portn, 5126 #if defined(__i386) 5127 (uint8_t)(uint32_t)(&mii_regs->bmcr), 5128 #else 5129 (uint8_t)(uint64_t)(&mii_regs->bmcr), 5130 #endif 5131 bmcr.value)) != NXGE_OK) 5132 goto fail; 5133 5134 if ((status = nxge_mii_read(nxgep, xcvr_portn, 5135 #if defined(__i386) 5136 (uint8_t)(uint32_t)(&mii_regs->bmcr), 5137 #else 5138 (uint8_t)(uint64_t)(&mii_regs->bmcr), 5139 #endif 5140 &bmcr.value)) != NXGE_OK) 5141 goto fail; 5142 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "bmcr = 0x%04X", bmcr.value)); 5143 5144 /* 5145 * Initialize the xcvr status kept in the context structure. 5146 */ 5147 nxgep->soft_bmsr.value = 0; 5148 5149 if ((status = nxge_mii_read(nxgep, xcvr_portn, 5150 #if defined(__i386) 5151 (uint8_t)(uint32_t)(&mii_regs->bmsr), 5152 #else 5153 (uint8_t)(uint64_t)(&mii_regs->bmsr), 5154 #endif 5155 &nxgep->bmsr.value)) != NXGE_OK) 5156 goto fail; 5157 5158 statsp->mac_stats.xcvr_inits++; 5159 nxgep->bmsr.value = 0; 5160 5161 fail: 5162 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5163 "<== nxge_mii_xcvr_init status 0x%x", status)); 5164 return (status); 5165 } 5166 5167 nxge_status_t 5168 nxge_mii_xcvr_fiber_init(p_nxge_t nxgep) 5169 { 5170 p_nxge_param_t param_arr; 5171 p_nxge_stats_t statsp; 5172 uint8_t xcvr_portn; 5173 p_mii_regs_t mii_regs; 5174 mii_bmcr_t bmcr; 5175 mii_bmsr_t bmsr; 5176 mii_gcr_t gcr; 5177 mii_esr_t esr; 5178 mii_aux_ctl_t bcm5464r_aux; 5179 int status = NXGE_OK; 5180 5181 uint_t delay; 5182 5183 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_fiber_init")); 5184 5185 param_arr = nxgep->param_arr; 5186 statsp = nxgep->statsp; 5187 xcvr_portn = statsp->mac_stats.xcvr_portn; 5188 5189 mii_regs = NULL; 5190 5191 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5192 "nxge_mii_xcvr_fiber_init: " 5193 "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value)); 5194 5195 /* 5196 * Reset the transceiver. 5197 */ 5198 delay = 0; 5199 bmcr.value = 0; 5200 bmcr.bits.reset = 1; 5201 5202 #if defined(__i386) 5203 5204 if ((status = nxge_mii_write(nxgep, xcvr_portn, 5205 (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 5206 goto fail; 5207 #else 5208 if ((status = nxge_mii_write(nxgep, xcvr_portn, 5209 (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 5210 goto fail; 5211 #endif 5212 do { 5213 drv_usecwait(500); 5214 #if defined(__i386) 5215 if ((status = nxge_mii_read(nxgep, xcvr_portn, 5216 (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) 5217 != NXGE_OK) 5218 goto fail; 5219 #else 5220 if ((status = nxge_mii_read(nxgep, xcvr_portn, 5221 (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) 5222 != NXGE_OK) 5223 goto fail; 5224 #endif 5225 delay++; 5226 } while ((bmcr.bits.reset) && (delay < 1000)); 5227 if (delay == 1000) { 5228 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed.")); 5229 goto fail; 5230 } 5231 5232 #if defined(__i386) 5233 if ((status = nxge_mii_read(nxgep, xcvr_portn, 5234 (uint8_t)(uint32_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK) 5235 goto fail; 5236 #else 5237 if ((status = nxge_mii_read(nxgep, xcvr_portn, 5238 (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK) 5239 goto fail; 5240 #endif 5241 5242 param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able; 5243 param_arr[param_anar_100T4].value = 0; 5244 param_arr[param_anar_100fdx].value = 0; 5245 param_arr[param_anar_100hdx].value = 0; 5246 param_arr[param_anar_10fdx].value = 0; 5247 param_arr[param_anar_10hdx].value = 0; 5248 5249 /* 5250 * Initialize the xcvr statistics. 5251 */ 5252 statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able; 5253 statsp->mac_stats.cap_100T4 = 0; 5254 statsp->mac_stats.cap_100fdx = 0; 5255 statsp->mac_stats.cap_100hdx = 0; 5256 statsp->mac_stats.cap_10fdx = 0; 5257 statsp->mac_stats.cap_10hdx = 0; 5258 statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value; 5259 statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value; 5260 5261 /* 5262 * Initialize the xcvr advertised capability statistics. 5263 */ 5264 statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value; 5265 statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 5266 statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 5267 statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value; 5268 statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value; 5269 statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value; 5270 statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value; 5271 statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value; 5272 statsp->mac_stats.adv_cap_asmpause = 5273 param_arr[param_anar_asmpause].value; 5274 statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value; 5275 5276 /* 5277 * Check for extended status just in case we're 5278 * running a Gigibit phy. 5279 */ 5280 if (bmsr.bits.extend_status) { 5281 #if defined(__i386) 5282 if ((status = nxge_mii_read(nxgep, xcvr_portn, 5283 (uint8_t)(uint32_t)(&mii_regs->esr), &esr.value)) != 5284 NXGE_OK) 5285 goto fail; 5286 #else 5287 if ((status = nxge_mii_read(nxgep, xcvr_portn, 5288 (uint8_t)(uint64_t)(&mii_regs->esr), &esr.value)) != 5289 NXGE_OK) 5290 goto fail; 5291 #endif 5292 param_arr[param_anar_1000fdx].value &= 5293 esr.bits.link_1000fdx; 5294 param_arr[param_anar_1000hdx].value = 0; 5295 5296 statsp->mac_stats.cap_1000fdx = 5297 (esr.bits.link_1000Xfdx || esr.bits.link_1000fdx); 5298 statsp->mac_stats.cap_1000hdx = 0; 5299 } else { 5300 param_arr[param_anar_1000fdx].value = 0; 5301 param_arr[param_anar_1000hdx].value = 0; 5302 } 5303 5304 /* 5305 * Initialize 1G Statistics once the capability is established. 5306 */ 5307 statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 5308 statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 5309 5310 /* 5311 * Initialize the link statistics. 5312 */ 5313 statsp->mac_stats.link_T4 = 0; 5314 statsp->mac_stats.link_asmpause = 0; 5315 statsp->mac_stats.link_pause = 0; 5316 statsp->mac_stats.link_speed = 0; 5317 statsp->mac_stats.link_duplex = 0; 5318 statsp->mac_stats.link_up = 0; 5319 5320 /* 5321 * Switch off Auto-negotiation, 100M and full duplex. 5322 */ 5323 bmcr.value = 0; 5324 #if defined(__i386) 5325 if ((status = nxge_mii_write(nxgep, xcvr_portn, 5326 (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 5327 goto fail; 5328 #else 5329 if ((status = nxge_mii_write(nxgep, xcvr_portn, 5330 (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 5331 goto fail; 5332 #endif 5333 5334 if ((statsp->port_stats.lb_mode == nxge_lb_phy) || 5335 (statsp->port_stats.lb_mode == nxge_lb_phy1000)) { 5336 bmcr.bits.loopback = 1; 5337 bmcr.bits.enable_autoneg = 0; 5338 if (statsp->port_stats.lb_mode == nxge_lb_phy1000) 5339 bmcr.bits.speed_1000_sel = 1; 5340 bmcr.bits.duplex_mode = 1; 5341 param_arr[param_autoneg].value = 0; 5342 } else { 5343 bmcr.bits.loopback = 0; 5344 } 5345 5346 if (statsp->port_stats.lb_mode == nxge_lb_ext1000) { 5347 param_arr[param_autoneg].value = 0; 5348 bcm5464r_aux.value = 0; 5349 bcm5464r_aux.bits.ext_lb = 1; 5350 bcm5464r_aux.bits.write_1 = 1; 5351 if ((status = nxge_mii_write(nxgep, xcvr_portn, 5352 BCM5464R_AUX_CTL, bcm5464r_aux.value)) != NXGE_OK) 5353 goto fail; 5354 } 5355 5356 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode.")); 5357 bmcr.bits.speed_1000_sel = 1; 5358 bmcr.bits.speed_sel = 0; 5359 bmcr.bits.duplex_mode = 1; 5360 statsp->mac_stats.link_speed = 1000; 5361 statsp->mac_stats.link_duplex = 2; 5362 5363 if ((statsp->port_stats.lb_mode == nxge_lb_ext1000)) { 5364 /* BCM5464R 1000mbps external loopback mode */ 5365 gcr.value = 0; 5366 gcr.bits.ms_mode_en = 1; 5367 gcr.bits.master = 1; 5368 #if defined(__i386) 5369 if ((status = nxge_mii_write(nxgep, xcvr_portn, 5370 (uint8_t)(uint32_t)(&mii_regs->gcr), 5371 gcr.value)) != NXGE_OK) 5372 goto fail; 5373 #else 5374 if ((status = nxge_mii_write(nxgep, xcvr_portn, 5375 (uint8_t)(uint64_t)(&mii_regs->gcr), 5376 gcr.value)) != NXGE_OK) 5377 goto fail; 5378 #endif 5379 bmcr.value = 0; 5380 bmcr.bits.speed_1000_sel = 1; 5381 statsp->mac_stats.link_speed = 1000; 5382 } 5383 5384 #if defined(__i386) 5385 if ((status = nxge_mii_write(nxgep, xcvr_portn, 5386 (uint8_t)(uint32_t)(&mii_regs->bmcr), 5387 bmcr.value)) != NXGE_OK) 5388 goto fail; 5389 #else 5390 if ((status = nxge_mii_write(nxgep, xcvr_portn, 5391 (uint8_t)(uint64_t)(&mii_regs->bmcr), 5392 bmcr.value)) != NXGE_OK) 5393 goto fail; 5394 #endif 5395 5396 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5397 "nxge_mii_xcvr_fiber_init: value wrote bmcr = 0x%x", 5398 bmcr.value)); 5399 5400 #if defined(__i386) 5401 if ((status = nxge_mii_read(nxgep, xcvr_portn, 5402 (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK) 5403 goto fail; 5404 #else 5405 if ((status = nxge_mii_read(nxgep, xcvr_portn, 5406 (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK) 5407 goto fail; 5408 #endif 5409 5410 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5411 "nxge_mii_xcvr_fiber_init: read bmcr = 0x%04X", bmcr.value)); 5412 5413 /* 5414 * Initialize the xcvr status kept in the context structure. 5415 */ 5416 nxgep->soft_bmsr.value = 0; 5417 #if defined(__i386) 5418 if ((status = nxge_mii_read(nxgep, xcvr_portn, 5419 (uint8_t)(uint32_t)(&mii_regs->bmsr), 5420 &nxgep->bmsr.value)) != NXGE_OK) 5421 goto fail; 5422 #else 5423 if ((status = nxge_mii_read(nxgep, xcvr_portn, 5424 (uint8_t)(uint64_t)(&mii_regs->bmsr), 5425 &nxgep->bmsr.value)) != NXGE_OK) 5426 goto fail; 5427 #endif 5428 5429 statsp->mac_stats.xcvr_inits++; 5430 nxgep->bmsr.value = 0; 5431 5432 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5433 "<== nxge_mii_xcvr_fiber_init status 0x%x", status)); 5434 return (status); 5435 5436 fail: 5437 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5438 "<== nxge_mii_xcvr_fiber_init status 0x%x", status)); 5439 return (status); 5440 } 5441 5442 /* Read from a MII compliant register */ 5443 5444 nxge_status_t 5445 nxge_mii_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg, 5446 uint16_t *value) 5447 { 5448 npi_status_t rs = NPI_SUCCESS; 5449 5450 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_read: xcvr_port<%d>" 5451 "xcvr_reg<%d>", xcvr_portn, xcvr_reg)); 5452 5453 MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 5454 5455 if ((nxgep->mac.portmode == PORT_1G_COPPER) || 5456 (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) { 5457 if ((rs = npi_mac_mif_mii_read(nxgep->npi_handle, 5458 xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 5459 goto fail; 5460 } else if ((nxgep->mac.portmode == PORT_1G_FIBER) || 5461 (nxgep->mac.portmode == PORT_1G_SERDES)) { 5462 if ((rs = npi_mac_pcs_mii_read(nxgep->npi_handle, 5463 xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 5464 goto fail; 5465 } else 5466 goto fail; 5467 5468 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 5469 5470 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_read: xcvr_port<%d>" 5471 "xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg, *value)); 5472 return (NXGE_OK); 5473 fail: 5474 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 5475 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5476 "nxge_mii_read: Failed to read mii on xcvr %d", xcvr_portn)); 5477 5478 return (NXGE_ERROR | rs); 5479 } 5480 5481 /* Write to a MII compliant Register */ 5482 5483 nxge_status_t 5484 nxge_mii_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg, 5485 uint16_t value) 5486 { 5487 npi_status_t rs = NPI_SUCCESS; 5488 5489 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_write: xcvr_port<%d>" 5490 "xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg, value)); 5491 5492 MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 5493 5494 if ((nxgep->mac.portmode == PORT_1G_COPPER) || 5495 (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) { 5496 if ((rs = npi_mac_mif_mii_write(nxgep->npi_handle, 5497 xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 5498 goto fail; 5499 } else if ((nxgep->mac.portmode == PORT_1G_FIBER) || 5500 (nxgep->mac.portmode == PORT_1G_SERDES)) { 5501 if ((rs = npi_mac_pcs_mii_write(nxgep->npi_handle, 5502 xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 5503 goto fail; 5504 } else 5505 goto fail; 5506 5507 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 5508 5509 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_write: xcvr_port<%d>" 5510 "xcvr_reg<%d>", xcvr_portn, xcvr_reg)); 5511 return (NXGE_OK); 5512 fail: 5513 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 5514 5515 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5516 "nxge_mii_write: Failed to write mii on xcvr %d", xcvr_portn)); 5517 5518 return (NXGE_ERROR | rs); 5519 } 5520 5521 /* 5522 * Perform write to Clause45 serdes / transceiver device 5523 * Arguments: 5524 * xcvr_portn: The IEEE 802.3 Clause45 PHYAD, it is the same as port 5525 * number if nxge_mdio_write is used for accessing the 5526 * internal LSIL serdes. Otherwise PHYAD is different 5527 * for different platforms. 5528 * device: With each PHYAD, the driver can use MDIO to control 5529 * multiple devices inside the PHY, here "device" is an 5530 * MMD (MDIO managable device). 5531 * xcvr_reg: Each device has multiple registers. xcvr_reg specifies 5532 * the register which the driver will write value to. 5533 * value: The register value will be filled in. 5534 */ 5535 nxge_status_t 5536 nxge_mdio_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device, 5537 uint16_t xcvr_reg, uint16_t *value) 5538 { 5539 npi_status_t rs = NPI_SUCCESS; 5540 5541 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_read: xcvr_port<%d>", 5542 xcvr_portn)); 5543 5544 MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 5545 5546 if ((rs = npi_mac_mif_mdio_read(nxgep->npi_handle, 5547 xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS) 5548 goto fail; 5549 5550 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 5551 5552 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_read: xcvr_port<%d>", 5553 xcvr_portn)); 5554 return (NXGE_OK); 5555 fail: 5556 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 5557 5558 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5559 "nxge_mdio_read: Failed to read mdio on xcvr %d", xcvr_portn)); 5560 5561 return (NXGE_ERROR | rs); 5562 } 5563 5564 /* Perform write to Clause45 serdes / transceiver device */ 5565 5566 nxge_status_t 5567 nxge_mdio_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device, 5568 uint16_t xcvr_reg, uint16_t value) 5569 { 5570 npi_status_t rs = NPI_SUCCESS; 5571 5572 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_write: xcvr_port<%d>", 5573 xcvr_portn)); 5574 5575 MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 5576 5577 if ((rs = npi_mac_mif_mdio_write(nxgep->npi_handle, 5578 xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS) 5579 goto fail; 5580 5581 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 5582 5583 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_write: xcvr_port<%d>", 5584 xcvr_portn)); 5585 return (NXGE_OK); 5586 fail: 5587 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 5588 5589 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5590 "nxge_mdio_write: Failed to write mdio on xcvr %d", xcvr_portn)); 5591 5592 return (NXGE_ERROR | rs); 5593 } 5594 5595 5596 /* Check MII to see if there is any link status change */ 5597 5598 nxge_status_t 5599 nxge_mii_check(p_nxge_t nxgep, mii_bmsr_t bmsr, mii_bmsr_t bmsr_ints, 5600 nxge_link_state_t *link_up) 5601 { 5602 p_nxge_param_t param_arr; 5603 p_nxge_stats_t statsp; 5604 p_mii_regs_t mii_regs; 5605 p_mii_bmsr_t soft_bmsr; 5606 mii_anar_t anar; 5607 mii_anlpar_t anlpar; 5608 mii_anar_t an_common; 5609 mii_aner_t aner; 5610 mii_gsr_t gsr; 5611 nxge_status_t status = NXGE_OK; 5612 5613 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_check")); 5614 5615 mii_regs = NULL; 5616 param_arr = nxgep->param_arr; 5617 statsp = nxgep->statsp; 5618 soft_bmsr = &nxgep->soft_bmsr; 5619 *link_up = LINK_NO_CHANGE; 5620 5621 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5622 "==> nxge_mii_check bmsr 0x%x bmsr_int 0x%x", 5623 bmsr.value, bmsr_ints.value)); 5624 5625 if (bmsr_ints.bits.link_status) { 5626 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5627 "==> nxge_mii_check (link up) bmsr 0x%x bmsr_int 0x%x", 5628 bmsr.value, bmsr_ints.value)); 5629 if (bmsr.bits.link_status) { 5630 soft_bmsr->bits.link_status = 1; 5631 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5632 "==> nxge_mii_check (link up) soft bmsr 0x%x bmsr_int " 5633 "0x%x", bmsr.value, bmsr_ints.value)); 5634 } else { 5635 /* Only status change will update *link_up */ 5636 if (statsp->mac_stats.link_up == 1) { 5637 *link_up = LINK_IS_DOWN; 5638 /* Will notify, turn off further msg */ 5639 nxgep->link_notify = B_FALSE; 5640 } 5641 statsp->mac_stats.link_up = 0; 5642 soft_bmsr->bits.link_status = 0; 5643 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5644 "Link down cable problem")); 5645 } 5646 } 5647 5648 if (nxgep->mac.portmode == PORT_1G_COPPER && 5649 param_arr[param_autoneg].value) { 5650 if (bmsr_ints.bits.auto_neg_complete) { 5651 if (bmsr.bits.auto_neg_complete) 5652 soft_bmsr->bits.auto_neg_complete = 1; 5653 else 5654 soft_bmsr->bits.auto_neg_complete = 0; 5655 } 5656 if (soft_bmsr->bits.link_status == 0) { 5657 statsp->mac_stats.link_T4 = 0; 5658 statsp->mac_stats.link_speed = 0; 5659 statsp->mac_stats.link_duplex = 0; 5660 statsp->mac_stats.link_asmpause = 0; 5661 statsp->mac_stats.link_pause = 0; 5662 statsp->mac_stats.lp_cap_autoneg = 0; 5663 statsp->mac_stats.lp_cap_100T4 = 0; 5664 statsp->mac_stats.lp_cap_1000fdx = 0; 5665 statsp->mac_stats.lp_cap_1000hdx = 0; 5666 statsp->mac_stats.lp_cap_100fdx = 0; 5667 statsp->mac_stats.lp_cap_100hdx = 0; 5668 statsp->mac_stats.lp_cap_10fdx = 0; 5669 statsp->mac_stats.lp_cap_10hdx = 0; 5670 statsp->mac_stats.lp_cap_10gfdx = 0; 5671 statsp->mac_stats.lp_cap_10ghdx = 0; 5672 statsp->mac_stats.lp_cap_asmpause = 0; 5673 statsp->mac_stats.lp_cap_pause = 0; 5674 } 5675 } else 5676 soft_bmsr->bits.auto_neg_complete = 1; 5677 5678 if ((bmsr_ints.bits.link_status || 5679 bmsr_ints.bits.auto_neg_complete) && 5680 soft_bmsr->bits.link_status && 5681 soft_bmsr->bits.auto_neg_complete) { 5682 if (statsp->mac_stats.link_up == 0) { 5683 *link_up = LINK_IS_UP; 5684 nxgep->link_notify = B_FALSE; 5685 } 5686 statsp->mac_stats.link_up = 1; 5687 5688 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5689 "==> nxge_mii_check " 5690 "(auto negotiation complete or link up) " 5691 "soft bmsr 0x%x bmsr_int 0x%x", 5692 bmsr.value, bmsr_ints.value)); 5693 5694 if (nxgep->mac.portmode == PORT_1G_COPPER && 5695 param_arr[param_autoneg].value) { 5696 if ((status = nxge_mii_read(nxgep, 5697 statsp->mac_stats.xcvr_portn, 5698 #if defined(__i386) 5699 (uint8_t)(uint32_t)(&mii_regs->anar), 5700 #else 5701 (uint8_t)(uint64_t)(&mii_regs->anar), 5702 #endif 5703 &anar.value)) != NXGE_OK) 5704 goto fail; 5705 if ((status = nxge_mii_read(nxgep, 5706 statsp->mac_stats.xcvr_portn, 5707 #if defined(__i386) 5708 (uint8_t)(uint32_t)(&mii_regs->anlpar), 5709 #else 5710 (uint8_t)(uint64_t)(&mii_regs->anlpar), 5711 #endif 5712 &anlpar.value)) != NXGE_OK) 5713 goto fail; 5714 if ((status = nxge_mii_read(nxgep, 5715 statsp->mac_stats.xcvr_portn, 5716 #if defined(__i386) 5717 (uint8_t)(uint32_t)(&mii_regs->aner), 5718 #else 5719 (uint8_t)(uint64_t)(&mii_regs->aner), 5720 #endif 5721 &aner.value)) != NXGE_OK) 5722 goto fail; 5723 statsp->mac_stats.lp_cap_autoneg = aner.bits.lp_an_able; 5724 statsp->mac_stats.lp_cap_100T4 = anlpar.bits.cap_100T4; 5725 statsp->mac_stats.lp_cap_100fdx = 5726 anlpar.bits.cap_100fdx; 5727 statsp->mac_stats.lp_cap_100hdx = 5728 anlpar.bits.cap_100hdx; 5729 statsp->mac_stats.lp_cap_10fdx = anlpar.bits.cap_10fdx; 5730 statsp->mac_stats.lp_cap_10hdx = anlpar.bits.cap_10hdx; 5731 statsp->mac_stats.lp_cap_asmpause = 5732 anlpar.bits.cap_asmpause; 5733 statsp->mac_stats.lp_cap_pause = anlpar.bits.cap_pause; 5734 an_common.value = anar.value & anlpar.value; 5735 if (param_arr[param_anar_1000fdx].value || 5736 param_arr[param_anar_1000hdx].value) { 5737 if ((status = nxge_mii_read(nxgep, 5738 statsp->mac_stats.xcvr_portn, 5739 #if defined(__i386) 5740 (uint8_t)(uint32_t)(&mii_regs->gsr), 5741 #else 5742 (uint8_t)(uint64_t)(&mii_regs->gsr), 5743 #endif 5744 &gsr.value)) != NXGE_OK) 5745 goto fail; 5746 statsp->mac_stats.lp_cap_1000fdx = 5747 gsr.bits.link_1000fdx; 5748 statsp->mac_stats.lp_cap_1000hdx = 5749 gsr.bits.link_1000hdx; 5750 if (param_arr[param_anar_1000fdx].value && 5751 gsr.bits.link_1000fdx) { 5752 statsp->mac_stats.link_speed = 1000; 5753 statsp->mac_stats.link_duplex = 2; 5754 } else if ( 5755 param_arr[param_anar_1000hdx].value && 5756 gsr.bits.link_1000hdx) { 5757 statsp->mac_stats.link_speed = 1000; 5758 statsp->mac_stats.link_duplex = 1; 5759 } 5760 } 5761 if ((an_common.value != 0) && 5762 !(statsp->mac_stats.link_speed)) { 5763 if (an_common.bits.cap_100T4) { 5764 statsp->mac_stats.link_T4 = 1; 5765 statsp->mac_stats.link_speed = 100; 5766 statsp->mac_stats.link_duplex = 1; 5767 } else if (an_common.bits.cap_100fdx) { 5768 statsp->mac_stats.link_speed = 100; 5769 statsp->mac_stats.link_duplex = 2; 5770 } else if (an_common.bits.cap_100hdx) { 5771 statsp->mac_stats.link_speed = 100; 5772 statsp->mac_stats.link_duplex = 1; 5773 } else if (an_common.bits.cap_10fdx) { 5774 statsp->mac_stats.link_speed = 10; 5775 statsp->mac_stats.link_duplex = 2; 5776 } else if (an_common.bits.cap_10hdx) { 5777 statsp->mac_stats.link_speed = 10; 5778 statsp->mac_stats.link_duplex = 1; 5779 } else { 5780 goto fail; 5781 } 5782 } 5783 if (statsp->mac_stats.link_duplex != 1) { 5784 int link_pause; 5785 int cp, lcp; 5786 5787 statsp->mac_stats.link_asmpause = 5788 an_common.bits.cap_asmpause; 5789 cp = statsp->mac_stats.cap_pause; 5790 lcp = statsp->mac_stats.lp_cap_pause; 5791 if (statsp->mac_stats.link_asmpause) { 5792 if ((cp == 0) && (lcp == 1)) { 5793 link_pause = 0; 5794 } else { 5795 link_pause = 1; 5796 } 5797 } else { 5798 link_pause = an_common.bits.cap_pause; 5799 } 5800 statsp->mac_stats.link_pause = link_pause; 5801 } 5802 } else if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) { 5803 statsp->mac_stats.link_speed = 1000; 5804 statsp->mac_stats.link_duplex = 2; 5805 } 5806 } 5807 /* Initial link_notify, delay link down msg */ 5808 if (nxgep->link_notify && nxgep->nxge_mac_state == NXGE_MAC_STARTED && 5809 (statsp->mac_stats.link_up == 1 || nxgep->link_check_count > 3)) { 5810 *link_up = ((statsp->mac_stats.link_up) ? LINK_IS_UP : 5811 LINK_IS_DOWN); 5812 nxgep->link_notify = B_FALSE; 5813 } 5814 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mii_check")); 5815 return (NXGE_OK); 5816 fail: 5817 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5818 "nxge_mii_check: Unable to check MII")); 5819 return (status); 5820 } 5821 5822 /* 5823 * Check PCS to see if there is any link status change. 5824 * This function is called by PORT_1G_SERDES only. 5825 */ 5826 void 5827 nxge_pcs_check(p_nxge_t nxgep, uint8_t portn, nxge_link_state_t *link_up) 5828 { 5829 p_nxge_stats_t statsp; 5830 boolean_t linkup; 5831 5832 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_check")); 5833 5834 statsp = nxgep->statsp; 5835 *link_up = LINK_NO_CHANGE; 5836 5837 (void) npi_mac_get_link_status(nxgep->npi_handle, portn, &linkup); 5838 if (linkup) { 5839 if ((nxgep->link_notify && 5840 nxgep->nxge_mac_state == NXGE_MAC_STARTED) || 5841 nxgep->statsp->mac_stats.link_up == 0) { 5842 statsp->mac_stats.link_up = 1; 5843 statsp->mac_stats.link_speed = 1000; 5844 statsp->mac_stats.link_duplex = 2; 5845 *link_up = LINK_IS_UP; 5846 nxgep->link_notify = B_FALSE; 5847 } 5848 } else { 5849 if ((nxgep->link_notify && nxgep->link_check_count > 3 && 5850 nxgep->nxge_mac_state == NXGE_MAC_STARTED) || 5851 nxgep->statsp->mac_stats.link_up == 1) { 5852 statsp->mac_stats.link_up = 0; 5853 statsp->mac_stats.link_speed = 0; 5854 statsp->mac_stats.link_duplex = 0; 5855 *link_up = LINK_IS_DOWN; 5856 nxgep->link_notify = B_FALSE; 5857 } 5858 } 5859 5860 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_check")); 5861 } 5862 5863 /* Add a multicast address entry into the HW hash table */ 5864 5865 nxge_status_t 5866 nxge_add_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp) 5867 { 5868 uint32_t mchash; 5869 p_hash_filter_t hash_filter; 5870 uint16_t hash_bit; 5871 uint_t j; 5872 nxge_status_t status = NXGE_OK; 5873 npi_status_t rs; 5874 5875 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_add_mcast_addr")); 5876 5877 RW_ENTER_WRITER(&nxgep->filter_lock); 5878 mchash = crc32_mchash(addrp); 5879 if (nxgep->hash_filter == NULL) { 5880 NXGE_DEBUG_MSG((NULL, STR_CTL, 5881 "Allocating hash filter storage.")); 5882 nxgep->hash_filter = KMEM_ZALLOC(sizeof (hash_filter_t), 5883 KM_SLEEP); 5884 } 5885 5886 hash_filter = nxgep->hash_filter; 5887 j = mchash / HASH_REG_WIDTH; 5888 hash_bit = (1 << (mchash % HASH_REG_WIDTH)); 5889 hash_filter->hash_filter_regs[j] |= hash_bit; 5890 hash_filter->hash_bit_ref_cnt[mchash]++; 5891 if (hash_filter->hash_bit_ref_cnt[mchash] == 1) { 5892 hash_filter->hash_ref_cnt++; 5893 } 5894 5895 rs = nxge_rx_mac_mcast_hash_table(nxgep); 5896 if (rs != NPI_SUCCESS) 5897 goto fail; 5898 5899 RW_EXIT(&nxgep->filter_lock); 5900 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_add_mcast_addr")); 5901 return (NXGE_OK); 5902 fail: 5903 RW_EXIT(&nxgep->filter_lock); 5904 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_add_mcast_addr: " 5905 "Unable to add multicast address")); 5906 return (status); 5907 } 5908 5909 /* Remove a multicast address entry from the HW hash table */ 5910 5911 nxge_status_t 5912 nxge_del_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp) 5913 { 5914 uint32_t mchash; 5915 p_hash_filter_t hash_filter; 5916 uint16_t hash_bit; 5917 uint_t j; 5918 nxge_status_t status = NXGE_OK; 5919 npi_status_t rs; 5920 5921 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_del_mcast_addr")); 5922 RW_ENTER_WRITER(&nxgep->filter_lock); 5923 mchash = crc32_mchash(addrp); 5924 if (nxgep->hash_filter == NULL) { 5925 NXGE_DEBUG_MSG((NULL, STR_CTL, 5926 "Hash filter already de_allocated.")); 5927 RW_EXIT(&nxgep->filter_lock); 5928 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr")); 5929 return (NXGE_OK); 5930 } 5931 hash_filter = nxgep->hash_filter; 5932 hash_filter->hash_bit_ref_cnt[mchash]--; 5933 if (hash_filter->hash_bit_ref_cnt[mchash] == 0) { 5934 j = mchash / HASH_REG_WIDTH; 5935 hash_bit = (1 << (mchash % HASH_REG_WIDTH)); 5936 hash_filter->hash_filter_regs[j] &= ~hash_bit; 5937 hash_filter->hash_ref_cnt--; 5938 } 5939 5940 if (hash_filter->hash_ref_cnt == 0) { 5941 NXGE_DEBUG_MSG((NULL, STR_CTL, 5942 "De-allocating hash filter storage.")); 5943 KMEM_FREE(hash_filter, sizeof (hash_filter_t)); 5944 nxgep->hash_filter = NULL; 5945 } 5946 5947 rs = nxge_rx_mac_mcast_hash_table(nxgep); 5948 if (rs != NPI_SUCCESS) 5949 goto fail; 5950 5951 RW_EXIT(&nxgep->filter_lock); 5952 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr")); 5953 5954 return (NXGE_OK); 5955 fail: 5956 RW_EXIT(&nxgep->filter_lock); 5957 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_del_mcast_addr: " 5958 "Unable to remove multicast address")); 5959 5960 return (status); 5961 } 5962 5963 /* Set MAC address into MAC address HW registers */ 5964 5965 nxge_status_t 5966 nxge_set_mac_addr(p_nxge_t nxgep, struct ether_addr *addrp) 5967 { 5968 nxge_status_t status = NXGE_OK; 5969 5970 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_mac_addr")); 5971 5972 MUTEX_ENTER(&nxgep->ouraddr_lock); 5973 /* 5974 * Exit if the address is same as ouraddr or multicast or broadcast 5975 */ 5976 if (((addrp->ether_addr_octet[0] & 01) == 1) || 5977 (ether_cmp(addrp, ðerbroadcastaddr) == 0) || 5978 (ether_cmp(addrp, &nxgep->ouraddr) == 0)) { 5979 goto nxge_set_mac_addr_exit; 5980 } 5981 nxgep->ouraddr = *addrp; 5982 /* 5983 * Set new interface local address and re-init device. 5984 * This is destructive to any other streams attached 5985 * to this device. 5986 */ 5987 RW_ENTER_WRITER(&nxgep->filter_lock); 5988 if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 5989 goto fail; 5990 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 5991 goto fail; 5992 5993 RW_EXIT(&nxgep->filter_lock); 5994 MUTEX_EXIT(&nxgep->ouraddr_lock); 5995 goto nxge_set_mac_addr_end; 5996 nxge_set_mac_addr_exit: 5997 MUTEX_EXIT(&nxgep->ouraddr_lock); 5998 nxge_set_mac_addr_end: 5999 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_mac_addr")); 6000 6001 return (NXGE_OK); 6002 fail: 6003 MUTEX_EXIT(&nxgep->ouraddr_lock); 6004 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_mac_addr: " 6005 "Unable to set mac address")); 6006 return (status); 6007 } 6008 6009 static 6010 check_link_state_t 6011 nxge_check_link_stop(nxge_t *nxge) 6012 { 6013 /* If the poll has been cancelled, return STOP. */ 6014 MUTEX_ENTER(&nxge->poll_lock); 6015 if (nxge->suspended || nxge->poll_state == LINK_MONITOR_STOPPING) { 6016 nxge->poll_state = LINK_MONITOR_STOP; 6017 nxge->nxge_link_poll_timerid = 0; 6018 cv_broadcast(&nxge->poll_cv); 6019 MUTEX_EXIT(&nxge->poll_lock); 6020 6021 NXGE_DEBUG_MSG((nxge, MAC_CTL, 6022 "nxge_check_%s_link(port<%d>) stopped.", 6023 nxge->mac.portmode == PORT_10G_FIBER ? "10g" : "mii", 6024 nxge->mac.portnum)); 6025 return (CHECK_LINK_STOP); 6026 } 6027 MUTEX_EXIT(&nxge->poll_lock); 6028 6029 return (CHECK_LINK_RESCHEDULE); 6030 } 6031 6032 /* 6033 * Check status of MII (MIF or PCS) link. 6034 * This function is called once per second, that is because this function 6035 * calls nxge_link_monitor with LINK_MONITOR_START, which starts a timer to 6036 * call this function recursively. 6037 */ 6038 static nxge_status_t 6039 nxge_check_mii_link(p_nxge_t nxgep) 6040 { 6041 mii_bmsr_t bmsr_ints, bmsr_data; 6042 mii_anlpar_t anlpar; 6043 mii_gsr_t gsr; 6044 p_mii_regs_t mii_regs; 6045 nxge_status_t status = NXGE_OK; 6046 uint8_t portn; 6047 nxge_link_state_t link_up; 6048 6049 if (nxgep->nxge_magic != NXGE_MAGIC) 6050 return (NXGE_ERROR); 6051 6052 if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 6053 return (NXGE_OK); 6054 6055 portn = nxgep->mac.portnum; 6056 6057 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_mii_link port<%d>", 6058 portn)); 6059 6060 mii_regs = NULL; 6061 6062 RW_ENTER_WRITER(&nxgep->filter_lock); 6063 6064 if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10) 6065 goto nxge_check_mii_link_exit; 6066 6067 switch (nxgep->mac.portmode) { 6068 default: 6069 bmsr_data.value = 0; 6070 if ((status = nxge_mii_read(nxgep, 6071 nxgep->statsp->mac_stats.xcvr_portn, 6072 #if defined(__i386) 6073 (uint8_t)(uint32_t)(&mii_regs->bmsr), 6074 #else 6075 (uint8_t)(uint64_t)(&mii_regs->bmsr), 6076 #endif 6077 &bmsr_data.value)) != NXGE_OK) { 6078 goto fail; 6079 } 6080 6081 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6082 "==> nxge_check_mii_link port<0x%x> " 6083 "RIGHT AFTER READ bmsr_data 0x%x (nxgep->bmsr 0x%x ", 6084 portn, bmsr_data.value, nxgep->bmsr.value)); 6085 6086 if (nxgep->param_arr[param_autoneg].value) { 6087 if ((status = nxge_mii_read(nxgep, 6088 nxgep->statsp->mac_stats.xcvr_portn, 6089 #if defined(__i386) 6090 (uint8_t)(uint32_t)(&mii_regs->gsr), 6091 #else 6092 (uint8_t)(uint64_t)(&mii_regs->gsr), 6093 #endif 6094 &gsr.value)) != NXGE_OK) 6095 goto fail; 6096 if ((status = nxge_mii_read(nxgep, 6097 nxgep->statsp->mac_stats.xcvr_portn, 6098 #if defined(__i386) 6099 (uint8_t)(uint32_t)(&mii_regs->anlpar), 6100 #else 6101 (uint8_t)(uint64_t)(&mii_regs->anlpar), 6102 #endif 6103 &anlpar.value)) != NXGE_OK) 6104 goto fail; 6105 if (nxgep->mac.portmode != PORT_1G_RGMII_FIBER) { 6106 6107 if (nxgep->statsp->mac_stats.link_up && 6108 ((nxgep->statsp->mac_stats.lp_cap_1000fdx ^ 6109 gsr.bits.link_1000fdx) || 6110 (nxgep->statsp->mac_stats.lp_cap_1000hdx ^ 6111 gsr.bits.link_1000hdx) || 6112 (nxgep->statsp->mac_stats.lp_cap_100T4 ^ 6113 anlpar.bits.cap_100T4) || 6114 (nxgep->statsp->mac_stats.lp_cap_100fdx ^ 6115 anlpar.bits.cap_100fdx) || 6116 (nxgep->statsp->mac_stats.lp_cap_100hdx ^ 6117 anlpar.bits.cap_100hdx) || 6118 (nxgep->statsp->mac_stats.lp_cap_10fdx ^ 6119 anlpar.bits.cap_10fdx) || 6120 (nxgep->statsp->mac_stats.lp_cap_10hdx ^ 6121 anlpar.bits.cap_10hdx))) { 6122 bmsr_data.bits.link_status = 0; 6123 } 6124 } 6125 } 6126 6127 /* Workaround for link down issue */ 6128 if (bmsr_data.value == 0) { 6129 cmn_err(CE_NOTE, "!LINK DEBUG: Read zero bmsr\n"); 6130 goto nxge_check_mii_link_exit; 6131 } 6132 6133 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6134 "==> nxge_check_mii_link port<0x%x> :" 6135 "BEFORE BMSR ^ nxgep->bmsr 0x%x bmsr_data 0x%x", 6136 portn, nxgep->bmsr.value, bmsr_data.value)); 6137 6138 bmsr_ints.value = nxgep->bmsr.value ^ bmsr_data.value; 6139 nxgep->bmsr.value = bmsr_data.value; 6140 6141 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6142 "==> nxge_check_mii_link port<0x%x> CALLING " 6143 "bmsr_data 0x%x bmsr_ints.value 0x%x", 6144 portn, bmsr_data.value, bmsr_ints.value)); 6145 6146 if ((status = nxge_mii_check(nxgep, bmsr_data, bmsr_ints, 6147 &link_up)) != NXGE_OK) { 6148 goto fail; 6149 } 6150 break; 6151 6152 case PORT_1G_SERDES: 6153 /* 6154 * Above default is for all cases except PORT_1G_SERDES. 6155 * The default case gets information from the PHY, but a 6156 * nxge whose portmode equals PORT_1G_SERDES does not 6157 * have a PHY. 6158 */ 6159 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6160 "==> nxge_check_mii_link port<%d> (SERDES)", portn)); 6161 nxge_pcs_check(nxgep, portn, &link_up); 6162 break; 6163 } 6164 6165 nxge_check_mii_link_exit: 6166 RW_EXIT(&nxgep->filter_lock); 6167 if (link_up == LINK_IS_UP) { 6168 nxge_link_is_up(nxgep); 6169 } else if (link_up == LINK_IS_DOWN) { 6170 nxge_link_is_down(nxgep); 6171 } 6172 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 6173 6174 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_mii_link port<%d>", 6175 portn)); 6176 return (NXGE_OK); 6177 6178 fail: 6179 RW_EXIT(&nxgep->filter_lock); 6180 6181 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 6182 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6183 "nxge_check_mii_link: Failed to check link port<%d>", portn)); 6184 return (status); 6185 } 6186 6187 /*ARGSUSED*/ 6188 static nxge_status_t 6189 nxge_check_10g_link(p_nxge_t nxgep) 6190 { 6191 uint8_t portn; 6192 nxge_status_t status = NXGE_OK; 6193 boolean_t link_up; 6194 uint32_t val; 6195 npi_status_t rs; 6196 6197 if (nxgep->nxge_magic != NXGE_MAGIC) 6198 return (NXGE_ERROR); 6199 6200 if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 6201 return (NXGE_OK); 6202 6203 portn = nxgep->mac.portnum; 6204 val = 0; 6205 rs = NPI_SUCCESS; 6206 6207 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_10g_link port<%d>", 6208 portn)); 6209 6210 switch (nxgep->mac.portmode) { 6211 default: 6212 /* 6213 * Check if the phy is present in case of hot swappable phy 6214 */ 6215 if (nxgep->hot_swappable_phy) { 6216 boolean_t phy_present_now = B_FALSE; 6217 6218 if (nxge_hswap_phy_present(nxgep, portn)) 6219 phy_present_now = B_TRUE; 6220 6221 /* Check back-to-back XAUI connect to detect Opus NEM */ 6222 rs = npi_xmac_xpcs_read(nxgep->npi_handle, 6223 nxgep->mac.portnum, XPCS_REG_STATUS, &val); 6224 if (rs != 0) 6225 goto fail; 6226 6227 link_up = B_FALSE; 6228 if (val & XPCS_STATUS_LANE_ALIGN) { 6229 link_up = B_TRUE; 6230 } 6231 6232 if (nxgep->phy_absent) { 6233 if (phy_present_now) { 6234 /* 6235 * Detect, Initialize phy and do link up 6236 * set xcvr vals, link_init, nxge_init 6237 */ 6238 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6239 "Hot swappable phy DETECTED!!")); 6240 nxgep->phy_absent = B_FALSE; 6241 (void) nxge_xcvr_find(nxgep); 6242 (void) nxge_link_init(nxgep); 6243 if (!(nxgep->drv_state & 6244 STATE_HW_INITIALIZED)) { 6245 status = nxge_init(nxgep); 6246 if (status != NXGE_OK) { 6247 NXGE_ERROR_MSG((nxgep, 6248 NXGE_ERR_CTL, 6249 "Hot swappable " 6250 "phy present, but" 6251 " driver init" 6252 " failed...")); 6253 goto fail; 6254 } 6255 } 6256 } else if (link_up) { /* XAUI linkup, no PHY */ 6257 /* 6258 * This is the back-to-back XAUI 6259 * connect case for Opus NEM. 6260 */ 6261 nxgep->statsp->mac_stats.xcvr_inuse = 6262 XPCS_XCVR; 6263 nxgep->mac.portmode = PORT_10G_SERDES; 6264 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6265 "HSP 10G Serdes DETECTED!!")); 6266 break; 6267 } 6268 6269 if (nxgep->link_notify && 6270 nxgep->link_check_count > 3 && 6271 nxgep->nxge_mac_state == NXGE_MAC_STARTED || 6272 nxgep->statsp->mac_stats.link_up == 1) { 6273 nxgep->statsp->mac_stats.link_up = 0; 6274 nxgep->statsp->mac_stats.link_speed = 0; 6275 nxgep->statsp->mac_stats.link_duplex = 6276 0; 6277 6278 nxge_link_is_down(nxgep); 6279 nxgep->link_notify = B_FALSE; 6280 } 6281 6282 goto start_link_check; 6283 6284 } else if (!phy_present_now) { 6285 /* 6286 * Phy gone, bring link down reset xcvr vals 6287 */ 6288 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6289 "Hot swappable phy REMOVED!!")); 6290 nxgep->phy_absent = B_TRUE; 6291 nxgep->statsp->mac_stats.link_up = 0; 6292 nxgep->statsp->mac_stats.link_speed = 0; 6293 nxgep->statsp->mac_stats.link_duplex = 0; 6294 nxge_link_is_down(nxgep); 6295 nxgep->link_notify = B_FALSE; 6296 6297 (void) nxge_xcvr_find(nxgep); 6298 6299 goto start_link_check; 6300 6301 } 6302 } 6303 6304 switch (nxgep->chip_id) { 6305 case MRVL88X201X_CHIP_ID: 6306 status = nxge_check_mrvl88x2011_link(nxgep, &link_up); 6307 break; 6308 case NLP2020_CHIP_ID: 6309 status = nxge_check_nlp2020_link(nxgep, &link_up); 6310 break; 6311 default: 6312 status = nxge_check_bcm8704_link(nxgep, &link_up); 6313 break; 6314 } 6315 6316 if (status != NXGE_OK) 6317 goto fail; 6318 break; 6319 case PORT_10G_SERDES: 6320 rs = npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 6321 XPCS_REG_STATUS, &val); 6322 if (rs != 0) 6323 goto fail; 6324 6325 link_up = B_FALSE; 6326 if (val & XPCS_STATUS_LANE_ALIGN) { 6327 link_up = B_TRUE; 6328 } 6329 6330 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6331 "==> nxge_check_10g_link port<%d> " 6332 "XPCS_REG_STATUS2 0x%x link_up %d", 6333 portn, val, link_up)); 6334 6335 break; 6336 } 6337 6338 if (link_up) { 6339 if ((nxgep->link_notify && 6340 nxgep->nxge_mac_state == NXGE_MAC_STARTED) || 6341 nxgep->statsp->mac_stats.link_up == 0) { 6342 if (nxge_10g_link_led_on(nxgep) != NXGE_OK) 6343 goto fail; 6344 nxgep->statsp->mac_stats.link_up = 1; 6345 nxgep->statsp->mac_stats.link_speed = 10000; 6346 nxgep->statsp->mac_stats.link_duplex = 2; 6347 6348 nxge_link_is_up(nxgep); 6349 nxgep->link_notify = B_FALSE; 6350 } 6351 } else { 6352 if ((nxgep->link_notify && nxgep->link_check_count > 3 && 6353 nxgep->nxge_mac_state == NXGE_MAC_STARTED) || 6354 nxgep->statsp->mac_stats.link_up == 1) { 6355 if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 6356 goto fail; 6357 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6358 "Link down cable problem")); 6359 nxgep->statsp->mac_stats.link_up = 0; 6360 nxgep->statsp->mac_stats.link_speed = 0; 6361 nxgep->statsp->mac_stats.link_duplex = 0; 6362 6363 nxge_link_is_down(nxgep); 6364 nxgep->link_notify = B_FALSE; 6365 6366 if (nxgep->mac.portmode == PORT_10G_SERDES) { 6367 /* 6368 * NEM was unplugged, set up xcvr table 6369 * to find another xcvr in the future. 6370 */ 6371 (void) nxge_xcvr_find(nxgep); 6372 } 6373 } 6374 } 6375 6376 start_link_check: 6377 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 6378 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_10g_link port<%d>", 6379 portn)); 6380 return (NXGE_OK); 6381 6382 fail: 6383 (void) nxge_check_link_stop(nxgep); 6384 6385 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6386 "nxge_check_10g_link: Failed to check link port<%d>", 6387 portn)); 6388 return (status); 6389 } 6390 6391 6392 /* Declare link down */ 6393 6394 void 6395 nxge_link_is_down(p_nxge_t nxgep) 6396 { 6397 p_nxge_stats_t statsp; 6398 char link_stat_msg[64]; 6399 6400 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_down")); 6401 6402 statsp = nxgep->statsp; 6403 (void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is down", 6404 statsp->mac_stats.xcvr_portn); 6405 6406 if (nxge_no_msg == B_FALSE) { 6407 NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg)); 6408 } 6409 6410 mac_link_update(nxgep->mach, LINK_STATE_DOWN); 6411 6412 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_down")); 6413 } 6414 6415 /* Declare link up */ 6416 6417 void 6418 nxge_link_is_up(p_nxge_t nxgep) 6419 { 6420 p_nxge_stats_t statsp; 6421 char link_stat_msg[64]; 6422 uint32_t val; 6423 6424 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_up")); 6425 6426 statsp = nxgep->statsp; 6427 (void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is up %d Mbps ", 6428 statsp->mac_stats.xcvr_portn, 6429 statsp->mac_stats.link_speed); 6430 6431 if (statsp->mac_stats.link_T4) 6432 (void) strcat(link_stat_msg, "T4"); 6433 else if (statsp->mac_stats.link_duplex == 2) 6434 (void) strcat(link_stat_msg, "full duplex"); 6435 else 6436 (void) strcat(link_stat_msg, "half duplex"); 6437 6438 6439 /* Clean up symbol errors incurred during link transition */ 6440 if ((nxgep->mac.portmode == PORT_10G_FIBER) || 6441 (nxgep->mac.portmode == PORT_10G_COPPER) || 6442 (nxgep->mac.portmode == PORT_10G_SERDES)) { 6443 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 6444 XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val); 6445 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 6446 XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val); 6447 } 6448 6449 /* 6450 * If the driver was plumbed without a link (therefore auto-negotiation 6451 * could not complete), the driver will detect a link up when a cable 6452 * conneting to a link partner is plugged into the port. By the time 6453 * link-up is detected, auto-negotiation should have completed (The 6454 * TN1010 tries to contact a link partner every 8~24ms). Here we re- 6455 * configure the Neptune/NIU according to the newly negotiated speed. 6456 * This is necessary only for the TN1010 basad device because only the 6457 * TN1010 supports dual speeds. 6458 */ 6459 if (nxgep->mac.portmode == PORT_1G_TN1010 || 6460 nxgep->mac.portmode == PORT_10G_TN1010) { 6461 6462 (void) nxge_set_tn1010_param(nxgep); 6463 6464 /* 6465 * nxge_xcvr_find calls nxge_get_xcvr_type (which sets 6466 * nxgep->portmode) and nxge_setup_xcvr_table (which sets 6467 * the nxgep->xcvr to the proper nxge_xcvr_table_t struct). 6468 */ 6469 if (nxge_xcvr_find(nxgep) != NXGE_OK) { 6470 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6471 "nxge_link_is_up: nxge_xcvr_find failed")); 6472 } 6473 6474 /* nxge_link_init calls nxge_xcvr_init and nxge_serdes_init */ 6475 if (nxge_link_init(nxgep) != NXGE_OK) { 6476 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6477 "nxge_link_is_up: nxge_link_init failed")); 6478 } 6479 6480 /* 6481 * nxge_mac_init calls many subroutines including 6482 * nxge_xif_init which sets XGMII or GMII mode 6483 */ 6484 if (nxge_mac_init(nxgep) != NXGE_OK) { 6485 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6486 "nxge_link_is_up: nxge_mac_init failed")); 6487 } 6488 } else { 6489 (void) nxge_xif_init(nxgep); 6490 } 6491 6492 if (nxge_no_msg == B_FALSE) { 6493 NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg)); 6494 } 6495 6496 mac_link_update(nxgep->mach, LINK_STATE_UP); 6497 6498 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_up")); 6499 } 6500 6501 #ifdef NXGE_DEBUG 6502 /* Dump all TN1010 Status registers */ 6503 static void 6504 nxge_dump_tn1010_status_regs(p_nxge_t nxgep) 6505 { 6506 uint16_t val; 6507 6508 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 6509 TN1010_PMA_PMD_DEV_ADDR, 1, &val); 6510 cmn_err(CE_NOTE, "PMA status1 = 0x%x", val); 6511 6512 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 6513 TN1010_PMA_PMD_DEV_ADDR, 8, &val); 6514 cmn_err(CE_NOTE, "PMA status2 = 0x%x", val); 6515 6516 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 6517 TN1010_PMA_PMD_DEV_ADDR, 129, &val); 6518 cmn_err(CE_NOTE, "10BASET-T status = 0x%x", val); 6519 6520 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 6521 TN1010_PCS_DEV_ADDR, 1, &val); 6522 cmn_err(CE_NOTE, "PCS status1 = 0x%x", val); 6523 6524 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 6525 TN1010_PCS_DEV_ADDR, 8, &val); 6526 cmn_err(CE_NOTE, "PCS status2 = 0x%x", val); 6527 6528 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 6529 TN1010_PCS_DEV_ADDR, 32, &val); 6530 cmn_err(CE_NOTE, "10GBASE-R status1 = 0x%x", val); 6531 6532 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 6533 TN1010_PCS_DEV_ADDR, 33, &val); 6534 cmn_err(CE_NOTE, "10GBASE-R Status2 = 0x%x", val); 6535 6536 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 6537 TN1010_PHYXS_DEV_ADDR, 1, &val); 6538 cmn_err(CE_NOTE, "PHYXS status1 = 0x%x", val); 6539 6540 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 6541 TN1010_PHYXS_DEV_ADDR, 8, &val); 6542 cmn_err(CE_NOTE, "PHYXS status2 = 0x%x", val); 6543 6544 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 6545 TN1010_PHYXS_DEV_ADDR, 24, &val); 6546 cmn_err(CE_NOTE, "XGXS Lane status = 0x%x", val); 6547 6548 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 6549 TN1010_AUTONEG_DEV_ADDR, 1, &val); 6550 cmn_err(CE_NOTE, "Autoneg status = 0x%x", val); 6551 6552 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 6553 TN1010_AUTONEG_DEV_ADDR, 33, &val); 6554 cmn_err(CE_NOTE, "10Gbase-T An status = 0x%x", val); 6555 6556 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 6557 TN1010_VENDOR_MMD1_DEV_ADDR, 1, &val); 6558 cmn_err(CE_NOTE, "TN1010 status = 0x%x", val); 6559 6560 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 6561 TN1010_VENDOR_MMD1_DEV_ADDR, 8, &val); 6562 cmn_err(CE_NOTE, "Device status = 0x%x", val); 6563 6564 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 6565 TN1010_VENDOR_MMD1_DEV_ADDR, 16, &val); 6566 cmn_err(CE_NOTE, "DDR status = 0x%x", val); 6567 6568 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 6569 TN1010_VENDOR_MMD1_DEV_ADDR, 17, &val); 6570 cmn_err(CE_NOTE, "DDR fault status = 0x%x", val); 6571 6572 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 6573 TN1010_VENDOR_MMD1_DEV_ADDR, 11, &val); 6574 cmn_err(CE_NOTE, "Firmware Revision = 0x%x Major = 0x%x Minor = 0x%x", 6575 val, (val & 0xFF00) >> 8, val & 0x00FF); 6576 } 6577 #endif 6578 6579 /* 6580 * Calculate the bit in the multicast address filter 6581 * that selects the given * address. 6582 * Note: For GEM, the last 8-bits are used. 6583 */ 6584 uint32_t 6585 crc32_mchash(p_ether_addr_t addr) 6586 { 6587 uint8_t *cp; 6588 uint32_t crc; 6589 uint32_t c; 6590 int byte; 6591 int bit; 6592 6593 cp = (uint8_t *)addr; 6594 crc = (uint32_t)0xffffffff; 6595 for (byte = 0; byte < 6; byte++) { 6596 c = (uint32_t)cp[byte]; 6597 for (bit = 0; bit < 8; bit++) { 6598 if ((c & 0x1) ^ (crc & 0x1)) 6599 crc = (crc >> 1)^0xedb88320; 6600 else 6601 crc = (crc >> 1); 6602 c >>= 1; 6603 } 6604 } 6605 return ((~crc) >> (32 - HASH_BITS)); 6606 } 6607 6608 /* Reset serdes */ 6609 6610 nxge_status_t 6611 nxge_serdes_reset(p_nxge_t nxgep) 6612 { 6613 npi_handle_t handle; 6614 6615 handle = nxgep->npi_handle; 6616 6617 ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0 | ESR_RESET_1); 6618 drv_usecwait(500); 6619 ESR_REG_WR(handle, ESR_CONFIG_REG, 0); 6620 6621 return (NXGE_OK); 6622 } 6623 6624 /* 6625 * This function monitors link status using interrupt or polling. 6626 * It calls nxgep->xcvr.check_link, a member function of 6627 * nxge_xcvr_table_t. But nxgep->xcvr.check_link calls this 6628 * function back, that is why the check_link routine is 6629 * executed periodically. 6630 */ 6631 nxge_status_t 6632 nxge_link_monitor(p_nxge_t nxgep, link_mon_enable_t enable) 6633 { 6634 nxge_status_t status = NXGE_OK; 6635 6636 /* If we are a guest domain driver, don't bother. */ 6637 if (isLDOMguest(nxgep)) 6638 return (status); 6639 6640 /* 6641 * Return immediately if this is an imaginary XMAC port. 6642 * (At least, we don't have 4-port XMAC cards yet.) 6643 */ 6644 if ((nxgep->mac.portmode == PORT_10G_FIBER || 6645 nxgep->mac.portmode == PORT_10G_COPPER || 6646 nxgep->mac.portmode == PORT_10G_SERDES) && 6647 (nxgep->mac.portnum > 1)) 6648 return (NXGE_OK); 6649 6650 if (nxgep->statsp == NULL) { 6651 /* stats has not been allocated. */ 6652 return (NXGE_OK); 6653 } 6654 /* Don't check link if we're in internal loopback mode */ 6655 if (nxgep->statsp->port_stats.lb_mode >= nxge_lb_serdes10g) 6656 return (NXGE_OK); 6657 6658 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6659 "==> nxge_link_monitor port<%d> enable=%d", 6660 nxgep->mac.portnum, enable)); 6661 if (enable == LINK_MONITOR_START) { 6662 if (nxgep->mac.linkchkmode == LINKCHK_INTR) { 6663 if ((status = nxge_link_intr(nxgep, LINK_INTR_START)) 6664 != NXGE_OK) 6665 goto fail; 6666 } else { 6667 timeout_id_t timerid; 6668 /* 6669 * check_link_stop means "Stop the link check", so 6670 * we return without starting the timer. 6671 */ 6672 if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 6673 return (NXGE_OK); 6674 6675 /* 6676 * Otherwise fire the timer for the nxge to check 6677 * the link using the check_link function 6678 * of the nxge_xcvr_table and pass "nxgep" as the 6679 * argument to the check_link function. 6680 */ 6681 if (nxgep->xcvr.check_link) { 6682 timerid = timeout((fptrv_t)(uintptr_t) 6683 (nxgep->xcvr.check_link), 6684 nxgep, 6685 drv_usectohz(LINK_MONITOR_PERIOD)); 6686 MUTEX_ENTER(&nxgep->poll_lock); 6687 nxgep->nxge_link_poll_timerid = timerid; 6688 MUTEX_EXIT(&nxgep->poll_lock); 6689 nxgep->link_check_count ++; 6690 } else { 6691 return (NXGE_ERROR); 6692 } 6693 } 6694 } else { 6695 if (nxgep->mac.linkchkmode == LINKCHK_INTR) { 6696 if ((status = nxge_link_intr(nxgep, LINK_INTR_STOP)) 6697 != NXGE_OK) 6698 goto fail; 6699 } else { 6700 clock_t rv; 6701 6702 MUTEX_ENTER(&nxgep->poll_lock); 6703 6704 /* If <timerid> == 0, the link monitor has */ 6705 /* never been started, or just now stopped. */ 6706 if (nxgep->nxge_link_poll_timerid == 0) { 6707 MUTEX_EXIT(&nxgep->poll_lock); 6708 return (NXGE_OK); 6709 } 6710 6711 nxgep->poll_state = LINK_MONITOR_STOPPING; 6712 rv = cv_reltimedwait(&nxgep->poll_cv, &nxgep->poll_lock, 6713 drv_usectohz(LM_WAIT_MULTIPLIER * 6714 LINK_MONITOR_PERIOD), TR_CLOCK_TICK); 6715 if (rv == -1) { 6716 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6717 "==> stopping port %d: " 6718 "cv_timedwait(%d) timed out", 6719 nxgep->mac.portnum, nxgep->poll_state)); 6720 nxgep->poll_state = LINK_MONITOR_STOP; 6721 nxgep->nxge_link_poll_timerid = 0; 6722 } 6723 6724 MUTEX_EXIT(&nxgep->poll_lock); 6725 } 6726 } 6727 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6728 "<== nxge_link_monitor port<%d> enable=%d", 6729 nxgep->mac.portnum, enable)); 6730 6731 return (NXGE_OK); 6732 fail: 6733 return (status); 6734 6735 } 6736 6737 nxge_status_t 6738 nxge_check_tn1010_link(p_nxge_t nxgep) 6739 { 6740 nxge_status_t status = NXGE_OK; 6741 nxge_link_state_t link_up; 6742 6743 if (nxgep->nxge_magic != NXGE_MAGIC) { 6744 /* magic is 0 if driver is not attached */ 6745 return (NXGE_ERROR); 6746 } 6747 6748 /* Link has been stopped, no need to continue */ 6749 if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) { 6750 return (NXGE_OK); 6751 } 6752 6753 if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10) 6754 goto nxge_check_tn1010_link_exit; 6755 6756 if ((status = nxge_tn1010_check(nxgep, &link_up)) != NXGE_OK) 6757 goto fail; 6758 6759 nxge_check_tn1010_link_exit: 6760 if (link_up == LINK_IS_UP) 6761 nxge_link_is_up(nxgep); 6762 else if (link_up == LINK_IS_DOWN) 6763 nxge_link_is_down(nxgep); 6764 6765 /* 6766 * nxge_link_monitor will call (nxgep->xcvr.check_link) 6767 * which could be THIS function. 6768 */ 6769 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 6770 6771 return (NXGE_OK); 6772 6773 fail: 6774 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 6775 6776 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6777 "nxge_check_tn1010_link: Failed to check link")); 6778 return (status); 6779 } 6780 6781 6782 /* 6783 * Fill variable "link_up" with either LINK_IS_UP or LINK_IS_DOWN. 6784 */ 6785 static nxge_status_t 6786 nxge_tn1010_check(p_nxge_t nxgep, nxge_link_state_t *link_up) 6787 { 6788 nxge_status_t status = NXGE_OK; 6789 p_nxge_stats_t statsp; 6790 uint8_t phy_port_addr, portn; 6791 uint16_t val; 6792 6793 *link_up = LINK_NO_CHANGE; 6794 6795 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 6796 phy_port_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 6797 statsp = nxgep->statsp; 6798 6799 /* Check if link is up */ 6800 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 6801 TN1010_AUTONEG_DEV_ADDR, TN1010_AUTONEG_STATUS_REG, &val)) 6802 != NXGE_OK) { 6803 goto fail; 6804 } 6805 /* 6806 * nxge_link_is_up has called nxge_set_tn1010_param and set 6807 * portmode and link_speed 6808 */ 6809 if (val & TN1010_AN_LINK_STAT_BIT) { 6810 if ((nxgep->link_notify && 6811 nxgep->nxge_mac_state == NXGE_MAC_STARTED) || 6812 nxgep->statsp->mac_stats.link_up == 0) { 6813 statsp->mac_stats.link_up = 1; 6814 statsp->mac_stats.link_duplex = 2; 6815 *link_up = LINK_IS_UP; 6816 nxgep->link_notify = B_FALSE; 6817 } 6818 } else { 6819 if ((nxgep->link_notify && nxgep->link_check_count > 3 && 6820 nxgep->nxge_mac_state == NXGE_MAC_STARTED) || 6821 nxgep->statsp->mac_stats.link_up == 1) { 6822 statsp->mac_stats.link_up = 0; 6823 statsp->mac_stats.link_speed = 0; 6824 statsp->mac_stats.link_duplex = 0; 6825 *link_up = LINK_IS_DOWN; 6826 nxgep->link_notify = B_FALSE; 6827 } 6828 } 6829 return (NXGE_OK); 6830 6831 fail: 6832 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6833 "nxge_tn1010_check: Unable to check TN1010")); 6834 return (status); 6835 } 6836 6837 6838 /* Set promiscous mode */ 6839 6840 nxge_status_t 6841 nxge_set_promisc(p_nxge_t nxgep, boolean_t on) 6842 { 6843 nxge_status_t status = NXGE_OK; 6844 6845 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_promisc: on %d", on)); 6846 6847 nxgep->filter.all_phys_cnt = ((on) ? 1 : 0); 6848 6849 RW_ENTER_WRITER(&nxgep->filter_lock); 6850 6851 if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) { 6852 goto fail; 6853 } 6854 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) { 6855 goto fail; 6856 } 6857 6858 RW_EXIT(&nxgep->filter_lock); 6859 6860 if (on) 6861 nxgep->statsp->mac_stats.promisc = B_TRUE; 6862 else 6863 nxgep->statsp->mac_stats.promisc = B_FALSE; 6864 6865 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_promisc")); 6866 6867 return (NXGE_OK); 6868 fail: 6869 RW_EXIT(&nxgep->filter_lock); 6870 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_promisc: " 6871 "Unable to set promisc (%d)", on)); 6872 6873 return (status); 6874 } 6875 6876 /*ARGSUSED*/ 6877 uint_t 6878 nxge_mif_intr(void *arg1, void *arg2) 6879 { 6880 #ifdef NXGE_DEBUG 6881 p_nxge_t nxgep = (p_nxge_t)arg2; 6882 #endif 6883 #if NXGE_MIF 6884 p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1; 6885 uint32_t status; 6886 npi_handle_t handle; 6887 uint8_t portn; 6888 p_nxge_stats_t statsp; 6889 #endif 6890 6891 #ifdef NXGE_MIF 6892 if (arg2 == NULL || (void *)ldvp->nxgep != arg2) { 6893 nxgep = ldvp->nxgep; 6894 } 6895 nxgep = ldvp->nxgep; 6896 #endif 6897 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mif_intr")); 6898 6899 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr")); 6900 return (DDI_INTR_CLAIMED); 6901 6902 mif_intr_fail: 6903 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr")); 6904 return (DDI_INTR_UNCLAIMED); 6905 } 6906 6907 /*ARGSUSED*/ 6908 uint_t 6909 nxge_mac_intr(void *arg1, void *arg2) 6910 { 6911 p_nxge_t nxgep = (p_nxge_t)arg2; 6912 p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1; 6913 p_nxge_ldg_t ldgp; 6914 uint32_t status; 6915 npi_handle_t handle; 6916 uint8_t portn; 6917 p_nxge_stats_t statsp; 6918 npi_status_t rs = NPI_SUCCESS; 6919 6920 if (arg2 == NULL || (void *)ldvp->nxgep != arg2) { 6921 nxgep = ldvp->nxgep; 6922 } 6923 6924 ldgp = ldvp->ldgp; 6925 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mac_intr: " 6926 "group %d", ldgp->ldg)); 6927 6928 handle = NXGE_DEV_NPI_HANDLE(nxgep); 6929 /* 6930 * This interrupt handler is for a specific 6931 * mac port. 6932 */ 6933 statsp = (p_nxge_stats_t)nxgep->statsp; 6934 portn = nxgep->mac.portnum; 6935 6936 NXGE_DEBUG_MSG((nxgep, INT_CTL, 6937 "==> nxge_mac_intr: reading mac stats: port<%d>", portn)); 6938 6939 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 6940 rs = npi_xmac_tx_get_istatus(handle, portn, 6941 (xmac_tx_iconfig_t *)&status); 6942 if (rs != NPI_SUCCESS) 6943 goto npi_fail; 6944 if (status & ICFG_XMAC_TX_ALL) { 6945 if (status & ICFG_XMAC_TX_UNDERRUN) { 6946 statsp->xmac_stats.tx_underflow_err++; 6947 NXGE_FM_REPORT_ERROR(nxgep, portn, 0, 6948 NXGE_FM_EREPORT_TXMAC_UNDERFLOW); 6949 } 6950 if (status & ICFG_XMAC_TX_MAX_PACKET_ERR) { 6951 statsp->xmac_stats.tx_maxpktsize_err++; 6952 /* 6953 * Do not send FMA ereport because this 6954 * error does not indicate HW failure. 6955 */ 6956 } 6957 if (status & ICFG_XMAC_TX_OVERFLOW) { 6958 statsp->xmac_stats.tx_overflow_err++; 6959 NXGE_FM_REPORT_ERROR(nxgep, portn, 0, 6960 NXGE_FM_EREPORT_TXMAC_OVERFLOW); 6961 } 6962 if (status & ICFG_XMAC_TX_FIFO_XFR_ERR) { 6963 statsp->xmac_stats.tx_fifo_xfr_err++; 6964 NXGE_FM_REPORT_ERROR(nxgep, portn, 0, 6965 NXGE_FM_EREPORT_TXMAC_TXFIFO_XFR_ERR); 6966 } 6967 if (status & ICFG_XMAC_TX_BYTE_CNT_EXP) { 6968 statsp->xmac_stats.tx_byte_cnt += 6969 XTXMAC_BYTE_CNT_MASK; 6970 } 6971 if (status & ICFG_XMAC_TX_FRAME_CNT_EXP) { 6972 statsp->xmac_stats.tx_frame_cnt += 6973 XTXMAC_FRM_CNT_MASK; 6974 } 6975 } 6976 6977 rs = npi_xmac_rx_get_istatus(handle, portn, 6978 (xmac_rx_iconfig_t *)&status); 6979 if (rs != NPI_SUCCESS) 6980 goto npi_fail; 6981 if (status & ICFG_XMAC_RX_ALL) { 6982 if (status & ICFG_XMAC_RX_OVERFLOW) 6983 statsp->xmac_stats.rx_overflow_err++; 6984 if (status & ICFG_XMAC_RX_UNDERFLOW) { 6985 statsp->xmac_stats.rx_underflow_err++; 6986 NXGE_FM_REPORT_ERROR(nxgep, portn, 0, 6987 NXGE_FM_EREPORT_RXMAC_UNDERFLOW); 6988 } 6989 /* 6990 * Do not send FMA ereport for the following 3 errors 6991 * because they do not indicate HW failures. 6992 */ 6993 if (status & ICFG_XMAC_RX_CRC_ERR_CNT_EXP) { 6994 statsp->xmac_stats.rx_crc_err_cnt += 6995 XRXMAC_CRC_ER_CNT_MASK; 6996 } 6997 if (status & ICFG_XMAC_RX_LEN_ERR_CNT_EXP) { 6998 statsp->xmac_stats.rx_len_err_cnt += 6999 MAC_LEN_ER_CNT_MASK; 7000 } 7001 if (status & ICFG_XMAC_RX_VIOL_ERR_CNT_EXP) { 7002 statsp->xmac_stats.rx_viol_err_cnt += 7003 XRXMAC_CD_VIO_CNT_MASK; 7004 } 7005 if (status & ICFG_XMAC_RX_OCT_CNT_EXP) { 7006 statsp->xmac_stats.rx_byte_cnt += 7007 XRXMAC_BT_CNT_MASK; 7008 } 7009 if (status & ICFG_XMAC_RX_HST_CNT1_EXP) { 7010 statsp->xmac_stats.rx_hist1_cnt += 7011 XRXMAC_HIST_CNT1_MASK; 7012 } 7013 if (status & ICFG_XMAC_RX_HST_CNT2_EXP) { 7014 statsp->xmac_stats.rx_hist2_cnt += 7015 XRXMAC_HIST_CNT2_MASK; 7016 } 7017 if (status & ICFG_XMAC_RX_HST_CNT3_EXP) { 7018 statsp->xmac_stats.rx_hist3_cnt += 7019 XRXMAC_HIST_CNT3_MASK; 7020 } 7021 if (status & ICFG_XMAC_RX_HST_CNT4_EXP) { 7022 statsp->xmac_stats.rx_hist4_cnt += 7023 XRXMAC_HIST_CNT4_MASK; 7024 } 7025 if (status & ICFG_XMAC_RX_HST_CNT5_EXP) { 7026 statsp->xmac_stats.rx_hist5_cnt += 7027 XRXMAC_HIST_CNT5_MASK; 7028 } 7029 if (status & ICFG_XMAC_RX_HST_CNT6_EXP) { 7030 statsp->xmac_stats.rx_hist6_cnt += 7031 XRXMAC_HIST_CNT6_MASK; 7032 } 7033 if (status & ICFG_XMAC_RX_BCAST_CNT_EXP) { 7034 statsp->xmac_stats.rx_broadcast_cnt += 7035 XRXMAC_BC_FRM_CNT_MASK; 7036 } 7037 if (status & ICFG_XMAC_RX_MCAST_CNT_EXP) { 7038 statsp->xmac_stats.rx_mult_cnt += 7039 XRXMAC_MC_FRM_CNT_MASK; 7040 } 7041 /* 7042 * Do not send FMA ereport for the following 3 errors 7043 * because they do not indicate HW failures. 7044 */ 7045 if (status & ICFG_XMAC_RX_FRAG_CNT_EXP) { 7046 statsp->xmac_stats.rx_frag_cnt += 7047 XRXMAC_FRAG_CNT_MASK; 7048 } 7049 if (status & ICFG_XMAC_RX_ALIGNERR_CNT_EXP) { 7050 statsp->xmac_stats.rx_frame_align_err_cnt += 7051 XRXMAC_AL_ER_CNT_MASK; 7052 } 7053 if (status & ICFG_XMAC_RX_LINK_FLT_CNT_EXP) { 7054 statsp->xmac_stats.rx_linkfault_err_cnt += 7055 XMAC_LINK_FLT_CNT_MASK; 7056 } 7057 if (status & ICFG_XMAC_RX_REMOTE_FLT_DET) { 7058 statsp->xmac_stats.rx_remotefault_err++; 7059 } 7060 if (status & ICFG_XMAC_RX_LOCAL_FLT_DET) { 7061 statsp->xmac_stats.rx_localfault_err++; 7062 } 7063 } 7064 7065 rs = npi_xmac_ctl_get_istatus(handle, portn, 7066 (xmac_ctl_iconfig_t *)&status); 7067 if (rs != NPI_SUCCESS) 7068 goto npi_fail; 7069 if (status & ICFG_XMAC_CTRL_ALL) { 7070 if (status & ICFG_XMAC_CTRL_PAUSE_RCVD) 7071 statsp->xmac_stats.rx_pause_cnt++; 7072 if (status & ICFG_XMAC_CTRL_PAUSE_STATE) 7073 statsp->xmac_stats.tx_pause_state++; 7074 if (status & ICFG_XMAC_CTRL_NOPAUSE_STATE) 7075 statsp->xmac_stats.tx_nopause_state++; 7076 } 7077 } else if (nxgep->mac.porttype == PORT_TYPE_BMAC) { 7078 rs = npi_bmac_tx_get_istatus(handle, portn, 7079 (bmac_tx_iconfig_t *)&status); 7080 if (rs != NPI_SUCCESS) 7081 goto npi_fail; 7082 if (status & ICFG_BMAC_TX_ALL) { 7083 if (status & ICFG_BMAC_TX_UNDERFLOW) { 7084 statsp->bmac_stats.tx_underrun_err++; 7085 NXGE_FM_REPORT_ERROR(nxgep, portn, 0, 7086 NXGE_FM_EREPORT_TXMAC_UNDERFLOW); 7087 } 7088 if (status & ICFG_BMAC_TX_MAXPKTSZ_ERR) { 7089 statsp->bmac_stats.tx_max_pkt_err++; 7090 NXGE_FM_REPORT_ERROR(nxgep, portn, 0, 7091 NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR); 7092 } 7093 if (status & ICFG_BMAC_TX_BYTE_CNT_EXP) { 7094 statsp->bmac_stats.tx_byte_cnt += 7095 BTXMAC_BYTE_CNT_MASK; 7096 } 7097 if (status & ICFG_BMAC_TX_FRAME_CNT_EXP) { 7098 statsp->bmac_stats.tx_frame_cnt += 7099 BTXMAC_FRM_CNT_MASK; 7100 } 7101 } 7102 7103 rs = npi_bmac_rx_get_istatus(handle, portn, 7104 (bmac_rx_iconfig_t *)&status); 7105 if (rs != NPI_SUCCESS) 7106 goto npi_fail; 7107 if (status & ICFG_BMAC_RX_ALL) { 7108 if (status & ICFG_BMAC_RX_OVERFLOW) { 7109 statsp->bmac_stats.rx_overflow_err++; 7110 } 7111 if (status & ICFG_BMAC_RX_FRAME_CNT_EXP) { 7112 statsp->bmac_stats.rx_frame_cnt += 7113 RXMAC_FRM_CNT_MASK; 7114 } 7115 if (status & ICFG_BMAC_RX_CRC_ERR_CNT_EXP) { 7116 statsp->bmac_stats.rx_crc_err_cnt += 7117 BMAC_CRC_ER_CNT_MASK; 7118 NXGE_FM_REPORT_ERROR(nxgep, portn, 0, 7119 NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP); 7120 } 7121 if (status & ICFG_BMAC_RX_LEN_ERR_CNT_EXP) { 7122 statsp->bmac_stats.rx_len_err_cnt += 7123 MAC_LEN_ER_CNT_MASK; 7124 NXGE_FM_REPORT_ERROR(nxgep, portn, 0, 7125 NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP); 7126 } 7127 if (status & ICFG_BMAC_RX_VIOL_ERR_CNT_EXP) { 7128 statsp->bmac_stats.rx_viol_err_cnt += 7129 BMAC_CD_VIO_CNT_MASK; 7130 NXGE_FM_REPORT_ERROR(nxgep, portn, 0, 7131 NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP); 7132 } 7133 if (status & ICFG_BMAC_RX_BYTE_CNT_EXP) { 7134 statsp->bmac_stats.rx_byte_cnt += 7135 BRXMAC_BYTE_CNT_MASK; 7136 } 7137 if (status & ICFG_BMAC_RX_ALIGNERR_CNT_EXP) { 7138 statsp->bmac_stats.rx_align_err_cnt += 7139 BMAC_AL_ER_CNT_MASK; 7140 NXGE_FM_REPORT_ERROR(nxgep, portn, 0, 7141 NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP); 7142 } 7143 7144 rs = npi_bmac_ctl_get_istatus(handle, portn, 7145 (bmac_ctl_iconfig_t *)&status); 7146 if (rs != NPI_SUCCESS) 7147 goto npi_fail; 7148 7149 if (status & ICFG_BMAC_CTL_ALL) { 7150 if (status & ICFG_BMAC_CTL_RCVPAUSE) 7151 statsp->bmac_stats.rx_pause_cnt++; 7152 if (status & ICFG_BMAC_CTL_INPAUSE_ST) 7153 statsp->bmac_stats.tx_pause_state++; 7154 if (status & ICFG_BMAC_CTL_INNOTPAUSE_ST) 7155 statsp->bmac_stats.tx_nopause_state++; 7156 } 7157 } 7158 } 7159 7160 if (ldgp->nldvs == 1) { 7161 (void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg, 7162 B_TRUE, ldgp->ldg_timer); 7163 } 7164 7165 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mac_intr")); 7166 return (DDI_INTR_CLAIMED); 7167 7168 npi_fail: 7169 NXGE_ERROR_MSG((nxgep, INT_CTL, "<== nxge_mac_intr")); 7170 return (DDI_INTR_UNCLAIMED); 7171 } 7172 7173 nxge_status_t 7174 nxge_check_bcm8704_link(p_nxge_t nxgep, boolean_t *link_up) 7175 { 7176 uint8_t phy_port_addr; 7177 nxge_status_t status = NXGE_OK; 7178 boolean_t rx_sig_ok; 7179 boolean_t pcs_blk_lock; 7180 boolean_t link_align; 7181 uint16_t val1, val2, val3; 7182 #ifdef NXGE_DEBUG_SYMBOL_ERR 7183 uint16_t val_debug; 7184 uint32_t val; 7185 #endif 7186 7187 phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn; 7188 7189 #ifdef NXGE_DEBUG_SYMBOL_ERR 7190 /* Check Device 3 Register Device 3 0xC809 */ 7191 (void) nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0xC809, &val_debug); 7192 if ((val_debug & ~0x200) != 0) { 7193 cmn_err(CE_NOTE, "!Port%d BCM8704 Dev3 Reg 0xc809 = 0x%x\n", 7194 nxgep->mac.portnum, val_debug); 7195 (void) nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, 7196 &val_debug); 7197 cmn_err(CE_NOTE, "!Port%d BCM8704 Dev4 Reg 0x18 = 0x%x\n", 7198 nxgep->mac.portnum, val_debug); 7199 } 7200 7201 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 7202 XPCS_REG_DESCWERR_COUNTER, &val); 7203 if (val != 0) 7204 cmn_err(CE_NOTE, "!XPCS DESCWERR = 0x%x\n", val); 7205 7206 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 7207 XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val); 7208 if (val != 0) 7209 cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L0_1 = 0x%x\n", val); 7210 7211 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 7212 XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val); 7213 if (val != 0) 7214 cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L2_3 = 0x%x\n", val); 7215 #endif 7216 7217 /* Check from BCM8704 if 10G link is up or down */ 7218 7219 /* Check Device 1 Register 0xA bit0 */ 7220 status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PMA_PMD_DEV_ADDR, 7221 BCM8704_PMD_RECEIVE_SIG_DETECT, &val1); 7222 if (status != NXGE_OK) 7223 goto fail; 7224 rx_sig_ok = ((val1 & GLOB_PMD_RX_SIG_OK) ? B_TRUE : B_FALSE); 7225 7226 /* Check Device 3 Register 0x20 bit0 */ 7227 if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PCS_DEV_ADDR, 7228 BCM8704_10GBASE_R_PCS_STATUS_REG, &val2)) != NPI_SUCCESS) 7229 goto fail; 7230 pcs_blk_lock = ((val2 & PCS_10GBASE_R_PCS_BLK_LOCK) ? B_TRUE : B_FALSE); 7231 7232 /* Check Device 4 Register 0x18 bit12 */ 7233 status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 7234 BCM8704_PHYXS_XGXS_LANE_STATUS_REG, &val3); 7235 if (status != NXGE_OK) 7236 goto fail; 7237 7238 switch (nxgep->chip_id) { 7239 case BCM8704_CHIP_ID: 7240 link_align = (val3 == (XGXS_LANE_ALIGN_STATUS | 7241 XGXS_LANE3_SYNC | XGXS_LANE2_SYNC | XGXS_LANE1_SYNC | 7242 XGXS_LANE0_SYNC | 0x400)) ? B_TRUE : B_FALSE; 7243 break; 7244 case BCM8706_CHIP_ID: 7245 link_align = ((val3 & XGXS_LANE_ALIGN_STATUS) && 7246 (val3 & XGXS_LANE3_SYNC) && (val3 & XGXS_LANE2_SYNC) && 7247 (val3 & XGXS_LANE1_SYNC) && (val3 & XGXS_LANE0_SYNC)) ? 7248 B_TRUE : B_FALSE; 7249 break; 7250 default: 7251 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_check_bcm8704_link:" 7252 "Unknown chip ID [0x%x]", nxgep->chip_id)); 7253 goto fail; 7254 } 7255 7256 #ifdef NXGE_DEBUG_ALIGN_ERR 7257 /* Temp workaround for link down issue */ 7258 if (pcs_blk_lock == B_FALSE) { 7259 if (val2 != 0x4) { 7260 pcs_blk_lock = B_TRUE; 7261 cmn_err(CE_NOTE, "!LINK DEBUG: port%d PHY Dev3 " 7262 "Reg 0x20 = 0x%x\n", nxgep->mac.portnum, val2); 7263 } 7264 } 7265 7266 if (link_align == B_FALSE) { 7267 if (val3 != 0x140f) { 7268 link_align = B_TRUE; 7269 cmn_err(CE_NOTE, "!LINK DEBUG: port%d PHY Dev4 " 7270 "Reg 0x18 = 0x%x\n", nxgep->mac.portnum, val3); 7271 } 7272 } 7273 7274 if (rx_sig_ok == B_FALSE) { 7275 if ((val2 == 0) || (val3 == 0)) { 7276 rx_sig_ok = B_TRUE; 7277 cmn_err(CE_NOTE, 7278 "!LINK DEBUG: port %d Dev3 or Dev4 read zero\n", 7279 nxgep->mac.portnum); 7280 } 7281 } 7282 #endif 7283 7284 *link_up = ((rx_sig_ok == B_TRUE) && (pcs_blk_lock == B_TRUE) && 7285 (link_align == B_TRUE)) ? B_TRUE : B_FALSE; 7286 7287 return (NXGE_OK); 7288 fail: 7289 return (status); 7290 } 7291 7292 static nxge_status_t 7293 nxge_check_mrvl88x2011_link(p_nxge_t nxgep, boolean_t *link_up) 7294 { 7295 uint8_t phy; 7296 nxge_status_t status = NXGE_OK; 7297 boolean_t pma_status; 7298 boolean_t pcs_status; 7299 boolean_t xgxs_status; 7300 uint16_t val; 7301 7302 phy = nxgep->statsp->mac_stats.xcvr_portn; 7303 7304 MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR, 7305 MRVL_88X2011_10G_PMD_STAT_2, &val); 7306 7307 *link_up = B_FALSE; 7308 7309 /* Check from Marvell 88X2011 if 10G link is up or down */ 7310 7311 /* Check PMA/PMD Register: 1.0001.2 == 1 */ 7312 MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR, 7313 MRVL_88X2011_PMA_PMD_STAT_1, &val); 7314 7315 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7316 "nxge_check_mrvl88x2011_link: pmd=0x%x", val)); 7317 7318 pma_status = ((val & MRVL_88X2011_LNK_STATUS_OK) ? B_TRUE : B_FALSE); 7319 7320 /* Check PMC Register : 3.0001.2 == 1: read twice */ 7321 MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR, 7322 MRVL_88X2011_PMA_PMD_STAT_1, &val); 7323 MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR, 7324 MRVL_88X2011_PMA_PMD_STAT_1, &val); 7325 7326 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7327 "nxge_check_mrvl88x2011_link: pcs=0x%x", val)); 7328 7329 pcs_status = ((val & MRVL_88X2011_LNK_STATUS_OK) ? B_TRUE : B_FALSE); 7330 7331 /* Check XGXS Register : 4.0018.[0-3,12] */ 7332 MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV4_ADDR, 7333 MRVL_88X2011_10G_XGXS_LANE_STAT, &val); 7334 7335 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7336 "nxge_check_mrvl88x2011_link: xgxs=0x%x", val)); 7337 7338 xgxs_status = (val == (XGXS_LANE_ALIGN_STATUS | XGXS_LANE3_SYNC | 7339 XGXS_LANE2_SYNC | XGXS_LANE1_SYNC | 7340 XGXS_LANE0_SYNC | XGXS_PATTERN_TEST_ABILITY | 7341 XGXS_LANE_STAT_MAGIC)) ? B_TRUE : B_FALSE; 7342 7343 *link_up = (pma_status && pcs_status && xgxs_status) ? 7344 B_TRUE : B_FALSE; 7345 7346 fail: 7347 7348 if (*link_up == B_FALSE) { 7349 /* PCS OFF */ 7350 nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_CTL_OFF); 7351 } else { 7352 /* PCS Activity */ 7353 nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_CTL_PCS_ACT); 7354 } 7355 7356 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7357 " <== nxge_check_mrvl88x2011_link: up=%d", *link_up)); 7358 7359 return (status); 7360 } 7361 7362 static nxge_status_t 7363 nxge_check_nlp2020_link(p_nxge_t nxgep, boolean_t *link_up) 7364 { 7365 uint8_t phy; 7366 nxge_status_t status = NXGE_OK; 7367 uint16_t pmd_rx_sig, pcs_10gbr_stat1, phy_xs_ln_stat; 7368 uint8_t connector = 0; 7369 7370 phy = nxgep->statsp->mac_stats.xcvr_portn; 7371 *link_up = B_FALSE; 7372 7373 /* Check from Netlogic AEL2020 if 10G link is up or down */ 7374 7375 status = nxge_mdio_read(nxgep, phy, NLP2020_PMA_PMD_ADDR, 7376 NLP2020_PMA_PMD_RX_SIG_DET_REG, &pmd_rx_sig); 7377 if (status != NXGE_OK) 7378 goto fail; 7379 7380 status = nxge_mdio_read(nxgep, phy, NLP2020_PHY_PCS_ADDR, 7381 NLP2020_PHY_PCS_10GBR_STAT1_REG, &pcs_10gbr_stat1); 7382 if (status != NXGE_OK) 7383 goto fail; 7384 7385 status = nxge_mdio_read(nxgep, phy, NLP2020_PHY_XS_ADDR, 7386 NLP2020_PHY_XS_LN_ST_REG, &phy_xs_ln_stat); 7387 if (status != NXGE_OK) 7388 goto fail; 7389 7390 if ((pmd_rx_sig & NLP2020_PMA_PMD_RX_SIG_ON) && 7391 (pcs_10gbr_stat1 & NLP2020_PHY_PCS_10GBR_RX_LINK_UP) && 7392 (phy_xs_ln_stat & NLP2020_PHY_XS_LN_ALIGN_SYNC)) 7393 *link_up = B_TRUE; 7394 /* 7395 * If previously link was down, check the connector type as 7396 * it might have been changed. 7397 */ 7398 if (nxgep->statsp->mac_stats.link_up == 0) { 7399 (void) nxge_nlp2020_i2c_read(nxgep, phy, 7400 NLP2020_XCVR_I2C_ADDR, QSFP_MSA_CONN_REG, &connector); 7401 7402 switch (connector) { 7403 case SFPP_FIBER: 7404 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7405 "nxge_check_nlp2020_link: SFPP_FIBER")); 7406 if (nxgep->mac.portmode != PORT_10G_FIBER) { 7407 nxgep->mac.portmode = PORT_10G_FIBER; 7408 (void) nxge_nlp2020_xcvr_init(nxgep); 7409 } 7410 break; 7411 case QSFP_FIBER: 7412 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7413 "nxge_check_nlp2020_link: QSFP_FIBER")); 7414 if (nxgep->mac.portmode != PORT_10G_FIBER) { 7415 nxgep->mac.portmode = PORT_10G_FIBER; 7416 (void) nxge_nlp2020_xcvr_init(nxgep); 7417 } 7418 break; 7419 case QSFP_COPPER_TWINAX: 7420 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7421 "nxge_check_nlp2020_link: " 7422 "QSFP_COPPER_TWINAX/" 7423 "SFPP_COPPER_TWINAX")); 7424 if (nxgep->mac.portmode != PORT_10G_COPPER) { 7425 nxgep->mac.portmode = PORT_10G_COPPER; 7426 (void) nxge_nlp2020_xcvr_init(nxgep); 7427 } else { 7428 uint8_t len = 0; 7429 (void) nxge_nlp2020_i2c_read(nxgep, phy, 7430 NLP2020_XCVR_I2C_ADDR, QSFP_MSA_LEN_REG, 7431 &len); 7432 if (((len < 7) && 7433 (nxgep->nlp_conn == 7434 NXGE_NLP_CONN_COPPER_7M_ABOVE)) || 7435 ((len >= 7) && 7436 (nxgep->nlp_conn == 7437 NXGE_NLP_CONN_COPPER_LT_7M))) { 7438 (void) nxge_nlp2020_xcvr_init(nxgep); 7439 } 7440 } 7441 break; 7442 default: 7443 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7444 "nxge_check_nlp2020_link: Unknown type [0x%x] " 7445 "detected...setting to QSFP_FIBER", 7446 connector)); 7447 if (nxgep->mac.portmode != PORT_10G_FIBER) { 7448 nxgep->mac.portmode = PORT_10G_FIBER; 7449 (void) nxge_nlp2020_xcvr_init(nxgep); 7450 } 7451 break; 7452 } 7453 } 7454 fail: 7455 if (*link_up == B_FALSE && nxgep->statsp->mac_stats.link_up == 1) { 7456 /* Turn link LED OFF */ 7457 (void) nxge_mdio_write(nxgep, phy, 7458 NLP2020_GPIO_ADDR, NLP2020_GPIO_CTL_REG, 0xb000); 7459 (void) nxge_mdio_write(nxgep, phy, 7460 NLP2020_GPIO_ADDR, NLP2020_GPIO_PT3_CFG_REG, 0x0); 7461 } else if (*link_up == B_TRUE && 7462 nxgep->statsp->mac_stats.link_up == 0) { 7463 /* Turn link LED ON */ 7464 (void) nxge_mdio_write(nxgep, phy, 7465 NLP2020_GPIO_ADDR, NLP2020_GPIO_CTL_REG, 0xd000); 7466 (void) nxge_mdio_write(nxgep, phy, 7467 NLP2020_GPIO_ADDR, NLP2020_GPIO_PT3_CFG_REG, 0xfbff); 7468 (void) nxge_mdio_write(nxgep, phy, 7469 NLP2020_GPIO_ADDR, 0xff2a, 0x004a); 7470 } 7471 7472 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7473 " <== nxge_check_nlp2020_link: up=%d", *link_up)); 7474 return (status); 7475 } 7476 7477 7478 nxge_status_t 7479 nxge_10g_link_led_on(p_nxge_t nxgep) 7480 { 7481 if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_TRUE) 7482 != NPI_SUCCESS) 7483 return (NXGE_ERROR); 7484 else 7485 return (NXGE_OK); 7486 } 7487 7488 nxge_status_t 7489 nxge_10g_link_led_off(p_nxge_t nxgep) 7490 { 7491 if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_FALSE) 7492 != NPI_SUCCESS) 7493 return (NXGE_ERROR); 7494 else 7495 return (NXGE_OK); 7496 } 7497 7498 static boolean_t 7499 nxge_hswap_phy_present(p_nxge_t nxgep, uint8_t portn) 7500 { 7501 /* 7502 * check for BCM PHY (GOA NEM) 7503 */ 7504 /* 7505 * If this is the 2nd NIU port, then check 2 addresses 7506 * to take care of the Goa NEM card. Port 1 can have addr 17 7507 * (in the eval board) or 20 (in the P0 board). 7508 */ 7509 if (portn == 1) { 7510 if (nxge_is_phy_present(nxgep, ALT_GOA_CLAUSE45_PORT1_ADDR, 7511 BCM8706_DEV_ID, BCM_PHY_ID_MASK)) { 7512 nxgep->xcvr_addr = ALT_GOA_CLAUSE45_PORT1_ADDR; 7513 goto found_phy; 7514 } 7515 } 7516 if (nxge_is_phy_present(nxgep, GOA_CLAUSE45_PORT_ADDR_BASE + portn, 7517 BCM8706_DEV_ID, BCM_PHY_ID_MASK)) { 7518 nxgep->xcvr_addr = GOA_CLAUSE45_PORT_ADDR_BASE + portn; 7519 goto found_phy; 7520 } 7521 7522 /* 7523 * check for NLP2020 PHY on C4 NEM 7524 */ 7525 switch (portn) { 7526 case 0: 7527 if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT0_ADDR0, 7528 NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) { 7529 nxgep->xcvr_addr = NLP2020_CL45_PORT0_ADDR0; 7530 goto found_phy; 7531 } else if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT0_ADDR1, 7532 NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) { 7533 nxgep->xcvr_addr = NLP2020_CL45_PORT0_ADDR1; 7534 goto found_phy; 7535 } else if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT0_ADDR2, 7536 NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) { 7537 nxgep->xcvr_addr = NLP2020_CL45_PORT0_ADDR2; 7538 goto found_phy; 7539 } else if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT0_ADDR3, 7540 NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) { 7541 nxgep->xcvr_addr = NLP2020_CL45_PORT0_ADDR3; 7542 goto found_phy; 7543 } 7544 break; 7545 7546 case 1: 7547 if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT1_ADDR0, 7548 NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) { 7549 nxgep->xcvr_addr = NLP2020_CL45_PORT1_ADDR0; 7550 goto found_phy; 7551 } else if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT1_ADDR1, 7552 NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) { 7553 nxgep->xcvr_addr = NLP2020_CL45_PORT1_ADDR1; 7554 goto found_phy; 7555 } else if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT1_ADDR2, 7556 NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) { 7557 nxgep->xcvr_addr = NLP2020_CL45_PORT1_ADDR2; 7558 goto found_phy; 7559 } else if (nxge_is_phy_present(nxgep, NLP2020_CL45_PORT1_ADDR3, 7560 NLP2020_DEV_ID, NLP2020_DEV_ID_MASK)) { 7561 nxgep->xcvr_addr = NLP2020_CL45_PORT1_ADDR3; 7562 goto found_phy; 7563 } 7564 break; 7565 default: 7566 break; 7567 } 7568 7569 return (B_FALSE); 7570 found_phy: 7571 return (B_TRUE); 7572 7573 } 7574 7575 static boolean_t 7576 nxge_is_phy_present(p_nxge_t nxgep, int addr, uint32_t id, uint32_t mask) 7577 { 7578 uint32_t pma_pmd_id = 0; 7579 uint32_t pcs_id = 0; 7580 uint32_t phy_id = 0; 7581 7582 pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, addr); 7583 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7584 "nxge_is_phy_present: pma_pmd_id[0x%x]", pma_pmd_id)); 7585 if ((pma_pmd_id & mask) == (id & mask)) 7586 goto found_phy; 7587 pcs_id = nxge_get_cl45_pcs_id(nxgep, addr); 7588 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7589 "nxge_is_phy_present: pcs_id[0x%x]", pcs_id)); 7590 if ((pcs_id & mask) == (id & mask)) 7591 goto found_phy; 7592 phy_id = nxge_get_cl22_phy_id(nxgep, addr); 7593 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7594 "nxge_is_phy_present: phy_id[0x%x]", phy_id)); 7595 if ((phy_id & mask) == (id & mask)) 7596 goto found_phy; 7597 7598 return (B_FALSE); 7599 7600 found_phy: 7601 return (B_TRUE); 7602 } 7603 7604 /* Check if the given id read using the given MDIO Clause is supported */ 7605 7606 static boolean_t 7607 nxge_is_supported_phy(uint32_t id, uint8_t type) 7608 { 7609 int i; 7610 boolean_t found = B_FALSE; 7611 7612 switch (type) { 7613 case CLAUSE_45_TYPE: 7614 for (i = 0; i < NUM_CLAUSE_45_IDS; i++) { 7615 if (((nxge_supported_cl45_ids[i] & BCM_PHY_ID_MASK) == 7616 (id & BCM_PHY_ID_MASK)) || 7617 (TN1010_DEV_ID == (id & TN1010_DEV_ID_MASK)) || 7618 (NLP2020_DEV_ID == (id & NLP2020_DEV_ID_MASK))) { 7619 found = B_TRUE; 7620 break; 7621 } 7622 } 7623 break; 7624 case CLAUSE_22_TYPE: 7625 for (i = 0; i < NUM_CLAUSE_22_IDS; i++) { 7626 if ((nxge_supported_cl22_ids[i] & BCM_PHY_ID_MASK) == 7627 (id & BCM_PHY_ID_MASK)) { 7628 found = B_TRUE; 7629 break; 7630 } 7631 } 7632 break; 7633 default: 7634 break; 7635 } 7636 7637 return (found); 7638 } 7639 7640 static uint32_t 7641 nxge_get_cl45_pma_pmd_id(p_nxge_t nxgep, int phy_port) 7642 { 7643 uint16_t val1 = 0; 7644 uint16_t val2 = 0; 7645 uint32_t pma_pmd_dev_id = 0; 7646 npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep); 7647 7648 MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 7649 (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR, 7650 NXGE_DEV_ID_REG_1, &val1); 7651 (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR, 7652 NXGE_DEV_ID_REG_2, &val2); 7653 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 7654 7655 /* Concatenate the Device ID stored in two registers. */ 7656 pma_pmd_dev_id = val1; 7657 pma_pmd_dev_id = (pma_pmd_dev_id << 16); 7658 pma_pmd_dev_id |= val2; 7659 7660 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PMA/PMD " 7661 "devid[0x%llx]", phy_port, pma_pmd_dev_id)); 7662 7663 return (pma_pmd_dev_id); 7664 } 7665 7666 static uint32_t 7667 nxge_get_cl45_pcs_id(p_nxge_t nxgep, int phy_port) 7668 { 7669 uint16_t val1 = 0; 7670 uint16_t val2 = 0; 7671 uint32_t pcs_dev_id = 0; 7672 npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep); 7673 7674 MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 7675 (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR, 7676 NXGE_DEV_ID_REG_1, &val1); 7677 (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR, 7678 NXGE_DEV_ID_REG_2, &val2); 7679 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 7680 7681 pcs_dev_id = val1; 7682 pcs_dev_id = (pcs_dev_id << 16); 7683 pcs_dev_id |= val2; 7684 7685 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS " 7686 "devid[0x%llx]", phy_port, pcs_dev_id)); 7687 7688 return (pcs_dev_id); 7689 } 7690 7691 static uint32_t 7692 nxge_get_cl22_phy_id(p_nxge_t nxgep, int phy_port) 7693 { 7694 uint16_t val1 = 0; 7695 uint16_t val2 = 0; 7696 uint32_t phy_id = 0; 7697 npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep); 7698 npi_status_t npi_status = NPI_SUCCESS; 7699 7700 MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 7701 npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_1, 7702 &val1); 7703 if (npi_status != NPI_SUCCESS) { 7704 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] " 7705 "clause 22 read to reg 2 failed!!!")); 7706 goto exit; 7707 } 7708 npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_2, 7709 &val2); 7710 if (npi_status != 0) { 7711 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] " 7712 "clause 22 read to reg 3 failed!!!")); 7713 goto exit; 7714 } 7715 phy_id = val1; 7716 phy_id = (phy_id << 16); 7717 phy_id |= val2; 7718 7719 exit: 7720 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 7721 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID [0x%llx]", 7722 phy_port, phy_id)); 7723 7724 return (phy_id); 7725 } 7726 7727 /* 7728 * Scan the PHY ports 0 through 31 to get the PHY ID using Clause 22 MDIO 7729 * read and the PMA/PMD device ID and the PCS device ID using Clause 45 MDIO 7730 * read. Then use the values obtained to determine the phy type of each port 7731 * and the Neptune type. 7732 * 7733 * This function sets hw_p->xcvr_addr[i] for future MDIO access and set 7734 * hw_p->niu_type for each nxge instance to figure out nxgep->mac.portmode 7735 * in case the portmode information is not available via OBP, nxge.conf, 7736 * VPD or SEEPROM. 7737 */ 7738 nxge_status_t 7739 nxge_scan_ports_phy(p_nxge_t nxgep, p_nxge_hw_list_t hw_p) 7740 { 7741 int i, j, l; 7742 uint32_t pma_pmd_dev_id = 0; 7743 uint32_t pcs_dev_id = 0; 7744 uint32_t phy_id = 0; 7745 uint32_t port_pma_pmd_dev_id[NXGE_PORTS_NEPTUNE]; 7746 uint32_t port_pcs_dev_id[NXGE_PORTS_NEPTUNE]; 7747 uint32_t port_phy_id[NXGE_PORTS_NEPTUNE]; 7748 uint8_t pma_pmd_dev_fd[NXGE_MAX_PHY_PORTS]; 7749 uint8_t pcs_dev_fd[NXGE_MAX_PHY_PORTS]; 7750 uint8_t phy_fd_arr[NXGE_MAX_PHY_PORTS]; 7751 uint8_t port_fd_arr[NXGE_MAX_PHY_PORTS]; 7752 uint8_t total_port_fd, total_phy_fd; 7753 uint8_t num_xaui; 7754 nxge_status_t status = NXGE_OK; 7755 7756 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_scan_ports_phy: ")); 7757 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7758 "==> nxge_scan_ports_phy: nxge niu_type[0x%x]", 7759 nxgep->niu_type)); 7760 7761 if (isLDOMguest(nxgep)) { 7762 hw_p->niu_type = NIU_TYPE_NONE; 7763 hw_p->platform_type = P_NEPTUNE_NONE; 7764 return (NXGE_OK); 7765 } 7766 7767 j = l = 0; 7768 total_port_fd = total_phy_fd = 0; 7769 /* 7770 * Clause 45 and Clause 22 port/phy addresses 0 through 5 are reserved 7771 * for on chip serdes usages. "i" in the following for loop starts at 6. 7772 */ 7773 for (i = NXGE_EXT_PHY_PORT_ST; i < NXGE_MAX_PHY_PORTS; i++) { 7774 7775 pma_pmd_dev_id = nxge_get_cl45_pma_pmd_id(nxgep, i); 7776 7777 if (nxge_is_supported_phy(pma_pmd_dev_id, CLAUSE_45_TYPE)) { 7778 pma_pmd_dev_fd[i] = 1; 7779 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] " 7780 "PMA/PMD dev %x found", i, pma_pmd_dev_id)); 7781 if (j < NXGE_PORTS_NEPTUNE) { 7782 if ((pma_pmd_dev_id & TN1010_DEV_ID_MASK) 7783 == TN1010_DEV_ID) { 7784 port_pma_pmd_dev_id[j] = TN1010_DEV_ID; 7785 } else if ((pma_pmd_dev_id & 7786 NLP2020_DEV_ID_MASK) == NLP2020_DEV_ID) { 7787 port_pma_pmd_dev_id[j] = 7788 NLP2020_DEV_ID; 7789 } else { 7790 port_pma_pmd_dev_id[j] = 7791 pma_pmd_dev_id & BCM_PHY_ID_MASK; 7792 } 7793 port_fd_arr[j] = (uint8_t)i; 7794 j++; 7795 } 7796 } else { 7797 pma_pmd_dev_fd[i] = 0; 7798 } 7799 7800 pcs_dev_id = nxge_get_cl45_pcs_id(nxgep, i); 7801 7802 if (nxge_is_supported_phy(pcs_dev_id, CLAUSE_45_TYPE)) { 7803 pcs_dev_fd[i] = 1; 7804 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS " 7805 "dev %x found", i, pcs_dev_id)); 7806 if (pma_pmd_dev_fd[i] == 1) { 7807 if ((pcs_dev_id & TN1010_DEV_ID_MASK) 7808 == TN1010_DEV_ID) { 7809 port_pcs_dev_id[j - 1] = 7810 TN1010_DEV_ID; 7811 } else if ((pcs_dev_id & NLP2020_DEV_ID_MASK) 7812 == NLP2020_DEV_ID) { 7813 port_pcs_dev_id[j - 1] = 7814 NLP2020_DEV_ID; 7815 } else { 7816 port_pcs_dev_id[j - 1] = 7817 pcs_dev_id & 7818 BCM_PHY_ID_MASK; 7819 } 7820 } else { 7821 if (j < NXGE_PORTS_NEPTUNE) { 7822 if ((pcs_dev_id & TN1010_DEV_ID_MASK) 7823 == TN1010_DEV_ID) { 7824 port_pcs_dev_id[j] = 7825 TN1010_DEV_ID; 7826 } else if ((pcs_dev_id & 7827 NLP2020_DEV_ID_MASK) 7828 == NLP2020_DEV_ID) { 7829 port_pcs_dev_id[j] = 7830 NLP2020_DEV_ID; 7831 } else { 7832 port_pcs_dev_id[j] = 7833 pcs_dev_id & 7834 BCM_PHY_ID_MASK; 7835 } 7836 port_fd_arr[j] = (uint8_t)i; 7837 j++; 7838 } 7839 } 7840 } else { 7841 pcs_dev_fd[i] = 0; 7842 } 7843 7844 if (pcs_dev_fd[i] || pma_pmd_dev_fd[i]) { 7845 total_port_fd ++; 7846 } 7847 7848 phy_id = nxge_get_cl22_phy_id(nxgep, i); 7849 if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) { 7850 total_phy_fd ++; 7851 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID" 7852 "%x found", i, phy_id)); 7853 if (l < NXGE_PORTS_NEPTUNE) { 7854 if ((phy_id & TN1010_DEV_ID_MASK) 7855 == TN1010_DEV_ID) { 7856 port_phy_id[l] = TN1010_DEV_ID; 7857 } else { 7858 port_phy_id[l] 7859 = phy_id & BCM_PHY_ID_MASK; 7860 } 7861 phy_fd_arr[l] = (uint8_t)i; 7862 l++; 7863 } 7864 } 7865 } 7866 7867 switch (total_port_fd) { 7868 case 2: 7869 switch (total_phy_fd) { 7870 case 2: 7871 /* 2 10G, 2 1G RGMII Fiber / copper */ 7872 if ((((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) && 7873 (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) || 7874 ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) && 7875 (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) && 7876 ((port_phy_id[0] == PHY_BCM5482_FAMILY) && 7877 (port_phy_id[1] == PHY_BCM5482_FAMILY))) { 7878 7879 switch (hw_p->platform_type) { 7880 case P_NEPTUNE_ROCK: 7881 hw_p->niu_type = NEPTUNE_2_10GF_2_1GC; 7882 /* 7883 * ROCK platform has assigned a lower 7884 * addr to port 1. (port 0 = 0x9 and 7885 * port 1 = 0x8). 7886 */ 7887 hw_p->xcvr_addr[1] = port_fd_arr[0]; 7888 hw_p->xcvr_addr[0] = port_fd_arr[1]; 7889 7890 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7891 "Rock with 2 10G, 2 1GC")); 7892 break; 7893 7894 case P_NEPTUNE_NONE: 7895 default: 7896 hw_p->platform_type = 7897 P_NEPTUNE_GENERIC; 7898 hw_p->niu_type = NEPTUNE_2_10GF_2_1GRF; 7899 7900 hw_p->xcvr_addr[0] = port_fd_arr[0]; 7901 hw_p->xcvr_addr[1] = port_fd_arr[1]; 7902 7903 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7904 "ARTM card with 2 10G, 2 1GF")); 7905 break; 7906 } 7907 7908 hw_p->xcvr_addr[2] = phy_fd_arr[0]; 7909 hw_p->xcvr_addr[3] = phy_fd_arr[1]; 7910 7911 } else { 7912 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7913 "Unsupported neptune type 1")); 7914 goto error_exit; 7915 } 7916 break; 7917 7918 case 1: 7919 /* TODO - 2 10G, 1 1G */ 7920 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7921 "Unsupported neptune type 2 10G, 1 1G")); 7922 goto error_exit; 7923 case 0: 7924 /* 7925 * 2 10G: 2XGF NIC, Marvell, Goa, Huron with 2 XAUI 7926 * cards, etc. 7927 */ 7928 if (((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) && 7929 (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) || 7930 ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) && 7931 (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY)) || 7932 ((port_pcs_dev_id[0] == MARVELL_88X201X_PHY_ID) && 7933 (port_pcs_dev_id[1] == MARVELL_88X201X_PHY_ID)) || 7934 ((port_pma_pmd_dev_id[0] == 7935 MARVELL_88X201X_PHY_ID) && 7936 (port_pma_pmd_dev_id[1] == 7937 MARVELL_88X201X_PHY_ID))) { 7938 7939 /* 7940 * Check the first phy port address against 7941 * the known phy start addresses to determine 7942 * the platform type. 7943 */ 7944 7945 switch (port_fd_arr[0]) { 7946 case NEPTUNE_CLAUSE45_PORT_ADDR_BASE: 7947 /* 7948 * The Marvell case also falls into 7949 * this case as 7950 * MRVL88X2011_NEPTUNE_PORT_ADDR_BASE 7951 * == NEPTUNE_CLAUSE45_PORT_ADDR_BASE. 7952 * This is OK for the 2 10G case. 7953 */ 7954 hw_p->niu_type = NEPTUNE_2_10GF; 7955 hw_p->platform_type = 7956 P_NEPTUNE_ATLAS_2PORT; 7957 break; 7958 case GOA_CLAUSE45_PORT_ADDR_BASE: 7959 if (hw_p->platform_type != 7960 P_NEPTUNE_NIU) { 7961 hw_p->platform_type = 7962 P_NEPTUNE_GENERIC; 7963 hw_p->niu_type = 7964 NEPTUNE_2_10GF; 7965 } 7966 break; 7967 default: 7968 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7969 "Unsupported neptune type 2 - 1")); 7970 goto error_exit; 7971 } 7972 7973 for (i = 0; i < 2; i++) { 7974 hw_p->xcvr_addr[i] = port_fd_arr[i]; 7975 } 7976 7977 /* 2 10G optical Netlogic AEL2020 ports */ 7978 } else if (((port_pcs_dev_id[0] == NLP2020_DEV_ID) && 7979 (port_pcs_dev_id[1] == NLP2020_DEV_ID)) || 7980 ((port_pma_pmd_dev_id[0] == NLP2020_DEV_ID) && 7981 (port_pma_pmd_dev_id[1] == NLP2020_DEV_ID))) { 7982 if (hw_p->platform_type != P_NEPTUNE_NIU) { 7983 hw_p->platform_type = 7984 P_NEPTUNE_GENERIC; 7985 hw_p->niu_type = 7986 NEPTUNE_2_10GF; 7987 } 7988 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7989 "Found 2 NL PHYs at addrs 0x%x and 0x%x", 7990 port_fd_arr[0], port_fd_arr[1])); 7991 hw_p->xcvr_addr[0] = port_fd_arr[0]; 7992 hw_p->xcvr_addr[1] = port_fd_arr[1]; 7993 7994 /* Both XAUI slots have copper XAUI cards */ 7995 } else if ((((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 7996 == TN1010_DEV_ID) && 7997 ((port_pcs_dev_id[1] & TN1010_DEV_ID_MASK) 7998 == TN1010_DEV_ID)) || 7999 (((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK) 8000 == TN1010_DEV_ID) && 8001 ((port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK) 8002 == TN1010_DEV_ID))) { 8003 hw_p->niu_type = NEPTUNE_2_TN1010; 8004 hw_p->xcvr_addr[0] = port_fd_arr[0]; 8005 hw_p->xcvr_addr[1] = port_fd_arr[1]; 8006 8007 /* Slot0 has fiber XAUI, slot1 has copper XAUI */ 8008 } else if ((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY && 8009 (port_pcs_dev_id[1] & TN1010_DEV_ID_MASK) 8010 == TN1010_DEV_ID) || 8011 (port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY && 8012 (port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK) == 8013 TN1010_DEV_ID)) { 8014 hw_p->niu_type = NEPTUNE_1_10GF_1_TN1010; 8015 hw_p->xcvr_addr[0] = port_fd_arr[0]; 8016 hw_p->xcvr_addr[1] = port_fd_arr[1]; 8017 8018 /* Slot0 has copper XAUI, slot1 has fiber XAUI */ 8019 } else if ((port_pcs_dev_id[1] == PHY_BCM8704_FAMILY && 8020 (port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 8021 == TN1010_DEV_ID) || 8022 (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY && 8023 (port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK) 8024 == TN1010_DEV_ID)) { 8025 hw_p->niu_type = NEPTUNE_1_TN1010_1_10GF; 8026 hw_p->xcvr_addr[0] = port_fd_arr[0]; 8027 hw_p->xcvr_addr[1] = port_fd_arr[1]; 8028 8029 } else { 8030 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8031 "Unsupported neptune type 2")); 8032 goto error_exit; 8033 } 8034 break; 8035 8036 case 4: 8037 if (nxge_get_num_of_xaui( 8038 port_pma_pmd_dev_id, port_pcs_dev_id, 8039 port_phy_id, &num_xaui) == NXGE_ERROR) { 8040 goto error_exit; 8041 } 8042 if (num_xaui != 2) 8043 goto error_exit; 8044 8045 /* 8046 * Maramba with 2 XAUIs (either fiber or copper) 8047 * 8048 * Check the first phy port address against 8049 * the known phy start addresses to determine 8050 * the platform type. 8051 */ 8052 switch (phy_fd_arr[0]) { 8053 case MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE: 8054 hw_p->platform_type = 8055 P_NEPTUNE_MARAMBA_P0; 8056 break; 8057 case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE: 8058 hw_p->platform_type = 8059 P_NEPTUNE_MARAMBA_P1; 8060 break; 8061 default: 8062 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 8063 "Unknown port %d...Cannot " 8064 "determine platform type", i)); 8065 goto error_exit; 8066 } 8067 8068 hw_p->xcvr_addr[0] = port_fd_arr[0]; 8069 hw_p->xcvr_addr[1] = port_fd_arr[1]; 8070 hw_p->xcvr_addr[2] = phy_fd_arr[2]; 8071 hw_p->xcvr_addr[3] = phy_fd_arr[3]; 8072 8073 /* slot0 has fiber XAUI, slot1 has Cu XAUI */ 8074 if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY && 8075 (port_pcs_dev_id[1] & TN1010_DEV_ID_MASK) 8076 == TN1010_DEV_ID) { 8077 hw_p->niu_type = NEPTUNE_1_10GF_1_TN1010_2_1GC; 8078 8079 /* slot0 has Cu XAUI, slot1 has fiber XAUI */ 8080 } else if (((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 8081 == TN1010_DEV_ID) && 8082 port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) { 8083 hw_p->niu_type = NEPTUNE_1_TN1010_1_10GF_2_1GC; 8084 8085 /* Both slots have fiber XAUI */ 8086 } else if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY && 8087 port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) { 8088 hw_p->niu_type = NEPTUNE_2_10GF_2_1GC; 8089 8090 /* Both slots have copper XAUI */ 8091 } else if (((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 8092 == TN1010_DEV_ID) && 8093 (port_pcs_dev_id[1] & TN1010_DEV_ID_MASK) 8094 == TN1010_DEV_ID) { 8095 hw_p->niu_type = NEPTUNE_2_TN1010_2_1GC; 8096 8097 } else { 8098 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8099 "Unsupported neptune type 3")); 8100 goto error_exit; 8101 } 8102 break; 8103 default: 8104 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8105 "Unsupported neptune type 5")); 8106 goto error_exit; 8107 } 8108 break; 8109 case 1: /* Only one clause45 port */ 8110 switch (total_phy_fd) { /* Number of clause22 ports */ 8111 case 3: 8112 /* 8113 * TODO 3 1G, 1 10G mode. 8114 * Differentiate between 1_1G_1_10G_2_1G and 8115 * 1_10G_3_1G 8116 */ 8117 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8118 "Unsupported neptune type 7")); 8119 goto error_exit; 8120 case 2: 8121 /* 8122 * TODO 2 1G, 1 10G mode. 8123 * Differentiate between 1_1G_1_10G_1_1G and 8124 * 1_10G_2_1G 8125 */ 8126 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8127 "Unsupported neptune type 8")); 8128 goto error_exit; 8129 case 1: 8130 /* 8131 * TODO 1 1G, 1 10G mode. 8132 * Differentiate between 1_1G_1_10G and 8133 * 1_10G_1_1G 8134 */ 8135 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8136 "Unsupported neptune type 9")); 8137 goto error_exit; 8138 case 0: /* N2 with 1 XAUI (fiber or copper) */ 8139 /* Fiber XAUI */ 8140 if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY || 8141 port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) { 8142 8143 /* 8144 * Check the first phy port address against 8145 * the known phy start addresses to determine 8146 * the platform type. 8147 */ 8148 8149 switch (port_fd_arr[0]) { 8150 case N2_CLAUSE45_PORT_ADDR_BASE: 8151 case (N2_CLAUSE45_PORT_ADDR_BASE + 1): 8152 case ALT_GOA_CLAUSE45_PORT1_ADDR: 8153 /* 8154 * If hw_p->platform_type == 8155 * P_NEPTUNE_NIU, then portmode 8156 * is already known, so there is 8157 * no need to figure out hw_p-> 8158 * platform_type because 8159 * platform_type is only for 8160 * figuring out portmode. 8161 */ 8162 if (hw_p->platform_type != 8163 P_NEPTUNE_NIU) { 8164 hw_p->platform_type = 8165 P_NEPTUNE_GENERIC; 8166 hw_p->niu_type = 8167 NEPTUNE_2_10GF; 8168 } 8169 break; 8170 default: 8171 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 8172 "Unsupported neptune type 10")); 8173 goto error_exit; 8174 } 8175 /* 8176 * For GOA, which is a hot swappable PHY, the 8177 * phy address to function number mapping 8178 * should be preserved, i.e., addr 16 is 8179 * assigned to function 0 and 20 to function 1 8180 * But for Huron XAUI, the assignment should 8181 * be by function number, i.e., whichever 8182 * function number attaches should be 8183 * assigned the available PHY (this is required 8184 * primarily to support pre-production Huron 8185 * boards where function 0 is mapped to addr 17 8186 */ 8187 if (port_fd_arr[0] == 8188 ALT_GOA_CLAUSE45_PORT1_ADDR) { 8189 hw_p->xcvr_addr[1] = port_fd_arr[0]; 8190 } else { 8191 hw_p->xcvr_addr[nxgep->function_num] = 8192 port_fd_arr[0]; 8193 } 8194 } else if (port_pcs_dev_id[0] == NLP2020_DEV_ID || 8195 port_pma_pmd_dev_id[0] == NLP2020_DEV_ID) { 8196 /* A 10G NLP2020 PHY in slot0 or slot1 */ 8197 switch (port_fd_arr[0]) { 8198 case NLP2020_CL45_PORT0_ADDR0: 8199 case NLP2020_CL45_PORT0_ADDR1: 8200 case NLP2020_CL45_PORT0_ADDR2: 8201 case NLP2020_CL45_PORT0_ADDR3: 8202 case NLP2020_CL45_PORT1_ADDR0: 8203 case NLP2020_CL45_PORT1_ADDR1: 8204 case NLP2020_CL45_PORT1_ADDR2: 8205 case NLP2020_CL45_PORT1_ADDR3: 8206 /* 8207 * If hw_p->platform_type == 8208 * P_NEPTUNE_NIU, then portmode 8209 * is already known, so there is 8210 * no need to figure out hw_p-> 8211 * platform_type because 8212 * platform_type is only for 8213 * figuring out portmode. 8214 */ 8215 if (hw_p->platform_type != 8216 P_NEPTUNE_NIU) { 8217 hw_p->platform_type = 8218 P_NEPTUNE_GENERIC; 8219 hw_p->niu_type = 8220 NEPTUNE_2_10GF; 8221 } 8222 break; 8223 default: 8224 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 8225 "Unsupported neptune type 10-1")); 8226 goto error_exit; 8227 } 8228 switch (port_fd_arr[0]) { 8229 case NLP2020_CL45_PORT0_ADDR0: 8230 case NLP2020_CL45_PORT0_ADDR1: 8231 case NLP2020_CL45_PORT0_ADDR2: 8232 case NLP2020_CL45_PORT0_ADDR3: 8233 hw_p->xcvr_addr[0] = port_fd_arr[0]; 8234 break; 8235 case NLP2020_CL45_PORT1_ADDR0: 8236 case NLP2020_CL45_PORT1_ADDR1: 8237 case NLP2020_CL45_PORT1_ADDR2: 8238 case NLP2020_CL45_PORT1_ADDR3: 8239 hw_p->xcvr_addr[1] = port_fd_arr[0]; 8240 break; 8241 default: 8242 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 8243 "Unsupported neptune type 10-11")); 8244 goto error_exit; 8245 } 8246 8247 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8248 "Found 1 NL PHYs at addr 0x%x", 8249 port_fd_arr[0])); 8250 8251 /* A 10G copper XAUI in either slot0 or slot1 */ 8252 } else if ((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 8253 == TN1010_DEV_ID || 8254 (port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK) 8255 == TN1010_DEV_ID) { 8256 switch (port_fd_arr[0]) { 8257 /* The XAUI is in slot0 */ 8258 case N2_CLAUSE45_PORT_ADDR_BASE: 8259 hw_p->niu_type = NEPTUNE_1_TN1010; 8260 break; 8261 8262 /* The XAUI is in slot1 */ 8263 case (N2_CLAUSE45_PORT_ADDR_BASE + 1): 8264 hw_p->niu_type 8265 = NEPTUNE_1_NONE_1_TN1010; 8266 break; 8267 default: 8268 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 8269 "Unsupported XAUI port address")); 8270 goto error_exit; 8271 } 8272 hw_p->xcvr_addr[nxgep->function_num] 8273 = port_fd_arr[0]; 8274 8275 } else { 8276 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8277 "Unsupported PHY type")); 8278 goto error_exit; 8279 } 8280 break; 8281 case 4: /* Maramba always have 4 clause 45 ports */ 8282 8283 /* Maramba with 1 XAUI */ 8284 if ((port_pcs_dev_id[0] != PHY_BCM8704_FAMILY) && 8285 (port_pma_pmd_dev_id[0] != PHY_BCM8704_FAMILY) && 8286 ((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 8287 != TN1010_DEV_ID) && 8288 ((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK) 8289 != TN1010_DEV_ID)) { 8290 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8291 "Unsupported neptune type 12")); 8292 goto error_exit; 8293 } 8294 8295 /* 8296 * Check the first phy port address against 8297 * the known phy start addresses to determine 8298 * the platform type. 8299 */ 8300 switch (phy_fd_arr[0]) { 8301 case MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE: 8302 hw_p->platform_type = 8303 P_NEPTUNE_MARAMBA_P0; 8304 break; 8305 case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE: 8306 hw_p->platform_type = 8307 P_NEPTUNE_MARAMBA_P1; 8308 break; 8309 default: 8310 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 8311 "Unknown port %d...Cannot " 8312 "determine platform type 10 - 2", 8313 i)); 8314 goto error_exit; 8315 } 8316 8317 /* 8318 * Check the clause45 address to determine 8319 * if XAUI is in port 0 or port 1. 8320 */ 8321 switch (port_fd_arr[0]) { 8322 case MARAMBA_CLAUSE45_PORT_ADDR_BASE: 8323 if (port_pcs_dev_id[0] 8324 == PHY_BCM8704_FAMILY || 8325 port_pma_pmd_dev_id[0] 8326 == PHY_BCM8704_FAMILY) { 8327 hw_p->niu_type 8328 = NEPTUNE_1_10GF_3_1GC; 8329 } else { 8330 hw_p->niu_type 8331 = NEPTUNE_1_TN1010_3_1GC; 8332 } 8333 hw_p->xcvr_addr[0] = port_fd_arr[0]; 8334 for (i = 1; i < NXGE_MAX_PORTS; i++) { 8335 hw_p->xcvr_addr[i] = 8336 phy_fd_arr[i]; 8337 } 8338 break; 8339 case (MARAMBA_CLAUSE45_PORT_ADDR_BASE + 1): 8340 if (port_pcs_dev_id[0] 8341 == PHY_BCM8704_FAMILY || 8342 port_pma_pmd_dev_id[0] 8343 == PHY_BCM8704_FAMILY) { 8344 hw_p->niu_type = 8345 NEPTUNE_1_1GC_1_10GF_2_1GC; 8346 } else { 8347 hw_p->niu_type = 8348 NEPTUNE_1_1GC_1_TN1010_2_1GC; 8349 } 8350 hw_p->xcvr_addr[0] = phy_fd_arr[0]; 8351 hw_p->xcvr_addr[1] = port_fd_arr[0]; 8352 hw_p->xcvr_addr[2] = phy_fd_arr[2]; 8353 hw_p->xcvr_addr[3] = phy_fd_arr[3]; 8354 break; 8355 default: 8356 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8357 "Unsupported neptune type 11")); 8358 goto error_exit; 8359 } 8360 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8361 "Maramba with 1 XAUI (fiber or copper)")); 8362 break; 8363 default: 8364 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8365 "Unsupported neptune type 13")); 8366 goto error_exit; 8367 } 8368 break; 8369 case 0: /* 4 ports Neptune based NIC */ 8370 switch (total_phy_fd) { 8371 case 4: 8372 if ((port_phy_id[0] == PHY_BCM5464R_FAMILY) && 8373 (port_phy_id[1] == PHY_BCM5464R_FAMILY) && 8374 (port_phy_id[2] == PHY_BCM5464R_FAMILY) && 8375 (port_phy_id[3] == PHY_BCM5464R_FAMILY)) { 8376 8377 /* 8378 * Check the first phy port address against 8379 * the known phy start addresses to determine 8380 * the platform type. 8381 */ 8382 switch (phy_fd_arr[0]) { 8383 case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE: 8384 hw_p->platform_type = 8385 P_NEPTUNE_MARAMBA_P1; 8386 break; 8387 case NEPTUNE_CLAUSE22_PORT_ADDR_BASE: 8388 hw_p->platform_type = 8389 P_NEPTUNE_ATLAS_4PORT; 8390 break; 8391 default: 8392 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 8393 "Unknown port %d...Cannot " 8394 "determine platform type", i)); 8395 goto error_exit; 8396 } 8397 hw_p->niu_type = NEPTUNE_4_1GC; 8398 for (i = 0; i < NXGE_MAX_PORTS; i++) { 8399 hw_p->xcvr_addr[i] = phy_fd_arr[i]; 8400 } 8401 } else { 8402 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8403 "Unsupported neptune type 14")); 8404 goto error_exit; 8405 } 8406 break; 8407 case 3: 8408 /* TODO 3 1G mode */ 8409 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8410 "Unsupported neptune type 15")); 8411 goto error_exit; 8412 case 2: 8413 /* TODO 2 1G mode */ 8414 if ((port_phy_id[0] == PHY_BCM5482_FAMILY) && 8415 (port_phy_id[1] == PHY_BCM5482_FAMILY)) { 8416 hw_p->platform_type = P_NEPTUNE_GENERIC; 8417 hw_p->niu_type = NEPTUNE_2_1GRF; 8418 hw_p->xcvr_addr[2] = phy_fd_arr[0]; 8419 hw_p->xcvr_addr[3] = phy_fd_arr[1]; 8420 } else { 8421 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 8422 "Unsupported neptune type 16")); 8423 goto error_exit; 8424 } 8425 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8426 "2 RGMII Fiber ports - RTM")); 8427 break; 8428 8429 case 1: 8430 /* TODO 1 1G mode */ 8431 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8432 "Unsupported neptune type 17")); 8433 goto error_exit; 8434 default: 8435 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8436 "Unsupported neptune type 18, total phy fd %d", 8437 total_phy_fd)); 8438 goto error_exit; 8439 } 8440 break; 8441 default: 8442 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8443 "Unsupported neptune type 19")); 8444 goto error_exit; 8445 } 8446 8447 scan_exit: 8448 8449 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_scan_ports_phy, " 8450 "niu type [0x%x]\n", hw_p->niu_type)); 8451 return (status); 8452 8453 error_exit: 8454 return (NXGE_ERROR); 8455 } 8456 8457 boolean_t 8458 nxge_is_valid_local_mac(ether_addr_st mac_addr) 8459 { 8460 if ((mac_addr.ether_addr_octet[0] & 0x01) || 8461 (ether_cmp(&mac_addr, ðerbroadcastaddr) == 0) || 8462 (ether_cmp(&mac_addr, ðerzeroaddr) == 0)) 8463 return (B_FALSE); 8464 else 8465 return (B_TRUE); 8466 } 8467 8468 static void 8469 nxge_bcm5464_link_led_off(p_nxge_t nxgep) 8470 { 8471 8472 npi_status_t rs = NPI_SUCCESS; 8473 uint8_t xcvr_portn; 8474 uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 8475 8476 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_bcm5464_link_led_off")); 8477 8478 if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P1) { 8479 xcvr_portn = MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE; 8480 } else if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P0) { 8481 xcvr_portn = MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE; 8482 } 8483 /* 8484 * For Altas 4-1G copper, Xcvr port numbers are 8485 * swapped with ethernet port number. This is 8486 * designed for better signal integrity in routing. 8487 */ 8488 switch (portn) { 8489 case 0: 8490 xcvr_portn += 3; 8491 break; 8492 case 1: 8493 xcvr_portn += 2; 8494 break; 8495 case 2: 8496 xcvr_portn += 1; 8497 break; 8498 case 3: 8499 default: 8500 break; 8501 } 8502 8503 MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 8504 rs = npi_mac_mif_mii_write(nxgep->npi_handle, 8505 xcvr_portn, BCM5464R_MISC, 0xb4ee); 8506 if (rs != NPI_SUCCESS) { 8507 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 8508 "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write " 8509 "returned error 0x[%x]", rs)); 8510 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 8511 return; 8512 } 8513 8514 rs = npi_mac_mif_mii_write(nxgep->npi_handle, 8515 xcvr_portn, BCM5464R_MISC, 0xb8ee); 8516 if (rs != NPI_SUCCESS) { 8517 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 8518 "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write " 8519 "returned error 0x[%x]", rs)); 8520 } 8521 8522 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 8523 } 8524 8525 static nxge_status_t 8526 nxge_mii_get_link_mode(p_nxge_t nxgep) 8527 { 8528 p_nxge_stats_t statsp; 8529 uint8_t xcvr_portn; 8530 p_mii_regs_t mii_regs; 8531 mii_mode_control_stat_t mode; 8532 int status = NXGE_OK; 8533 8534 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_get_link_mode")); 8535 8536 statsp = nxgep->statsp; 8537 xcvr_portn = statsp->mac_stats.xcvr_portn; 8538 mii_regs = NULL; 8539 mode.value = 0; 8540 mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG; 8541 #if defined(__i386) 8542 if ((status = nxge_mii_write(nxgep, xcvr_portn, 8543 (uint8_t)(uint32_t)(&mii_regs->shadow), 8544 mode.value)) != NXGE_OK) { 8545 goto fail; 8546 #else 8547 if ((status = nxge_mii_write(nxgep, xcvr_portn, 8548 (uint8_t)(uint64_t)(&mii_regs->shadow), 8549 mode.value)) != NXGE_OK) { 8550 goto fail; 8551 #endif 8552 } 8553 #if defined(__i386) 8554 if ((status = nxge_mii_read(nxgep, xcvr_portn, 8555 (uint8_t)(uint32_t)(&mii_regs->shadow), 8556 &mode.value)) != NXGE_OK) { 8557 goto fail; 8558 } 8559 #else 8560 if ((status = nxge_mii_read(nxgep, xcvr_portn, 8561 (uint8_t)(uint64_t)(&mii_regs->shadow), 8562 &mode.value)) != NXGE_OK) { 8563 goto fail; 8564 } 8565 #endif 8566 8567 if (mode.bits.mode == NXGE_MODE_SELECT_FIBER) { 8568 nxgep->mac.portmode = PORT_1G_RGMII_FIBER; 8569 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8570 "nxge_mii_get_link_mode: fiber mode")); 8571 } 8572 8573 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8574 "nxge_mii_get_link_mode: " 8575 "(address 0x%x) port 0x%x mode value 0x%x link mode 0x%x", 8576 NXGE_MII_MODE_CONTROL_REG, xcvr_portn, 8577 mode.value, nxgep->mac.portmode)); 8578 8579 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8580 "<== nxge_mii_get_link_mode")); 8581 return (status); 8582 fail: 8583 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 8584 "<== nxge_mii_get_link_mode (failed)")); 8585 return (NXGE_ERROR); 8586 } 8587 8588 nxge_status_t 8589 nxge_mac_set_framesize(p_nxge_t nxgep) 8590 { 8591 npi_attr_t ap; 8592 uint8_t portn; 8593 npi_handle_t handle; 8594 npi_status_t rs = NPI_SUCCESS; 8595 8596 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_set_framesize")); 8597 8598 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 8599 handle = nxgep->npi_handle; 8600 8601 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8602 "==> nxge_mac_sec_framesize: port<%d> " 8603 "min framesize %d max framesize %d ", 8604 portn, 8605 nxgep->mac.minframesize, 8606 nxgep->mac.maxframesize)); 8607 8608 SET_MAC_ATTR2(handle, ap, portn, 8609 MAC_PORT_FRAME_SIZE, 8610 nxgep->mac.minframesize, 8611 nxgep->mac.maxframesize, 8612 rs); 8613 if (rs != NPI_SUCCESS) { 8614 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8615 "<== nxge_mac_set_framesize: failed to configure " 8616 "max/min frame size port %d", portn)); 8617 8618 return (NXGE_ERROR | rs); 8619 } 8620 8621 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8622 "<== nxge_mac_set_framesize: port<%d>", portn)); 8623 8624 return (NXGE_OK); 8625 } 8626 8627 static nxge_status_t 8628 nxge_get_num_of_xaui(uint32_t *port_pma_pmd_dev_id, 8629 uint32_t *port_pcs_dev_id, uint32_t *port_phy_id, uint8_t *num_xaui) 8630 { 8631 uint8_t i; 8632 8633 for (i = 0; i < 4; i++) { 8634 if (port_phy_id[i] != PHY_BCM5464R_FAMILY) 8635 return (NXGE_ERROR); 8636 } 8637 8638 *num_xaui = 0; 8639 if ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY && 8640 port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) || 8641 (((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK) 8642 == TN1010_DEV_ID) && 8643 ((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 8644 == TN1010_DEV_ID))) { 8645 (*num_xaui) ++; 8646 } 8647 if ((port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY && 8648 port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) || 8649 (((port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK) 8650 == TN1010_DEV_ID) && 8651 ((port_pcs_dev_id[1] & TN1010_DEV_ID_MASK) 8652 == TN1010_DEV_ID))) { 8653 (*num_xaui) ++; 8654 } 8655 return (NXGE_OK); 8656 } 8657 8658 /* 8659 * Instruction from Teranetics: Once you detect link is up, go 8660 * read Reg 30.1.4 for link speed: '1' for 1G and '0' for 10G. You 8661 * may want to qualify it by first checking Register 30.1.7:6 and 8662 * making sure it reads "01" (Auto-Neg Complete). 8663 * 8664 * If this function is called when the link is down or before auto- 8665 * negotiation has completed, then the speed of the PHY is not certain. 8666 * In such cases, this function returns 1G as the default speed with 8667 * NXGE_OK status instead of NXGE_ERROR. It is OK to initialize the 8668 * driver based on a default speed because this function will be called 8669 * again when the link comes up. Returning NXGE_ERROR, which may 8670 * cause brutal chain reaction in caller functions, is not necessary. 8671 */ 8672 static nxge_status_t 8673 nxge_get_tn1010_speed(p_nxge_t nxgep, uint16_t *speed) 8674 { 8675 uint8_t phy_port_addr, autoneg_stat, link_up; 8676 nxge_status_t status = NXGE_OK; 8677 uint16_t val; 8678 uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 8679 8680 /* Set default speed to 10G */ 8681 *speed = TN1010_SPEED_10G; 8682 8683 /* Set Clause 45 */ 8684 npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE); 8685 8686 phy_port_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 8687 8688 /* Check Device 1 Register 0xA bit0 for link up status */ 8689 status = nxge_mdio_read(nxgep, phy_port_addr, 8690 TN1010_AUTONEG_DEV_ADDR, TN1010_AUTONEG_STATUS_REG, &val); 8691 if (status != NXGE_OK) 8692 goto fail; 8693 8694 link_up = ((val & TN1010_AN_LINK_STAT_BIT) 8695 ? B_TRUE : B_FALSE); 8696 if (link_up == B_FALSE) { 8697 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8698 "nxge_get_tn1010_speed: link is down")); 8699 goto nxge_get_tn1010_speed_exit; 8700 } 8701 8702 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 8703 TN1010_VENDOR_MMD1_DEV_ADDR, TN1010_VENDOR_MMD1_STATUS_REG, 8704 &val)) != NXGE_OK) { 8705 goto fail; 8706 } 8707 autoneg_stat = (val & TN1010_VENDOR_MMD1_AN_STAT_BITS) >> 8708 TN1010_VENDOR_MMD1_AN_STAT_SHIFT; 8709 8710 /* 8711 * Return NXGE_OK even when we can not get a settled speed. In 8712 * such case, the speed reported should not be trusted but that 8713 * is OK, we will call this function periodically and will get 8714 * the correct speed after the link is up. 8715 */ 8716 switch (autoneg_stat) { 8717 case TN1010_AN_IN_PROG: 8718 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8719 "nxge_get_tn1010_speed: Auto-negotiation in progress")); 8720 break; 8721 case TN1010_AN_COMPLETE: 8722 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 8723 TN1010_VENDOR_MMD1_DEV_ADDR, 8724 TN1010_VENDOR_MMD1_STATUS_REG, 8725 &val)) != NXGE_OK) { 8726 goto fail; 8727 } 8728 *speed = (val & TN1010_VENDOR_MMD1_AN_SPEED_BIT) >> 8729 TN1010_VENDOR_MMD1_AN_SPEED_SHIFT; 8730 break; 8731 case TN1010_AN_RSVD: 8732 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 8733 "nxge_get_tn1010_speed: Autoneg status undefined")); 8734 break; 8735 case TN1010_AN_FAILED: 8736 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 8737 "nxge_get_tn1010_speed: Auto-negotiation failed")); 8738 break; 8739 default: 8740 break; 8741 } 8742 nxge_get_tn1010_speed_exit: 8743 return (NXGE_OK); 8744 fail: 8745 return (status); 8746 } 8747 8748 8749 /* 8750 * Teranetics TN1010 PHY chip supports both 1G and 10G modes, this function 8751 * figures out the speed of the PHY determined by the autonegotiation 8752 * process and sets the following 3 parameters, 8753 * nxgep->mac.portmode 8754 * nxgep->statsp->mac_stats.link_speed 8755 * nxgep->statsp->mac_stats.xcvr_inuse 8756 */ 8757 static nxge_status_t 8758 nxge_set_tn1010_param(p_nxge_t nxgep) 8759 { 8760 uint16_t speed; 8761 8762 if (nxge_get_tn1010_speed(nxgep, &speed) != NXGE_OK) { 8763 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 8764 "nxge_set_tn1010_param: " 8765 "Failed to get TN1010 speed")); 8766 return (NXGE_ERROR); 8767 } 8768 if (speed == TN1010_SPEED_1G) { 8769 nxgep->mac.portmode = PORT_1G_TN1010; 8770 nxgep->statsp->mac_stats.link_speed = 1000; 8771 nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 8772 } else { 8773 nxgep->mac.portmode = PORT_10G_TN1010; 8774 nxgep->statsp->mac_stats.link_speed = 10000; 8775 nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 8776 } 8777 return (NXGE_OK); 8778 } 8779 8780 #ifdef NXGE_DEBUG 8781 static void 8782 nxge_mii_dump(p_nxge_t nxgep) 8783 { 8784 p_nxge_stats_t statsp; 8785 uint8_t xcvr_portn; 8786 p_mii_regs_t mii_regs; 8787 mii_bmcr_t bmcr; 8788 mii_bmsr_t bmsr; 8789 mii_idr1_t idr1; 8790 mii_idr2_t idr2; 8791 mii_mode_control_stat_t mode; 8792 p_nxge_param_t param_arr; 8793 8794 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "==> nxge_mii_dump")); 8795 8796 statsp = nxgep->statsp; 8797 xcvr_portn = statsp->mac_stats.xcvr_portn; 8798 8799 mii_regs = NULL; 8800 8801 #if defined(__i386) 8802 (void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn, 8803 (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value); 8804 #else 8805 (void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn, 8806 (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value); 8807 #endif 8808 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 8809 "nxge_mii_dump: bmcr (0) xcvr 0x%x value 0x%x", 8810 xcvr_portn, bmcr.value)); 8811 8812 #if defined(__i386) 8813 (void) nxge_mii_read(nxgep, 8814 nxgep->statsp->mac_stats.xcvr_portn, 8815 (uint8_t)(uint32_t)(&mii_regs->bmsr), &bmsr.value); 8816 #else 8817 (void) nxge_mii_read(nxgep, 8818 nxgep->statsp->mac_stats.xcvr_portn, 8819 (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value); 8820 #endif 8821 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 8822 "nxge_mii_dump: bmsr (1) xcvr 0x%x value 0x%x", 8823 xcvr_portn, bmsr.value)); 8824 8825 #if defined(__i386) 8826 (void) nxge_mii_read(nxgep, 8827 nxgep->statsp->mac_stats.xcvr_portn, 8828 (uint8_t)(uint32_t)(&mii_regs->idr1), &idr1.value); 8829 #else 8830 (void) nxge_mii_read(nxgep, 8831 nxgep->statsp->mac_stats.xcvr_portn, 8832 (uint8_t)(uint64_t)(&mii_regs->idr1), &idr1.value); 8833 #endif 8834 8835 8836 #if defined(__i386) 8837 (void) nxge_mii_read(nxgep, 8838 nxgep->statsp->mac_stats.xcvr_portn, 8839 (uint8_t)(uint32_t)(&mii_regs->idr2), &idr2.value); 8840 #else 8841 (void) nxge_mii_read(nxgep, 8842 nxgep->statsp->mac_stats.xcvr_portn, 8843 (uint8_t)(uint64_t)(&mii_regs->idr2), &idr2.value); 8844 #endif 8845 8846 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 8847 "nxge_mii_dump: idr1 (2) xcvr 0x%x value 0x%x", 8848 xcvr_portn, idr1.value)); 8849 8850 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 8851 "nxge_mii_dump: idr2 (3) xcvr 0x%x value 0x%x", 8852 xcvr_portn, idr2.value)); 8853 8854 mode.value = 0; 8855 mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG; 8856 8857 #if defined(__i386) 8858 (void) nxge_mii_write(nxgep, xcvr_portn, 8859 (uint8_t)(uint32_t)(&mii_regs->shadow), mode.value); 8860 8861 (void) nxge_mii_read(nxgep, xcvr_portn, 8862 (uint8_t)(uint32_t)(&mii_regs->shadow), &mode.value); 8863 #else 8864 (void) nxge_mii_write(nxgep, xcvr_portn, 8865 (uint8_t)(uint64_t)(&mii_regs->shadow), mode.value); 8866 8867 (void) nxge_mii_read(nxgep, xcvr_portn, 8868 (uint8_t)(uint64_t)(&mii_regs->shadow), &mode.value); 8869 #endif 8870 8871 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 8872 "nxge_mii_dump: mode control xcvr 0x%x value 0x%x", 8873 xcvr_portn, mode.value)); 8874 } 8875 #endif 8876