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