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