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