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