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