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