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 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <sys/nxge/nxge_impl.h> 29 #include <sys/nxge/nxge_mac.h> 30 31 #define LINK_MONITOR_PERIOD (1000 * 1000) 32 #define LM_WAIT_MULTIPLIER 8 33 34 extern uint32_t nxge_no_link_notify; 35 extern boolean_t nxge_no_msg; 36 extern uint32_t nxge_lb_dbg; 37 extern nxge_os_mutex_t nxge_mdio_lock; 38 extern nxge_os_mutex_t nxge_mii_lock; 39 extern boolean_t nxge_jumbo_enable; 40 41 typedef enum { 42 CHECK_LINK_RESCHEDULE, 43 CHECK_LINK_STOP 44 } check_link_state_t; 45 46 static check_link_state_t nxge_check_link_stop(nxge_t *); 47 48 /* 49 * Ethernet broadcast address definition. 50 */ 51 static ether_addr_st etherbroadcastaddr = 52 {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}; 53 /* 54 * Ethernet zero address definition. 55 */ 56 static ether_addr_st etherzeroaddr = 57 {{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; 58 /* 59 * Supported chip types 60 */ 61 static uint32_t nxge_supported_cl45_ids[] = {BCM8704_DEV_ID}; 62 static uint32_t nxge_supported_cl22_ids[] = {BCM5464R_PHY_ID}; 63 64 #define NUM_CLAUSE_45_IDS (sizeof (nxge_supported_cl45_ids) / \ 65 sizeof (uint32_t)) 66 #define NUM_CLAUSE_22_IDS (sizeof (nxge_supported_cl22_ids) / \ 67 sizeof (uint32_t)) 68 /* 69 * static functions 70 */ 71 static uint32_t nxge_get_cl45_pma_pmd_id(p_nxge_t, int); 72 static uint32_t nxge_get_cl45_pcs_id(p_nxge_t, int); 73 static uint32_t nxge_get_cl22_phy_id(p_nxge_t, int); 74 static boolean_t nxge_is_supported_phy(uint32_t, uint8_t); 75 static nxge_status_t nxge_n2_serdes_init(p_nxge_t); 76 static nxge_status_t nxge_neptune_10G_serdes_init(p_nxge_t); 77 static nxge_status_t nxge_1G_serdes_init(p_nxge_t); 78 static nxge_status_t nxge_10G_link_intr_stop(p_nxge_t); 79 static nxge_status_t nxge_10G_link_intr_start(p_nxge_t); 80 static nxge_status_t nxge_1G_copper_link_intr_stop(p_nxge_t); 81 static nxge_status_t nxge_1G_copper_link_intr_start(p_nxge_t); 82 static nxge_status_t nxge_1G_fiber_link_intr_stop(p_nxge_t); 83 static nxge_status_t nxge_1G_fiber_link_intr_start(p_nxge_t); 84 static nxge_status_t nxge_check_mii_link(p_nxge_t); 85 static nxge_status_t nxge_check_10g_link(p_nxge_t); 86 static nxge_status_t nxge_10G_xcvr_init(p_nxge_t); 87 static nxge_status_t nxge_1G_xcvr_init(p_nxge_t); 88 static void nxge_bcm5464_link_led_off(p_nxge_t); 89 90 /* 91 * xcvr tables for supported transceivers 92 */ 93 94 static nxge_xcvr_table_t nxge_n2_10G_table = { 95 nxge_n2_serdes_init, 96 nxge_10G_xcvr_init, 97 nxge_10G_link_intr_stop, 98 nxge_10G_link_intr_start, 99 nxge_check_10g_link, 100 PCS_XCVR, 101 BCM8704_N2_PORT_ADDR_BASE 102 }; 103 104 static nxge_xcvr_table_t nxge_n2_1G_table = { 105 nxge_n2_serdes_init, 106 nxge_1G_xcvr_init, 107 nxge_1G_fiber_link_intr_stop, 108 nxge_1G_fiber_link_intr_start, 109 nxge_check_mii_link, 110 PCS_XCVR, 111 0 112 }; 113 114 static nxge_xcvr_table_t nxge_10G_fiber_table = { 115 nxge_neptune_10G_serdes_init, 116 nxge_10G_xcvr_init, 117 nxge_10G_link_intr_stop, 118 nxge_10G_link_intr_start, 119 nxge_check_10g_link, 120 PCS_XCVR, 121 BCM8704_NEPTUNE_PORT_ADDR_BASE 122 }; 123 124 static nxge_xcvr_table_t nxge_1G_copper_table = { 125 NULL, 126 nxge_1G_xcvr_init, 127 nxge_1G_copper_link_intr_stop, 128 nxge_1G_copper_link_intr_start, 129 nxge_check_mii_link, 130 INT_MII_XCVR, 131 BCM5464_NEPTUNE_PORT_ADDR_BASE 132 }; 133 134 static nxge_xcvr_table_t nxge_1G_fiber_table = { 135 nxge_1G_serdes_init, 136 nxge_1G_xcvr_init, 137 nxge_1G_fiber_link_intr_stop, 138 nxge_1G_fiber_link_intr_start, 139 nxge_check_mii_link, 140 PCS_XCVR, 141 0 142 }; 143 144 static nxge_xcvr_table_t nxge_10G_copper_table = { 145 nxge_neptune_10G_serdes_init, 146 NULL, 147 NULL, 148 NULL, 149 NULL, 150 PCS_XCVR, 151 0 152 }; 153 154 nxge_status_t nxge_mac_init(p_nxge_t); 155 156 #ifdef NXGE_DEBUG 157 static void nxge_mii_dump(p_nxge_t); 158 #endif 159 static nxge_status_t nxge_mii_get_link_mode(p_nxge_t); 160 161 nxge_status_t 162 nxge_get_xcvr_type(p_nxge_t nxgep) 163 { 164 nxge_status_t status = NXGE_OK; 165 char *phy_type; 166 char *prop_val; 167 168 nxgep->mac.portmode = 0; 169 170 /* Get property from the driver conf. file */ 171 if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip, 172 DDI_PROP_DONTPASS | DDI_PROP_NOTPROM, 173 "phy-type", &prop_val)) == DDI_PROP_SUCCESS) { 174 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 175 "found conf file: phy-type %s", prop_val)); 176 if (strcmp("xgsd", prop_val) == 0) { 177 nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 178 nxgep->mac.portmode = PORT_10G_SERDES; 179 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 180 "found: 10G Serdes")); 181 } else if (strcmp("gsd", prop_val) == 0) { 182 nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 183 nxgep->mac.portmode = PORT_1G_SERDES; 184 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Serdes")); 185 } else if (strcmp("mif", prop_val) == 0) { 186 nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR; 187 nxgep->mac.portmode = PORT_1G_COPPER; 188 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G Copper Xcvr")); 189 } else if (strcmp("pcs", prop_val) == 0) { 190 nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 191 nxgep->mac.portmode = PORT_1G_FIBER; 192 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G FIBER Xcvr")); 193 } 194 195 (void) ddi_prop_update_string(DDI_DEV_T_NONE, nxgep->dip, 196 "phy-type", prop_val); 197 ddi_prop_free(prop_val); 198 199 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: " 200 "Got phy type [0x%x] from conf file", 201 nxgep->mac.portmode)); 202 203 return (NXGE_OK); 204 } 205 /* 206 * TODO add MDIO support for Monza RTM card, Glendale (also Goa) - 207 * only N2-NIU 208 */ 209 if (nxgep->niu_type == N2_NIU) { 210 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip, 0, 211 "phy-type", &prop_val) == DDI_PROP_SUCCESS) { 212 if (strcmp("xgf", prop_val) == 0) { 213 nxgep->statsp->mac_stats.xcvr_inuse = 214 XPCS_XCVR; 215 nxgep->mac.portmode = PORT_10G_FIBER; 216 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 217 "10G Fiber Xcvr")); 218 } else if (strcmp("mif", prop_val) == 0) { 219 nxgep->statsp->mac_stats.xcvr_inuse = 220 INT_MII_XCVR; 221 nxgep->mac.portmode = PORT_1G_COPPER; 222 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 223 "1G Copper Xcvr")); 224 } else if (strcmp("pcs", prop_val) == 0) { 225 nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 226 nxgep->mac.portmode = PORT_1G_FIBER; 227 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 228 "1G Fiber Xcvr")); 229 } else if (strcmp("xgc", prop_val) == 0) { 230 nxgep->statsp->mac_stats.xcvr_inuse = 231 XPCS_XCVR; 232 nxgep->mac.portmode = PORT_10G_COPPER; 233 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 234 "10G Copper Xcvr")); 235 } else if (strcmp("xgsd", prop_val) == 0) { 236 nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 237 nxgep->mac.portmode = PORT_10G_SERDES; 238 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 239 "OBP: 10G Serdes")); 240 } else if (strcmp("gsd", prop_val) == 0) { 241 nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 242 nxgep->mac.portmode = PORT_1G_SERDES; 243 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 244 "OBP: 1G Serdes")); 245 } else { 246 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 247 "Unknown phy-type: %s", prop_val)); 248 ddi_prop_free(prop_val); 249 return (NXGE_ERROR); 250 } 251 status = NXGE_OK; 252 (void) ddi_prop_update_string(DDI_DEV_T_NONE, 253 nxgep->dip, "phy-type", prop_val); 254 ddi_prop_free(prop_val); 255 256 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: " 257 "Got phy type [0x%x] from OBP", 258 nxgep->mac.portmode)); 259 260 return (status); 261 } else { 262 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 263 "Exiting...phy-type property not found")); 264 return (NXGE_ERROR); 265 } 266 } 267 268 269 if (!nxgep->vpd_info.present) { 270 return (NXGE_OK); 271 } 272 273 if (!nxgep->vpd_info.ver_valid) { 274 goto read_seeprom; 275 } 276 277 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 278 "Reading phy type from expansion ROM")); 279 /* 280 * Try to read the phy type from the vpd data read off the 281 * expansion ROM. 282 */ 283 phy_type = nxgep->vpd_info.phy_type; 284 285 if (strncmp(phy_type, "mif", 3) == 0) { 286 nxgep->mac.portmode = PORT_1G_COPPER; 287 nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR; 288 } else if (strncmp(phy_type, "xgf", 3) == 0) { 289 nxgep->mac.portmode = PORT_10G_FIBER; 290 nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 291 } else if (strncmp(phy_type, "pcs", 3) == 0) { 292 nxgep->mac.portmode = PORT_1G_FIBER; 293 nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 294 } else if (strncmp(phy_type, "xgc", 3) == 0) { 295 nxgep->mac.portmode = PORT_10G_COPPER; 296 nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 297 } else if (strncmp(phy_type, "xgsd", 4) == 0) { 298 nxgep->mac.portmode = PORT_10G_SERDES; 299 nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 300 } else if (strncmp(phy_type, "gsd", 3) == 0) { 301 nxgep->mac.portmode = PORT_1G_SERDES; 302 nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 303 } else { 304 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 305 "nxge_get_xcvr_type: Unknown phy type [%c%c%c] in EEPROM", 306 phy_type[0], phy_type[1], phy_type[2])); 307 goto read_seeprom; 308 } 309 310 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_get_xcvr_type: " 311 "Got phy type [0x%x] from VPD", nxgep->mac.portmode)); 312 313 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_get_xcvr_type")); 314 return (status); 315 316 read_seeprom: 317 /* 318 * read the phy type from the SEEPROM - NCR registers 319 */ 320 status = nxge_espc_phy_type_get(nxgep); 321 if (status != NXGE_OK) { 322 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 323 "Failed to get phy type")); 324 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "EEPROM version " 325 "[%s] invalid...please update", nxgep->vpd_info.ver)); 326 } 327 328 return (status); 329 330 } 331 332 /* Set up the PHY specific values. */ 333 334 nxge_status_t 335 nxge_setup_xcvr_table(p_nxge_t nxgep) 336 { 337 nxge_status_t status = NXGE_OK; 338 uint32_t port_type; 339 uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 340 uint32_t pcs_id = 0; 341 uint32_t pma_pmd_id = 0; 342 uint32_t phy_id = 0; 343 344 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_setup_xcvr_table: port<%d>", 345 portn)); 346 347 switch (nxgep->niu_type) { 348 case N2_NIU: 349 switch (nxgep->mac.portmode) { 350 case PORT_1G_FIBER: 351 case PORT_1G_SERDES: 352 nxgep->xcvr = nxge_n2_1G_table; 353 nxgep->xcvr.xcvr_addr = portn; 354 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 1G %s Xcvr", 355 (nxgep->mac.portmode == PORT_1G_FIBER) ? "Fiber" : 356 "Serdes")); 357 break; 358 case PORT_10G_FIBER: 359 case PORT_10G_SERDES: 360 nxgep->xcvr = nxge_n2_10G_table; 361 nxgep->xcvr.xcvr_addr += portn; 362 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "NIU 10G %s Xcvr", 363 (nxgep->mac.portmode == PORT_10G_FIBER) ? "Fiber" : 364 "Serdes")); 365 break; 366 default: 367 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 368 "<== nxge_setup_xcvr_table: " 369 "Unable to determine NIU portmode")); 370 return (NXGE_ERROR); 371 } 372 break; 373 default: 374 if (nxgep->mac.portmode == 0) { 375 /* 376 * Would be the case for platforms like Maramba 377 * in which the phy type could not be got from conf 378 * file, OBP, VPD or Serial PROM. 379 */ 380 if (!NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) { 381 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 382 "<== nxge_setup_xcvr_table:" 383 " Invalid Neptune type [0x%x]", 384 nxgep->niu_type)); 385 return (NXGE_ERROR); 386 } 387 388 port_type = nxgep->niu_type >> 389 (NXGE_PORT_TYPE_SHIFT * portn); 390 port_type = port_type & (NXGE_PORT_TYPE_MASK); 391 392 switch (port_type) { 393 394 case NXGE_PORT_1G_COPPER: 395 nxgep->mac.portmode = PORT_1G_COPPER; 396 break; 397 case NXGE_PORT_10G_COPPER: 398 nxgep->mac.portmode = PORT_10G_COPPER; 399 break; 400 case NXGE_PORT_1G_FIBRE: 401 nxgep->mac.portmode = PORT_1G_FIBER; 402 break; 403 case NXGE_PORT_10G_FIBRE: 404 nxgep->mac.portmode = PORT_10G_FIBER; 405 break; 406 case NXGE_PORT_1G_SERDES: 407 nxgep->mac.portmode = PORT_1G_SERDES; 408 break; 409 case NXGE_PORT_10G_SERDES: 410 nxgep->mac.portmode = PORT_10G_SERDES; 411 break; 412 case NXGE_PORT_1G_RGMII_FIBER: 413 nxgep->mac.portmode = PORT_1G_RGMII_FIBER; 414 break; 415 default: 416 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 417 "<== nxge_setup_xcvr_table: " 418 "Unknown port-type: 0x%x", port_type)); 419 return (NXGE_ERROR); 420 } 421 } 422 423 switch (nxgep->mac.portmode) { 424 case PORT_1G_COPPER: 425 case PORT_1G_RGMII_FIBER: 426 nxgep->xcvr = nxge_1G_copper_table; 427 428 /* 429 * For Altas 4-1G copper, Xcvr port numbers are 430 * swapped with ethernet port number. This is 431 * designed for better signal integrity in 432 * routing. This is also the case for the 433 * on-board Neptune copper ports on the Maramba 434 * platform. 435 */ 436 switch (nxgep->platform_type) { 437 case P_NEPTUNE_MARAMBA_P1: 438 nxgep->xcvr.xcvr_addr = 439 BCM5464_MARAMBA_P1_PORT_ADDR_BASE; 440 break; 441 case P_NEPTUNE_MARAMBA_P0: 442 nxgep->xcvr.xcvr_addr = 443 BCM5464_MARAMBA_P0_PORT_ADDR_BASE; 444 break; 445 default: 446 break; 447 } 448 /* 449 * For Altas 4-1G copper, Xcvr port numbers are 450 * swapped with ethernet port number. This is 451 * designed for better signal integrity in 452 * routing. This is also the case for the 453 * on-board Neptune copper ports on the Maramba 454 * platform. 455 */ 456 switch (nxgep->platform_type) { 457 case P_NEPTUNE_ATLAS_4PORT: 458 case P_NEPTUNE_MARAMBA_P0: 459 case P_NEPTUNE_MARAMBA_P1: 460 switch (portn) { 461 case 0: 462 nxgep->xcvr.xcvr_addr += 3; 463 break; 464 case 1: 465 nxgep->xcvr.xcvr_addr += 2; 466 break; 467 case 2: 468 nxgep->xcvr.xcvr_addr += 1; 469 break; 470 case 3: 471 break; 472 default: 473 return (NXGE_ERROR); 474 } 475 break; 476 case P_NEPTUNE_ALONSO: 477 /* 478 * The Alonso Neptune, xcvr port numbers for 479 * ports 2 and 3 are not swapped. Port 2 has 480 * the BCM5464_PORT_BASE_ADDR and port 3 has 481 * next address. 482 */ 483 if (portn == 3) { 484 nxgep->xcvr.xcvr_addr += 1; 485 } 486 break; 487 default: 488 break; 489 } 490 491 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G %s Xcvr", 492 (nxgep->mac.portmode == PORT_1G_COPPER) ? 493 "Copper" : "RGMII Fiber")); 494 break; 495 case PORT_10G_COPPER: 496 nxgep->xcvr = nxge_10G_copper_table; 497 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G Copper Xcvr")); 498 break; 499 case PORT_1G_FIBER: 500 case PORT_1G_SERDES: 501 nxgep->xcvr = nxge_1G_fiber_table; 502 nxgep->xcvr.xcvr_addr = portn; 503 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "1G %s Xcvr", 504 (nxgep->mac.portmode == PORT_1G_FIBER) ? 505 "Fiber" : "Serdes")); 506 break; 507 case PORT_10G_FIBER: 508 case PORT_10G_SERDES: 509 nxgep->xcvr = nxge_10G_fiber_table; 510 switch (nxgep->platform_type) { 511 case P_NEPTUNE_MARAMBA_P0: 512 case P_NEPTUNE_MARAMBA_P1: 513 nxgep->xcvr.xcvr_addr = 514 BCM8704_MARAMBA_PORT_ADDR_BASE; 515 /* 516 * Switch off LED for corresponding copper 517 * port 518 */ 519 nxge_bcm5464_link_led_off(nxgep); 520 break; 521 default: 522 break; 523 } 524 nxgep->xcvr.xcvr_addr += portn; 525 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "10G %s Xcvr", 526 (nxgep->mac.portmode == PORT_10G_FIBER) ? 527 "Fiber" : "Serdes")); 528 break; 529 default: 530 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 531 "Unknown port-type: 0x%x", port_type)); 532 return (NXGE_ERROR); 533 } 534 } 535 536 nxgep->statsp->mac_stats.xcvr_inuse = nxgep->xcvr.xcvr_inuse; 537 nxgep->statsp->mac_stats.xcvr_portn = nxgep->xcvr.xcvr_addr; 538 539 /* 540 * Get the actual device ID value returned by MDIO read. 541 */ 542 nxgep->statsp->mac_stats.xcvr_id = 0; 543 544 pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, nxgep->xcvr.xcvr_addr); 545 if (nxge_is_supported_phy(pma_pmd_id, CLAUSE_45_TYPE)) { 546 nxgep->statsp->mac_stats.xcvr_id = pma_pmd_id; 547 } else { 548 pcs_id = nxge_get_cl45_pcs_id(nxgep, nxgep->xcvr.xcvr_addr); 549 if (nxge_is_supported_phy(pcs_id, CLAUSE_45_TYPE)) { 550 nxgep->statsp->mac_stats.xcvr_id = pcs_id; 551 } else { 552 phy_id = nxge_get_cl22_phy_id(nxgep, 553 nxgep->xcvr.xcvr_addr); 554 if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) { 555 nxgep->statsp->mac_stats.xcvr_id = phy_id; 556 } 557 } 558 } 559 560 nxgep->mac.linkchkmode = LINKCHK_TIMER; 561 562 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_setup_xcvr_table: niu_type" 563 "[0x%x] platform type[0x%x]", nxgep->niu_type, 564 nxgep->platform_type)); 565 566 return (status); 567 } 568 569 /* Initialize the entire MAC and physical layer */ 570 571 nxge_status_t 572 nxge_mac_init(p_nxge_t nxgep) 573 { 574 uint8_t portn; 575 nxge_status_t status = NXGE_OK; 576 577 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 578 579 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_init: port<%d>", portn)); 580 581 nxgep->mac.portnum = portn; 582 nxgep->mac.porttype = PORT_TYPE_XMAC; 583 584 if ((portn == BMAC_PORT_0) || (portn == BMAC_PORT_1)) 585 nxgep->mac.porttype = PORT_TYPE_BMAC; 586 587 /* Initialize XIF to configure a network mode */ 588 if ((status = nxge_xif_init(nxgep)) != NXGE_OK) { 589 goto fail; 590 } 591 592 if ((status = nxge_pcs_init(nxgep)) != NXGE_OK) { 593 goto fail; 594 } 595 596 /* Initialize TX and RX MACs */ 597 /* 598 * Always perform XIF init first, before TX and RX MAC init 599 */ 600 if ((status = nxge_tx_mac_reset(nxgep)) != NXGE_OK) 601 goto fail; 602 603 if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK) 604 goto fail; 605 606 if ((status = nxge_rx_mac_reset(nxgep)) != NXGE_OK) 607 goto fail; 608 609 if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK) 610 goto fail; 611 612 if ((status = nxge_tx_mac_enable(nxgep)) != NXGE_OK) 613 goto fail; 614 615 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 616 goto fail; 617 618 nxgep->statsp->mac_stats.mac_mtu = nxgep->mac.maxframesize; 619 620 /* The Neptune Serdes needs to be reinitialized again */ 621 if ((NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) && 622 ((nxgep->mac.portmode == PORT_1G_SERDES) || 623 (nxgep->mac.portmode == PORT_1G_FIBER)) && 624 ((portn == 0) || (portn == 1))) { 625 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 626 "nxge_mac_init: reinit Neptune 1G Serdes ")); 627 if ((status = nxge_1G_serdes_init(nxgep)) != NXGE_OK) { 628 goto fail; 629 } 630 } 631 632 633 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_init: port<%d>", portn)); 634 635 return (NXGE_OK); 636 fail: 637 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 638 "nxge_mac_init: failed to initialize MAC port<%d>", 639 portn)); 640 return (status); 641 } 642 643 /* Initialize the Ethernet Link */ 644 645 nxge_status_t 646 nxge_link_init(p_nxge_t nxgep) 647 { 648 nxge_status_t status = NXGE_OK; 649 nxge_port_mode_t portmode; 650 #ifdef NXGE_DEBUG 651 uint8_t portn; 652 653 portn = nxgep->mac.portnum; 654 655 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_init: port<%d>", portn)); 656 #endif 657 658 portmode = nxgep->mac.portmode; 659 if (nxgep->niu_type == N2_NIU && (portmode != PORT_10G_SERDES) && 660 (portmode != PORT_1G_SERDES)) { 661 /* Workaround to get link up in both NIU ports */ 662 if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK) { 663 goto fail; 664 } 665 } 666 NXGE_DELAY(200000); 667 /* Initialize internal serdes */ 668 if ((status = nxge_serdes_init(nxgep)) != NXGE_OK) 669 goto fail; 670 NXGE_DELAY(200000); 671 if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK) 672 goto fail; 673 674 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_init: port<%d>", portn)); 675 676 return (NXGE_OK); 677 678 fail: 679 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 680 "nxge_link_init: ", 681 "failed to initialize Ethernet link on port<%d>", 682 portn)); 683 684 return (status); 685 } 686 687 688 /* Initialize the XIF sub-block within the MAC */ 689 690 nxge_status_t 691 nxge_xif_init(p_nxge_t nxgep) 692 { 693 uint32_t xif_cfg = 0; 694 npi_attr_t ap; 695 uint8_t portn; 696 nxge_port_t portt; 697 nxge_port_mode_t portmode; 698 p_nxge_stats_t statsp; 699 npi_status_t rs = NPI_SUCCESS; 700 npi_handle_t handle; 701 702 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 703 704 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xif_init: port<%d>", portn)); 705 706 handle = nxgep->npi_handle; 707 portmode = nxgep->mac.portmode; 708 portt = nxgep->mac.porttype; 709 statsp = nxgep->statsp; 710 711 if ((NXGE_IS_VALID_NEPTUNE_TYPE(nxgep)) && 712 ((nxgep->mac.portmode == PORT_1G_SERDES) || 713 (nxgep->mac.portmode == PORT_1G_FIBER)) && 714 ((portn == 0) || (portn == 1))) { 715 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 716 "nxge_xcvr_init: set ATCA mode")); 717 npi_mac_mif_set_atca_mode(nxgep->npi_handle, B_TRUE); 718 } 719 720 if (portt == PORT_TYPE_XMAC) { 721 722 /* Setup XIF Configuration for XMAC */ 723 724 if ((portmode == PORT_10G_FIBER) || 725 (portmode == PORT_10G_COPPER) || 726 (portmode == PORT_10G_SERDES)) 727 xif_cfg |= CFG_XMAC_XIF_LFS; 728 729 if (portmode == PORT_1G_COPPER) { 730 xif_cfg |= CFG_XMAC_XIF_1G_PCS_BYPASS; 731 } 732 733 /* Set MAC Internal Loopback if necessary */ 734 if (statsp->port_stats.lb_mode == nxge_lb_mac1000) 735 xif_cfg |= CFG_XMAC_XIF_LOOPBACK; 736 737 if (statsp->mac_stats.link_speed == 100) 738 xif_cfg |= CFG_XMAC_XIF_SEL_CLK_25MHZ; 739 740 xif_cfg |= CFG_XMAC_XIF_TX_OUTPUT; 741 742 if ((portmode == PORT_10G_FIBER) || 743 (portmode == PORT_10G_SERDES)) { 744 if (statsp->mac_stats.link_up) { 745 xif_cfg |= CFG_XMAC_XIF_LED_POLARITY; 746 } else { 747 xif_cfg |= CFG_XMAC_XIF_LED_FORCE; 748 } 749 } 750 751 rs = npi_xmac_xif_config(handle, INIT, portn, xif_cfg); 752 if (rs != NPI_SUCCESS) 753 goto fail; 754 755 nxgep->mac.xif_config = xif_cfg; 756 757 /* Set Port Mode */ 758 if ((portmode == PORT_10G_FIBER) || 759 (portmode == PORT_10G_COPPER) || 760 (portmode == PORT_10G_SERDES)) { 761 SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE, 762 MAC_XGMII_MODE, rs); 763 if (rs != NPI_SUCCESS) 764 goto fail; 765 if (statsp->mac_stats.link_up) { 766 if (nxge_10g_link_led_on(nxgep) != NXGE_OK) 767 goto fail; 768 } else { 769 if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 770 goto fail; 771 } 772 } else if ((portmode == PORT_1G_FIBER) || 773 (portmode == PORT_1G_COPPER) || 774 (portmode == PORT_1G_SERDES) || 775 (portmode == PORT_1G_RGMII_FIBER)) { 776 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 777 "nxge_xif_init: Port[%d] Mode[%d] Speed[%d]", 778 portn, portmode, statsp->mac_stats.link_speed)); 779 if (statsp->mac_stats.link_speed == 1000) { 780 SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE, 781 MAC_GMII_MODE, rs); 782 } else { 783 SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE, 784 MAC_MII_MODE, rs); 785 } 786 if (rs != NPI_SUCCESS) 787 goto fail; 788 } else { 789 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 790 "nxge_xif_init: Unknown port mode (%d)" 791 " for port<%d>", portmode, portn)); 792 goto fail; 793 } 794 795 /* Enable ATCA mode */ 796 797 } else if (portt == PORT_TYPE_BMAC) { 798 799 /* Setup XIF Configuration for BMAC */ 800 801 if ((portmode == PORT_1G_COPPER) || 802 (portmode == PORT_1G_RGMII_FIBER)) { 803 if (statsp->mac_stats.link_speed == 100) 804 xif_cfg |= CFG_BMAC_XIF_SEL_CLK_25MHZ; 805 } 806 807 if (statsp->port_stats.lb_mode == nxge_lb_mac1000) 808 xif_cfg |= CFG_BMAC_XIF_LOOPBACK; 809 810 if (statsp->mac_stats.link_speed == 1000) 811 xif_cfg |= CFG_BMAC_XIF_GMII_MODE; 812 813 xif_cfg |= CFG_BMAC_XIF_TX_OUTPUT; 814 815 rs = npi_bmac_xif_config(handle, INIT, portn, xif_cfg); 816 if (rs != NPI_SUCCESS) 817 goto fail; 818 nxgep->mac.xif_config = xif_cfg; 819 } 820 821 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xif_init: port<%d>", portn)); 822 return (NXGE_OK); 823 fail: 824 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 825 "nxge_xif_init: Failed to initialize XIF port<%d>", 826 portn)); 827 return (NXGE_ERROR | rs); 828 } 829 830 /* Initialize the PCS sub-block in the MAC */ 831 832 nxge_status_t 833 nxge_pcs_init(p_nxge_t nxgep) 834 { 835 pcs_cfg_t pcs_cfg; 836 uint32_t val; 837 uint8_t portn; 838 nxge_port_mode_t portmode; 839 npi_handle_t handle; 840 p_nxge_stats_t statsp; 841 npi_status_t rs = NPI_SUCCESS; 842 843 handle = nxgep->npi_handle; 844 portmode = nxgep->mac.portmode; 845 portn = nxgep->mac.portnum; 846 statsp = nxgep->statsp; 847 848 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_init: port<%d>", portn)); 849 850 if ((portmode == PORT_1G_FIBER) || (portmode == PORT_1G_SERDES)) { 851 if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS) { 852 goto fail; 853 } 854 855 /* Initialize port's PCS */ 856 pcs_cfg.value = 0; 857 pcs_cfg.bits.w0.enable = 1; 858 pcs_cfg.bits.w0.mask = 1; 859 PCS_REG_WR(handle, portn, PCS_CONFIG_REG, pcs_cfg.value); 860 PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG, 0); 861 862 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 863 "==> nxge_pcs_init: (1G) port<%d> write config 0x%llx", 864 portn, pcs_cfg.value)); 865 } else if ((portmode == PORT_10G_FIBER) || 866 (portmode == PORT_10G_COPPER) || (portmode == PORT_10G_SERDES)) { 867 /* Use internal XPCS, bypass 1G PCS */ 868 XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val); 869 val &= ~XMAC_XIF_XPCS_BYPASS; 870 XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val); 871 872 if ((rs = npi_xmac_xpcs_reset(handle, portn)) != NPI_SUCCESS) 873 goto fail; 874 875 /* Set XPCS Internal Loopback if necessary */ 876 if ((rs = npi_xmac_xpcs_read(handle, portn, 877 XPCS_REG_CONTROL1, &val)) 878 != NPI_SUCCESS) 879 goto fail; 880 if ((statsp->port_stats.lb_mode == nxge_lb_mac10g) || 881 (statsp->port_stats.lb_mode == nxge_lb_mac1000)) 882 val |= XPCS_CTRL1_LOOPBK; 883 else 884 val &= ~XPCS_CTRL1_LOOPBK; 885 if ((rs = npi_xmac_xpcs_write(handle, portn, 886 XPCS_REG_CONTROL1, val)) 887 != NPI_SUCCESS) 888 goto fail; 889 890 /* Clear descw errors */ 891 if ((rs = npi_xmac_xpcs_write(handle, portn, 892 XPCS_REG_DESCWERR_COUNTER, 0)) 893 != NPI_SUCCESS) 894 goto fail; 895 /* Clear symbol errors */ 896 if ((rs = npi_xmac_xpcs_read(handle, portn, 897 XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val)) 898 != NPI_SUCCESS) 899 goto fail; 900 if ((rs = npi_xmac_xpcs_read(handle, portn, 901 XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val)) 902 != NPI_SUCCESS) 903 goto fail; 904 905 } else if ((portmode == PORT_1G_COPPER) || 906 (portmode == PORT_1G_RGMII_FIBER)) { 907 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 908 "==> nxge_pcs_init: (1G) copper port<%d>", portn)); 909 if (portn < 4) { 910 PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG, 911 PCS_DATAPATH_MODE_MII); 912 } 913 if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS) 914 goto fail; 915 916 } else { 917 goto fail; 918 } 919 pass: 920 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_init: port<%d>", portn)); 921 return (NXGE_OK); 922 fail: 923 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 924 "nxge_pcs_init: Failed to initialize PCS port<%d>", 925 portn)); 926 return (NXGE_ERROR | rs); 927 } 928 929 /* Initialize the Internal Serdes */ 930 931 nxge_status_t 932 nxge_serdes_init(p_nxge_t nxgep) 933 { 934 p_nxge_stats_t statsp; 935 #ifdef NXGE_DEBUG 936 uint8_t portn; 937 #endif 938 nxge_status_t status = NXGE_OK; 939 940 #ifdef NXGE_DEBUG 941 portn = nxgep->mac.portnum; 942 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 943 "==> nxge_serdes_init port<%d>", portn)); 944 #endif 945 946 if (nxgep->xcvr.serdes_init) { 947 statsp = nxgep->statsp; 948 status = nxgep->xcvr.serdes_init(nxgep); 949 if (status != NXGE_OK) 950 goto fail; 951 statsp->mac_stats.serdes_inits++; 952 } 953 954 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_serdes_init port<%d>", 955 portn)); 956 957 return (NXGE_OK); 958 959 fail: 960 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 961 "nxge_serdes_init: Failed to initialize serdes for port<%d>", 962 portn)); 963 964 return (status); 965 } 966 967 /* Initialize the TI Hedwig Internal Serdes (N2-NIU only) */ 968 969 static nxge_status_t 970 nxge_n2_serdes_init(p_nxge_t nxgep) 971 { 972 uint8_t portn; 973 int chan; 974 esr_ti_cfgpll_l_t pll_cfg_l; 975 esr_ti_cfgpll_l_t pll_sts_l; 976 esr_ti_cfgrx_l_t rx_cfg_l; 977 esr_ti_cfgrx_h_t rx_cfg_h; 978 esr_ti_cfgtx_l_t tx_cfg_l; 979 esr_ti_cfgtx_h_t tx_cfg_h; 980 #ifdef NXGE_DEBUG 981 esr_ti_testcfg_t cfg; 982 #endif 983 esr_ti_testcfg_t test_cfg; 984 nxge_status_t status = NXGE_OK; 985 986 portn = nxgep->mac.portnum; 987 988 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_n2_serdes_init port<%d>", 989 portn)); 990 991 tx_cfg_l.value = 0; 992 tx_cfg_h.value = 0; 993 rx_cfg_l.value = 0; 994 rx_cfg_h.value = 0; 995 pll_cfg_l.value = 0; 996 pll_sts_l.value = 0; 997 test_cfg.value = 0; 998 999 if ((nxgep->mac.portmode == PORT_10G_FIBER) || 1000 (nxgep->mac.portmode == PORT_10G_SERDES)) { 1001 /* 0x0E01 */ 1002 tx_cfg_l.bits.entx = 1; 1003 tx_cfg_l.bits.swing = CFGTX_SWING_1375MV; 1004 1005 /* 0x9101 */ 1006 rx_cfg_l.bits.enrx = 1; 1007 rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT; 1008 rx_cfg_l.bits.align = CFGRX_ALIGN_EN; 1009 rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES; 1010 1011 /* 0x0008 */ 1012 rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF; 1013 1014 /* Set loopback mode if necessary */ 1015 if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) { 1016 tx_cfg_l.bits.entest = 1; 1017 rx_cfg_l.bits.entest = 1; 1018 test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK; 1019 if ((status = nxge_mdio_write(nxgep, portn, 1020 ESR_N2_DEV_ADDR, 1021 ESR_N2_TEST_CFG_REG, test_cfg.value)) 1022 != NXGE_OK) 1023 goto fail; 1024 } 1025 1026 /* Use default PLL value */ 1027 1028 } else if ((nxgep->mac.portmode == PORT_1G_FIBER) || 1029 (nxgep->mac.portmode == PORT_1G_SERDES)) { 1030 1031 /* 0x0E21 */ 1032 tx_cfg_l.bits.entx = 1; 1033 tx_cfg_l.bits.rate = CFGTX_RATE_HALF; 1034 tx_cfg_l.bits.swing = CFGTX_SWING_1375MV; 1035 1036 /* 0x9121 */ 1037 rx_cfg_l.bits.enrx = 1; 1038 rx_cfg_l.bits.rate = CFGRX_RATE_HALF; 1039 rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT; 1040 rx_cfg_l.bits.align = CFGRX_ALIGN_EN; 1041 rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES; 1042 1043 if (portn == 0) { 1044 /* 0x8 */ 1045 rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF; 1046 } 1047 1048 /* MPY = 0x100 */ 1049 pll_cfg_l.bits.mpy = CFGPLL_MPY_8X; 1050 1051 /* Set PLL */ 1052 pll_cfg_l.bits.enpll = 1; 1053 pll_sts_l.bits.enpll = 1; 1054 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 1055 ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value)) 1056 != NXGE_OK) 1057 goto fail; 1058 1059 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 1060 ESR_N2_PLL_STS_L_REG, pll_sts_l.value)) != NXGE_OK) 1061 goto fail; 1062 1063 #ifdef NXGE_DEBUG 1064 nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR, 1065 ESR_N2_PLL_CFG_L_REG, &cfg.value); 1066 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1067 "==> nxge_n2_serdes_init port<%d>: PLL cfg.l 0x%x (0x%x)", 1068 portn, pll_cfg_l.value, cfg.value)); 1069 1070 nxge_mdio_read(nxgep, portn, ESR_N2_DEV_ADDR, 1071 ESR_N2_PLL_STS_L_REG, &cfg.value); 1072 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1073 "==> nxge_n2_serdes_init port<%d>: PLL sts.l 0x%x (0x%x)", 1074 portn, pll_sts_l.value, cfg.value)); 1075 #endif 1076 1077 /* Set loopback mode if necessary */ 1078 if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) { 1079 tx_cfg_l.bits.entest = 1; 1080 rx_cfg_l.bits.entest = 1; 1081 test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK; 1082 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1083 "==> nxge_n2_serdes_init port<%d>: loopback 0x%x", 1084 portn, test_cfg.value)); 1085 if ((status = nxge_mdio_write(nxgep, portn, 1086 ESR_N2_DEV_ADDR, 1087 ESR_N2_TEST_CFG_REG, test_cfg.value)) != NXGE_OK) { 1088 goto fail; 1089 } 1090 } 1091 } else { 1092 goto fail; 1093 } 1094 1095 /* MIF_REG_WR(handle, MIF_MASK_REG, ~mask); */ 1096 1097 NXGE_DELAY(20); 1098 1099 /* init TX channels */ 1100 for (chan = 0; chan < 4; chan++) { 1101 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 1102 ESR_N2_TX_CFG_L_REG_ADDR(chan), tx_cfg_l.value)) 1103 != NXGE_OK) 1104 goto fail; 1105 1106 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 1107 ESR_N2_TX_CFG_H_REG_ADDR(chan), tx_cfg_h.value)) 1108 != NXGE_OK) 1109 goto fail; 1110 1111 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1112 "==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_l 0x%x", 1113 portn, chan, tx_cfg_l.value)); 1114 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1115 "==> nxge_n2_serdes_init port<%d>: chan %d tx_cfg_h 0x%x", 1116 portn, chan, tx_cfg_h.value)); 1117 } 1118 1119 /* init RX channels */ 1120 for (chan = 0; chan < 4; chan++) { 1121 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 1122 ESR_N2_RX_CFG_L_REG_ADDR(chan), rx_cfg_l.value)) 1123 != NXGE_OK) 1124 goto fail; 1125 1126 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 1127 ESR_N2_RX_CFG_H_REG_ADDR(chan), rx_cfg_h.value)) 1128 != NXGE_OK) 1129 goto fail; 1130 1131 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1132 "==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_l 0x%x", 1133 portn, chan, rx_cfg_l.value)); 1134 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1135 "==> nxge_n2_serdes_init port<%d>: chan %d rx_cfg_h 0x%x", 1136 portn, chan, rx_cfg_h.value)); 1137 } 1138 1139 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_n2_serdes_init port<%d>", 1140 portn)); 1141 1142 return (NXGE_OK); 1143 fail: 1144 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1145 "nxge_n2_serdes_init: Failed to initialize N2 serdes for port<%d>", 1146 portn)); 1147 1148 return (status); 1149 } 1150 1151 /* Initialize the Neptune Internal Serdes for 10G (Neptune only) */ 1152 1153 static nxge_status_t 1154 nxge_neptune_10G_serdes_init(p_nxge_t nxgep) 1155 { 1156 npi_handle_t handle; 1157 uint8_t portn; 1158 int chan; 1159 sr_rx_tx_ctrl_l_t rx_tx_ctrl_l; 1160 sr_rx_tx_ctrl_h_t rx_tx_ctrl_h; 1161 sr_glue_ctrl0_l_t glue_ctrl0_l; 1162 sr_glue_ctrl0_h_t glue_ctrl0_h; 1163 uint64_t val; 1164 uint16_t val16l; 1165 uint16_t val16h; 1166 nxge_status_t status = NXGE_OK; 1167 1168 portn = nxgep->mac.portnum; 1169 1170 if ((portn != 0) && (portn != 1)) 1171 return (NXGE_OK); 1172 1173 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1174 "==> nxge_neptune_10G_serdes_init port<%d>", portn)); 1175 1176 handle = nxgep->npi_handle; 1177 switch (portn) { 1178 case 0: 1179 ESR_REG_WR(handle, ESR_0_CONTROL_REG, 1180 ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 | 1181 ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 | 1182 (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) | 1183 (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) | 1184 (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) | 1185 (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 1186 (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 1187 (0x1 << ESR_CTL_LOSADJ_0_SHIFT) | 1188 (0x1 << ESR_CTL_LOSADJ_1_SHIFT) | 1189 (0x1 << ESR_CTL_LOSADJ_2_SHIFT) | 1190 (0x1 << ESR_CTL_LOSADJ_3_SHIFT)); 1191 1192 /* Set Serdes0 Internal Loopback if necessary */ 1193 if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) { 1194 ESR_REG_WR(handle, 1195 ESR_0_TEST_CONFIG_REG, 1196 ESR_PAD_LOOPBACK_CH3 | 1197 ESR_PAD_LOOPBACK_CH2 | 1198 ESR_PAD_LOOPBACK_CH1 | 1199 ESR_PAD_LOOPBACK_CH0); 1200 } else { 1201 ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0); 1202 } 1203 break; 1204 case 1: 1205 ESR_REG_WR(handle, ESR_1_CONTROL_REG, 1206 ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 | 1207 ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 | 1208 (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) | 1209 (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) | 1210 (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) | 1211 (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 1212 (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 1213 (0x1 << ESR_CTL_LOSADJ_0_SHIFT) | 1214 (0x1 << ESR_CTL_LOSADJ_1_SHIFT) | 1215 (0x1 << ESR_CTL_LOSADJ_2_SHIFT) | 1216 (0x1 << ESR_CTL_LOSADJ_3_SHIFT)); 1217 1218 /* Set Serdes1 Internal Loopback if necessary */ 1219 if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) { 1220 ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 1221 ESR_PAD_LOOPBACK_CH3 | ESR_PAD_LOOPBACK_CH2 | 1222 ESR_PAD_LOOPBACK_CH1 | ESR_PAD_LOOPBACK_CH0); 1223 } else { 1224 ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0); 1225 } 1226 break; 1227 default: 1228 /* Nothing to do here */ 1229 goto done; 1230 } 1231 1232 /* init TX RX channels */ 1233 for (chan = 0; chan < 4; chan++) { 1234 if ((status = nxge_mdio_read(nxgep, portn, 1235 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 1236 &rx_tx_ctrl_l.value)) != NXGE_OK) 1237 goto fail; 1238 if ((status = nxge_mdio_read(nxgep, portn, 1239 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 1240 &rx_tx_ctrl_h.value)) != NXGE_OK) 1241 goto fail; 1242 if ((status = nxge_mdio_read(nxgep, portn, 1243 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 1244 &glue_ctrl0_l.value)) != NXGE_OK) 1245 goto fail; 1246 if ((status = nxge_mdio_read(nxgep, portn, 1247 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 1248 &glue_ctrl0_h.value)) != NXGE_OK) 1249 goto fail; 1250 rx_tx_ctrl_l.bits.enstretch = 1; 1251 rx_tx_ctrl_h.bits.vmuxlo = 2; 1252 rx_tx_ctrl_h.bits.vpulselo = 2; 1253 glue_ctrl0_l.bits.rxlosenable = 1; 1254 glue_ctrl0_l.bits.samplerate = 0xF; 1255 glue_ctrl0_l.bits.thresholdcount = 0xFF; 1256 glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES; 1257 if ((status = nxge_mdio_write(nxgep, portn, 1258 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 1259 rx_tx_ctrl_l.value)) != NXGE_OK) 1260 goto fail; 1261 if ((status = nxge_mdio_write(nxgep, portn, 1262 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 1263 rx_tx_ctrl_h.value)) != NXGE_OK) 1264 goto fail; 1265 if ((status = nxge_mdio_write(nxgep, portn, 1266 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 1267 glue_ctrl0_l.value)) != NXGE_OK) 1268 goto fail; 1269 if ((status = nxge_mdio_write(nxgep, portn, 1270 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 1271 glue_ctrl0_h.value)) != NXGE_OK) 1272 goto fail; 1273 } 1274 1275 /* Apply Tx core reset */ 1276 if ((status = nxge_mdio_write(nxgep, portn, 1277 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), 1278 (uint16_t)0)) != NXGE_OK) 1279 goto fail; 1280 1281 if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 1282 ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) != 1283 NXGE_OK) 1284 goto fail; 1285 1286 NXGE_DELAY(200); 1287 1288 /* Apply Rx core reset */ 1289 if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 1290 ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) != 1291 NXGE_OK) 1292 goto fail; 1293 1294 NXGE_DELAY(200); 1295 if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 1296 ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK) 1297 goto fail; 1298 1299 NXGE_DELAY(200); 1300 if ((status = nxge_mdio_read(nxgep, portn, 1301 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), 1302 &val16l)) != NXGE_OK) 1303 goto fail; 1304 if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 1305 ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK) 1306 goto fail; 1307 if ((val16l != 0) || (val16h != 0)) { 1308 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1309 "Failed to reset port<%d> XAUI Serdes " 1310 "(val16l 0x%x val16h 0x%x)", 1311 portn, val16l, val16h)); 1312 } 1313 1314 ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val); 1315 1316 if (portn == 0) { 1317 if ((val & ESR_SIG_P0_BITS_MASK) != 1318 (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0 | 1319 ESR_SIG_XSERDES_RDY_P0 | 1320 ESR_SIG_XDETECT_P0_CH3 | 1321 ESR_SIG_XDETECT_P0_CH2 | 1322 ESR_SIG_XDETECT_P0_CH1 | 1323 ESR_SIG_XDETECT_P0_CH0)) { 1324 goto fail; 1325 } 1326 } else if (portn == 1) { 1327 if ((val & ESR_SIG_P1_BITS_MASK) != 1328 (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1 | 1329 ESR_SIG_XSERDES_RDY_P1 | 1330 ESR_SIG_XDETECT_P1_CH3 | 1331 ESR_SIG_XDETECT_P1_CH2 | 1332 ESR_SIG_XDETECT_P1_CH1 | 1333 ESR_SIG_XDETECT_P1_CH0)) { 1334 goto fail; 1335 } 1336 } 1337 1338 done: 1339 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1340 "<== nxge_neptune_10G_serdes_init port<%d>", portn)); 1341 1342 return (NXGE_OK); 1343 fail: 1344 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1345 "nxge_neptune_10G_serdes_init: " 1346 "Failed to initialize Neptune serdes for port<%d>", portn)); 1347 1348 return (status); 1349 } 1350 1351 /* Initialize Neptune Internal Serdes for 1G (Neptune only) */ 1352 1353 static nxge_status_t 1354 nxge_1G_serdes_init(p_nxge_t nxgep) 1355 { 1356 npi_handle_t handle; 1357 uint8_t portn; 1358 int chan; 1359 sr_rx_tx_ctrl_l_t rx_tx_ctrl_l; 1360 sr_rx_tx_ctrl_h_t rx_tx_ctrl_h; 1361 sr_glue_ctrl0_l_t glue_ctrl0_l; 1362 sr_glue_ctrl0_h_t glue_ctrl0_h; 1363 uint64_t val; 1364 uint16_t val16l; 1365 uint16_t val16h; 1366 nxge_status_t status = NXGE_OK; 1367 1368 portn = nxgep->mac.portnum; 1369 1370 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1371 "==> nxge_1G_serdes_init port<%d>", portn)); 1372 1373 handle = nxgep->npi_handle; 1374 1375 switch (portn) { 1376 case 0: 1377 /* Assert the reset register */ 1378 ESR_REG_RD(handle, ESR_RESET_REG, &val); 1379 val |= ESR_RESET_0; 1380 ESR_REG_WR(handle, ESR_RESET_REG, val); 1381 1382 /* Set the PLL register to 0x79 */ 1383 ESR_REG_WR(handle, ESR_0_PLL_CONFIG_REG, 1384 ESR_PLL_CFG_1G_SERDES); 1385 1386 /* Set the control register to 0x249249f */ 1387 ESR_REG_WR(handle, ESR_0_CONTROL_REG, ESR_CTL_1G_SERDES); 1388 1389 /* Set Serdes0 Internal Loopback if necessary */ 1390 if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) { 1391 /* Set pad loopback modes 0xaa */ 1392 ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 1393 ESR_TSTCFG_LBTEST_PAD); 1394 } else { 1395 ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0); 1396 } 1397 1398 /* Deassert the reset register */ 1399 ESR_REG_RD(handle, ESR_RESET_REG, &val); 1400 val &= ~ESR_RESET_0; 1401 ESR_REG_WR(handle, ESR_RESET_REG, val); 1402 break; 1403 1404 case 1: 1405 /* Assert the reset register */ 1406 ESR_REG_RD(handle, ESR_RESET_REG, &val); 1407 val |= ESR_RESET_1; 1408 ESR_REG_WR(handle, ESR_RESET_REG, val); 1409 1410 /* Set PLL register to 0x79 */ 1411 ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG, 1412 ESR_PLL_CFG_1G_SERDES); 1413 1414 /* Set the control register to 0x249249f */ 1415 ESR_REG_WR(handle, ESR_1_CONTROL_REG, ESR_CTL_1G_SERDES); 1416 1417 /* Set Serdes1 Internal Loopback if necessary */ 1418 if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) { 1419 /* Set pad loopback mode 0xaa */ 1420 ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 1421 ESR_TSTCFG_LBTEST_PAD); 1422 } else { 1423 ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0); 1424 } 1425 1426 /* Deassert the reset register */ 1427 ESR_REG_RD(handle, ESR_RESET_REG, &val); 1428 val &= ~ESR_RESET_1; 1429 ESR_REG_WR(handle, ESR_RESET_REG, val); 1430 break; 1431 1432 default: 1433 /* Nothing to do here */ 1434 goto done; 1435 } 1436 1437 /* init TX RX channels */ 1438 for (chan = 0; chan < 4; chan++) { 1439 if ((status = nxge_mdio_read(nxgep, portn, 1440 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 1441 &rx_tx_ctrl_l.value)) != NXGE_OK) { 1442 goto fail; 1443 } 1444 if ((status = nxge_mdio_read(nxgep, portn, 1445 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 1446 &rx_tx_ctrl_h.value)) != NXGE_OK) { 1447 goto fail; 1448 } 1449 if ((status = nxge_mdio_read(nxgep, portn, 1450 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 1451 &glue_ctrl0_l.value)) != NXGE_OK) { 1452 goto fail; 1453 } 1454 if ((status = nxge_mdio_read(nxgep, portn, 1455 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 1456 &glue_ctrl0_h.value)) != NXGE_OK) { 1457 goto fail; 1458 } 1459 1460 rx_tx_ctrl_l.bits.enstretch = 1; 1461 rx_tx_ctrl_h.bits.vmuxlo = 2; 1462 rx_tx_ctrl_h.bits.vpulselo = 2; 1463 glue_ctrl0_l.bits.rxlosenable = 1; 1464 glue_ctrl0_l.bits.samplerate = 0xF; 1465 glue_ctrl0_l.bits.thresholdcount = 0xFF; 1466 glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES; 1467 if ((status = nxge_mdio_write(nxgep, portn, 1468 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 1469 rx_tx_ctrl_l.value)) != NXGE_OK) { 1470 goto fail; 1471 } 1472 if ((status = nxge_mdio_write(nxgep, portn, 1473 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 1474 rx_tx_ctrl_h.value)) != NXGE_OK) { 1475 goto fail; 1476 } 1477 if ((status = nxge_mdio_write(nxgep, portn, 1478 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 1479 glue_ctrl0_l.value)) != NXGE_OK) { 1480 goto fail; 1481 } 1482 if ((status = nxge_mdio_write(nxgep, portn, 1483 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 1484 glue_ctrl0_h.value)) != NXGE_OK) { 1485 goto fail; 1486 } 1487 } 1488 1489 if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 1490 ESR_NEP_RX_POWER_CONTROL_L_ADDR(), 0xfff)) != NXGE_OK) { 1491 goto fail; 1492 } 1493 if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 1494 ESR_NEP_RX_POWER_CONTROL_H_ADDR(), 0xfff)) != NXGE_OK) { 1495 goto fail; 1496 } 1497 if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 1498 ESR_NEP_TX_POWER_CONTROL_L_ADDR(), 0x70)) != NXGE_OK) { 1499 goto fail; 1500 } 1501 if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 1502 ESR_NEP_TX_POWER_CONTROL_H_ADDR(), 0xfff)) != NXGE_OK) { 1503 goto fail; 1504 } 1505 1506 /* Apply Tx core reset */ 1507 if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 1508 ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0)) != NXGE_OK) { 1509 goto fail; 1510 } 1511 1512 if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 1513 ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) != 1514 NXGE_OK) { 1515 goto fail; 1516 } 1517 1518 NXGE_DELAY(200); 1519 1520 /* Apply Rx core reset */ 1521 if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 1522 ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) != 1523 NXGE_OK) { 1524 goto fail; 1525 } 1526 1527 NXGE_DELAY(200); 1528 if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 1529 ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK) { 1530 goto fail; 1531 } 1532 1533 NXGE_DELAY(200); 1534 if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 1535 ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), &val16l)) != NXGE_OK) { 1536 goto fail; 1537 } 1538 if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 1539 ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK) { 1540 goto fail; 1541 } 1542 if ((val16l != 0) || (val16h != 0)) { 1543 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1544 "Failed to reset port<%d> XAUI Serdes " 1545 "(val16l 0x%x val16h 0x%x)", portn, val16l, val16h)); 1546 status = NXGE_ERROR; 1547 goto fail; 1548 } 1549 1550 NXGE_DELAY(200); 1551 ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val); 1552 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1553 "nxge_neptune_serdes_init: read internal signal reg port<%d> " 1554 "val 0x%x", portn, val)); 1555 if (portn == 0) { 1556 if ((val & ESR_SIG_P0_BITS_MASK_1G) != 1557 (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0)) { 1558 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1559 "nxge_neptune_serdes_init: " 1560 "Failed to get Serdes up for port<%d> val 0x%x", 1561 portn, (val & ESR_SIG_P0_BITS_MASK))); 1562 status = NXGE_ERROR; 1563 goto fail; 1564 } 1565 } else if (portn == 1) { 1566 if ((val & ESR_SIG_P1_BITS_MASK_1G) != 1567 (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1)) { 1568 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1569 "nxge_neptune_serdes_init: " 1570 "Failed to get Serdes up for port<%d> val 0x%x", 1571 portn, (val & ESR_SIG_P1_BITS_MASK))); 1572 status = NXGE_ERROR; 1573 goto fail; 1574 } 1575 } 1576 done: 1577 1578 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1579 "<== nxge_1G_serdes_init port<%d>", portn)); 1580 return (NXGE_OK); 1581 fail: 1582 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1583 "nxge_1G_serdes_init: " 1584 "Failed to initialize Neptune serdes for port<%d>", 1585 portn)); 1586 1587 return (status); 1588 } 1589 1590 /* Initialize the 10G (BCM8704) Transceiver */ 1591 1592 static nxge_status_t 1593 nxge_10G_xcvr_init(p_nxge_t nxgep) 1594 { 1595 p_nxge_stats_t statsp; 1596 uint16_t val; 1597 #ifdef NXGE_DEBUG 1598 uint8_t portn; 1599 uint16_t val1; 1600 #endif 1601 uint8_t phy_port_addr; 1602 pmd_tx_control_t tx_ctl; 1603 control_t ctl; 1604 phyxs_control_t phyxs_ctl; 1605 pcs_control_t pcs_ctl; 1606 uint32_t delay = 0; 1607 optics_dcntr_t op_ctr; 1608 nxge_status_t status = NXGE_OK; 1609 #ifdef NXGE_DEBUG 1610 portn = nxgep->mac.portnum; 1611 #endif 1612 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>", 1613 portn)); 1614 1615 statsp = nxgep->statsp; 1616 1617 if (nxgep->mac.portmode == PORT_10G_SERDES) { 1618 goto done; 1619 } 1620 1621 phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn; 1622 1623 /* Disable Link LEDs */ 1624 if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 1625 goto fail; 1626 1627 /* Set Clause 45 */ 1628 npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE); 1629 1630 /* Reset the transceiver */ 1631 if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 1632 BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK) 1633 goto fail; 1634 1635 phyxs_ctl.bits.reset = 1; 1636 if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 1637 BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK) 1638 goto fail; 1639 1640 do { 1641 drv_usecwait(500); 1642 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 1643 BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG, 1644 &phyxs_ctl.value)) != NXGE_OK) 1645 goto fail; 1646 delay++; 1647 } while ((phyxs_ctl.bits.reset) && (delay < 100)); 1648 if (delay == 100) { 1649 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: " 1650 "failed to reset Transceiver on port<%d>", portn)); 1651 status = NXGE_ERROR; 1652 goto fail; 1653 } 1654 1655 /* Set to 0x7FBF */ 1656 ctl.value = 0; 1657 ctl.bits.res1 = 0x3F; 1658 ctl.bits.optxon_lvl = 1; 1659 ctl.bits.oprxflt_lvl = 1; 1660 ctl.bits.optrxlos_lvl = 1; 1661 ctl.bits.optxflt_lvl = 1; 1662 ctl.bits.opprflt_lvl = 1; 1663 ctl.bits.obtmpflt_lvl = 1; 1664 ctl.bits.opbiasflt_lvl = 1; 1665 ctl.bits.optxrst_lvl = 1; 1666 if ((status = nxge_mdio_write(nxgep, phy_port_addr, 1667 BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, ctl.value)) 1668 != NXGE_OK) 1669 goto fail; 1670 1671 /* Set to 0x164 */ 1672 tx_ctl.value = 0; 1673 tx_ctl.bits.tsck_lpwren = 1; 1674 tx_ctl.bits.tx_dac_txck = 0x2; 1675 tx_ctl.bits.tx_dac_txd = 0x1; 1676 tx_ctl.bits.xfp_clken = 1; 1677 if ((status = nxge_mdio_write(nxgep, phy_port_addr, 1678 BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, 1679 tx_ctl.value)) != NXGE_OK) 1680 goto fail; 1681 /* 1682 * According to Broadcom's instruction, SW needs to read 1683 * back these registers twice after written. 1684 */ 1685 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 1686 BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val)) 1687 != NXGE_OK) 1688 goto fail; 1689 1690 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 1691 BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val)) 1692 != NXGE_OK) 1693 goto fail; 1694 1695 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 1696 BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val)) 1697 != NXGE_OK) 1698 goto fail; 1699 1700 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 1701 BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val)) 1702 != NXGE_OK) 1703 goto fail; 1704 1705 /* Enable Tx and Rx LEDs to be driven by traffic */ 1706 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 1707 BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 1708 &op_ctr.value)) != NXGE_OK) 1709 goto fail; 1710 op_ctr.bits.gpio_sel = 0x3; 1711 if ((status = nxge_mdio_write(nxgep, phy_port_addr, 1712 BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 1713 op_ctr.value)) != NXGE_OK) 1714 goto fail; 1715 1716 NXGE_DELAY(1000000); 1717 1718 /* Set BCM8704 Internal Loopback mode if necessary */ 1719 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 1720 BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value)) 1721 != NXGE_OK) 1722 goto fail; 1723 if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g) 1724 pcs_ctl.bits.loopback = 1; 1725 else 1726 pcs_ctl.bits.loopback = 0; 1727 if ((status = nxge_mdio_write(nxgep, phy_port_addr, 1728 BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value)) 1729 != NXGE_OK) 1730 goto fail; 1731 1732 status = nxge_mdio_read(nxgep, phy_port_addr, 0x1, 0xA, &val); 1733 if (status != NXGE_OK) 1734 goto fail; 1735 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1736 "BCM8704 port<%d> Dev 1 Reg 0xA = 0x%x\n", portn, val)); 1737 status = nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0x20, &val); 1738 if (status != NXGE_OK) 1739 goto fail; 1740 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1741 "BCM8704 port<%d> Dev 3 Reg 0x20 = 0x%x\n", portn, val)); 1742 status = nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, &val); 1743 if (status != NXGE_OK) 1744 goto fail; 1745 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1746 "BCM8704 port<%d> Dev 4 Reg 0x18 = 0x%x\n", portn, val)); 1747 1748 #ifdef NXGE_DEBUG 1749 /* Diagnose link issue if link is not up */ 1750 status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_USER_DEV3_ADDR, 1751 BCM8704_USER_ANALOG_STATUS0_REG, 1752 &val); 1753 if (status != NXGE_OK) 1754 goto fail; 1755 1756 status = nxge_mdio_read(nxgep, phy_port_addr, 1757 BCM8704_USER_DEV3_ADDR, 1758 BCM8704_USER_ANALOG_STATUS0_REG, 1759 &val); 1760 if (status != NXGE_OK) 1761 goto fail; 1762 1763 status = nxge_mdio_read(nxgep, phy_port_addr, 1764 BCM8704_USER_DEV3_ADDR, 1765 BCM8704_USER_TX_ALARM_STATUS_REG, 1766 &val1); 1767 if (status != NXGE_OK) 1768 goto fail; 1769 1770 status = nxge_mdio_read(nxgep, phy_port_addr, 1771 BCM8704_USER_DEV3_ADDR, 1772 BCM8704_USER_TX_ALARM_STATUS_REG, 1773 &val1); 1774 if (status != NXGE_OK) 1775 goto fail; 1776 1777 if (val != 0x3FC) { 1778 if ((val == 0x43BC) && (val1 != 0)) { 1779 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1780 "Cable not connected to peer or bad" 1781 " cable on port<%d>\n", portn)); 1782 } else if (val == 0x639C) { 1783 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1784 "Optical module (XFP) is bad or absent" 1785 " on port<%d>\n", portn)); 1786 } 1787 } 1788 #endif 1789 1790 done: 1791 statsp->mac_stats.cap_10gfdx = 1; 1792 statsp->mac_stats.lp_cap_10gfdx = 1; 1793 1794 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>", 1795 portn)); 1796 return (NXGE_OK); 1797 1798 fail: 1799 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1800 "nxge_10G_xcvr_init: failed to initialize transceiver for " 1801 "port<%d>", portn)); 1802 return (status); 1803 } 1804 1805 /* Initialize the 1G copper (BCM 5464) Transceiver */ 1806 1807 static nxge_status_t 1808 nxge_1G_xcvr_init(p_nxge_t nxgep) 1809 { 1810 p_nxge_param_t param_arr = nxgep->param_arr; 1811 p_nxge_stats_t statsp = nxgep->statsp; 1812 nxge_status_t status = NXGE_OK; 1813 1814 if (nxgep->mac.portmode == PORT_1G_SERDES) { 1815 statsp->mac_stats.cap_1000fdx = 1816 param_arr[param_anar_1000fdx].value; 1817 goto done; 1818 } 1819 1820 /* Set Clause 22 */ 1821 npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_FALSE); 1822 1823 /* Set capability flags */ 1824 statsp->mac_stats.cap_1000fdx = param_arr[param_anar_1000fdx].value; 1825 if ((nxgep->mac.portmode == PORT_1G_COPPER) || 1826 (nxgep->mac.portmode == PORT_1G_FIBER)) { 1827 statsp->mac_stats.cap_100fdx = 1828 param_arr[param_anar_100fdx].value; 1829 statsp->mac_stats.cap_10fdx = 1830 param_arr[param_anar_10fdx].value; 1831 } 1832 1833 status = nxge_mii_xcvr_init(nxgep); 1834 done: 1835 return (status); 1836 } 1837 1838 /* Initialize transceiver */ 1839 1840 nxge_status_t 1841 nxge_xcvr_init(p_nxge_t nxgep) 1842 { 1843 p_nxge_stats_t statsp; 1844 #ifdef NXGE_DEBUG 1845 uint8_t portn; 1846 #endif 1847 1848 nxge_status_t status = NXGE_OK; 1849 #ifdef NXGE_DEBUG 1850 portn = nxgep->mac.portnum; 1851 #endif 1852 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", portn)); 1853 statsp = nxgep->statsp; 1854 1855 /* 1856 * Initialize the xcvr statistics. 1857 */ 1858 statsp->mac_stats.cap_autoneg = 0; 1859 statsp->mac_stats.cap_100T4 = 0; 1860 statsp->mac_stats.cap_100fdx = 0; 1861 statsp->mac_stats.cap_100hdx = 0; 1862 statsp->mac_stats.cap_10fdx = 0; 1863 statsp->mac_stats.cap_10hdx = 0; 1864 statsp->mac_stats.cap_asmpause = 0; 1865 statsp->mac_stats.cap_pause = 0; 1866 statsp->mac_stats.cap_1000fdx = 0; 1867 statsp->mac_stats.cap_1000hdx = 0; 1868 statsp->mac_stats.cap_10gfdx = 0; 1869 statsp->mac_stats.cap_10ghdx = 0; 1870 1871 /* 1872 * Initialize the link statistics. 1873 */ 1874 statsp->mac_stats.link_T4 = 0; 1875 statsp->mac_stats.link_asmpause = 0; 1876 statsp->mac_stats.link_pause = 0; 1877 1878 if (nxgep->xcvr.xcvr_init) { 1879 status = nxgep->xcvr.xcvr_init(nxgep); 1880 if (status != NXGE_OK) 1881 goto fail; 1882 statsp->mac_stats.xcvr_inits++; 1883 } 1884 1885 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", 1886 portn)); 1887 return (NXGE_OK); 1888 1889 fail: 1890 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1891 "nxge_xcvr_init: failed to initialize transceiver for port<%d>", 1892 portn)); 1893 return (status); 1894 } 1895 1896 /* Look for transceiver type */ 1897 1898 nxge_status_t 1899 nxge_xcvr_find(p_nxge_t nxgep) 1900 { 1901 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_find: port<%d>", 1902 nxgep->mac.portnum)); 1903 1904 if (nxge_get_xcvr_type(nxgep) != NXGE_OK) 1905 return (NXGE_ERROR); 1906 1907 if (nxge_setup_xcvr_table(nxgep) != NXGE_OK) 1908 return (NXGE_ERROR); 1909 1910 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xcvr_find: xcvr_inuse = %d", 1911 nxgep->statsp->mac_stats.xcvr_inuse)); 1912 return (NXGE_OK); 1913 } 1914 1915 /* Initialize the TxMAC sub-block */ 1916 1917 nxge_status_t 1918 nxge_tx_mac_init(p_nxge_t nxgep) 1919 { 1920 npi_attr_t ap; 1921 uint8_t portn; 1922 nxge_port_mode_t portmode; 1923 nxge_port_t portt; 1924 npi_handle_t handle; 1925 npi_status_t rs = NPI_SUCCESS; 1926 1927 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 1928 portt = nxgep->mac.porttype; 1929 handle = nxgep->npi_handle; 1930 portmode = nxgep->mac.portmode; 1931 1932 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_init: port<%d>", 1933 portn)); 1934 1935 /* Set Max and Min Frame Size */ 1936 if (nxgep->param_arr[param_accept_jumbo].value || nxge_jumbo_enable) { 1937 SET_MAC_ATTR2(handle, ap, portn, 1938 MAC_PORT_FRAME_SIZE, 64, 0x2400, rs); 1939 } else { 1940 /* Do not add CRC 4 bytes to the max or the min frame size */ 1941 SET_MAC_ATTR2(handle, ap, portn, 1942 MAC_PORT_FRAME_SIZE, 64, 0x5EE, rs); 1943 } 1944 1945 if (rs != NPI_SUCCESS) 1946 goto fail; 1947 if (nxgep->param_arr[param_accept_jumbo].value || 1948 nxgep->mac.is_jumbo == B_TRUE) 1949 nxgep->mac.maxframesize = 0x2400; 1950 else 1951 nxgep->mac.maxframesize = 0x5EE + 4; 1952 nxgep->mac.minframesize = 64; 1953 1954 if (portt == PORT_TYPE_XMAC) { 1955 if ((rs = npi_xmac_tx_iconfig(handle, INIT, portn, 1956 0)) != NPI_SUCCESS) 1957 goto fail; 1958 nxgep->mac.tx_iconfig = NXGE_XMAC_TX_INTRS; 1959 if ((portmode == PORT_10G_FIBER) || 1960 (portmode == PORT_10G_COPPER) || 1961 (portmode == PORT_10G_SERDES)) { 1962 SET_MAC_ATTR1(handle, ap, portn, XMAC_10G_PORT_IPG, 1963 XGMII_IPG_12_15, rs); 1964 if (rs != NPI_SUCCESS) 1965 goto fail; 1966 nxgep->mac.ipg[0] = XGMII_IPG_12_15; 1967 } else { 1968 SET_MAC_ATTR1(handle, ap, portn, XMAC_PORT_IPG, 1969 MII_GMII_IPG_12, rs); 1970 if (rs != NPI_SUCCESS) 1971 goto fail; 1972 nxgep->mac.ipg[0] = MII_GMII_IPG_12; 1973 } 1974 if ((rs = npi_xmac_tx_config(handle, INIT, portn, 1975 CFG_XMAC_TX_CRC | CFG_XMAC_TX)) != NPI_SUCCESS) 1976 goto fail; 1977 nxgep->mac.tx_config = CFG_XMAC_TX_CRC | CFG_XMAC_TX; 1978 nxgep->mac.maxburstsize = 0; /* not programmable */ 1979 nxgep->mac.ctrltype = 0; /* not programmable */ 1980 nxgep->mac.pa_size = 0; /* not programmable */ 1981 1982 if ((rs = npi_xmac_zap_tx_counters(handle, portn)) 1983 != NPI_SUCCESS) 1984 goto fail; 1985 1986 } else { 1987 if ((rs = npi_bmac_tx_iconfig(handle, INIT, portn, 1988 0)) != NPI_SUCCESS) 1989 goto fail; 1990 nxgep->mac.tx_iconfig = NXGE_BMAC_TX_INTRS; 1991 1992 SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_CTRL_TYPE, 0x8808, 1993 rs); 1994 if (rs != NPI_SUCCESS) 1995 goto fail; 1996 nxgep->mac.ctrltype = 0x8808; 1997 1998 SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_PA_SIZE, 0x7, rs); 1999 if (rs != NPI_SUCCESS) 2000 goto fail; 2001 nxgep->mac.pa_size = 0x7; 2002 2003 if ((rs = npi_bmac_tx_config(handle, INIT, portn, 2004 CFG_BMAC_TX_CRC | CFG_BMAC_TX)) != NPI_SUCCESS) 2005 goto fail; 2006 nxgep->mac.tx_config = CFG_BMAC_TX_CRC | CFG_BMAC_TX; 2007 } 2008 2009 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_init: port<%d>", 2010 portn)); 2011 2012 return (NXGE_OK); 2013 fail: 2014 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2015 "nxge_tx_mac_init: failed to initialize port<%d> TXMAC", 2016 portn)); 2017 2018 return (NXGE_ERROR | rs); 2019 } 2020 2021 /* Initialize the RxMAC sub-block */ 2022 2023 nxge_status_t 2024 nxge_rx_mac_init(p_nxge_t nxgep) 2025 { 2026 npi_attr_t ap; 2027 uint32_t i; 2028 uint16_t hashtab_e; 2029 p_hash_filter_t hash_filter; 2030 nxge_port_t portt; 2031 uint8_t portn; 2032 npi_handle_t handle; 2033 npi_status_t rs = NPI_SUCCESS; 2034 uint16_t *addr16p; 2035 uint16_t addr0, addr1, addr2; 2036 xmac_rx_config_t xconfig; 2037 bmac_rx_config_t bconfig; 2038 2039 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 2040 2041 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_init: port<%d>\n", 2042 portn)); 2043 handle = nxgep->npi_handle; 2044 portt = nxgep->mac.porttype; 2045 2046 addr16p = (uint16_t *)nxgep->ouraddr.ether_addr_octet; 2047 addr0 = ntohs(addr16p[2]); 2048 addr1 = ntohs(addr16p[1]); 2049 addr2 = ntohs(addr16p[0]); 2050 SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR, addr0, addr1, addr2, 2051 rs); 2052 2053 if (rs != NPI_SUCCESS) 2054 goto fail; 2055 SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR_FILTER, 0, 0, 0, rs); 2056 if (rs != NPI_SUCCESS) 2057 goto fail; 2058 SET_MAC_ATTR2(handle, ap, portn, MAC_PORT_ADDR_FILTER_MASK, 0, 0, rs); 2059 if (rs != NPI_SUCCESS) 2060 goto fail; 2061 2062 /* 2063 * Load the multicast hash filter bits. 2064 */ 2065 hash_filter = nxgep->hash_filter; 2066 for (i = 0; i < MAC_MAX_HASH_ENTRY; i++) { 2067 if (hash_filter != NULL) { 2068 hashtab_e = (uint16_t)hash_filter->hash_filter_regs[ 2069 (NMCFILTER_REGS - 1) - i]; 2070 } else { 2071 hashtab_e = 0; 2072 } 2073 2074 if ((rs = npi_mac_hashtab_entry(handle, OP_SET, portn, i, 2075 (uint16_t *)&hashtab_e)) != NPI_SUCCESS) 2076 goto fail; 2077 } 2078 2079 if (portt == PORT_TYPE_XMAC) { 2080 if ((rs = npi_xmac_rx_iconfig(handle, INIT, portn, 2081 0)) != NPI_SUCCESS) 2082 goto fail; 2083 nxgep->mac.rx_iconfig = NXGE_XMAC_RX_INTRS; 2084 2085 (void) nxge_fflp_init_hostinfo(nxgep); 2086 2087 xconfig = CFG_XMAC_RX_ERRCHK | CFG_XMAC_RX_CRC_CHK | 2088 CFG_XMAC_RX | CFG_XMAC_RX_CODE_VIO_CHK & 2089 ~CFG_XMAC_RX_STRIP_CRC; 2090 2091 if (nxgep->filter.all_phys_cnt != 0) 2092 xconfig |= CFG_XMAC_RX_PROMISCUOUS; 2093 2094 if (nxgep->filter.all_multicast_cnt != 0) 2095 xconfig |= CFG_XMAC_RX_PROMISCUOUSGROUP; 2096 2097 xconfig |= CFG_XMAC_RX_HASH_FILTER; 2098 2099 if ((rs = npi_xmac_rx_config(handle, INIT, portn, 2100 xconfig)) != NPI_SUCCESS) 2101 goto fail; 2102 nxgep->mac.rx_config = xconfig; 2103 2104 /* Comparison of mac unique address is always enabled on XMAC */ 2105 2106 if ((rs = npi_xmac_zap_rx_counters(handle, portn)) 2107 != NPI_SUCCESS) 2108 goto fail; 2109 } else { 2110 (void) nxge_fflp_init_hostinfo(nxgep); 2111 2112 if (npi_bmac_rx_iconfig(nxgep->npi_handle, INIT, portn, 2113 0) != NPI_SUCCESS) 2114 goto fail; 2115 nxgep->mac.rx_iconfig = NXGE_BMAC_RX_INTRS; 2116 2117 bconfig = CFG_BMAC_RX_DISCARD_ON_ERR | CFG_BMAC_RX & 2118 ~CFG_BMAC_RX_STRIP_CRC; 2119 2120 if (nxgep->filter.all_phys_cnt != 0) 2121 bconfig |= CFG_BMAC_RX_PROMISCUOUS; 2122 2123 if (nxgep->filter.all_multicast_cnt != 0) 2124 bconfig |= CFG_BMAC_RX_PROMISCUOUSGROUP; 2125 2126 bconfig |= CFG_BMAC_RX_HASH_FILTER; 2127 if ((rs = npi_bmac_rx_config(handle, INIT, portn, 2128 bconfig)) != NPI_SUCCESS) 2129 goto fail; 2130 nxgep->mac.rx_config = bconfig; 2131 2132 /* Always enable comparison of mac unique address */ 2133 if ((rs = npi_mac_altaddr_enable(handle, portn, 0)) 2134 != NPI_SUCCESS) 2135 goto fail; 2136 } 2137 2138 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_init: port<%d>\n", 2139 portn)); 2140 2141 return (NXGE_OK); 2142 2143 fail: 2144 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2145 "nxge_rx_mac_init: Failed to Initialize port<%d> RxMAC", 2146 portn)); 2147 2148 return (NXGE_ERROR | rs); 2149 } 2150 2151 /* Enable TXMAC */ 2152 2153 nxge_status_t 2154 nxge_tx_mac_enable(p_nxge_t nxgep) 2155 { 2156 npi_handle_t handle; 2157 npi_status_t rs = NPI_SUCCESS; 2158 nxge_status_t status = NXGE_OK; 2159 2160 handle = nxgep->npi_handle; 2161 2162 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_enable: port<%d>", 2163 nxgep->mac.portnum)); 2164 2165 if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK) 2166 goto fail; 2167 2168 /* based on speed */ 2169 nxgep->msg_min = ETHERMIN; 2170 2171 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 2172 if ((rs = npi_xmac_tx_config(handle, ENABLE, nxgep->mac.portnum, 2173 CFG_XMAC_TX)) != NPI_SUCCESS) 2174 goto fail; 2175 } else { 2176 if ((rs = npi_bmac_tx_config(handle, ENABLE, nxgep->mac.portnum, 2177 CFG_BMAC_TX)) != NPI_SUCCESS) 2178 goto fail; 2179 } 2180 2181 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_enable: port<%d>", 2182 nxgep->mac.portnum)); 2183 2184 return (NXGE_OK); 2185 fail: 2186 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2187 "nxgep_tx_mac_enable: Failed to enable port<%d> TxMAC", 2188 nxgep->mac.portnum)); 2189 if (rs != NPI_SUCCESS) 2190 return (NXGE_ERROR | rs); 2191 else 2192 return (status); 2193 } 2194 2195 /* Disable TXMAC */ 2196 2197 nxge_status_t 2198 nxge_tx_mac_disable(p_nxge_t nxgep) 2199 { 2200 npi_handle_t handle; 2201 npi_status_t rs = NPI_SUCCESS; 2202 2203 handle = nxgep->npi_handle; 2204 2205 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_disable: port<%d>", 2206 nxgep->mac.portnum)); 2207 2208 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 2209 if ((rs = npi_xmac_tx_config(handle, DISABLE, 2210 nxgep->mac.portnum, CFG_XMAC_TX)) != NPI_SUCCESS) 2211 goto fail; 2212 } else { 2213 if ((rs = npi_bmac_tx_config(handle, DISABLE, 2214 nxgep->mac.portnum, CFG_BMAC_TX)) != NPI_SUCCESS) 2215 goto fail; 2216 } 2217 2218 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_disable: port<%d>", 2219 nxgep->mac.portnum)); 2220 return (NXGE_OK); 2221 fail: 2222 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2223 "nxge_tx_mac_disable: Failed to disable port<%d> TxMAC", 2224 nxgep->mac.portnum)); 2225 return (NXGE_ERROR | rs); 2226 } 2227 2228 /* Enable RXMAC */ 2229 2230 nxge_status_t 2231 nxge_rx_mac_enable(p_nxge_t nxgep) 2232 { 2233 npi_handle_t handle; 2234 uint8_t portn; 2235 npi_status_t rs = NPI_SUCCESS; 2236 nxge_status_t status = NXGE_OK; 2237 2238 handle = nxgep->npi_handle; 2239 portn = nxgep->mac.portnum; 2240 2241 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_enable: port<%d>", 2242 portn)); 2243 2244 if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK) 2245 goto fail; 2246 2247 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 2248 if ((rs = npi_xmac_rx_config(handle, ENABLE, portn, 2249 CFG_XMAC_RX)) != NPI_SUCCESS) 2250 goto fail; 2251 } else { 2252 if ((rs = npi_bmac_rx_config(handle, ENABLE, portn, 2253 CFG_BMAC_RX)) != NPI_SUCCESS) 2254 goto fail; 2255 } 2256 2257 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_enable: port<%d>", 2258 portn)); 2259 2260 return (NXGE_OK); 2261 fail: 2262 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2263 "nxgep_rx_mac_enable: Failed to enable port<%d> RxMAC", 2264 portn)); 2265 2266 if (rs != NPI_SUCCESS) 2267 return (NXGE_ERROR | rs); 2268 else 2269 return (status); 2270 } 2271 2272 /* Disable RXMAC */ 2273 2274 nxge_status_t 2275 nxge_rx_mac_disable(p_nxge_t nxgep) 2276 { 2277 npi_handle_t handle; 2278 uint8_t portn; 2279 npi_status_t rs = NPI_SUCCESS; 2280 2281 handle = nxgep->npi_handle; 2282 portn = nxgep->mac.portnum; 2283 2284 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_disable: port<%d>", 2285 portn)); 2286 2287 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 2288 if ((rs = npi_xmac_rx_config(handle, DISABLE, portn, 2289 CFG_XMAC_RX)) != NPI_SUCCESS) 2290 goto fail; 2291 } else { 2292 if ((rs = npi_bmac_rx_config(handle, DISABLE, portn, 2293 CFG_BMAC_RX)) != NPI_SUCCESS) 2294 goto fail; 2295 } 2296 2297 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_disable: port<%d>", 2298 portn)); 2299 return (NXGE_OK); 2300 fail: 2301 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2302 "nxgep_rx_mac_disable: ", 2303 "Failed to disable port<%d> RxMAC", 2304 portn)); 2305 2306 return (NXGE_ERROR | rs); 2307 } 2308 2309 /* Reset TXMAC */ 2310 2311 nxge_status_t 2312 nxge_tx_mac_reset(p_nxge_t nxgep) 2313 { 2314 npi_handle_t handle; 2315 uint8_t portn; 2316 npi_status_t rs = NPI_SUCCESS; 2317 2318 handle = nxgep->npi_handle; 2319 portn = nxgep->mac.portnum; 2320 2321 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_reset: port<%d>", 2322 portn)); 2323 2324 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 2325 if ((rs = npi_xmac_reset(handle, portn, XTX_MAC_RESET_ALL)) 2326 != NPI_SUCCESS) 2327 goto fail; 2328 } else { 2329 if ((rs = npi_bmac_reset(handle, portn, TX_MAC_RESET)) 2330 != NPI_SUCCESS) 2331 goto fail; 2332 } 2333 2334 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_reset: port<%d>", 2335 portn)); 2336 2337 return (NXGE_OK); 2338 fail: 2339 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2340 "nxge_tx_mac_reset: Failed to Reset TxMAC port<%d>", 2341 portn)); 2342 2343 return (NXGE_ERROR | rs); 2344 } 2345 2346 /* Reset RXMAC */ 2347 2348 nxge_status_t 2349 nxge_rx_mac_reset(p_nxge_t nxgep) 2350 { 2351 npi_handle_t handle; 2352 uint8_t portn; 2353 npi_status_t rs = NPI_SUCCESS; 2354 2355 handle = nxgep->npi_handle; 2356 portn = nxgep->mac.portnum; 2357 2358 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_reset: port<%d>", 2359 portn)); 2360 2361 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 2362 if ((rs = npi_xmac_reset(handle, portn, XRX_MAC_RESET_ALL)) 2363 != NPI_SUCCESS) 2364 goto fail; 2365 } else { 2366 if ((rs = npi_bmac_reset(handle, portn, RX_MAC_RESET)) 2367 != NPI_SUCCESS) 2368 goto fail; 2369 } 2370 2371 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_reset: port<%d>", 2372 portn)); 2373 2374 return (NXGE_OK); 2375 fail: 2376 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2377 "nxge_rx_mac_reset: Failed to Reset RxMAC port<%d>", 2378 portn)); 2379 return (NXGE_ERROR | rs); 2380 } 2381 2382 /* 10G fiber link interrupt start routine */ 2383 2384 static nxge_status_t 2385 nxge_10G_link_intr_start(p_nxge_t nxgep) 2386 { 2387 npi_status_t rs = NPI_SUCCESS; 2388 uint8_t portn = nxgep->mac.portnum; 2389 2390 rs = npi_xmac_xpcs_link_intr_enable(nxgep->npi_handle, portn); 2391 2392 if (rs != NPI_SUCCESS) 2393 return (NXGE_ERROR | rs); 2394 else 2395 return (NXGE_OK); 2396 } 2397 2398 /* 10G fiber link interrupt stop routine */ 2399 2400 static nxge_status_t 2401 nxge_10G_link_intr_stop(p_nxge_t nxgep) 2402 { 2403 npi_status_t rs = NPI_SUCCESS; 2404 uint8_t portn = nxgep->mac.portnum; 2405 2406 rs = npi_xmac_xpcs_link_intr_disable(nxgep->npi_handle, portn); 2407 2408 if (rs != NPI_SUCCESS) 2409 return (NXGE_ERROR | rs); 2410 else 2411 return (NXGE_OK); 2412 } 2413 2414 /* 1G fiber link interrupt start routine */ 2415 2416 static nxge_status_t 2417 nxge_1G_fiber_link_intr_start(p_nxge_t nxgep) 2418 { 2419 npi_status_t rs = NPI_SUCCESS; 2420 uint8_t portn = nxgep->mac.portnum; 2421 2422 rs = npi_mac_pcs_link_intr_enable(nxgep->npi_handle, portn); 2423 if (rs != NPI_SUCCESS) 2424 return (NXGE_ERROR | rs); 2425 else 2426 return (NXGE_OK); 2427 } 2428 2429 /* 1G fiber link interrupt stop routine */ 2430 2431 static nxge_status_t 2432 nxge_1G_fiber_link_intr_stop(p_nxge_t nxgep) 2433 { 2434 npi_status_t rs = NPI_SUCCESS; 2435 uint8_t portn = nxgep->mac.portnum; 2436 2437 rs = npi_mac_pcs_link_intr_disable(nxgep->npi_handle, portn); 2438 2439 if (rs != NPI_SUCCESS) 2440 return (NXGE_ERROR | rs); 2441 else 2442 return (NXGE_OK); 2443 } 2444 2445 /* 1G copper link interrupt start routine */ 2446 2447 static nxge_status_t 2448 nxge_1G_copper_link_intr_start(p_nxge_t nxgep) 2449 { 2450 npi_status_t rs = NPI_SUCCESS; 2451 uint8_t portn = nxgep->mac.portnum; 2452 2453 rs = npi_mac_mif_link_intr_enable(nxgep->npi_handle, portn, 2454 MII_STATUS, MII_STATUS_LINKUP); 2455 2456 if (rs != NPI_SUCCESS) 2457 return (NXGE_ERROR | rs); 2458 else 2459 return (NXGE_OK); 2460 } 2461 2462 /* 1G copper link interrupt stop routine */ 2463 2464 static nxge_status_t 2465 nxge_1G_copper_link_intr_stop(p_nxge_t nxgep) 2466 { 2467 npi_status_t rs = NPI_SUCCESS; 2468 uint8_t portn = nxgep->mac.portnum; 2469 2470 rs = npi_mac_mif_link_intr_disable(nxgep->npi_handle, portn); 2471 2472 if (rs != NPI_SUCCESS) 2473 return (NXGE_ERROR | rs); 2474 else 2475 return (NXGE_OK); 2476 } 2477 2478 /* Enable/Disable Link Status change interrupt */ 2479 2480 nxge_status_t 2481 nxge_link_intr(p_nxge_t nxgep, link_intr_enable_t enable) 2482 { 2483 uint8_t portn; 2484 nxge_status_t status = NXGE_OK; 2485 2486 portn = nxgep->mac.portnum; 2487 2488 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_intr: port<%d>", portn)); 2489 if (!nxgep->xcvr.link_intr_stop || !nxgep->xcvr.link_intr_start) 2490 return (NXGE_OK); 2491 2492 if (enable == LINK_INTR_START) 2493 status = nxgep->xcvr.link_intr_start(nxgep); 2494 else if (enable == LINK_INTR_STOP) 2495 status = nxgep->xcvr.link_intr_stop(nxgep); 2496 if (status != NXGE_OK) 2497 goto fail; 2498 2499 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_intr: port<%d>", portn)); 2500 2501 return (NXGE_OK); 2502 fail: 2503 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2504 "nxge_link_intr: Failed to set port<%d> mif intr mode", 2505 portn)); 2506 2507 return (status); 2508 } 2509 2510 /* Initialize 1G Fiber / Copper transceiver using Clause 22 */ 2511 2512 nxge_status_t 2513 nxge_mii_xcvr_init(p_nxge_t nxgep) 2514 { 2515 p_nxge_param_t param_arr; 2516 p_nxge_stats_t statsp; 2517 uint8_t xcvr_portn; 2518 p_mii_regs_t mii_regs; 2519 mii_bmcr_t bmcr; 2520 mii_bmsr_t bmsr; 2521 mii_anar_t anar; 2522 mii_gcr_t gcr; 2523 mii_esr_t esr; 2524 mii_aux_ctl_t bcm5464r_aux; 2525 int status = NXGE_OK; 2526 2527 uint_t delay; 2528 2529 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_init")); 2530 2531 param_arr = nxgep->param_arr; 2532 statsp = nxgep->statsp; 2533 xcvr_portn = statsp->mac_stats.xcvr_portn; 2534 2535 mii_regs = NULL; 2536 2537 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2538 "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value)); 2539 2540 /* 2541 * The mif phy mode may be connected to either a copper link 2542 * or fiber link. Read the mode control register to get the fiber 2543 * configuration if it is hard-wired to fiber link. 2544 */ 2545 (void) nxge_mii_get_link_mode(nxgep); 2546 if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) { 2547 return (nxge_mii_xcvr_fiber_init(nxgep)); 2548 } 2549 2550 /* 2551 * Reset the transceiver. 2552 */ 2553 delay = 0; 2554 bmcr.value = 0; 2555 bmcr.bits.reset = 1; 2556 if ((status = nxge_mii_write(nxgep, xcvr_portn, 2557 #if defined(__i386) 2558 (uint8_t)(uint32_t)&mii_regs->bmcr, bmcr.value)) != NXGE_OK) 2559 #else 2560 (uint8_t)(uint64_t)&mii_regs->bmcr, bmcr.value)) != NXGE_OK) 2561 #endif 2562 goto fail; 2563 do { 2564 drv_usecwait(500); 2565 if ((status = nxge_mii_read(nxgep, xcvr_portn, 2566 #if defined(__i386) 2567 (uint8_t)(uint32_t)&mii_regs->bmcr, &bmcr.value)) 2568 #else 2569 (uint8_t)(uint64_t)&mii_regs->bmcr, &bmcr.value)) 2570 #endif 2571 != NXGE_OK) 2572 goto fail; 2573 delay++; 2574 } while ((bmcr.bits.reset) && (delay < 1000)); 2575 if (delay == 1000) { 2576 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed.")); 2577 goto fail; 2578 } 2579 2580 if ((status = nxge_mii_read(nxgep, xcvr_portn, 2581 #if defined(__i386) 2582 (uint8_t)(uint32_t)(&mii_regs->bmsr), 2583 #else 2584 (uint8_t)(uint64_t)(&mii_regs->bmsr), 2585 #endif 2586 &bmsr.value)) != NXGE_OK) 2587 goto fail; 2588 2589 param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able; 2590 param_arr[param_anar_100T4].value &= bmsr.bits.link_100T4; 2591 param_arr[param_anar_100fdx].value &= bmsr.bits.link_100fdx; 2592 param_arr[param_anar_100hdx].value = 0; 2593 param_arr[param_anar_10fdx].value &= bmsr.bits.link_10fdx; 2594 param_arr[param_anar_10hdx].value = 0; 2595 2596 /* 2597 * Initialize the xcvr statistics. 2598 */ 2599 statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able; 2600 statsp->mac_stats.cap_100T4 = bmsr.bits.link_100T4; 2601 statsp->mac_stats.cap_100fdx = bmsr.bits.link_100fdx; 2602 statsp->mac_stats.cap_100hdx = 0; 2603 statsp->mac_stats.cap_10fdx = bmsr.bits.link_10fdx; 2604 statsp->mac_stats.cap_10hdx = 0; 2605 statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value; 2606 statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value; 2607 2608 /* 2609 * Initialise the xcvr advertised capability statistics. 2610 */ 2611 statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value; 2612 statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 2613 statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 2614 statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value; 2615 statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value; 2616 statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value; 2617 statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value; 2618 statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value; 2619 statsp->mac_stats.adv_cap_asmpause = 2620 param_arr[param_anar_asmpause].value; 2621 statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value; 2622 2623 2624 /* 2625 * Check for extended status just in case we're 2626 * running a Gigibit phy. 2627 */ 2628 if (bmsr.bits.extend_status) { 2629 if ((status = nxge_mii_read(nxgep, xcvr_portn, 2630 #if defined(__i386) 2631 (uint8_t)(uint32_t)(&mii_regs->esr), &esr.value)) 2632 #else 2633 (uint8_t)(uint64_t)(&mii_regs->esr), &esr.value)) 2634 #endif 2635 != NXGE_OK) 2636 goto fail; 2637 param_arr[param_anar_1000fdx].value &= 2638 esr.bits.link_1000fdx; 2639 param_arr[param_anar_1000hdx].value = 0; 2640 2641 statsp->mac_stats.cap_1000fdx = 2642 (esr.bits.link_1000Xfdx || 2643 esr.bits.link_1000fdx); 2644 statsp->mac_stats.cap_1000hdx = 0; 2645 } else { 2646 param_arr[param_anar_1000fdx].value = 0; 2647 param_arr[param_anar_1000hdx].value = 0; 2648 } 2649 2650 /* 2651 * Initialize 1G Statistics once the capability is established. 2652 */ 2653 statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 2654 statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 2655 2656 /* 2657 * Initialise the link statistics. 2658 */ 2659 statsp->mac_stats.link_T4 = 0; 2660 statsp->mac_stats.link_asmpause = 0; 2661 statsp->mac_stats.link_pause = 0; 2662 statsp->mac_stats.link_speed = 0; 2663 statsp->mac_stats.link_duplex = 0; 2664 statsp->mac_stats.link_up = 0; 2665 2666 /* 2667 * Switch off Auto-negotiation, 100M and full duplex. 2668 */ 2669 bmcr.value = 0; 2670 if ((status = nxge_mii_write(nxgep, xcvr_portn, 2671 #if defined(__i386) 2672 (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 2673 #else 2674 (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 2675 #endif 2676 goto fail; 2677 2678 if ((statsp->port_stats.lb_mode == nxge_lb_phy) || 2679 (statsp->port_stats.lb_mode == nxge_lb_phy1000)) { 2680 bmcr.bits.loopback = 1; 2681 bmcr.bits.enable_autoneg = 0; 2682 if (statsp->port_stats.lb_mode == nxge_lb_phy1000) 2683 bmcr.bits.speed_1000_sel = 1; 2684 bmcr.bits.duplex_mode = 1; 2685 param_arr[param_autoneg].value = 0; 2686 } else { 2687 bmcr.bits.loopback = 0; 2688 } 2689 2690 if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) || 2691 (statsp->port_stats.lb_mode == nxge_lb_ext100) || 2692 (statsp->port_stats.lb_mode == nxge_lb_ext10)) { 2693 param_arr[param_autoneg].value = 0; 2694 bcm5464r_aux.value = 0; 2695 bcm5464r_aux.bits.ext_lb = 1; 2696 bcm5464r_aux.bits.write_1 = 1; 2697 if ((status = nxge_mii_write(nxgep, xcvr_portn, 2698 BCM5464R_AUX_CTL, bcm5464r_aux.value)) 2699 != NXGE_OK) 2700 goto fail; 2701 } 2702 2703 if (param_arr[param_autoneg].value) { 2704 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2705 "Restarting Auto-negotiation.")); 2706 /* 2707 * Setup our Auto-negotiation advertisement register. 2708 */ 2709 anar.value = 0; 2710 anar.bits.selector = 1; 2711 anar.bits.cap_100T4 = param_arr[param_anar_100T4].value; 2712 anar.bits.cap_100fdx = param_arr[param_anar_100fdx].value; 2713 anar.bits.cap_100hdx = param_arr[param_anar_100hdx].value; 2714 anar.bits.cap_10fdx = param_arr[param_anar_10fdx].value; 2715 anar.bits.cap_10hdx = param_arr[param_anar_10hdx].value; 2716 anar.bits.cap_asmpause = 0; 2717 anar.bits.cap_pause = 0; 2718 if (param_arr[param_anar_1000fdx].value || 2719 param_arr[param_anar_100fdx].value || 2720 param_arr[param_anar_10fdx].value) { 2721 anar.bits.cap_asmpause = statsp->mac_stats.cap_asmpause; 2722 anar.bits.cap_pause = statsp->mac_stats.cap_pause; 2723 } 2724 2725 if ((status = nxge_mii_write(nxgep, xcvr_portn, 2726 #if defined(__i386) 2727 (uint8_t)(uint32_t)(&mii_regs->anar), anar.value)) 2728 #else 2729 (uint8_t)(uint64_t)(&mii_regs->anar), anar.value)) 2730 #endif 2731 != NXGE_OK) 2732 goto fail; 2733 if (bmsr.bits.extend_status) { 2734 gcr.value = 0; 2735 gcr.bits.ms_mode_en = 2736 param_arr[param_master_cfg_enable].value; 2737 gcr.bits.master = 2738 param_arr[param_master_cfg_value].value; 2739 gcr.bits.link_1000fdx = 2740 param_arr[param_anar_1000fdx].value; 2741 gcr.bits.link_1000hdx = 2742 param_arr[param_anar_1000hdx].value; 2743 if ((status = nxge_mii_write(nxgep, xcvr_portn, 2744 #if defined(__i386) 2745 (uint8_t)(uint32_t)(&mii_regs->gcr), gcr.value)) 2746 #else 2747 (uint8_t)(uint64_t)(&mii_regs->gcr), gcr.value)) 2748 #endif 2749 != NXGE_OK) 2750 goto fail; 2751 } 2752 2753 bmcr.bits.enable_autoneg = 1; 2754 bmcr.bits.restart_autoneg = 1; 2755 2756 } else { 2757 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode.")); 2758 bmcr.bits.speed_1000_sel = 2759 param_arr[param_anar_1000fdx].value | 2760 param_arr[param_anar_1000hdx].value; 2761 bmcr.bits.speed_sel = (~bmcr.bits.speed_1000_sel) & 2762 (param_arr[param_anar_100fdx].value | 2763 param_arr[param_anar_100hdx].value); 2764 if (bmcr.bits.speed_1000_sel) { 2765 statsp->mac_stats.link_speed = 1000; 2766 gcr.value = 0; 2767 gcr.bits.ms_mode_en = 2768 param_arr[param_master_cfg_enable].value; 2769 gcr.bits.master = 2770 param_arr[param_master_cfg_value].value; 2771 if ((status = nxge_mii_write(nxgep, xcvr_portn, 2772 #if defined(__i386) 2773 (uint8_t)(uint32_t)(&mii_regs->gcr), 2774 #else 2775 (uint8_t)(uint64_t)(&mii_regs->gcr), 2776 #endif 2777 gcr.value)) 2778 != NXGE_OK) 2779 goto fail; 2780 if (param_arr[param_anar_1000fdx].value) { 2781 bmcr.bits.duplex_mode = 1; 2782 statsp->mac_stats.link_duplex = 2; 2783 } else 2784 statsp->mac_stats.link_duplex = 1; 2785 } else if (bmcr.bits.speed_sel) { 2786 statsp->mac_stats.link_speed = 100; 2787 if (param_arr[param_anar_100fdx].value) { 2788 bmcr.bits.duplex_mode = 1; 2789 statsp->mac_stats.link_duplex = 2; 2790 } else 2791 statsp->mac_stats.link_duplex = 1; 2792 } else { 2793 statsp->mac_stats.link_speed = 10; 2794 if (param_arr[param_anar_10fdx].value) { 2795 bmcr.bits.duplex_mode = 1; 2796 statsp->mac_stats.link_duplex = 2; 2797 } else 2798 statsp->mac_stats.link_duplex = 1; 2799 } 2800 if (statsp->mac_stats.link_duplex != 1) { 2801 statsp->mac_stats.link_asmpause = 2802 statsp->mac_stats.cap_asmpause; 2803 statsp->mac_stats.link_pause = 2804 statsp->mac_stats.cap_pause; 2805 } 2806 2807 if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) || 2808 (statsp->port_stats.lb_mode == nxge_lb_ext100) || 2809 (statsp->port_stats.lb_mode == nxge_lb_ext10)) { 2810 if (statsp->port_stats.lb_mode == nxge_lb_ext1000) { 2811 /* BCM5464R 1000mbps external loopback mode */ 2812 gcr.value = 0; 2813 gcr.bits.ms_mode_en = 1; 2814 gcr.bits.master = 1; 2815 if ((status = nxge_mii_write(nxgep, xcvr_portn, 2816 #if defined(__i386) 2817 (uint8_t)(uint32_t)(&mii_regs->gcr), 2818 #else 2819 (uint8_t)(uint64_t)(&mii_regs->gcr), 2820 #endif 2821 gcr.value)) 2822 != NXGE_OK) 2823 goto fail; 2824 bmcr.value = 0; 2825 bmcr.bits.speed_1000_sel = 1; 2826 statsp->mac_stats.link_speed = 1000; 2827 } else if (statsp->port_stats.lb_mode 2828 == nxge_lb_ext100) { 2829 /* BCM5464R 100mbps external loopback mode */ 2830 bmcr.value = 0; 2831 bmcr.bits.speed_sel = 1; 2832 bmcr.bits.duplex_mode = 1; 2833 statsp->mac_stats.link_speed = 100; 2834 } else if (statsp->port_stats.lb_mode 2835 == nxge_lb_ext10) { 2836 /* BCM5464R 10mbps external loopback mode */ 2837 bmcr.value = 0; 2838 bmcr.bits.duplex_mode = 1; 2839 statsp->mac_stats.link_speed = 10; 2840 } 2841 } 2842 } 2843 2844 if ((status = nxge_mii_write(nxgep, xcvr_portn, 2845 #if defined(__i386) 2846 (uint8_t)(uint32_t)(&mii_regs->bmcr), 2847 #else 2848 (uint8_t)(uint64_t)(&mii_regs->bmcr), 2849 #endif 2850 bmcr.value)) != NXGE_OK) 2851 goto fail; 2852 2853 if ((status = nxge_mii_read(nxgep, xcvr_portn, 2854 #if defined(__i386) 2855 (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK) 2856 #else 2857 (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK) 2858 #endif 2859 goto fail; 2860 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "bmcr = 0x%04X", bmcr.value)); 2861 2862 /* 2863 * Initialize the xcvr status kept in the context structure. 2864 */ 2865 nxgep->soft_bmsr.value = 0; 2866 2867 if ((status = nxge_mii_read(nxgep, xcvr_portn, 2868 #if defined(__i386) 2869 (uint8_t)(uint32_t)(&mii_regs->bmsr), 2870 #else 2871 (uint8_t)(uint64_t)(&mii_regs->bmsr), 2872 #endif 2873 &nxgep->bmsr.value)) != NXGE_OK) 2874 goto fail; 2875 2876 statsp->mac_stats.xcvr_inits++; 2877 nxgep->bmsr.value = 0; 2878 2879 fail: 2880 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2881 "<== nxge_mii_xcvr_init status 0x%x", status)); 2882 return (status); 2883 } 2884 2885 nxge_status_t 2886 nxge_mii_xcvr_fiber_init(p_nxge_t nxgep) 2887 { 2888 p_nxge_param_t param_arr; 2889 p_nxge_stats_t statsp; 2890 uint8_t xcvr_portn; 2891 p_mii_regs_t mii_regs; 2892 mii_bmcr_t bmcr; 2893 mii_bmsr_t bmsr; 2894 mii_gcr_t gcr; 2895 mii_esr_t esr; 2896 mii_aux_ctl_t bcm5464r_aux; 2897 int status = NXGE_OK; 2898 2899 uint_t delay; 2900 2901 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_fiber_init")); 2902 2903 param_arr = nxgep->param_arr; 2904 statsp = nxgep->statsp; 2905 xcvr_portn = statsp->mac_stats.xcvr_portn; 2906 2907 mii_regs = NULL; 2908 2909 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2910 "nxge_mii_xcvr_fiber_init: " 2911 "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value)); 2912 2913 /* 2914 * Reset the transceiver. 2915 */ 2916 delay = 0; 2917 bmcr.value = 0; 2918 bmcr.bits.reset = 1; 2919 2920 #if defined(__i386) 2921 2922 if ((status = nxge_mii_write(nxgep, xcvr_portn, 2923 (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 2924 goto fail; 2925 #else 2926 if ((status = nxge_mii_write(nxgep, xcvr_portn, 2927 (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 2928 goto fail; 2929 #endif 2930 do { 2931 drv_usecwait(500); 2932 #if defined(__i386) 2933 if ((status = nxge_mii_read(nxgep, xcvr_portn, 2934 (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) 2935 != NXGE_OK) 2936 goto fail; 2937 #else 2938 if ((status = nxge_mii_read(nxgep, xcvr_portn, 2939 (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) 2940 != NXGE_OK) 2941 goto fail; 2942 #endif 2943 delay++; 2944 } while ((bmcr.bits.reset) && (delay < 1000)); 2945 if (delay == 1000) { 2946 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed.")); 2947 goto fail; 2948 } 2949 2950 #if defined(__i386) 2951 if ((status = nxge_mii_read(nxgep, xcvr_portn, 2952 (uint8_t)(uint32_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK) 2953 goto fail; 2954 #else 2955 if ((status = nxge_mii_read(nxgep, xcvr_portn, 2956 (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK) 2957 goto fail; 2958 #endif 2959 2960 param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able; 2961 param_arr[param_anar_100T4].value = 0; 2962 param_arr[param_anar_100fdx].value = 0; 2963 param_arr[param_anar_100hdx].value = 0; 2964 param_arr[param_anar_10fdx].value = 0; 2965 param_arr[param_anar_10hdx].value = 0; 2966 2967 /* 2968 * Initialize the xcvr statistics. 2969 */ 2970 statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able; 2971 statsp->mac_stats.cap_100T4 = 0; 2972 statsp->mac_stats.cap_100fdx = 0; 2973 statsp->mac_stats.cap_100hdx = 0; 2974 statsp->mac_stats.cap_10fdx = 0; 2975 statsp->mac_stats.cap_10hdx = 0; 2976 statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value; 2977 statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value; 2978 2979 /* 2980 * Initialize the xcvr advertised capability statistics. 2981 */ 2982 statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value; 2983 statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 2984 statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 2985 statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value; 2986 statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value; 2987 statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value; 2988 statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value; 2989 statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value; 2990 statsp->mac_stats.adv_cap_asmpause = 2991 param_arr[param_anar_asmpause].value; 2992 statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value; 2993 2994 /* 2995 * Check for extended status just in case we're 2996 * running a Gigibit phy. 2997 */ 2998 if (bmsr.bits.extend_status) { 2999 #if defined(__i386) 3000 if ((status = nxge_mii_read(nxgep, xcvr_portn, 3001 (uint8_t)(uint32_t)(&mii_regs->esr), &esr.value)) != 3002 NXGE_OK) 3003 goto fail; 3004 #else 3005 if ((status = nxge_mii_read(nxgep, xcvr_portn, 3006 (uint8_t)(uint64_t)(&mii_regs->esr), &esr.value)) != 3007 NXGE_OK) 3008 goto fail; 3009 #endif 3010 param_arr[param_anar_1000fdx].value &= 3011 esr.bits.link_1000fdx; 3012 param_arr[param_anar_1000hdx].value = 0; 3013 3014 statsp->mac_stats.cap_1000fdx = 3015 (esr.bits.link_1000Xfdx || esr.bits.link_1000fdx); 3016 statsp->mac_stats.cap_1000hdx = 0; 3017 } else { 3018 param_arr[param_anar_1000fdx].value = 0; 3019 param_arr[param_anar_1000hdx].value = 0; 3020 } 3021 3022 /* 3023 * Initialize 1G Statistics once the capability is established. 3024 */ 3025 statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 3026 statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 3027 3028 /* 3029 * Initialize the link statistics. 3030 */ 3031 statsp->mac_stats.link_T4 = 0; 3032 statsp->mac_stats.link_asmpause = 0; 3033 statsp->mac_stats.link_pause = 0; 3034 statsp->mac_stats.link_speed = 0; 3035 statsp->mac_stats.link_duplex = 0; 3036 statsp->mac_stats.link_up = 0; 3037 3038 /* 3039 * Switch off Auto-negotiation, 100M and full duplex. 3040 */ 3041 bmcr.value = 0; 3042 #if defined(__i386) 3043 if ((status = nxge_mii_write(nxgep, xcvr_portn, 3044 (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 3045 goto fail; 3046 #else 3047 if ((status = nxge_mii_write(nxgep, xcvr_portn, 3048 (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 3049 goto fail; 3050 #endif 3051 3052 if ((statsp->port_stats.lb_mode == nxge_lb_phy) || 3053 (statsp->port_stats.lb_mode == nxge_lb_phy1000)) { 3054 bmcr.bits.loopback = 1; 3055 bmcr.bits.enable_autoneg = 0; 3056 if (statsp->port_stats.lb_mode == nxge_lb_phy1000) 3057 bmcr.bits.speed_1000_sel = 1; 3058 bmcr.bits.duplex_mode = 1; 3059 param_arr[param_autoneg].value = 0; 3060 } else { 3061 bmcr.bits.loopback = 0; 3062 } 3063 3064 if (statsp->port_stats.lb_mode == nxge_lb_ext1000) { 3065 param_arr[param_autoneg].value = 0; 3066 bcm5464r_aux.value = 0; 3067 bcm5464r_aux.bits.ext_lb = 1; 3068 bcm5464r_aux.bits.write_1 = 1; 3069 if ((status = nxge_mii_write(nxgep, xcvr_portn, 3070 BCM5464R_AUX_CTL, bcm5464r_aux.value)) != NXGE_OK) 3071 goto fail; 3072 } 3073 3074 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode.")); 3075 bmcr.bits.speed_1000_sel = 1; 3076 bmcr.bits.speed_sel = 0; 3077 bmcr.bits.duplex_mode = 1; 3078 statsp->mac_stats.link_speed = 1000; 3079 statsp->mac_stats.link_duplex = 2; 3080 3081 if ((statsp->port_stats.lb_mode == nxge_lb_ext1000)) { 3082 /* BCM5464R 1000mbps external loopback mode */ 3083 gcr.value = 0; 3084 gcr.bits.ms_mode_en = 1; 3085 gcr.bits.master = 1; 3086 #if defined(__i386) 3087 if ((status = nxge_mii_write(nxgep, xcvr_portn, 3088 (uint8_t)(uint32_t)(&mii_regs->gcr), 3089 gcr.value)) != NXGE_OK) 3090 goto fail; 3091 #else 3092 if ((status = nxge_mii_write(nxgep, xcvr_portn, 3093 (uint8_t)(uint64_t)(&mii_regs->gcr), 3094 gcr.value)) != NXGE_OK) 3095 goto fail; 3096 #endif 3097 bmcr.value = 0; 3098 bmcr.bits.speed_1000_sel = 1; 3099 statsp->mac_stats.link_speed = 1000; 3100 } 3101 3102 #if defined(__i386) 3103 if ((status = nxge_mii_write(nxgep, xcvr_portn, 3104 (uint8_t)(uint32_t)(&mii_regs->bmcr), 3105 bmcr.value)) != NXGE_OK) 3106 goto fail; 3107 #else 3108 if ((status = nxge_mii_write(nxgep, xcvr_portn, 3109 (uint8_t)(uint64_t)(&mii_regs->bmcr), 3110 bmcr.value)) != NXGE_OK) 3111 goto fail; 3112 #endif 3113 3114 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3115 "nxge_mii_xcvr_fiber_init: value wrote bmcr = 0x%x", 3116 bmcr.value)); 3117 3118 #if defined(__i386) 3119 if ((status = nxge_mii_read(nxgep, xcvr_portn, 3120 (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK) 3121 goto fail; 3122 #else 3123 if ((status = nxge_mii_read(nxgep, xcvr_portn, 3124 (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK) 3125 goto fail; 3126 #endif 3127 3128 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3129 "nxge_mii_xcvr_fiber_init: read bmcr = 0x%04X", bmcr.value)); 3130 3131 /* 3132 * Initialize the xcvr status kept in the context structure. 3133 */ 3134 nxgep->soft_bmsr.value = 0; 3135 #if defined(__i386) 3136 if ((status = nxge_mii_read(nxgep, xcvr_portn, 3137 (uint8_t)(uint32_t)(&mii_regs->bmsr), 3138 &nxgep->bmsr.value)) != NXGE_OK) 3139 goto fail; 3140 #else 3141 if ((status = nxge_mii_read(nxgep, xcvr_portn, 3142 (uint8_t)(uint64_t)(&mii_regs->bmsr), 3143 &nxgep->bmsr.value)) != NXGE_OK) 3144 goto fail; 3145 #endif 3146 3147 statsp->mac_stats.xcvr_inits++; 3148 nxgep->bmsr.value = 0; 3149 3150 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3151 "<== nxge_mii_xcvr_fiber_init status 0x%x", status)); 3152 return (status); 3153 3154 fail: 3155 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3156 "<== nxge_mii_xcvr_fiber_init status 0x%x", status)); 3157 return (status); 3158 } 3159 3160 /* Read from a MII compliant register */ 3161 3162 nxge_status_t 3163 nxge_mii_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg, 3164 uint16_t *value) 3165 { 3166 npi_status_t rs = NPI_SUCCESS; 3167 3168 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_read: xcvr_port<%d>" 3169 "xcvr_reg<%d>", xcvr_portn, xcvr_reg)); 3170 3171 MUTEX_ENTER(&nxge_mii_lock); 3172 3173 if ((nxgep->mac.portmode == PORT_1G_COPPER) || 3174 (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) { 3175 if ((rs = npi_mac_mif_mii_read(nxgep->npi_handle, 3176 xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 3177 goto fail; 3178 } else if ((nxgep->mac.portmode == PORT_1G_FIBER) || 3179 (nxgep->mac.portmode == PORT_1G_SERDES)) { 3180 if ((rs = npi_mac_pcs_mii_read(nxgep->npi_handle, 3181 xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 3182 goto fail; 3183 } else 3184 goto fail; 3185 3186 MUTEX_EXIT(&nxge_mii_lock); 3187 3188 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_read: xcvr_port<%d>" 3189 "xcvr_reg<%d> value=0x%x", 3190 xcvr_portn, xcvr_reg, *value)); 3191 return (NXGE_OK); 3192 fail: 3193 MUTEX_EXIT(&nxge_mii_lock); 3194 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3195 "nxge_mii_read: Failed to read mii on xcvr %d", 3196 xcvr_portn)); 3197 3198 return (NXGE_ERROR | rs); 3199 } 3200 3201 /* Write to a MII compliant Register */ 3202 3203 nxge_status_t 3204 nxge_mii_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg, 3205 uint16_t value) 3206 { 3207 npi_status_t rs = NPI_SUCCESS; 3208 3209 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_write: xcvr_port<%d>" 3210 "xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg, 3211 value)); 3212 3213 MUTEX_ENTER(&nxge_mii_lock); 3214 3215 if ((nxgep->mac.portmode == PORT_1G_COPPER) || 3216 (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) { 3217 if ((rs = npi_mac_mif_mii_write(nxgep->npi_handle, 3218 xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 3219 goto fail; 3220 } else if ((nxgep->mac.portmode == PORT_1G_FIBER) || 3221 (nxgep->mac.portmode == PORT_1G_SERDES)) { 3222 if ((rs = npi_mac_pcs_mii_write(nxgep->npi_handle, 3223 xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 3224 goto fail; 3225 } else 3226 goto fail; 3227 3228 MUTEX_EXIT(&nxge_mii_lock); 3229 3230 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_write: xcvr_port<%d>" 3231 "xcvr_reg<%d>", xcvr_portn, xcvr_reg)); 3232 return (NXGE_OK); 3233 fail: 3234 MUTEX_EXIT(&nxge_mii_lock); 3235 3236 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3237 "nxge_mii_write: Failed to write mii on xcvr %d", 3238 xcvr_portn)); 3239 3240 return (NXGE_ERROR | rs); 3241 } 3242 3243 /* Perform read from Clause45 serdes / transceiver device */ 3244 3245 nxge_status_t 3246 nxge_mdio_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device, 3247 uint16_t xcvr_reg, uint16_t *value) 3248 { 3249 npi_status_t rs = NPI_SUCCESS; 3250 3251 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_read: xcvr_port<%d>", 3252 xcvr_portn)); 3253 3254 MUTEX_ENTER(&nxge_mdio_lock); 3255 3256 if ((rs = npi_mac_mif_mdio_read(nxgep->npi_handle, 3257 xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS) 3258 goto fail; 3259 3260 MUTEX_EXIT(&nxge_mdio_lock); 3261 3262 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_read: xcvr_port<%d>", 3263 xcvr_portn)); 3264 return (NXGE_OK); 3265 fail: 3266 MUTEX_EXIT(&nxge_mdio_lock); 3267 3268 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3269 "nxge_mdio_read: Failed to read mdio on xcvr %d", 3270 xcvr_portn)); 3271 3272 return (NXGE_ERROR | rs); 3273 } 3274 3275 /* Perform write to Clause45 serdes / transceiver device */ 3276 3277 nxge_status_t 3278 nxge_mdio_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device, 3279 uint16_t xcvr_reg, uint16_t value) 3280 { 3281 npi_status_t rs = NPI_SUCCESS; 3282 3283 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_write: xcvr_port<%d>", 3284 xcvr_portn)); 3285 3286 MUTEX_ENTER(&nxge_mdio_lock); 3287 3288 if ((rs = npi_mac_mif_mdio_write(nxgep->npi_handle, 3289 xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS) 3290 goto fail; 3291 3292 MUTEX_EXIT(&nxge_mdio_lock); 3293 3294 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_write: xcvr_port<%d>", 3295 xcvr_portn)); 3296 return (NXGE_OK); 3297 fail: 3298 MUTEX_EXIT(&nxge_mdio_lock); 3299 3300 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3301 "nxge_mdio_write: Failed to write mdio on xcvr %d", 3302 xcvr_portn)); 3303 3304 return (NXGE_ERROR | rs); 3305 } 3306 3307 3308 /* Check MII to see if there is any link status change */ 3309 3310 nxge_status_t 3311 nxge_mii_check(p_nxge_t nxgep, mii_bmsr_t bmsr, mii_bmsr_t bmsr_ints, 3312 nxge_link_state_t *link_up) 3313 { 3314 p_nxge_param_t param_arr; 3315 p_nxge_stats_t statsp; 3316 p_mii_regs_t mii_regs; 3317 p_mii_bmsr_t soft_bmsr; 3318 mii_anar_t anar; 3319 mii_anlpar_t anlpar; 3320 mii_anar_t an_common; 3321 mii_aner_t aner; 3322 mii_gsr_t gsr; 3323 nxge_status_t status = NXGE_OK; 3324 3325 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_check")); 3326 3327 mii_regs = NULL; 3328 param_arr = nxgep->param_arr; 3329 statsp = nxgep->statsp; 3330 soft_bmsr = &nxgep->soft_bmsr; 3331 *link_up = LINK_NO_CHANGE; 3332 3333 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3334 "==> nxge_mii_check bmsr 0x%x bmsr_int 0x%x", 3335 bmsr.value, bmsr_ints.value)); 3336 3337 if (bmsr_ints.bits.link_status) { 3338 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3339 "==> nxge_mii_check (link up) bmsr 0x%x bmsr_int 0x%x", 3340 bmsr.value, bmsr_ints.value)); 3341 if (bmsr.bits.link_status) { 3342 soft_bmsr->bits.link_status = 1; 3343 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3344 "==> nxge_mii_check (link up) soft bmsr 0x%x bmsr_int " 3345 "0x%x", bmsr.value, bmsr_ints.value)); 3346 } else { 3347 statsp->mac_stats.link_up = 0; 3348 soft_bmsr->bits.link_status = 0; 3349 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3350 "Link down cable problem")); 3351 *link_up = LINK_IS_DOWN; 3352 } 3353 } 3354 3355 if (nxgep->mac.portmode == PORT_1G_COPPER && 3356 param_arr[param_autoneg].value) { 3357 if (bmsr_ints.bits.auto_neg_complete) { 3358 if (bmsr.bits.auto_neg_complete) 3359 soft_bmsr->bits.auto_neg_complete = 1; 3360 else 3361 soft_bmsr->bits.auto_neg_complete = 0; 3362 } 3363 if (soft_bmsr->bits.link_status == 0) { 3364 statsp->mac_stats.link_T4 = 0; 3365 statsp->mac_stats.link_speed = 0; 3366 statsp->mac_stats.link_duplex = 0; 3367 statsp->mac_stats.link_asmpause = 0; 3368 statsp->mac_stats.link_pause = 0; 3369 statsp->mac_stats.lp_cap_autoneg = 0; 3370 statsp->mac_stats.lp_cap_100T4 = 0; 3371 statsp->mac_stats.lp_cap_1000fdx = 0; 3372 statsp->mac_stats.lp_cap_1000hdx = 0; 3373 statsp->mac_stats.lp_cap_100fdx = 0; 3374 statsp->mac_stats.lp_cap_100hdx = 0; 3375 statsp->mac_stats.lp_cap_10fdx = 0; 3376 statsp->mac_stats.lp_cap_10hdx = 0; 3377 statsp->mac_stats.lp_cap_10gfdx = 0; 3378 statsp->mac_stats.lp_cap_10ghdx = 0; 3379 statsp->mac_stats.lp_cap_asmpause = 0; 3380 statsp->mac_stats.lp_cap_pause = 0; 3381 } 3382 } else 3383 soft_bmsr->bits.auto_neg_complete = 1; 3384 3385 if ((bmsr_ints.bits.link_status || 3386 bmsr_ints.bits.auto_neg_complete) && 3387 soft_bmsr->bits.link_status && 3388 soft_bmsr->bits.auto_neg_complete) { 3389 statsp->mac_stats.link_up = 1; 3390 3391 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3392 "==> nxge_mii_check " 3393 "(auto negotiation complete or link up) " 3394 "soft bmsr 0x%x bmsr_int 0x%x", 3395 bmsr.value, bmsr_ints.value)); 3396 3397 if (nxgep->mac.portmode == PORT_1G_COPPER && 3398 param_arr[param_autoneg].value) { 3399 if ((status = nxge_mii_read(nxgep, 3400 statsp->mac_stats.xcvr_portn, 3401 #if defined(__i386) 3402 (uint8_t)(uint32_t)(&mii_regs->anar), 3403 #else 3404 (uint8_t)(uint64_t)(&mii_regs->anar), 3405 #endif 3406 &anar.value)) != NXGE_OK) 3407 goto fail; 3408 if ((status = nxge_mii_read(nxgep, 3409 statsp->mac_stats.xcvr_portn, 3410 #if defined(__i386) 3411 (uint8_t)(uint32_t)(&mii_regs->anlpar), 3412 #else 3413 (uint8_t)(uint64_t)(&mii_regs->anlpar), 3414 #endif 3415 &anlpar.value)) != NXGE_OK) 3416 goto fail; 3417 if ((status = nxge_mii_read(nxgep, 3418 statsp->mac_stats.xcvr_portn, 3419 #if defined(__i386) 3420 (uint8_t)(uint32_t)(&mii_regs->aner), 3421 #else 3422 (uint8_t)(uint64_t)(&mii_regs->aner), 3423 #endif 3424 &aner.value)) != NXGE_OK) 3425 goto fail; 3426 statsp->mac_stats.lp_cap_autoneg = aner.bits.lp_an_able; 3427 statsp->mac_stats.lp_cap_100T4 = anlpar.bits.cap_100T4; 3428 statsp->mac_stats.lp_cap_100fdx = 3429 anlpar.bits.cap_100fdx; 3430 statsp->mac_stats.lp_cap_100hdx = 3431 anlpar.bits.cap_100hdx; 3432 statsp->mac_stats.lp_cap_10fdx = anlpar.bits.cap_10fdx; 3433 statsp->mac_stats.lp_cap_10hdx = anlpar.bits.cap_10hdx; 3434 statsp->mac_stats.lp_cap_asmpause = 3435 anlpar.bits.cap_asmpause; 3436 statsp->mac_stats.lp_cap_pause = anlpar.bits.cap_pause; 3437 an_common.value = anar.value & anlpar.value; 3438 if (param_arr[param_anar_1000fdx].value || 3439 param_arr[param_anar_1000hdx].value) { 3440 if ((status = nxge_mii_read(nxgep, 3441 statsp->mac_stats.xcvr_portn, 3442 #if defined(__i386) 3443 (uint8_t)(uint32_t)(&mii_regs->gsr), 3444 #else 3445 (uint8_t)(uint64_t)(&mii_regs->gsr), 3446 #endif 3447 &gsr.value)) 3448 != NXGE_OK) 3449 goto fail; 3450 statsp->mac_stats.lp_cap_1000fdx = 3451 gsr.bits.link_1000fdx; 3452 statsp->mac_stats.lp_cap_1000hdx = 3453 gsr.bits.link_1000hdx; 3454 if (param_arr[param_anar_1000fdx].value && 3455 gsr.bits.link_1000fdx) { 3456 statsp->mac_stats.link_speed = 1000; 3457 statsp->mac_stats.link_duplex = 2; 3458 } else if ( 3459 param_arr[param_anar_1000hdx].value && 3460 gsr.bits.link_1000hdx) { 3461 statsp->mac_stats.link_speed = 1000; 3462 statsp->mac_stats.link_duplex = 1; 3463 } 3464 } 3465 if ((an_common.value != 0) && 3466 !(statsp->mac_stats.link_speed)) { 3467 if (an_common.bits.cap_100T4) { 3468 statsp->mac_stats.link_T4 = 1; 3469 statsp->mac_stats.link_speed = 100; 3470 statsp->mac_stats.link_duplex = 1; 3471 } else if (an_common.bits.cap_100fdx) { 3472 statsp->mac_stats.link_speed = 100; 3473 statsp->mac_stats.link_duplex = 2; 3474 } else if (an_common.bits.cap_100hdx) { 3475 statsp->mac_stats.link_speed = 100; 3476 statsp->mac_stats.link_duplex = 1; 3477 } else if (an_common.bits.cap_10fdx) { 3478 statsp->mac_stats.link_speed = 10; 3479 statsp->mac_stats.link_duplex = 2; 3480 } else if (an_common.bits.cap_10hdx) { 3481 statsp->mac_stats.link_speed = 10; 3482 statsp->mac_stats.link_duplex = 1; 3483 } else { 3484 goto fail; 3485 } 3486 } 3487 if (statsp->mac_stats.link_duplex != 1) { 3488 statsp->mac_stats.link_asmpause = 3489 an_common.bits.cap_asmpause; 3490 if (statsp->mac_stats.link_asmpause) 3491 if ((statsp->mac_stats.cap_pause == 0) && 3492 (statsp->mac_stats.lp_cap_pause 3493 == 1)) 3494 statsp->mac_stats.link_pause 3495 = 0; 3496 else 3497 statsp->mac_stats.link_pause 3498 = 1; 3499 else 3500 statsp->mac_stats.link_pause = 3501 an_common.bits.cap_pause; 3502 } 3503 } else if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) { 3504 statsp->mac_stats.link_speed = 1000; 3505 statsp->mac_stats.link_duplex = 2; 3506 } 3507 *link_up = LINK_IS_UP; 3508 } 3509 3510 if (nxgep->link_notify) { 3511 *link_up = ((statsp->mac_stats.link_up) ? LINK_IS_UP : 3512 LINK_IS_DOWN); 3513 nxgep->link_notify = B_FALSE; 3514 } 3515 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mii_check")); 3516 return (NXGE_OK); 3517 fail: 3518 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3519 "nxge_mii_check: Unable to check MII")); 3520 return (status); 3521 } 3522 3523 /* Check PCS to see if there is any link status change */ 3524 nxge_status_t 3525 nxge_pcs_check(p_nxge_t nxgep, uint8_t portn, nxge_link_state_t *link_up) 3526 { 3527 p_nxge_stats_t statsp; 3528 nxge_status_t status = NXGE_OK; 3529 boolean_t linkup; 3530 3531 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_check")); 3532 3533 statsp = nxgep->statsp; 3534 *link_up = LINK_NO_CHANGE; 3535 3536 (void) npi_mac_get_link_status(nxgep->npi_handle, portn, &linkup); 3537 if (linkup) { 3538 if (nxgep->link_notify || 3539 nxgep->statsp->mac_stats.link_up == 0) { 3540 statsp->mac_stats.link_up = 1; 3541 statsp->mac_stats.link_speed = 1000; 3542 statsp->mac_stats.link_duplex = 2; 3543 *link_up = LINK_IS_UP; 3544 nxgep->link_notify = B_FALSE; 3545 } 3546 } else { 3547 if (nxgep->link_notify || 3548 nxgep->statsp->mac_stats.link_up == 1) { 3549 statsp->mac_stats.link_up = 0; 3550 statsp->mac_stats.link_speed = 0; 3551 statsp->mac_stats.link_duplex = 0; 3552 *link_up = LINK_IS_DOWN; 3553 nxgep->link_notify = B_FALSE; 3554 } 3555 } 3556 3557 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_check")); 3558 return (NXGE_OK); 3559 fail: 3560 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3561 "nxge_pcs_check: Unable to check PCS")); 3562 return (status); 3563 } 3564 3565 /* Add a multicast address entry into the HW hash table */ 3566 3567 nxge_status_t 3568 nxge_add_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp) 3569 { 3570 uint32_t mchash; 3571 p_hash_filter_t hash_filter; 3572 uint16_t hash_bit; 3573 boolean_t rx_init = B_FALSE; 3574 uint_t j; 3575 nxge_status_t status = NXGE_OK; 3576 3577 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_add_mcast_addr")); 3578 3579 RW_ENTER_WRITER(&nxgep->filter_lock); 3580 mchash = crc32_mchash(addrp); 3581 if (nxgep->hash_filter == NULL) { 3582 NXGE_DEBUG_MSG((NULL, STR_CTL, 3583 "Allocating hash filter storage.")); 3584 nxgep->hash_filter = KMEM_ZALLOC(sizeof (hash_filter_t), 3585 KM_SLEEP); 3586 } 3587 hash_filter = nxgep->hash_filter; 3588 j = mchash / HASH_REG_WIDTH; 3589 hash_bit = (1 << (mchash % HASH_REG_WIDTH)); 3590 hash_filter->hash_filter_regs[j] |= hash_bit; 3591 hash_filter->hash_bit_ref_cnt[mchash]++; 3592 if (hash_filter->hash_bit_ref_cnt[mchash] == 1) { 3593 hash_filter->hash_ref_cnt++; 3594 rx_init = B_TRUE; 3595 } 3596 if (rx_init) { 3597 if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 3598 goto fail; 3599 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 3600 goto fail; 3601 } 3602 3603 RW_EXIT(&nxgep->filter_lock); 3604 3605 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_add_mcast_addr")); 3606 3607 return (NXGE_OK); 3608 fail: 3609 RW_EXIT(&nxgep->filter_lock); 3610 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_add_mcast_addr: " 3611 "Unable to add multicast address")); 3612 return (status); 3613 } 3614 3615 /* Remove a multicast address entry from the HW hash table */ 3616 3617 nxge_status_t 3618 nxge_del_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp) 3619 { 3620 uint32_t mchash; 3621 p_hash_filter_t hash_filter; 3622 uint16_t hash_bit; 3623 boolean_t rx_init = B_FALSE; 3624 uint_t j; 3625 nxge_status_t status = NXGE_OK; 3626 3627 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_del_mcast_addr")); 3628 RW_ENTER_WRITER(&nxgep->filter_lock); 3629 mchash = crc32_mchash(addrp); 3630 if (nxgep->hash_filter == NULL) { 3631 NXGE_DEBUG_MSG((NULL, STR_CTL, 3632 "Hash filter already de_allocated.")); 3633 RW_EXIT(&nxgep->filter_lock); 3634 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr")); 3635 return (NXGE_OK); 3636 } 3637 hash_filter = nxgep->hash_filter; 3638 hash_filter->hash_bit_ref_cnt[mchash]--; 3639 if (hash_filter->hash_bit_ref_cnt[mchash] == 0) { 3640 j = mchash / HASH_REG_WIDTH; 3641 hash_bit = (1 << (mchash % HASH_REG_WIDTH)); 3642 hash_filter->hash_filter_regs[j] &= ~hash_bit; 3643 hash_filter->hash_ref_cnt--; 3644 rx_init = B_TRUE; 3645 } 3646 if (hash_filter->hash_ref_cnt == 0) { 3647 NXGE_DEBUG_MSG((NULL, STR_CTL, 3648 "De-allocating hash filter storage.")); 3649 KMEM_FREE(hash_filter, sizeof (hash_filter_t)); 3650 nxgep->hash_filter = NULL; 3651 } 3652 3653 if (rx_init) { 3654 if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 3655 goto fail; 3656 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 3657 goto fail; 3658 } 3659 RW_EXIT(&nxgep->filter_lock); 3660 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr")); 3661 3662 return (NXGE_OK); 3663 fail: 3664 RW_EXIT(&nxgep->filter_lock); 3665 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_del_mcast_addr: " 3666 "Unable to remove multicast address")); 3667 3668 return (status); 3669 } 3670 3671 /* Set MAC address into MAC address HW registers */ 3672 3673 nxge_status_t 3674 nxge_set_mac_addr(p_nxge_t nxgep, struct ether_addr *addrp) 3675 { 3676 nxge_status_t status = NXGE_OK; 3677 3678 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_mac_addr")); 3679 3680 MUTEX_ENTER(&nxgep->ouraddr_lock); 3681 /* 3682 * Exit if the address is same as ouraddr or multicast or broadcast 3683 */ 3684 if (((addrp->ether_addr_octet[0] & 01) == 1) || 3685 (ether_cmp(addrp, ðerbroadcastaddr) == 0) || 3686 (ether_cmp(addrp, &nxgep->ouraddr) == 0)) { 3687 goto nxge_set_mac_addr_exit; 3688 } 3689 nxgep->ouraddr = *addrp; 3690 /* 3691 * Set new interface local address and re-init device. 3692 * This is destructive to any other streams attached 3693 * to this device. 3694 */ 3695 RW_ENTER_WRITER(&nxgep->filter_lock); 3696 if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 3697 goto fail; 3698 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 3699 goto fail; 3700 3701 RW_EXIT(&nxgep->filter_lock); 3702 MUTEX_EXIT(&nxgep->ouraddr_lock); 3703 goto nxge_set_mac_addr_end; 3704 nxge_set_mac_addr_exit: 3705 MUTEX_EXIT(&nxgep->ouraddr_lock); 3706 nxge_set_mac_addr_end: 3707 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_mac_addr")); 3708 3709 return (NXGE_OK); 3710 fail: 3711 MUTEX_EXIT(&nxgep->ouraddr_lock); 3712 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_mac_addr: " 3713 "Unable to set mac address")); 3714 return (status); 3715 } 3716 3717 static 3718 check_link_state_t 3719 nxge_check_link_stop( 3720 nxge_t *nxge) 3721 { 3722 /* If the poll has been cancelled, return STOP. */ 3723 MUTEX_ENTER(&nxge->poll_lock); 3724 if (nxge->suspended || nxge->poll_state == LINK_MONITOR_STOPPING) { 3725 nxge->poll_state = LINK_MONITOR_STOP; 3726 nxge->nxge_link_poll_timerid = 0; 3727 cv_broadcast(&nxge->poll_cv); 3728 MUTEX_EXIT(&nxge->poll_lock); 3729 3730 NXGE_DEBUG_MSG((nxge, MAC_CTL, 3731 "nxge_check_%s_link(port<%d>) stopped.", 3732 nxge->mac.portmode == PORT_10G_FIBER ? "10g" : "mii", 3733 nxge->mac.portnum)); 3734 return (CHECK_LINK_STOP); 3735 } 3736 MUTEX_EXIT(&nxge->poll_lock); 3737 3738 return (CHECK_LINK_RESCHEDULE); 3739 } 3740 3741 /* Check status of MII (MIF or PCS) link */ 3742 3743 static nxge_status_t 3744 nxge_check_mii_link(p_nxge_t nxgep) 3745 { 3746 mii_bmsr_t bmsr_ints, bmsr_data; 3747 mii_anlpar_t anlpar; 3748 mii_gsr_t gsr; 3749 p_mii_regs_t mii_regs; 3750 nxge_status_t status = NXGE_OK; 3751 uint8_t portn; 3752 nxge_link_state_t link_up; 3753 3754 if (nxgep->nxge_magic != NXGE_MAGIC) 3755 return (NXGE_ERROR); 3756 3757 if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 3758 return (NXGE_OK); 3759 3760 portn = nxgep->mac.portnum; 3761 3762 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_mii_link port<%d>", 3763 portn)); 3764 3765 mii_regs = NULL; 3766 3767 RW_ENTER_WRITER(&nxgep->filter_lock); 3768 3769 if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10) 3770 goto nxge_check_mii_link_exit; 3771 3772 switch (nxgep->mac.portmode) { 3773 default: 3774 bmsr_data.value = 0; 3775 if ((status = nxge_mii_read(nxgep, 3776 nxgep->statsp->mac_stats.xcvr_portn, 3777 #if defined(__i386) 3778 (uint8_t)(uint32_t)(&mii_regs->bmsr), 3779 #else 3780 (uint8_t)(uint64_t)(&mii_regs->bmsr), 3781 #endif 3782 &bmsr_data.value)) != NXGE_OK) { 3783 goto fail; 3784 } 3785 3786 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3787 "==> nxge_check_mii_link port<0x%x> " 3788 "RIGHT AFTER READ bmsr_data 0x%x (nxgep->bmsr 0x%x ", 3789 xcvr_portn, bmsr_data.value, nxgep->bmsr.value)); 3790 3791 if (nxgep->param_arr[param_autoneg].value) { 3792 if ((status = nxge_mii_read(nxgep, 3793 nxgep->statsp->mac_stats.xcvr_portn, 3794 #if defined(__i386) 3795 (uint8_t)(uint32_t)(&mii_regs->gsr), 3796 #else 3797 (uint8_t)(uint64_t)(&mii_regs->gsr), 3798 #endif 3799 &gsr.value)) != NXGE_OK) 3800 goto fail; 3801 if ((status = nxge_mii_read(nxgep, 3802 nxgep->statsp->mac_stats.xcvr_portn, 3803 #if defined(__i386) 3804 (uint8_t)(uint32_t)(&mii_regs->anlpar), 3805 #else 3806 (uint8_t)(uint64_t)(&mii_regs->anlpar), 3807 #endif 3808 &anlpar.value)) != NXGE_OK) 3809 goto fail; 3810 if (nxgep->mac.portmode != PORT_1G_RGMII_FIBER) { 3811 3812 if (nxgep->statsp->mac_stats.link_up && 3813 ((nxgep->statsp->mac_stats.lp_cap_1000fdx ^ 3814 gsr.bits.link_1000fdx) || 3815 (nxgep->statsp->mac_stats.lp_cap_1000hdx ^ 3816 gsr.bits.link_1000hdx) || 3817 (nxgep->statsp->mac_stats.lp_cap_100T4 ^ 3818 anlpar.bits.cap_100T4) || 3819 (nxgep->statsp->mac_stats.lp_cap_100fdx ^ 3820 anlpar.bits.cap_100fdx) || 3821 (nxgep->statsp->mac_stats.lp_cap_100hdx ^ 3822 anlpar.bits.cap_100hdx) || 3823 (nxgep->statsp->mac_stats.lp_cap_10fdx ^ 3824 anlpar.bits.cap_10fdx) || 3825 (nxgep->statsp->mac_stats.lp_cap_10hdx ^ 3826 anlpar.bits.cap_10hdx))) { 3827 bmsr_data.bits.link_status = 0; 3828 } 3829 } 3830 } 3831 3832 /* Workaround for link down issue */ 3833 if (bmsr_data.value == 0) { 3834 cmn_err(CE_NOTE, "!LINK DEBUG: Read zero bmsr\n"); 3835 goto nxge_check_mii_link_exit; 3836 } 3837 3838 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3839 "==> nxge_check_mii_link port<0x%x> :" 3840 "BEFORE BMSR ^ nxgep->bmsr 0x%x bmsr_data 0x%x", 3841 xcvr_portn, nxgep->bmsr.value, bmsr_data.value)); 3842 3843 bmsr_ints.value = nxgep->bmsr.value ^ bmsr_data.value; 3844 nxgep->bmsr.value = bmsr_data.value; 3845 3846 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3847 "==> nxge_check_mii_link port<0x%x> CALLING " 3848 "bmsr_data 0x%x bmsr_ints.value 0x%x", 3849 xcvr_portn, bmsr_data.value, bmsr_ints.value)); 3850 3851 if ((status = nxge_mii_check(nxgep, bmsr_data, bmsr_ints, 3852 &link_up)) != NXGE_OK) { 3853 goto fail; 3854 } 3855 break; 3856 3857 case PORT_1G_SERDES: 3858 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3859 "==> nxge_check_mii_link port<%d> (SERDES)", portn)); 3860 if ((status = nxge_pcs_check(nxgep, portn, &link_up)) 3861 != NXGE_OK) { 3862 goto fail; 3863 } 3864 break; 3865 } 3866 3867 nxge_check_mii_link_exit: 3868 RW_EXIT(&nxgep->filter_lock); 3869 if (link_up == LINK_IS_UP) { 3870 nxge_link_is_up(nxgep); 3871 } else if (link_up == LINK_IS_DOWN) { 3872 nxge_link_is_down(nxgep); 3873 } 3874 3875 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 3876 3877 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_mii_link port<%d>", 3878 portn)); 3879 return (NXGE_OK); 3880 3881 fail: 3882 RW_EXIT(&nxgep->filter_lock); 3883 3884 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 3885 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3886 "nxge_check_mii_link: Failed to check link port<%d>", 3887 portn)); 3888 return (status); 3889 } 3890 3891 3892 /*ARGSUSED*/ 3893 static nxge_status_t 3894 nxge_check_10g_link(p_nxge_t nxgep) 3895 { 3896 uint8_t portn; 3897 nxge_status_t status = NXGE_OK; 3898 boolean_t link_up; 3899 uint32_t val; 3900 npi_status_t rs; 3901 3902 if (nxgep->nxge_magic != NXGE_MAGIC) 3903 return (NXGE_ERROR); 3904 3905 if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 3906 return (NXGE_OK); 3907 3908 portn = nxgep->mac.portnum; 3909 val = 0; 3910 rs = NPI_SUCCESS; 3911 3912 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_10g_link port<%d>", 3913 portn)); 3914 3915 switch (nxgep->mac.portmode) { 3916 default: 3917 status = nxge_check_bcm8704_link(nxgep, &link_up); 3918 if (status != NXGE_OK) 3919 goto fail; 3920 break; 3921 case PORT_10G_SERDES: 3922 rs = npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 3923 XPCS_REG_STATUS, &val); 3924 if (rs != 0) 3925 goto fail; 3926 3927 link_up = B_FALSE; 3928 if (val & XPCS_STATUS_LANE_ALIGN) { 3929 link_up = B_TRUE; 3930 } 3931 3932 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3933 "==> nxge_check_10g_link port<%d> " 3934 "XPCS_REG_STATUS2 0x%x link_up %d", 3935 portn, val, link_up)); 3936 3937 break; 3938 } 3939 3940 if (link_up) { 3941 if (nxgep->link_notify || 3942 nxgep->statsp->mac_stats.link_up == 0) { 3943 if (nxge_10g_link_led_on(nxgep) != NXGE_OK) 3944 goto fail; 3945 nxgep->statsp->mac_stats.link_up = 1; 3946 nxgep->statsp->mac_stats.link_speed = 10000; 3947 nxgep->statsp->mac_stats.link_duplex = 2; 3948 3949 nxge_link_is_up(nxgep); 3950 nxgep->link_notify = B_FALSE; 3951 } 3952 } else { 3953 if (nxgep->link_notify || 3954 nxgep->statsp->mac_stats.link_up == 1) { 3955 if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 3956 goto fail; 3957 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3958 "Link down cable problem")); 3959 nxgep->statsp->mac_stats.link_up = 0; 3960 nxgep->statsp->mac_stats.link_speed = 0; 3961 nxgep->statsp->mac_stats.link_duplex = 0; 3962 3963 nxge_link_is_down(nxgep); 3964 nxgep->link_notify = B_FALSE; 3965 } 3966 } 3967 3968 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 3969 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_10g_link port<%d>", 3970 portn)); 3971 return (NXGE_OK); 3972 3973 fail: 3974 (void) nxge_check_link_stop(nxgep); 3975 3976 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3977 "nxge_check_10g_link: Failed to check link port<%d>", 3978 portn)); 3979 return (status); 3980 } 3981 3982 3983 /* Declare link down */ 3984 3985 void 3986 nxge_link_is_down(p_nxge_t nxgep) 3987 { 3988 p_nxge_stats_t statsp; 3989 char link_stat_msg[64]; 3990 3991 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_down")); 3992 3993 statsp = nxgep->statsp; 3994 (void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is down", 3995 statsp->mac_stats.xcvr_portn); 3996 3997 if (nxge_no_msg == B_FALSE) { 3998 NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg)); 3999 } 4000 4001 mac_link_update(nxgep->mach, LINK_STATE_DOWN); 4002 4003 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_down")); 4004 } 4005 4006 /* Declare link up */ 4007 4008 void 4009 nxge_link_is_up(p_nxge_t nxgep) 4010 { 4011 p_nxge_stats_t statsp; 4012 char link_stat_msg[64]; 4013 uint32_t val; 4014 4015 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_up")); 4016 4017 statsp = nxgep->statsp; 4018 (void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is up %d Mbps ", 4019 statsp->mac_stats.xcvr_portn, 4020 statsp->mac_stats.link_speed); 4021 4022 if (statsp->mac_stats.link_T4) 4023 (void) strcat(link_stat_msg, "T4"); 4024 else if (statsp->mac_stats.link_duplex == 2) 4025 (void) strcat(link_stat_msg, "full duplex"); 4026 else 4027 (void) strcat(link_stat_msg, "half duplex"); 4028 4029 (void) nxge_xif_init(nxgep); 4030 4031 /* Clean up symbol errors incurred during link transition */ 4032 if ((nxgep->mac.portmode == PORT_10G_FIBER) || 4033 (nxgep->mac.portmode == PORT_10G_SERDES)) { 4034 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 4035 XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val); 4036 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 4037 XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val); 4038 } 4039 4040 if (nxge_no_msg == B_FALSE) { 4041 NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg)); 4042 } 4043 4044 mac_link_update(nxgep->mach, LINK_STATE_UP); 4045 4046 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_up")); 4047 } 4048 4049 /* 4050 * Calculate the bit in the multicast address filter 4051 * that selects the given * address. 4052 * Note: For GEM, the last 8-bits are used. 4053 */ 4054 uint32_t 4055 crc32_mchash(p_ether_addr_t addr) 4056 { 4057 uint8_t *cp; 4058 uint32_t crc; 4059 uint32_t c; 4060 int byte; 4061 int bit; 4062 4063 cp = (uint8_t *)addr; 4064 crc = (uint32_t)0xffffffff; 4065 for (byte = 0; byte < 6; byte++) { 4066 c = (uint32_t)cp[byte]; 4067 for (bit = 0; bit < 8; bit++) { 4068 if ((c & 0x1) ^ (crc & 0x1)) 4069 crc = (crc >> 1)^0xedb88320; 4070 else 4071 crc = (crc >> 1); 4072 c >>= 1; 4073 } 4074 } 4075 return ((~crc) >> (32 - HASH_BITS)); 4076 } 4077 4078 /* Reset serdes */ 4079 4080 nxge_status_t 4081 nxge_serdes_reset(p_nxge_t nxgep) 4082 { 4083 npi_handle_t handle; 4084 4085 handle = nxgep->npi_handle; 4086 4087 ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0 | ESR_RESET_1); 4088 drv_usecwait(500); 4089 ESR_REG_WR(handle, ESR_CONFIG_REG, 0); 4090 4091 return (NXGE_OK); 4092 } 4093 4094 /* Monitor link status using interrupt or polling */ 4095 4096 nxge_status_t 4097 nxge_link_monitor(p_nxge_t nxgep, link_mon_enable_t enable) 4098 { 4099 nxge_status_t status = NXGE_OK; 4100 4101 /* 4102 * Return immediately if this is an imaginary XMAC port. 4103 * (At least, we don't have 4-port XMAC cards yet.) 4104 */ 4105 if ((nxgep->mac.portmode == PORT_10G_FIBER || 4106 nxgep->mac.portmode == PORT_10G_SERDES) && 4107 (nxgep->mac.portnum > 1)) 4108 return (NXGE_OK); 4109 4110 if (nxgep->statsp == NULL) { 4111 /* stats has not been allocated. */ 4112 return (NXGE_OK); 4113 } 4114 /* Don't check link if we're not in internal loopback mode */ 4115 if (nxgep->statsp->port_stats.lb_mode != nxge_lb_normal) 4116 return (NXGE_OK); 4117 4118 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4119 "==> nxge_link_monitor port<%d> enable=%d", 4120 nxgep->mac.portnum, enable)); 4121 if (enable == LINK_MONITOR_START) { 4122 if (nxgep->mac.linkchkmode == LINKCHK_INTR) { 4123 if ((status = nxge_link_intr(nxgep, LINK_INTR_START)) 4124 != NXGE_OK) 4125 goto fail; 4126 } else { 4127 timeout_id_t timerid; 4128 4129 if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 4130 return (NXGE_OK); 4131 4132 if (nxgep->xcvr.check_link) { 4133 timerid = timeout( 4134 (fptrv_t)(nxgep->xcvr.check_link), 4135 nxgep, 4136 drv_usectohz(LINK_MONITOR_PERIOD)); 4137 MUTEX_ENTER(&nxgep->poll_lock); 4138 nxgep->nxge_link_poll_timerid = timerid; 4139 MUTEX_EXIT(&nxgep->poll_lock); 4140 } else { 4141 return (NXGE_ERROR); 4142 } 4143 } 4144 } else { 4145 if (nxgep->mac.linkchkmode == LINKCHK_INTR) { 4146 if ((status = nxge_link_intr(nxgep, LINK_INTR_STOP)) 4147 != NXGE_OK) 4148 goto fail; 4149 } else { 4150 clock_t rv; 4151 4152 MUTEX_ENTER(&nxgep->poll_lock); 4153 4154 /* If <timerid> == 0, the link monitor has */ 4155 /* never been started, or just now stopped. */ 4156 if (nxgep->nxge_link_poll_timerid == 0) { 4157 MUTEX_EXIT(&nxgep->poll_lock); 4158 return (NXGE_OK); 4159 } 4160 4161 nxgep->poll_state = LINK_MONITOR_STOPPING; 4162 rv = cv_timedwait(&nxgep->poll_cv, 4163 &nxgep->poll_lock, 4164 ddi_get_lbolt() + 4165 drv_usectohz(LM_WAIT_MULTIPLIER * 4166 LINK_MONITOR_PERIOD)); 4167 if (rv == -1) { 4168 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4169 "==> stopping port %d: " 4170 "cv_timedwait(%d) timed out", 4171 nxgep->mac.portnum, nxgep->poll_state)); 4172 nxgep->poll_state = LINK_MONITOR_STOP; 4173 nxgep->nxge_link_poll_timerid = 0; 4174 } 4175 4176 MUTEX_EXIT(&nxgep->poll_lock); 4177 } 4178 } 4179 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4180 "<== nxge_link_monitor port<%d> enable=%d", 4181 nxgep->mac.portnum, enable)); 4182 return (NXGE_OK); 4183 fail: 4184 return (status); 4185 } 4186 4187 /* Set promiscous mode */ 4188 4189 nxge_status_t 4190 nxge_set_promisc(p_nxge_t nxgep, boolean_t on) 4191 { 4192 nxge_status_t status = NXGE_OK; 4193 4194 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_promisc: on %d", on)); 4195 4196 nxgep->filter.all_phys_cnt = ((on) ? 1 : 0); 4197 4198 RW_ENTER_WRITER(&nxgep->filter_lock); 4199 4200 if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) { 4201 goto fail; 4202 } 4203 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) { 4204 goto fail; 4205 } 4206 4207 RW_EXIT(&nxgep->filter_lock); 4208 4209 if (on) 4210 nxgep->statsp->mac_stats.promisc = B_TRUE; 4211 else 4212 nxgep->statsp->mac_stats.promisc = B_FALSE; 4213 4214 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_promisc")); 4215 4216 return (NXGE_OK); 4217 fail: 4218 RW_EXIT(&nxgep->filter_lock); 4219 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_promisc: " 4220 "Unable to set promisc (%d)", on)); 4221 4222 return (status); 4223 } 4224 4225 /*ARGSUSED*/ 4226 uint_t 4227 nxge_mif_intr(void *arg1, void *arg2) 4228 { 4229 #ifdef NXGE_DEBUG 4230 p_nxge_t nxgep = (p_nxge_t)arg2; 4231 #endif 4232 #if NXGE_MIF 4233 p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1; 4234 uint32_t status; 4235 npi_handle_t handle; 4236 uint8_t portn; 4237 p_nxge_stats_t statsp; 4238 #endif 4239 4240 #ifdef NXGE_MIF 4241 if (arg2 == NULL || (void *)ldvp->nxgep != arg2) { 4242 nxgep = ldvp->nxgep; 4243 } 4244 nxgep = ldvp->nxgep; 4245 #endif 4246 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mif_intr")); 4247 4248 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr")); 4249 return (DDI_INTR_CLAIMED); 4250 4251 mif_intr_fail: 4252 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr")); 4253 return (DDI_INTR_UNCLAIMED); 4254 } 4255 4256 /*ARGSUSED*/ 4257 uint_t 4258 nxge_mac_intr(void *arg1, void *arg2) 4259 { 4260 p_nxge_t nxgep = (p_nxge_t)arg2; 4261 p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1; 4262 p_nxge_ldg_t ldgp; 4263 uint32_t status; 4264 npi_handle_t handle; 4265 uint8_t portn; 4266 p_nxge_stats_t statsp; 4267 npi_status_t rs = NPI_SUCCESS; 4268 4269 if (arg2 == NULL || (void *)ldvp->nxgep != arg2) { 4270 nxgep = ldvp->nxgep; 4271 } 4272 4273 ldgp = ldvp->ldgp; 4274 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mac_intr: " 4275 "group %d", ldgp->ldg)); 4276 4277 handle = NXGE_DEV_NPI_HANDLE(nxgep); 4278 /* 4279 * This interrupt handler is for a specific 4280 * mac port. 4281 */ 4282 statsp = (p_nxge_stats_t)nxgep->statsp; 4283 portn = nxgep->mac.portnum; 4284 4285 NXGE_DEBUG_MSG((nxgep, INT_CTL, 4286 "==> nxge_mac_intr: reading mac stats: port<%d>", portn)); 4287 4288 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 4289 rs = npi_xmac_tx_get_istatus(handle, portn, 4290 (xmac_tx_iconfig_t *)&status); 4291 if (rs != NPI_SUCCESS) 4292 goto npi_fail; 4293 if (status & ICFG_XMAC_TX_ALL) { 4294 if (status & ICFG_XMAC_TX_UNDERRUN) { 4295 statsp->xmac_stats.tx_underflow_err++; 4296 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 4297 NXGE_FM_EREPORT_TXMAC_UNDERFLOW); 4298 } 4299 if (status & ICFG_XMAC_TX_MAX_PACKET_ERR) { 4300 statsp->xmac_stats.tx_maxpktsize_err++; 4301 /* 4302 * Do not send FMA ereport because this 4303 * error does not indicate HW failure. 4304 */ 4305 } 4306 if (status & ICFG_XMAC_TX_OVERFLOW) { 4307 statsp->xmac_stats.tx_overflow_err++; 4308 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 4309 NXGE_FM_EREPORT_TXMAC_OVERFLOW); 4310 } 4311 if (status & ICFG_XMAC_TX_FIFO_XFR_ERR) { 4312 statsp->xmac_stats.tx_fifo_xfr_err++; 4313 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 4314 NXGE_FM_EREPORT_TXMAC_TXFIFO_XFR_ERR); 4315 } 4316 if (status & ICFG_XMAC_TX_BYTE_CNT_EXP) { 4317 statsp->xmac_stats.tx_byte_cnt += 4318 XTXMAC_BYTE_CNT_MASK; 4319 } 4320 if (status & ICFG_XMAC_TX_FRAME_CNT_EXP) { 4321 statsp->xmac_stats.tx_frame_cnt += 4322 XTXMAC_FRM_CNT_MASK; 4323 } 4324 } 4325 4326 rs = npi_xmac_rx_get_istatus(handle, portn, 4327 (xmac_rx_iconfig_t *)&status); 4328 if (rs != NPI_SUCCESS) 4329 goto npi_fail; 4330 if (status & ICFG_XMAC_RX_ALL) { 4331 if (status & ICFG_XMAC_RX_OVERFLOW) 4332 statsp->xmac_stats.rx_overflow_err++; 4333 if (status & ICFG_XMAC_RX_UNDERFLOW) { 4334 statsp->xmac_stats.rx_underflow_err++; 4335 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 4336 NXGE_FM_EREPORT_RXMAC_UNDERFLOW); 4337 } 4338 /* 4339 * Do not send FMA ereport for the following 3 errors 4340 * because they do not indicate HW failures. 4341 */ 4342 if (status & ICFG_XMAC_RX_CRC_ERR_CNT_EXP) { 4343 statsp->xmac_stats.rx_crc_err_cnt += 4344 XRXMAC_CRC_ER_CNT_MASK; 4345 } 4346 if (status & ICFG_XMAC_RX_LEN_ERR_CNT_EXP) { 4347 statsp->xmac_stats.rx_len_err_cnt += 4348 MAC_LEN_ER_CNT_MASK; 4349 } 4350 if (status & ICFG_XMAC_RX_VIOL_ERR_CNT_EXP) { 4351 statsp->xmac_stats.rx_viol_err_cnt += 4352 XRXMAC_CD_VIO_CNT_MASK; 4353 } 4354 if (status & ICFG_XMAC_RX_OCT_CNT_EXP) { 4355 statsp->xmac_stats.rx_byte_cnt += 4356 XRXMAC_BT_CNT_MASK; 4357 } 4358 if (status & ICFG_XMAC_RX_HST_CNT1_EXP) { 4359 statsp->xmac_stats.rx_hist1_cnt += 4360 XRXMAC_HIST_CNT1_MASK; 4361 } 4362 if (status & ICFG_XMAC_RX_HST_CNT2_EXP) { 4363 statsp->xmac_stats.rx_hist2_cnt += 4364 XRXMAC_HIST_CNT2_MASK; 4365 } 4366 if (status & ICFG_XMAC_RX_HST_CNT3_EXP) { 4367 statsp->xmac_stats.rx_hist3_cnt += 4368 XRXMAC_HIST_CNT3_MASK; 4369 } 4370 if (status & ICFG_XMAC_RX_HST_CNT4_EXP) { 4371 statsp->xmac_stats.rx_hist4_cnt += 4372 XRXMAC_HIST_CNT4_MASK; 4373 } 4374 if (status & ICFG_XMAC_RX_HST_CNT5_EXP) { 4375 statsp->xmac_stats.rx_hist5_cnt += 4376 XRXMAC_HIST_CNT5_MASK; 4377 } 4378 if (status & ICFG_XMAC_RX_HST_CNT6_EXP) { 4379 statsp->xmac_stats.rx_hist6_cnt += 4380 XRXMAC_HIST_CNT6_MASK; 4381 } 4382 if (status & ICFG_XMAC_RX_BCAST_CNT_EXP) { 4383 statsp->xmac_stats.rx_broadcast_cnt += 4384 XRXMAC_BC_FRM_CNT_MASK; 4385 } 4386 if (status & ICFG_XMAC_RX_MCAST_CNT_EXP) { 4387 statsp->xmac_stats.rx_mult_cnt += 4388 XRXMAC_MC_FRM_CNT_MASK; 4389 } 4390 /* 4391 * Do not send FMA ereport for the following 3 errors 4392 * because they do not indicate HW failures. 4393 */ 4394 if (status & ICFG_XMAC_RX_FRAG_CNT_EXP) { 4395 statsp->xmac_stats.rx_frag_cnt += 4396 XRXMAC_FRAG_CNT_MASK; 4397 } 4398 if (status & ICFG_XMAC_RX_ALIGNERR_CNT_EXP) { 4399 statsp->xmac_stats.rx_frame_align_err_cnt += 4400 XRXMAC_AL_ER_CNT_MASK; 4401 } 4402 if (status & ICFG_XMAC_RX_LINK_FLT_CNT_EXP) { 4403 statsp->xmac_stats.rx_linkfault_err_cnt += 4404 XMAC_LINK_FLT_CNT_MASK; 4405 } 4406 if (status & ICFG_XMAC_RX_REMOTE_FLT_DET) { 4407 statsp->xmac_stats.rx_remotefault_err++; 4408 } 4409 if (status & ICFG_XMAC_RX_LOCAL_FLT_DET) { 4410 statsp->xmac_stats.rx_localfault_err++; 4411 } 4412 } 4413 4414 rs = npi_xmac_ctl_get_istatus(handle, portn, 4415 (xmac_ctl_iconfig_t *)&status); 4416 if (rs != NPI_SUCCESS) 4417 goto npi_fail; 4418 if (status & ICFG_XMAC_CTRL_ALL) { 4419 if (status & ICFG_XMAC_CTRL_PAUSE_RCVD) 4420 statsp->xmac_stats.rx_pause_cnt++; 4421 if (status & ICFG_XMAC_CTRL_PAUSE_STATE) 4422 statsp->xmac_stats.tx_pause_state++; 4423 if (status & ICFG_XMAC_CTRL_NOPAUSE_STATE) 4424 statsp->xmac_stats.tx_nopause_state++; 4425 } 4426 } else if (nxgep->mac.porttype == PORT_TYPE_BMAC) { 4427 rs = npi_bmac_tx_get_istatus(handle, portn, 4428 (bmac_tx_iconfig_t *)&status); 4429 if (rs != NPI_SUCCESS) 4430 goto npi_fail; 4431 if (status & ICFG_BMAC_TX_ALL) { 4432 if (status & ICFG_BMAC_TX_UNDERFLOW) { 4433 statsp->bmac_stats.tx_underrun_err++; 4434 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 4435 NXGE_FM_EREPORT_TXMAC_UNDERFLOW); 4436 } 4437 if (status & ICFG_BMAC_TX_MAXPKTSZ_ERR) { 4438 statsp->bmac_stats.tx_max_pkt_err++; 4439 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 4440 NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR); 4441 } 4442 if (status & ICFG_BMAC_TX_BYTE_CNT_EXP) { 4443 statsp->bmac_stats.tx_byte_cnt += 4444 BTXMAC_BYTE_CNT_MASK; 4445 } 4446 if (status & ICFG_BMAC_TX_FRAME_CNT_EXP) { 4447 statsp->bmac_stats.tx_frame_cnt += 4448 BTXMAC_FRM_CNT_MASK; 4449 } 4450 } 4451 4452 rs = npi_bmac_rx_get_istatus(handle, portn, 4453 (bmac_rx_iconfig_t *)&status); 4454 if (rs != NPI_SUCCESS) 4455 goto npi_fail; 4456 if (status & ICFG_BMAC_RX_ALL) { 4457 if (status & ICFG_BMAC_RX_OVERFLOW) { 4458 statsp->bmac_stats.rx_overflow_err++; 4459 } 4460 if (status & ICFG_BMAC_RX_FRAME_CNT_EXP) { 4461 statsp->bmac_stats.rx_frame_cnt += 4462 RXMAC_FRM_CNT_MASK; 4463 } 4464 if (status & ICFG_BMAC_RX_CRC_ERR_CNT_EXP) { 4465 statsp->bmac_stats.rx_crc_err_cnt += 4466 BMAC_CRC_ER_CNT_MASK; 4467 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 4468 NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP); 4469 } 4470 if (status & ICFG_BMAC_RX_LEN_ERR_CNT_EXP) { 4471 statsp->bmac_stats.rx_len_err_cnt += 4472 MAC_LEN_ER_CNT_MASK; 4473 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 4474 NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP); 4475 } 4476 if (status & ICFG_BMAC_RX_VIOL_ERR_CNT_EXP) 4477 statsp->bmac_stats.rx_viol_err_cnt += 4478 BMAC_CD_VIO_CNT_MASK; 4479 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 4480 NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP); 4481 } 4482 if (status & ICFG_BMAC_RX_BYTE_CNT_EXP) { 4483 statsp->bmac_stats.rx_byte_cnt += 4484 BRXMAC_BYTE_CNT_MASK; 4485 } 4486 if (status & ICFG_BMAC_RX_ALIGNERR_CNT_EXP) { 4487 statsp->bmac_stats.rx_align_err_cnt += 4488 BMAC_AL_ER_CNT_MASK; 4489 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 4490 NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP); 4491 } 4492 4493 rs = npi_bmac_ctl_get_istatus(handle, portn, 4494 (bmac_ctl_iconfig_t *)&status); 4495 if (rs != NPI_SUCCESS) 4496 goto npi_fail; 4497 4498 if (status & ICFG_BMAC_CTL_ALL) { 4499 if (status & ICFG_BMAC_CTL_RCVPAUSE) 4500 statsp->bmac_stats.rx_pause_cnt++; 4501 if (status & ICFG_BMAC_CTL_INPAUSE_ST) 4502 statsp->bmac_stats.tx_pause_state++; 4503 if (status & ICFG_BMAC_CTL_INNOTPAUSE_ST) 4504 statsp->bmac_stats.tx_nopause_state++; 4505 } 4506 } 4507 4508 if (ldgp->nldvs == 1) { 4509 (void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg, 4510 B_TRUE, ldgp->ldg_timer); 4511 } 4512 4513 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mac_intr")); 4514 return (DDI_INTR_CLAIMED); 4515 4516 npi_fail: 4517 NXGE_ERROR_MSG((nxgep, INT_CTL, "<== nxge_mac_intr")); 4518 return (DDI_INTR_UNCLAIMED); 4519 } 4520 4521 nxge_status_t 4522 nxge_check_bcm8704_link(p_nxge_t nxgep, boolean_t *link_up) 4523 { 4524 uint8_t phy_port_addr; 4525 nxge_status_t status = NXGE_OK; 4526 boolean_t rx_sig_ok; 4527 boolean_t pcs_blk_lock; 4528 boolean_t link_align; 4529 uint16_t val1, val2, val3; 4530 #ifdef NXGE_DEBUG_SYMBOL_ERR 4531 uint16_t val_debug; 4532 uint16_t val; 4533 #endif 4534 4535 phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn; 4536 4537 #ifdef NXGE_DEBUG_SYMBOL_ERR 4538 /* Check Device 3 Register Device 3 0xC809 */ 4539 (void) nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0xC809, &val_debug); 4540 if ((val_debug & ~0x200) != 0) { 4541 cmn_err(CE_NOTE, "!Port%d BCM8704 Dev3 Reg 0xc809 = 0x%x\n", 4542 nxgep->mac.portnum, val_debug); 4543 (void) nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, 4544 &val_debug); 4545 cmn_err(CE_NOTE, "!Port%d BCM8704 Dev4 Reg 0x18 = 0x%x\n", 4546 nxgep->mac.portnum, val_debug); 4547 } 4548 4549 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 4550 XPCS_REG_DESCWERR_COUNTER, &val); 4551 if (val != 0) 4552 cmn_err(CE_NOTE, "!XPCS DESCWERR = 0x%x\n", val); 4553 4554 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 4555 XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val); 4556 if (val != 0) 4557 cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L0_1 = 0x%x\n", val); 4558 4559 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 4560 XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val); 4561 if (val != 0) 4562 cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L2_3 = 0x%x\n", val); 4563 #endif 4564 4565 /* Check from BCM8704 if 10G link is up or down */ 4566 4567 /* Check Device 1 Register 0xA bit0 */ 4568 status = nxge_mdio_read(nxgep, phy_port_addr, 4569 BCM8704_PMA_PMD_DEV_ADDR, 4570 BCM8704_PMD_RECEIVE_SIG_DETECT, 4571 &val1); 4572 if (status != NXGE_OK) 4573 goto fail; 4574 rx_sig_ok = ((val1 & GLOB_PMD_RX_SIG_OK) ? B_TRUE : B_FALSE); 4575 4576 /* Check Device 3 Register 0x20 bit0 */ 4577 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 4578 BCM8704_PCS_DEV_ADDR, 4579 BCM8704_10GBASE_R_PCS_STATUS_REG, 4580 &val2)) != NPI_SUCCESS) 4581 goto fail; 4582 pcs_blk_lock = ((val2 & PCS_10GBASE_R_PCS_BLK_LOCK) ? B_TRUE : B_FALSE); 4583 4584 /* Check Device 4 Register 0x18 bit12 */ 4585 status = nxge_mdio_read(nxgep, phy_port_addr, 4586 BCM8704_PHYXS_ADDR, 4587 BCM8704_PHYXS_XGXS_LANE_STATUS_REG, 4588 &val3); 4589 if (status != NXGE_OK) 4590 goto fail; 4591 link_align = (val3 == (XGXS_LANE_ALIGN_STATUS | XGXS_LANE3_SYNC | 4592 XGXS_LANE2_SYNC | XGXS_LANE1_SYNC | 4593 XGXS_LANE0_SYNC | 0x400)) ? B_TRUE : B_FALSE; 4594 4595 #ifdef NXGE_DEBUG_ALIGN_ERR 4596 /* Temp workaround for link down issue */ 4597 if (pcs_blk_lock == B_FALSE) { 4598 if (val2 != 0x4) { 4599 pcs_blk_lock = B_TRUE; 4600 cmn_err(CE_NOTE, 4601 "!LINK DEBUG: port%d PHY Dev3 " 4602 "Reg 0x20 = 0x%x\n", 4603 nxgep->mac.portnum, val2); 4604 } 4605 } 4606 4607 if (link_align == B_FALSE) { 4608 if (val3 != 0x140f) { 4609 link_align = B_TRUE; 4610 cmn_err(CE_NOTE, 4611 "!LINK DEBUG: port%d PHY Dev4 " 4612 "Reg 0x18 = 0x%x\n", 4613 nxgep->mac.portnum, val3); 4614 } 4615 } 4616 4617 if (rx_sig_ok == B_FALSE) { 4618 if ((val2 == 0) || (val3 == 0)) { 4619 rx_sig_ok = B_TRUE; 4620 cmn_err(CE_NOTE, 4621 "!LINK DEBUG: port %d Dev3 or Dev4 read zero\n", 4622 nxgep->mac.portnum); 4623 } 4624 } 4625 #endif 4626 4627 *link_up = ((rx_sig_ok == B_TRUE) && (pcs_blk_lock == B_TRUE) && 4628 (link_align == B_TRUE)) ? B_TRUE : B_FALSE; 4629 4630 return (NXGE_OK); 4631 fail: 4632 return (status); 4633 } 4634 4635 nxge_status_t 4636 nxge_10g_link_led_on(p_nxge_t nxgep) 4637 { 4638 if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_TRUE) 4639 != NPI_SUCCESS) 4640 return (NXGE_ERROR); 4641 else 4642 return (NXGE_OK); 4643 } 4644 4645 nxge_status_t 4646 nxge_10g_link_led_off(p_nxge_t nxgep) 4647 { 4648 if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_FALSE) 4649 != NPI_SUCCESS) 4650 return (NXGE_ERROR); 4651 else 4652 return (NXGE_OK); 4653 } 4654 4655 /* Check if the given id read using the given MDIO Clause is supported */ 4656 4657 static boolean_t 4658 nxge_is_supported_phy(uint32_t id, uint8_t type) 4659 { 4660 int i; 4661 int cl45_arr_len = NUM_CLAUSE_45_IDS; 4662 int cl22_arr_len = NUM_CLAUSE_22_IDS; 4663 boolean_t found = B_FALSE; 4664 4665 switch (type) { 4666 case CLAUSE_45_TYPE: 4667 for (i = 0; i < cl45_arr_len; i++) { 4668 if ((nxge_supported_cl45_ids[i] & BCM_PHY_ID_MASK) == 4669 (id & BCM_PHY_ID_MASK)) { 4670 found = B_TRUE; 4671 break; 4672 } 4673 } 4674 break; 4675 case CLAUSE_22_TYPE: 4676 for (i = 0; i < cl22_arr_len; i++) { 4677 if ((nxge_supported_cl22_ids[i] & BCM_PHY_ID_MASK) == 4678 (id & BCM_PHY_ID_MASK)) { 4679 found = B_TRUE; 4680 break; 4681 } 4682 } 4683 break; 4684 default: 4685 break; 4686 } 4687 4688 return (found); 4689 } 4690 4691 static uint32_t 4692 nxge_get_cl45_pma_pmd_id(p_nxge_t nxgep, int phy_port) 4693 { 4694 uint16_t val1 = 0; 4695 uint16_t val2 = 0; 4696 uint32_t pma_pmd_dev_id = 0; 4697 npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep); 4698 4699 (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR, 4700 NXGE_DEV_ID_REG_1, &val1); 4701 (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR, 4702 NXGE_DEV_ID_REG_2, &val2); 4703 4704 pma_pmd_dev_id = val1; 4705 pma_pmd_dev_id = (pma_pmd_dev_id << 16); 4706 pma_pmd_dev_id |= val2; 4707 4708 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PMA/PMD " 4709 "devid[0x%llx]", phy_port, pma_pmd_dev_id)); 4710 4711 return (pma_pmd_dev_id); 4712 } 4713 4714 static uint32_t 4715 nxge_get_cl45_pcs_id(p_nxge_t nxgep, int phy_port) 4716 { 4717 uint16_t val1 = 0; 4718 uint16_t val2 = 0; 4719 uint32_t pcs_dev_id = 0; 4720 npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep); 4721 4722 (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR, 4723 NXGE_DEV_ID_REG_1, &val1); 4724 (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR, 4725 NXGE_DEV_ID_REG_2, &val2); 4726 4727 pcs_dev_id = val1; 4728 pcs_dev_id = (pcs_dev_id << 16); 4729 pcs_dev_id |= val2; 4730 4731 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS " 4732 "devid[0x%llx]", phy_port, pcs_dev_id)); 4733 4734 return (pcs_dev_id); 4735 } 4736 4737 static uint32_t 4738 nxge_get_cl22_phy_id(p_nxge_t nxgep, int phy_port) 4739 { 4740 uint16_t val1 = 0; 4741 uint16_t val2 = 0; 4742 uint32_t phy_id = 0; 4743 npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep); 4744 npi_status_t npi_status = NPI_SUCCESS; 4745 4746 npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_1, 4747 &val1); 4748 if (npi_status != NPI_SUCCESS) { 4749 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] " 4750 "clause 22 read to reg 2 failed!!!")); 4751 goto exit; 4752 } 4753 npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_2, 4754 &val2); 4755 if (npi_status != 0) { 4756 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] " 4757 "clause 22 read to reg 3 failed!!!")); 4758 goto exit; 4759 } 4760 phy_id = val1; 4761 phy_id = (phy_id << 16); 4762 phy_id |= val2; 4763 4764 exit: 4765 4766 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID [0x%llx]", 4767 phy_port, phy_id)); 4768 4769 return (phy_id); 4770 } 4771 4772 /* 4773 * Scan the PHY ports 0 through 31 to get the PHY ID using Clause 22 MDIO 4774 * read and the PMA/PMD device ID and the PCS device ID using Clause 45 MDIO 4775 * read. Then use the values obtained to determine the phy type of each port 4776 * and the Neptune type. 4777 */ 4778 4779 nxge_status_t 4780 nxge_scan_ports_phy(p_nxge_t nxgep, p_nxge_hw_list_t hw_p) 4781 { 4782 int i, j, k, l; 4783 uint32_t pma_pmd_dev_id = 0; 4784 uint32_t pcs_dev_id = 0; 4785 uint32_t phy_id = 0; 4786 uint32_t port_pma_pmd_dev_id[NXGE_PORTS_NEPTUNE]; 4787 uint32_t port_pcs_dev_id[NXGE_PORTS_NEPTUNE]; 4788 uint32_t port_phy_id[NXGE_PORTS_NEPTUNE]; 4789 uint8_t pma_pmd_dev_fd[NXGE_MAX_PHY_PORTS]; 4790 uint8_t pcs_dev_fd[NXGE_MAX_PHY_PORTS]; 4791 uint8_t phy_fd[NXGE_MAX_PHY_PORTS]; 4792 uint8_t port_fd[NXGE_MAX_PHY_PORTS]; 4793 uint8_t total_port_fd, total_phy_fd; 4794 nxge_status_t status = NXGE_OK; 4795 int prt_id = -1; 4796 4797 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_scan_ports_phy: ")); 4798 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4799 "==> nxge_scan_ports_phy: nxge niu_type[0x%x]", 4800 nxgep->niu_type)); 4801 4802 j = k = l = 0; 4803 total_port_fd = total_phy_fd = 0; 4804 /* 4805 * Clause 45 and Clause 22 port/phy addresses 0 through 7 are reserved 4806 * for on chip serdes usages. 4807 */ 4808 for (i = NXGE_EXT_PHY_PORT_ST; i < NXGE_MAX_PHY_PORTS; i++) { 4809 4810 pma_pmd_dev_id = nxge_get_cl45_pma_pmd_id(nxgep, i); 4811 4812 if (nxge_is_supported_phy(pma_pmd_dev_id, CLAUSE_45_TYPE)) { 4813 pma_pmd_dev_fd[i] = 1; 4814 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] " 4815 "PMA/PMD dev found", i)); 4816 if (j < NXGE_PORTS_NEPTUNE) { 4817 port_pma_pmd_dev_id[j] = pma_pmd_dev_id & 4818 BCM_PHY_ID_MASK; 4819 j++; 4820 } 4821 } else { 4822 pma_pmd_dev_fd[i] = 0; 4823 } 4824 4825 pcs_dev_id = nxge_get_cl45_pcs_id(nxgep, i); 4826 4827 if (nxge_is_supported_phy(pcs_dev_id, CLAUSE_45_TYPE)) { 4828 pcs_dev_fd[i] = 1; 4829 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS " 4830 "dev found", i)); 4831 if (k < NXGE_PORTS_NEPTUNE) { 4832 port_pcs_dev_id[k] = pcs_dev_id & 4833 BCM_PHY_ID_MASK; 4834 k++; 4835 } 4836 } else { 4837 pcs_dev_fd[i] = 0; 4838 } 4839 4840 if (pcs_dev_fd[i] || pma_pmd_dev_fd[i]) 4841 port_fd[i] = 1; 4842 else 4843 port_fd[i] = 0; 4844 total_port_fd += port_fd[i]; 4845 4846 phy_id = nxge_get_cl22_phy_id(nxgep, i); 4847 4848 if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) { 4849 phy_fd[i] = 1; 4850 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID" 4851 "found", i)); 4852 if (l < NXGE_PORTS_NEPTUNE) { 4853 port_phy_id[l] = phy_id & BCM_PHY_ID_MASK; 4854 l++; 4855 } 4856 } else { 4857 phy_fd[i] = 0; 4858 } 4859 total_phy_fd += phy_fd[i]; 4860 } 4861 4862 switch (total_port_fd) { 4863 case 2: 4864 switch (total_phy_fd) { 4865 case 2: 4866 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4867 "Unsupported neptune type 1")); 4868 goto error_exit; 4869 case 1: 4870 /* TODO - 2 10G, 1 1G */ 4871 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4872 "Unsupported neptune type 2 10G, 1 1G")); 4873 goto error_exit; 4874 case 0: 4875 /* 2 10G */ 4876 if (((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) && 4877 (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) || 4878 ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) && 4879 (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) { 4880 4881 /* 4882 * Check the first phy port address against 4883 * the known phy start addresses to determine 4884 * the platform type. 4885 */ 4886 for (i = NXGE_EXT_PHY_PORT_ST; 4887 i < NXGE_MAX_PHY_PORTS; i++) { 4888 if (port_fd[i] == 1) 4889 break; 4890 } 4891 if (i == BCM8704_NEPTUNE_PORT_ADDR_BASE) { 4892 hw_p->niu_type = NEPTUNE_2_10GF; 4893 hw_p->platform_type = 4894 P_NEPTUNE_ATLAS_2PORT; 4895 } else { 4896 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4897 "Unsupported neptune type 2 - 1")); 4898 goto error_exit; 4899 } 4900 hw_p->niu_type = NEPTUNE_2_10GF; 4901 } else { 4902 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4903 "Unsupported neptune type 2")); 4904 goto error_exit; 4905 } 4906 break; 4907 case 4: 4908 /* Maramba with 2 XAUI */ 4909 if ((((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) && 4910 (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) || 4911 ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) && 4912 (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) && 4913 ((port_phy_id[0] == PHY_BCM5464R_FAMILY) && 4914 (port_phy_id[1] == PHY_BCM5464R_FAMILY) && 4915 (port_phy_id[2] == PHY_BCM5464R_FAMILY) && 4916 (port_phy_id[3] == PHY_BCM5464R_FAMILY))) { 4917 4918 /* 4919 * Check the first phy port address against 4920 * the known phy start addresses to determine 4921 * the platform type. 4922 */ 4923 for (i = NXGE_EXT_PHY_PORT_ST; 4924 i < NXGE_MAX_PHY_PORTS; i++) { 4925 if (phy_fd[i] == 1) 4926 break; 4927 } 4928 if (i == BCM5464_MARAMBA_P0_PORT_ADDR_BASE) { 4929 hw_p->platform_type = 4930 P_NEPTUNE_MARAMBA_P0; 4931 } else if (i == 4932 BCM5464_MARAMBA_P1_PORT_ADDR_BASE) { 4933 hw_p->platform_type = 4934 P_NEPTUNE_MARAMBA_P1; 4935 } else { 4936 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4937 "Unknown port %d...Cannot " 4938 "determine platform type", i)); 4939 goto error_exit; 4940 } 4941 hw_p->niu_type = NEPTUNE_2_10GF_2_1GC; 4942 4943 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4944 "Maramba with 2 XAUI")); 4945 } else { 4946 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4947 "Unsupported neptune type 3")); 4948 goto error_exit; 4949 } 4950 break; 4951 default: 4952 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4953 "Unsupported neptune type 5")); 4954 goto error_exit; 4955 } 4956 break; 4957 case 1: 4958 switch (total_phy_fd) { 4959 case 3: 4960 /* 4961 * TODO 3 1G, 1 10G mode. 4962 * Differentiate between 1_1G_1_10G_2_1G and 4963 * 1_10G_3_1G 4964 */ 4965 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4966 "Unsupported neptune type 7")); 4967 goto error_exit; 4968 case 2: 4969 /* 4970 * TODO 2 1G, 1 10G mode. 4971 * Differentiate between 1_1G_1_10G_1_1G and 4972 * 1_10G_2_1G 4973 */ 4974 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4975 "Unsupported neptune type 8")); 4976 goto error_exit; 4977 case 1: 4978 /* 4979 * TODO 1 1G, 1 10G mode. 4980 * Differentiate between 1_1G_1_10G and 4981 * 1_10G_1_1G 4982 */ 4983 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4984 "Unsupported neptune type 9")); 4985 goto error_exit; 4986 case 0: 4987 /* TODO 1 10G mode */ 4988 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4989 "Unsupported neptune type 10")); 4990 goto error_exit; 4991 case 4: 4992 /* Maramba with 1 XAUI */ 4993 if ((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) || 4994 (port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY)) { 4995 4996 /* 4997 * Check the first phy port address against 4998 * the known phy start addresses to determine 4999 * the platform type. 5000 */ 5001 for (i = NXGE_EXT_PHY_PORT_ST; 5002 i < NXGE_MAX_PHY_PORTS; i++) { 5003 if (phy_fd[i] == 1) 5004 break; 5005 } 5006 5007 if (i == BCM5464_MARAMBA_P0_PORT_ADDR_BASE) { 5008 hw_p->platform_type = 5009 P_NEPTUNE_MARAMBA_P0; 5010 } else if (i == 5011 BCM5464_MARAMBA_P1_PORT_ADDR_BASE) { 5012 hw_p->platform_type = 5013 P_NEPTUNE_MARAMBA_P1; 5014 } else { 5015 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5016 "Unknown port %d...Cannot " 5017 "determine platform type", i)); 5018 goto error_exit; 5019 } 5020 5021 /* The 10G port is BCM8704 */ 5022 for (i = NXGE_EXT_PHY_PORT_ST; 5023 i < NXGE_MAX_PHY_PORTS; i++) { 5024 if (port_fd[i] == 1) { 5025 prt_id = i; 5026 break; 5027 } 5028 } 5029 5030 prt_id %= BCM8704_MARAMBA_PORT_ADDR_BASE; 5031 if (prt_id == 0) { 5032 hw_p->niu_type = NEPTUNE_1_10GF_3_1GC; 5033 } else if (prt_id == 1) { 5034 hw_p->niu_type = 5035 NEPTUNE_1_1GC_1_10GF_2_1GC; 5036 } else { 5037 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5038 "Unsupported neptune type 11")); 5039 goto error_exit; 5040 } 5041 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5042 "Maramba with 1 XAUI")); 5043 } else { 5044 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5045 "Unsupported neptune type 12")); 5046 goto error_exit; 5047 } 5048 break; 5049 default: 5050 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5051 "Unsupported neptune type 13")); 5052 goto error_exit; 5053 } 5054 break; 5055 case 0: 5056 switch (total_phy_fd) { 5057 case 4: 5058 if ((port_phy_id[0] == PHY_BCM5464R_FAMILY) && 5059 (port_phy_id[1] == PHY_BCM5464R_FAMILY) && 5060 (port_phy_id[2] == PHY_BCM5464R_FAMILY) && 5061 (port_phy_id[3] == PHY_BCM5464R_FAMILY)) { 5062 5063 /* 5064 * Check the first phy port address against 5065 * the known phy start addresses to determine 5066 * the platform type. 5067 */ 5068 for (i = NXGE_EXT_PHY_PORT_ST; 5069 i < NXGE_MAX_PHY_PORTS; i++) { 5070 if (phy_fd[i] == 1) 5071 break; 5072 } 5073 5074 if (i == BCM5464_MARAMBA_P1_PORT_ADDR_BASE) { 5075 hw_p->platform_type = 5076 P_NEPTUNE_MARAMBA_P1; 5077 } else if (i == 5078 BCM5464_NEPTUNE_PORT_ADDR_BASE) { 5079 hw_p->platform_type = 5080 P_NEPTUNE_ATLAS_4PORT; 5081 } else { 5082 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5083 "Unknown port %d...Cannot " 5084 "determine platform type", i)); 5085 goto error_exit; 5086 } 5087 hw_p->niu_type = NEPTUNE_4_1GC; 5088 } else { 5089 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5090 "Unsupported neptune type 14")); 5091 goto error_exit; 5092 } 5093 break; 5094 case 3: 5095 /* TODO 3 1G mode */ 5096 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5097 "Unsupported neptune type 15")); 5098 goto error_exit; 5099 case 2: 5100 /* TODO 2 1G mode */ 5101 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5102 "Unsupported neptune type 16")); 5103 goto error_exit; 5104 case 1: 5105 /* TODO 1 1G mode */ 5106 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5107 "Unsupported neptune type 17")); 5108 goto error_exit; 5109 default: 5110 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5111 "Unsupported neptune type 18, total phy fd %d", 5112 total_phy_fd)); 5113 goto error_exit; 5114 } 5115 break; 5116 default: 5117 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5118 "Unsupported neptune type 19")); 5119 goto error_exit; 5120 } 5121 5122 scan_exit: 5123 5124 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_scan_ports_phy, " 5125 "niu type [0x%x]\n", hw_p->niu_type)); 5126 return (status); 5127 5128 error_exit: 5129 return (NXGE_ERROR); 5130 } 5131 5132 boolean_t 5133 nxge_is_valid_local_mac(ether_addr_st mac_addr) 5134 { 5135 if ((mac_addr.ether_addr_octet[0] & 0x01) || 5136 (ether_cmp(&mac_addr, ðerbroadcastaddr) == 0) || 5137 (ether_cmp(&mac_addr, ðerzeroaddr) == 0)) 5138 return (B_FALSE); 5139 else 5140 return (B_TRUE); 5141 } 5142 5143 static void 5144 nxge_bcm5464_link_led_off(p_nxge_t nxgep) { 5145 5146 npi_status_t rs = NPI_SUCCESS; 5147 uint8_t xcvr_portn; 5148 uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 5149 5150 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_bcm5464_link_led_off")); 5151 5152 if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P1) { 5153 xcvr_portn = BCM5464_MARAMBA_P1_PORT_ADDR_BASE; 5154 } else if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P0) { 5155 xcvr_portn = BCM5464_MARAMBA_P0_PORT_ADDR_BASE; 5156 } 5157 /* 5158 * For Altas 4-1G copper, Xcvr port numbers are 5159 * swapped with ethernet port number. This is 5160 * designed for better signal integrity in routing. 5161 */ 5162 switch (portn) { 5163 case 0: 5164 xcvr_portn += 3; 5165 break; 5166 case 1: 5167 xcvr_portn += 2; 5168 break; 5169 case 2: 5170 xcvr_portn += 1; 5171 break; 5172 case 3: 5173 default: 5174 break; 5175 } 5176 5177 MUTEX_ENTER(&nxge_mii_lock); 5178 rs = npi_mac_mif_mii_write(nxgep->npi_handle, 5179 xcvr_portn, BCM5464R_MISC, 0xb4ee); 5180 if (rs != NPI_SUCCESS) { 5181 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5182 "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write " 5183 "returned error 0x[%x]", rs)); 5184 MUTEX_EXIT(&nxge_mii_lock); 5185 return; 5186 } 5187 5188 rs = npi_mac_mif_mii_write(nxgep->npi_handle, 5189 xcvr_portn, BCM5464R_MISC, 0xb8ee); 5190 if (rs != NPI_SUCCESS) { 5191 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5192 "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write " 5193 "returned error 0x[%x]", rs)); 5194 MUTEX_EXIT(&nxge_mii_lock); 5195 return; 5196 } 5197 5198 MUTEX_EXIT(&nxge_mii_lock); 5199 } 5200 5201 static nxge_status_t 5202 nxge_mii_get_link_mode(p_nxge_t nxgep) 5203 { 5204 p_nxge_stats_t statsp; 5205 uint8_t xcvr_portn; 5206 p_mii_regs_t mii_regs; 5207 mii_mode_control_stat_t mode; 5208 int status = NXGE_OK; 5209 5210 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_get_link_mode")); 5211 5212 statsp = nxgep->statsp; 5213 xcvr_portn = statsp->mac_stats.xcvr_portn; 5214 mii_regs = NULL; 5215 mode.value = 0; 5216 mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG; 5217 #if defined(__i386) 5218 if ((status = nxge_mii_write(nxgep, xcvr_portn, 5219 (uint8_t)(uint32_t)(&mii_regs->shadow), 5220 mode.value)) != NXGE_OK) { 5221 goto fail; 5222 #else 5223 if ((status = nxge_mii_write(nxgep, xcvr_portn, 5224 (uint8_t)(uint64_t)(&mii_regs->shadow), 5225 mode.value)) != NXGE_OK) { 5226 goto fail; 5227 #endif 5228 } 5229 #if defined(__i386) 5230 if ((status = nxge_mii_read(nxgep, xcvr_portn, 5231 (uint8_t)(uint32_t)(&mii_regs->shadow), 5232 &mode.value)) != NXGE_OK) { 5233 goto fail; 5234 } 5235 #else 5236 if ((status = nxge_mii_read(nxgep, xcvr_portn, 5237 (uint8_t)(uint64_t)(&mii_regs->shadow), 5238 &mode.value)) != NXGE_OK) { 5239 goto fail; 5240 } 5241 #endif 5242 5243 if (mode.bits.mode == NXGE_MODE_SELECT_FIBER) { 5244 nxgep->mac.portmode = PORT_1G_RGMII_FIBER; 5245 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5246 "nxge_mii_get_link_mode: fiber mode")); 5247 } 5248 5249 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5250 "nxge_mii_get_link_mode: " 5251 "(address 0x%x) port 0x%x mode value 0x%x link mode 0x%x", 5252 NXGE_MII_MODE_CONTROL_REG, xcvr_portn, 5253 mode.value, nxgep->mac.portmode)); 5254 5255 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5256 "<== nxge_mii_get_link_mode")); 5257 return (status); 5258 fail: 5259 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5260 "<== nxge_mii_get_link_mode (failed)")); 5261 return (NXGE_ERROR); 5262 } 5263 5264 #ifdef NXGE_DEBUG 5265 static void 5266 nxge_mii_dump(p_nxge_t nxgep) 5267 { 5268 p_nxge_stats_t statsp; 5269 uint8_t xcvr_portn; 5270 p_mii_regs_t mii_regs; 5271 mii_bmcr_t bmcr; 5272 mii_bmsr_t bmsr; 5273 mii_idr1_t idr1; 5274 mii_idr2_t idr2; 5275 mii_mode_control_stat_t mode; 5276 5277 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "==> nxge_mii_dump")); 5278 5279 param_arr = nxgep->param_arr; 5280 statsp = nxgep->statsp; 5281 xcvr_portn = statsp->mac_stats.xcvr_portn; 5282 5283 mii_regs = NULL; 5284 5285 #if defined(__i386) 5286 (void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn, 5287 (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value); 5288 #else 5289 (void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn, 5290 (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value); 5291 #endif 5292 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5293 "nxge_mii_dump: bmcr (0) xcvr 0x%x value 0x%x", 5294 xcvr_portn, bmcr.value)); 5295 5296 #if defined(__i386) 5297 (void) nxge_mii_read(nxgep, 5298 nxgep->statsp->mac_stats.xcvr_portn, 5299 (uint8_t)(uint32_t)(&mii_regs->bmsr), &bmsr.value); 5300 #else 5301 (void) nxge_mii_read(nxgep, 5302 nxgep->statsp->mac_stats.xcvr_portn, 5303 (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value); 5304 #endif 5305 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5306 "nxge_mii_dump: bmsr (1) xcvr 0x%x value 0x%x", 5307 xcvr_portn, bmsr.value)); 5308 5309 #if defined(__i386) 5310 (void) nxge_mii_read(nxgep, 5311 nxgep->statsp->mac_stats.xcvr_portn, 5312 (uint8_t)(uint32_t)(&mii_regs->idr1), &idr1.value); 5313 #else 5314 (void) nxge_mii_read(nxgep, 5315 nxgep->statsp->mac_stats.xcvr_portn, 5316 (uint8_t)(uint64_t)(&mii_regs->idr1), &idr1.value); 5317 #endif 5318 5319 5320 #if defined(__i386) 5321 (void) nxge_mii_read(nxgep, 5322 nxgep->statsp->mac_stats.xcvr_portn, 5323 (uint8_t)(uint32_t)(&mii_regs->idr2), &idr2.value); 5324 #else 5325 (void) nxge_mii_read(nxgep, 5326 nxgep->statsp->mac_stats.xcvr_portn, 5327 (uint8_t)(uint64_t)(&mii_regs->idr2), &idr2.value); 5328 #endif 5329 5330 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5331 "nxge_mii_dump: idr1 (2) xcvr 0x%x value 0x%x", 5332 xcvr_portn, idr1.value)); 5333 5334 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5335 "nxge_mii_dump: idr2 (3) xcvr 0x%x value 0x%x", 5336 xcvr_portn, idr2.value)); 5337 5338 mode.value = 0; 5339 mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG; 5340 5341 #if defined(__i386) 5342 (void) nxge_mii_write(nxgep, xcvr_portn, 5343 (uint8_t)(uint32_t)(&mii_regs->shadow), mode.value); 5344 5345 (void) nxge_mii_read(nxgep, xcvr_portn, 5346 (uint8_t)(uint32_t)(&mii_regs->shadow), &mode.value); 5347 #else 5348 (void) nxge_mii_write(nxgep, xcvr_portn, 5349 (uint8_t)(uint64_t)(&mii_regs->shadow), mode.value); 5350 5351 (void) nxge_mii_read(nxgep, xcvr_portn, 5352 (uint8_t)(uint64_t)(&mii_regs->shadow), &mode.value); 5353 #endif 5354 5355 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5356 "nxge_mii_dump: mode control xcvr 0x%x value 0x%x", 5357 xcvr_portn, mode.value)); 5358 } 5359 #endif 5360