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