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