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 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1593 "nxge_neptune_10G_serdes_init: " 1594 "Serdes/signal for port<%d> not ready", portn)); 1595 goto fail; 1596 } 1597 } else if (portn == 1) { 1598 /* Wait for serdes to be ready */ 1599 for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) { 1600 ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val); 1601 if ((val & ESR_SIG_P1_BITS_MASK) != 1602 (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1 | 1603 ESR_SIG_XSERDES_RDY_P1 | 1604 ESR_SIG_XDETECT_P1_CH3 | 1605 ESR_SIG_XDETECT_P1_CH2 | 1606 ESR_SIG_XDETECT_P1_CH1 | 1607 ESR_SIG_XDETECT_P1_CH0)) 1608 1609 NXGE_DELAY(SERDES_RDY_WT_INTERVAL); 1610 else 1611 break; 1612 } 1613 1614 if (i == MAX_SERDES_RDY_RETRIES) { 1615 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1616 "nxge_neptune_10G_serdes_init: " 1617 "Serdes/signal for port<%d> not ready", portn)); 1618 goto fail; 1619 } 1620 } 1621 1622 done: 1623 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1624 "<== nxge_neptune_10G_serdes_init port<%d>", portn)); 1625 1626 return (NXGE_OK); 1627 fail: 1628 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1629 "nxge_neptune_10G_serdes_init: " 1630 "Failed to initialize Neptune serdes for port<%d>", portn)); 1631 1632 return (status); 1633 } 1634 1635 /* Initialize Neptune Internal Serdes for 1G (Neptune only) */ 1636 1637 static nxge_status_t 1638 nxge_1G_serdes_init(p_nxge_t nxgep) 1639 { 1640 npi_handle_t handle; 1641 uint8_t portn; 1642 int chan; 1643 sr_rx_tx_ctrl_l_t rx_tx_ctrl_l; 1644 sr_rx_tx_ctrl_h_t rx_tx_ctrl_h; 1645 sr_glue_ctrl0_l_t glue_ctrl0_l; 1646 sr_glue_ctrl0_h_t glue_ctrl0_h; 1647 uint64_t val; 1648 uint16_t val16l; 1649 uint16_t val16h; 1650 nxge_status_t status = NXGE_OK; 1651 1652 portn = nxgep->mac.portnum; 1653 1654 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1655 "==> nxge_1G_serdes_init port<%d>", portn)); 1656 1657 handle = nxgep->npi_handle; 1658 1659 switch (portn) { 1660 case 0: 1661 /* Assert the reset register */ 1662 ESR_REG_RD(handle, ESR_RESET_REG, &val); 1663 val |= ESR_RESET_0; 1664 ESR_REG_WR(handle, ESR_RESET_REG, val); 1665 1666 /* Set the PLL register to 0x79 */ 1667 ESR_REG_WR(handle, ESR_0_PLL_CONFIG_REG, 1668 ESR_PLL_CFG_1G_SERDES); 1669 1670 /* Set the control register to 0x249249f */ 1671 ESR_REG_WR(handle, ESR_0_CONTROL_REG, ESR_CTL_1G_SERDES); 1672 1673 /* Set Serdes0 Internal Loopback if necessary */ 1674 if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) { 1675 /* Set pad loopback modes 0xaa */ 1676 ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 1677 ESR_TSTCFG_LBTEST_PAD); 1678 } else { 1679 ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0); 1680 } 1681 1682 /* Deassert the reset register */ 1683 ESR_REG_RD(handle, ESR_RESET_REG, &val); 1684 val &= ~ESR_RESET_0; 1685 ESR_REG_WR(handle, ESR_RESET_REG, val); 1686 break; 1687 1688 case 1: 1689 /* Assert the reset register */ 1690 ESR_REG_RD(handle, ESR_RESET_REG, &val); 1691 val |= ESR_RESET_1; 1692 ESR_REG_WR(handle, ESR_RESET_REG, val); 1693 1694 /* Set PLL register to 0x79 */ 1695 ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG, 1696 ESR_PLL_CFG_1G_SERDES); 1697 1698 /* Set the control register to 0x249249f */ 1699 ESR_REG_WR(handle, ESR_1_CONTROL_REG, ESR_CTL_1G_SERDES); 1700 1701 /* Set Serdes1 Internal Loopback if necessary */ 1702 if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) { 1703 /* Set pad loopback mode 0xaa */ 1704 ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 1705 ESR_TSTCFG_LBTEST_PAD); 1706 } else { 1707 ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0); 1708 } 1709 1710 /* Deassert the reset register */ 1711 ESR_REG_RD(handle, ESR_RESET_REG, &val); 1712 val &= ~ESR_RESET_1; 1713 ESR_REG_WR(handle, ESR_RESET_REG, val); 1714 break; 1715 1716 default: 1717 /* Nothing to do here */ 1718 goto done; 1719 } 1720 1721 /* init TX RX channels */ 1722 for (chan = 0; chan < 4; chan++) { 1723 if ((status = nxge_mdio_read(nxgep, portn, 1724 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 1725 &rx_tx_ctrl_l.value)) != NXGE_OK) { 1726 goto fail; 1727 } 1728 if ((status = nxge_mdio_read(nxgep, portn, 1729 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 1730 &rx_tx_ctrl_h.value)) != NXGE_OK) { 1731 goto fail; 1732 } 1733 if ((status = nxge_mdio_read(nxgep, portn, 1734 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 1735 &glue_ctrl0_l.value)) != NXGE_OK) { 1736 goto fail; 1737 } 1738 if ((status = nxge_mdio_read(nxgep, portn, 1739 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 1740 &glue_ctrl0_h.value)) != NXGE_OK) { 1741 goto fail; 1742 } 1743 1744 rx_tx_ctrl_l.bits.enstretch = 1; 1745 rx_tx_ctrl_h.bits.vmuxlo = 2; 1746 rx_tx_ctrl_h.bits.vpulselo = 2; 1747 glue_ctrl0_l.bits.rxlosenable = 1; 1748 glue_ctrl0_l.bits.samplerate = 0xF; 1749 glue_ctrl0_l.bits.thresholdcount = 0xFF; 1750 glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES; 1751 if ((status = nxge_mdio_write(nxgep, portn, 1752 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 1753 rx_tx_ctrl_l.value)) != NXGE_OK) { 1754 goto fail; 1755 } 1756 if ((status = nxge_mdio_write(nxgep, portn, 1757 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 1758 rx_tx_ctrl_h.value)) != NXGE_OK) { 1759 goto fail; 1760 } 1761 if ((status = nxge_mdio_write(nxgep, portn, 1762 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 1763 glue_ctrl0_l.value)) != NXGE_OK) { 1764 goto fail; 1765 } 1766 if ((status = nxge_mdio_write(nxgep, portn, 1767 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 1768 glue_ctrl0_h.value)) != NXGE_OK) { 1769 goto fail; 1770 } 1771 } 1772 1773 if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 1774 ESR_NEP_RX_POWER_CONTROL_L_ADDR(), 0xfff)) != NXGE_OK) { 1775 goto fail; 1776 } 1777 if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 1778 ESR_NEP_RX_POWER_CONTROL_H_ADDR(), 0xfff)) != NXGE_OK) { 1779 goto fail; 1780 } 1781 if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 1782 ESR_NEP_TX_POWER_CONTROL_L_ADDR(), 0x70)) != NXGE_OK) { 1783 goto fail; 1784 } 1785 if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 1786 ESR_NEP_TX_POWER_CONTROL_H_ADDR(), 0xfff)) != NXGE_OK) { 1787 goto fail; 1788 } 1789 1790 /* Apply Tx core reset */ 1791 if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 1792 ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0)) != NXGE_OK) { 1793 goto fail; 1794 } 1795 1796 if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 1797 ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) != 1798 NXGE_OK) { 1799 goto fail; 1800 } 1801 1802 NXGE_DELAY(200); 1803 1804 /* Apply Rx core reset */ 1805 if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 1806 ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) != 1807 NXGE_OK) { 1808 goto fail; 1809 } 1810 1811 NXGE_DELAY(200); 1812 if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 1813 ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK) { 1814 goto fail; 1815 } 1816 1817 NXGE_DELAY(200); 1818 if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 1819 ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), &val16l)) != NXGE_OK) { 1820 goto fail; 1821 } 1822 if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 1823 ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK) { 1824 goto fail; 1825 } 1826 if ((val16l != 0) || (val16h != 0)) { 1827 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1828 "Failed to reset port<%d> XAUI Serdes " 1829 "(val16l 0x%x val16h 0x%x)", portn, val16l, val16h)); 1830 status = NXGE_ERROR; 1831 goto fail; 1832 } 1833 1834 NXGE_DELAY(200); 1835 ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val); 1836 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1837 "nxge_neptune_serdes_init: read internal signal reg port<%d> " 1838 "val 0x%x", portn, val)); 1839 if (portn == 0) { 1840 if ((val & ESR_SIG_P0_BITS_MASK_1G) != 1841 (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0)) { 1842 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1843 "nxge_neptune_serdes_init: " 1844 "Failed to get Serdes up for port<%d> val 0x%x", 1845 portn, (val & ESR_SIG_P0_BITS_MASK))); 1846 status = NXGE_ERROR; 1847 goto fail; 1848 } 1849 } else if (portn == 1) { 1850 if ((val & ESR_SIG_P1_BITS_MASK_1G) != 1851 (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1)) { 1852 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1853 "nxge_neptune_serdes_init: " 1854 "Failed to get Serdes up for port<%d> val 0x%x", 1855 portn, (val & ESR_SIG_P1_BITS_MASK))); 1856 status = NXGE_ERROR; 1857 goto fail; 1858 } 1859 } 1860 done: 1861 1862 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1863 "<== nxge_1G_serdes_init port<%d>", portn)); 1864 return (NXGE_OK); 1865 fail: 1866 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1867 "nxge_1G_serdes_init: " 1868 "Failed to initialize Neptune serdes for port<%d>", 1869 portn)); 1870 1871 return (status); 1872 } 1873 1874 /* Initialize the BCM 8704 xcvr */ 1875 1876 static nxge_status_t 1877 nxge_BCM8704_xcvr_init(p_nxge_t nxgep) 1878 { 1879 uint16_t val; 1880 #ifdef NXGE_DEBUG 1881 uint8_t portn; 1882 uint16_t val1; 1883 #endif 1884 uint8_t phy_port_addr; 1885 pmd_tx_control_t tx_ctl; 1886 control_t ctl; 1887 phyxs_control_t phyxs_ctl; 1888 pcs_control_t pcs_ctl; 1889 uint32_t delay = 0; 1890 optics_dcntr_t op_ctr; 1891 nxge_status_t status = NXGE_OK; 1892 #ifdef NXGE_DEBUG 1893 portn = nxgep->mac.portnum; 1894 #endif 1895 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8704_xcvr_init: port<%d>", 1896 portn)); 1897 1898 phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn; 1899 1900 /* Reset the transceiver */ 1901 if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 1902 BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK) 1903 goto fail; 1904 1905 phyxs_ctl.bits.reset = 1; 1906 if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 1907 BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK) 1908 goto fail; 1909 1910 do { 1911 drv_usecwait(500); 1912 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 1913 BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG, 1914 &phyxs_ctl.value)) != NXGE_OK) 1915 goto fail; 1916 delay++; 1917 } while ((phyxs_ctl.bits.reset) && (delay < 100)); 1918 if (delay == 100) { 1919 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: " 1920 "failed to reset Transceiver on port<%d>", portn)); 1921 status = NXGE_ERROR; 1922 goto fail; 1923 } 1924 1925 /* Set to 0x7FBF */ 1926 ctl.value = 0; 1927 ctl.bits.res1 = 0x3F; 1928 ctl.bits.optxon_lvl = 1; 1929 ctl.bits.oprxflt_lvl = 1; 1930 ctl.bits.optrxlos_lvl = 1; 1931 ctl.bits.optxflt_lvl = 1; 1932 ctl.bits.opprflt_lvl = 1; 1933 ctl.bits.obtmpflt_lvl = 1; 1934 ctl.bits.opbiasflt_lvl = 1; 1935 ctl.bits.optxrst_lvl = 1; 1936 if ((status = nxge_mdio_write(nxgep, phy_port_addr, 1937 BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, ctl.value)) 1938 != NXGE_OK) 1939 goto fail; 1940 1941 /* Set to 0x164 */ 1942 tx_ctl.value = 0; 1943 tx_ctl.bits.tsck_lpwren = 1; 1944 tx_ctl.bits.tx_dac_txck = 0x2; 1945 tx_ctl.bits.tx_dac_txd = 0x1; 1946 tx_ctl.bits.xfp_clken = 1; 1947 if ((status = nxge_mdio_write(nxgep, phy_port_addr, 1948 BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, 1949 tx_ctl.value)) != NXGE_OK) 1950 goto fail; 1951 /* 1952 * According to Broadcom's instruction, SW needs to read 1953 * back these registers twice after written. 1954 */ 1955 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 1956 BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val)) 1957 != NXGE_OK) 1958 goto fail; 1959 1960 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 1961 BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val)) 1962 != NXGE_OK) 1963 goto fail; 1964 1965 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 1966 BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val)) 1967 != NXGE_OK) 1968 goto fail; 1969 1970 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 1971 BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val)) 1972 != NXGE_OK) 1973 goto fail; 1974 1975 /* Enable Tx and Rx LEDs to be driven by traffic */ 1976 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 1977 BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 1978 &op_ctr.value)) != NXGE_OK) 1979 goto fail; 1980 if (NXGE_IS_XAUI_PLATFORM(nxgep)) { 1981 op_ctr.bits.gpio_sel = 0x1; 1982 } else { 1983 op_ctr.bits.gpio_sel = 0x3; 1984 } 1985 if ((status = nxge_mdio_write(nxgep, phy_port_addr, 1986 BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 1987 op_ctr.value)) != NXGE_OK) 1988 goto fail; 1989 1990 NXGE_DELAY(1000000); 1991 1992 /* Set BCM8704 Internal Loopback mode if necessary */ 1993 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 1994 BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value)) 1995 != NXGE_OK) 1996 goto fail; 1997 if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g) 1998 pcs_ctl.bits.loopback = 1; 1999 else 2000 pcs_ctl.bits.loopback = 0; 2001 if ((status = nxge_mdio_write(nxgep, phy_port_addr, 2002 BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value)) 2003 != NXGE_OK) 2004 goto fail; 2005 2006 status = nxge_mdio_read(nxgep, phy_port_addr, 0x1, 0xA, &val); 2007 if (status != NXGE_OK) 2008 goto fail; 2009 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2010 "BCM8704 port<%d> Dev 1 Reg 0xA = 0x%x\n", portn, val)); 2011 status = nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0x20, &val); 2012 if (status != NXGE_OK) 2013 goto fail; 2014 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2015 "BCM8704 port<%d> Dev 3 Reg 0x20 = 0x%x\n", portn, val)); 2016 status = nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, &val); 2017 if (status != NXGE_OK) 2018 goto fail; 2019 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2020 "BCM8704 port<%d> Dev 4 Reg 0x18 = 0x%x\n", portn, val)); 2021 2022 #ifdef NXGE_DEBUG 2023 /* Diagnose link issue if link is not up */ 2024 status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_USER_DEV3_ADDR, 2025 BCM8704_USER_ANALOG_STATUS0_REG, 2026 &val); 2027 if (status != NXGE_OK) 2028 goto fail; 2029 2030 status = nxge_mdio_read(nxgep, phy_port_addr, 2031 BCM8704_USER_DEV3_ADDR, 2032 BCM8704_USER_ANALOG_STATUS0_REG, 2033 &val); 2034 if (status != NXGE_OK) 2035 goto fail; 2036 2037 status = nxge_mdio_read(nxgep, phy_port_addr, 2038 BCM8704_USER_DEV3_ADDR, 2039 BCM8704_USER_TX_ALARM_STATUS_REG, 2040 &val1); 2041 if (status != NXGE_OK) 2042 goto fail; 2043 2044 status = nxge_mdio_read(nxgep, phy_port_addr, 2045 BCM8704_USER_DEV3_ADDR, 2046 BCM8704_USER_TX_ALARM_STATUS_REG, 2047 &val1); 2048 if (status != NXGE_OK) 2049 goto fail; 2050 2051 if (val != 0x3FC) { 2052 if ((val == 0x43BC) && (val1 != 0)) { 2053 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2054 "Cable not connected to peer or bad" 2055 " cable on port<%d>\n", portn)); 2056 } else if (val == 0x639C) { 2057 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2058 "Optical module (XFP) is bad or absent" 2059 " on port<%d>\n", portn)); 2060 } 2061 } 2062 #endif 2063 2064 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8704_xcvr_init: port<%d>", 2065 portn)); 2066 return (NXGE_OK); 2067 2068 fail: 2069 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2070 "nxge_BCM8704_xcvr_init: failed to initialize transceiver for " 2071 "port<%d>", nxgep->mac.portnum)); 2072 return (NXGE_ERROR); 2073 } 2074 2075 /* Initialize the BCM 8706 Transceiver */ 2076 2077 static nxge_status_t 2078 nxge_BCM8706_xcvr_init(p_nxge_t nxgep) 2079 { 2080 uint8_t phy_port_addr; 2081 phyxs_control_t phyxs_ctl; 2082 pcs_control_t pcs_ctl; 2083 uint32_t delay = 0; 2084 optics_dcntr_t op_ctr; 2085 nxge_status_t status = NXGE_OK; 2086 #ifdef NXGE_DEBUG 2087 uint8_t portn = nxgep->mac.portnum; 2088 #endif 2089 2090 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8706_xcvr_init: port<%d>", 2091 portn)); 2092 2093 phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn; 2094 2095 /* Reset the transceiver */ 2096 if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 2097 BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK) 2098 goto fail; 2099 2100 phyxs_ctl.bits.reset = 1; 2101 if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 2102 BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK) 2103 goto fail; 2104 do { 2105 drv_usecwait(500); 2106 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 2107 BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG, 2108 &phyxs_ctl.value)) != NXGE_OK) 2109 goto fail; 2110 delay++; 2111 } while ((phyxs_ctl.bits.reset) && (delay < 100)); 2112 2113 if (delay == 100) { 2114 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: " 2115 "failed to reset Transceiver on port<%d>", portn)); 2116 status = NXGE_ERROR; 2117 goto fail; 2118 } 2119 2120 NXGE_DELAY(1000000); 2121 2122 /* Set BCM8706 Internal Loopback mode if necessary */ 2123 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 2124 BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value)) 2125 != NXGE_OK) 2126 goto fail; 2127 if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g) 2128 pcs_ctl.bits.loopback = 1; 2129 else 2130 pcs_ctl.bits.loopback = 0; 2131 if ((status = nxge_mdio_write(nxgep, phy_port_addr, 2132 BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value)) 2133 != NXGE_OK) 2134 goto fail; 2135 2136 /* Enable Tx and Rx LEDs to be driven by traffic */ 2137 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 2138 BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 2139 &op_ctr.value)) != NXGE_OK) 2140 goto fail; 2141 op_ctr.bits.gpio_sel = 0x3; 2142 op_ctr.bits.res2 = 0x1; 2143 2144 if ((status = nxge_mdio_write(nxgep, phy_port_addr, 2145 BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 2146 op_ctr.value)) != NXGE_OK) 2147 goto fail; 2148 2149 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8706_xcvr_init: port<%d>", 2150 portn)); 2151 return (NXGE_OK); 2152 2153 fail: 2154 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2155 "nxge_BCM8706_xcvr_init: failed to initialize transceiver for " 2156 "port<%d>", nxgep->mac.portnum)); 2157 return (status); 2158 } 2159 2160 #define CHK_STAT(x) status = (x); if (status != NXGE_OK) goto fail 2161 2162 #define MRVL88X2011_RD(nxgep, port, d, r, p) \ 2163 CHK_STAT(nxge_mdio_read(nxgep, port, d, r, p)) 2164 2165 #define MRVL88X2011_WR(nxgep, port, d, r, p) \ 2166 CHK_STAT(nxge_mdio_write(nxgep, port, d, r, p)) 2167 2168 2169 static void 2170 nxge_mrvl88x2011_led_blink_rate(p_nxge_t nxgep, uint16_t rate) 2171 { 2172 uint16_t value; 2173 uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn; 2174 2175 if (nxge_mdio_read(nxgep, phy, MRVL_88X2011_USER_DEV2_ADDR, 2176 MRVL_88X2011_LED_BLINK_CTL, &value) == NXGE_OK) { 2177 value &= ~MRVL_88X2011_LED_BLK_MASK; 2178 value |= (rate << MRVL_88X2011_LED_BLK_SHIFT); 2179 (void) nxge_mdio_write(nxgep, phy, 2180 MRVL_88X2011_USER_DEV2_ADDR, MRVL_88X2011_LED_BLINK_CTL, 2181 value); 2182 } 2183 } 2184 2185 static nxge_status_t 2186 nxge_mrvl88x2011_setup_lb(p_nxge_t nxgep) 2187 { 2188 nxge_status_t status; 2189 pcs_control_t pcs_ctl; 2190 uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn; 2191 2192 MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR, 2193 MRVL_88X2011_PMA_PMD_CTL_1, &pcs_ctl.value); 2194 2195 if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g) 2196 pcs_ctl.bits.loopback = 1; 2197 else 2198 pcs_ctl.bits.loopback = 0; 2199 2200 MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR, 2201 MRVL_88X2011_PMA_PMD_CTL_1, pcs_ctl.value); 2202 2203 fail: 2204 return (status); 2205 } 2206 2207 2208 static void 2209 nxge_mrvl88x2011_led(p_nxge_t nxgep, uint16_t val) 2210 { 2211 uint16_t val2; 2212 uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn; 2213 2214 val2 = MRVL_88X2011_LED(MRVL_88X2011_LED_ACT, val); 2215 val2 &= ~MRVL_88X2011_LED(MRVL_88X2011_LED_ACT, 2216 MRVL_88X2011_LED_CTL_MASK); 2217 val2 |= MRVL_88X2011_LED(MRVL_88X2011_LED_ACT, val); 2218 2219 if (nxge_mdio_write(nxgep, phy, MRVL_88X2011_USER_DEV2_ADDR, 2220 MRVL_88X2011_LED_8_TO_11_CTL, val2) != NXGE_OK) { 2221 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2222 "nxge_mrvl88x2011_led: nxge_mdio_write failed!!")); 2223 } 2224 } 2225 2226 2227 static nxge_status_t 2228 nxge_mrvl88x2011_xcvr_init(p_nxge_t nxgep) 2229 { 2230 uint8_t phy; 2231 nxge_status_t status; 2232 uint16_t clk; 2233 2234 phy = nxgep->statsp->mac_stats.xcvr_portn; 2235 2236 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2237 "==> nxge_mrvl88x2011_xcvr_init: port<%d> addr<0x%x>", 2238 nxgep->mac.portnum, phy)); 2239 2240 /* Set LED functions */ 2241 nxge_mrvl88x2011_led_blink_rate(nxgep, MRVL_88X2011_LED_BLK134MS); 2242 /* PCS activity */ 2243 nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_ACT); 2244 2245 MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR, 2246 MRVL_88X2011_GEN_CTL, &clk); 2247 clk |= MRVL_88X2011_ENA_XFPREFCLK; 2248 MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR, 2249 MRVL_88X2011_GEN_CTL, clk); 2250 2251 /* Set internal loopback mode if necessary */ 2252 2253 CHK_STAT(nxge_mrvl88x2011_setup_lb(nxgep)); 2254 2255 /* Enable PMD */ 2256 MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR, 2257 MRVL_88X2011_10G_PMD_TX_DIS, MRVL_88X2011_ENA_PMDTX); 2258 2259 NXGE_DEBUG_MSG((nxgep, MAC_CTL, " nxge_mrvl88x2011_reset: OK")); 2260 2261 fail: 2262 return (status); 2263 } 2264 2265 2266 2267 /* Initialize the 10G Transceiver */ 2268 2269 static nxge_status_t 2270 nxge_10G_xcvr_init(p_nxge_t nxgep) 2271 { 2272 p_nxge_stats_t statsp; 2273 p_nxge_param_t param_arr = nxgep->param_arr; 2274 nxge_status_t status = NXGE_OK; 2275 #ifdef NXGE_DEBUG 2276 uint8_t portn = nxgep->mac.portnum; 2277 #endif 2278 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>", 2279 portn)); 2280 2281 statsp = nxgep->statsp; 2282 2283 if (nxgep->mac.portmode == PORT_10G_SERDES) { 2284 goto done; 2285 } 2286 2287 /* Disable Link LEDs */ 2288 if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 2289 goto fail; 2290 2291 /* Set Clause 45 */ 2292 npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE); 2293 2294 switch (nxgep->chip_id) { 2295 case BCM8704_CHIP_ID: 2296 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: " 2297 "Chip ID 8704 [0x%x] for 10G xcvr", nxgep->chip_id)); 2298 status = nxge_BCM8704_xcvr_init(nxgep); 2299 break; 2300 case BCM8706_CHIP_ID: 2301 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: " 2302 "Chip ID 8706 [0x%x] for 10G xcvr", nxgep->chip_id)); 2303 status = nxge_BCM8706_xcvr_init(nxgep); 2304 break; 2305 case MRVL88X201X_CHIP_ID: 2306 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: " 2307 "Chip ID 8706 [0x%x] for 10G xcvr", nxgep->chip_id)); 2308 status = nxge_mrvl88x2011_xcvr_init(nxgep); 2309 break; 2310 default: 2311 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_xcvr_init: " 2312 "Unknown chip ID 0x%x for 10G xcvr addr[%d]", 2313 nxgep->chip_id, nxgep->statsp->mac_stats.xcvr_portn)); 2314 goto fail; 2315 } 2316 2317 if (status != NXGE_OK) { 2318 goto fail; 2319 } 2320 done: 2321 statsp->mac_stats.cap_10gfdx = 1; 2322 statsp->mac_stats.lp_cap_10gfdx = 1; 2323 statsp->mac_stats.adv_cap_asmpause = 2324 param_arr[param_anar_asmpause].value; 2325 statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value; 2326 2327 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>", 2328 portn)); 2329 return (NXGE_OK); 2330 2331 fail: 2332 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2333 "nxge_10G_xcvr_init: failed to initialize transceiver for " 2334 "port<%d>", nxgep->mac.portnum)); 2335 return (NXGE_ERROR); 2336 } 2337 2338 /* Initialize the 1G copper (BCM 5464) Transceiver */ 2339 2340 static nxge_status_t 2341 nxge_1G_xcvr_init(p_nxge_t nxgep) 2342 { 2343 p_nxge_param_t param_arr = nxgep->param_arr; 2344 p_nxge_stats_t statsp = nxgep->statsp; 2345 nxge_status_t status = NXGE_OK; 2346 2347 if (nxgep->mac.portmode == PORT_1G_SERDES) { 2348 statsp->mac_stats.cap_1000fdx = 2349 param_arr[param_anar_1000fdx].value; 2350 goto done; 2351 } 2352 2353 /* Set Clause 22 */ 2354 npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_FALSE); 2355 2356 /* Set capability flags */ 2357 statsp->mac_stats.cap_1000fdx = param_arr[param_anar_1000fdx].value; 2358 if ((nxgep->mac.portmode == PORT_1G_COPPER) || 2359 (nxgep->mac.portmode == PORT_1G_FIBER)) { 2360 statsp->mac_stats.cap_100fdx = 2361 param_arr[param_anar_100fdx].value; 2362 statsp->mac_stats.cap_10fdx = 2363 param_arr[param_anar_10fdx].value; 2364 } 2365 2366 status = nxge_mii_xcvr_init(nxgep); 2367 done: 2368 return (status); 2369 } 2370 2371 /* Initialize transceiver */ 2372 2373 nxge_status_t 2374 nxge_xcvr_init(p_nxge_t nxgep) 2375 { 2376 p_nxge_stats_t statsp; 2377 #ifdef NXGE_DEBUG 2378 uint8_t portn; 2379 #endif 2380 2381 nxge_status_t status = NXGE_OK; 2382 #ifdef NXGE_DEBUG 2383 portn = nxgep->mac.portnum; 2384 #endif 2385 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", portn)); 2386 statsp = nxgep->statsp; 2387 2388 /* 2389 * Initialize the xcvr statistics. 2390 */ 2391 statsp->mac_stats.cap_autoneg = 0; 2392 statsp->mac_stats.cap_100T4 = 0; 2393 statsp->mac_stats.cap_100fdx = 0; 2394 statsp->mac_stats.cap_100hdx = 0; 2395 statsp->mac_stats.cap_10fdx = 0; 2396 statsp->mac_stats.cap_10hdx = 0; 2397 statsp->mac_stats.cap_asmpause = 0; 2398 statsp->mac_stats.cap_pause = 0; 2399 statsp->mac_stats.cap_1000fdx = 0; 2400 statsp->mac_stats.cap_1000hdx = 0; 2401 statsp->mac_stats.cap_10gfdx = 0; 2402 statsp->mac_stats.cap_10ghdx = 0; 2403 2404 /* 2405 * Initialize the link statistics. 2406 */ 2407 statsp->mac_stats.link_T4 = 0; 2408 statsp->mac_stats.link_asmpause = 0; 2409 statsp->mac_stats.link_pause = 0; 2410 2411 if (nxgep->xcvr.xcvr_init) { 2412 status = nxgep->xcvr.xcvr_init(nxgep); 2413 if (status != NXGE_OK) 2414 goto fail; 2415 statsp->mac_stats.xcvr_inits++; 2416 } 2417 2418 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", 2419 portn)); 2420 return (NXGE_OK); 2421 2422 fail: 2423 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2424 "nxge_xcvr_init: failed to initialize transceiver for port<%d>", 2425 portn)); 2426 return (status); 2427 } 2428 2429 /* Look for transceiver type */ 2430 2431 nxge_status_t 2432 nxge_xcvr_find(p_nxge_t nxgep) 2433 { 2434 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_find: port<%d>", 2435 nxgep->mac.portnum)); 2436 2437 if (nxge_get_xcvr_type(nxgep) != NXGE_OK) 2438 return (NXGE_ERROR); 2439 2440 if (nxge_setup_xcvr_table(nxgep) != NXGE_OK) 2441 return (NXGE_ERROR); 2442 2443 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xcvr_find: xcvr_inuse = %d", 2444 nxgep->statsp->mac_stats.xcvr_inuse)); 2445 return (NXGE_OK); 2446 } 2447 2448 /* Initialize the TxMAC sub-block */ 2449 2450 nxge_status_t 2451 nxge_tx_mac_init(p_nxge_t nxgep) 2452 { 2453 npi_attr_t ap; 2454 uint8_t portn; 2455 nxge_port_mode_t portmode; 2456 nxge_port_t portt; 2457 npi_handle_t handle; 2458 npi_status_t rs = NPI_SUCCESS; 2459 2460 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 2461 portt = nxgep->mac.porttype; 2462 handle = nxgep->npi_handle; 2463 portmode = nxgep->mac.portmode; 2464 2465 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_init: port<%d>", 2466 portn)); 2467 /* Set Max and Min Frame Size */ 2468 /* 2469 * Use maxframesize to configure the hardware maxframe size 2470 * and minframesize to configure the hardwae minframe size. 2471 */ 2472 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2473 "==> nxge_tx_mac_init: port<%d> " 2474 "min framesize %d max framesize %d ", 2475 nxgep->mac.minframesize, 2476 nxgep->mac.maxframesize, 2477 portn)); 2478 2479 SET_MAC_ATTR2(handle, ap, portn, 2480 MAC_PORT_FRAME_SIZE, 2481 nxgep->mac.minframesize, 2482 nxgep->mac.maxframesize, 2483 rs); 2484 if (rs != NPI_SUCCESS) 2485 goto fail; 2486 2487 if (portt == PORT_TYPE_XMAC) { 2488 if ((rs = npi_xmac_tx_iconfig(handle, INIT, portn, 2489 0)) != NPI_SUCCESS) 2490 goto fail; 2491 nxgep->mac.tx_iconfig = NXGE_XMAC_TX_INTRS; 2492 if ((portmode == PORT_10G_FIBER) || 2493 (portmode == PORT_10G_COPPER) || 2494 (portmode == PORT_10G_SERDES)) { 2495 SET_MAC_ATTR1(handle, ap, portn, XMAC_10G_PORT_IPG, 2496 XGMII_IPG_12_15, rs); 2497 if (rs != NPI_SUCCESS) 2498 goto fail; 2499 nxgep->mac.ipg[0] = XGMII_IPG_12_15; 2500 } else { 2501 SET_MAC_ATTR1(handle, ap, portn, XMAC_PORT_IPG, 2502 MII_GMII_IPG_12, rs); 2503 if (rs != NPI_SUCCESS) 2504 goto fail; 2505 nxgep->mac.ipg[0] = MII_GMII_IPG_12; 2506 } 2507 if ((rs = npi_xmac_tx_config(handle, INIT, portn, 2508 CFG_XMAC_TX_CRC | CFG_XMAC_TX)) != NPI_SUCCESS) 2509 goto fail; 2510 nxgep->mac.tx_config = CFG_XMAC_TX_CRC | CFG_XMAC_TX; 2511 nxgep->mac.maxburstsize = 0; /* not programmable */ 2512 nxgep->mac.ctrltype = 0; /* not programmable */ 2513 nxgep->mac.pa_size = 0; /* not programmable */ 2514 2515 if ((rs = npi_xmac_zap_tx_counters(handle, portn)) 2516 != NPI_SUCCESS) 2517 goto fail; 2518 2519 } else { 2520 if ((rs = npi_bmac_tx_iconfig(handle, INIT, portn, 2521 0)) != NPI_SUCCESS) 2522 goto fail; 2523 nxgep->mac.tx_iconfig = NXGE_BMAC_TX_INTRS; 2524 2525 SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_CTRL_TYPE, 0x8808, 2526 rs); 2527 if (rs != NPI_SUCCESS) 2528 goto fail; 2529 nxgep->mac.ctrltype = 0x8808; 2530 2531 SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_PA_SIZE, 0x7, rs); 2532 if (rs != NPI_SUCCESS) 2533 goto fail; 2534 nxgep->mac.pa_size = 0x7; 2535 2536 if ((rs = npi_bmac_tx_config(handle, INIT, portn, 2537 CFG_BMAC_TX_CRC | CFG_BMAC_TX)) != NPI_SUCCESS) 2538 goto fail; 2539 nxgep->mac.tx_config = CFG_BMAC_TX_CRC | CFG_BMAC_TX; 2540 } 2541 2542 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_init: port<%d>", 2543 portn)); 2544 2545 return (NXGE_OK); 2546 fail: 2547 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2548 "nxge_tx_mac_init: failed to initialize port<%d> TXMAC", 2549 portn)); 2550 2551 return (NXGE_ERROR | rs); 2552 } 2553 2554 int 2555 nxge_hio_hostinfo_get_rdc_table(p_nxge_t nxgep) 2556 { 2557 int rdc_tbl; 2558 2559 /* 2560 * Get an RDC table (version 0). 2561 */ 2562 if ((rdc_tbl = nxge_fzc_rdc_tbl_bind(nxgep, -1, B_FALSE)) < 0) { 2563 NXGE_ERROR_MSG((nxgep, OBP_CTL, 2564 "nxge_hio_hostinfo_get_rdc_table: " 2565 "there are no free RDC tables!")); 2566 return (EBUSY); 2567 } 2568 2569 return (rdc_tbl); 2570 } 2571 2572 /* 2573 * nxge_hio_hostinfo_init 2574 * 2575 * Initialize an alternate MAC address, and bind a macrdctbln to it. 2576 * 2577 * Arguments: 2578 * nxge 2579 * vr The Virtualization Region 2580 * macaddr The alternate MAC address 2581 * 2582 * Notes: 2583 * 1. Find & bind an RDC table to <nxge>. 2584 * 2. Program an alternate MAC address (<macaddr>). 2585 * 3. Bind the RDC table to <macaddr>. 2586 * 2587 * Context: 2588 * Service domain 2589 * 2590 * Side Effects: 2591 * nxge->class_config.mac_host_info[slot].rdctbl 2592 * vr->slot & vr->altmac 2593 * 2594 */ 2595 int 2596 nxge_hio_hostinfo_init( 2597 nxge_t *nxge, 2598 nxge_hio_vr_t *vr, /* Virtualization Region */ 2599 ether_addr_t *macaddr) /* The alternate MAC address */ 2600 { 2601 int rdc_tbl, slot; 2602 2603 nxge_class_pt_cfg_t *class; 2604 hostinfo_t mac_rdc; 2605 npi_mac_addr_t altmac; 2606 nxge_mmac_t *mmac_info; 2607 nxge_rdc_grp_t *group; 2608 uint8_t *addr = (uint8_t *)macaddr; 2609 2610 mutex_enter(nxge->genlock); 2611 2612 rdc_tbl = vr->rdc_tbl; 2613 2614 /* Initialize the NXGE RDC table data structure. */ 2615 group = &nxge->pt_config.rdc_grps[rdc_tbl]; 2616 group->port = NXGE_GET_PORT_NUM(nxge->function_num); 2617 group->config_method = RDC_TABLE_ENTRY_METHOD_REP; 2618 group->flag = 1; /* This group has been configured. */ 2619 2620 mmac_info = &nxge->nxge_mmac_info; 2621 2622 /* 2623 * Are there free slots. 2624 */ 2625 if (mmac_info->naddrfree == 0) { 2626 mutex_exit(nxge->genlock); 2627 return (ENOSPC); 2628 } 2629 2630 /* 2631 * The vswitch has already added this MAC address. 2632 * Find its assigned slot. 2633 */ 2634 if (mmac_info->num_factory_mmac < mmac_info->num_mmac) { 2635 for (slot = mmac_info->num_factory_mmac + 1; 2636 slot <= mmac_info->num_mmac; slot++) { 2637 if (!(mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED)) 2638 break; 2639 } 2640 if (slot > mmac_info->num_mmac) { 2641 for (slot = 1; slot <= mmac_info->num_factory_mmac; 2642 slot++) { 2643 if (!(mmac_info->mac_pool[slot].flags 2644 & MMAC_SLOT_USED)) 2645 break; 2646 } 2647 } 2648 } else { 2649 for (slot = 1; slot <= mmac_info->num_mmac; slot++) { 2650 if (!(mmac_info->mac_pool[slot].flags & MMAC_SLOT_USED)) 2651 break; 2652 } 2653 } 2654 2655 ASSERT(slot <= mmac_info->num_mmac); 2656 vr->slot = slot; 2657 slot = vr->slot - 1; 2658 2659 /* 2660 * Programm the mac address. 2661 */ 2662 altmac.w2 = (((uint16_t)addr[0]) << 8) | 2663 (((uint16_t)addr[1]) & 0x0ff); 2664 altmac.w1 = (((uint16_t)addr[2]) << 8) | 2665 (((uint16_t)addr[3]) & 0x0ff); 2666 altmac.w0 = (((uint16_t)addr[4]) << 8) | 2667 (((uint16_t)addr[5]) & 0x0ff); 2668 2669 if (npi_mac_altaddr_entry(nxge->npi_handle, OP_SET, 2670 nxge->function_num, slot, &altmac) != NPI_SUCCESS) { 2671 mutex_exit(nxge->genlock); 2672 return (EIO); 2673 } 2674 2675 /* 2676 * Associate <rdc_tbl> with this MAC address slot. 2677 */ 2678 class = (p_nxge_class_pt_cfg_t)&nxge->class_config; 2679 2680 /* Update this variable. */ 2681 class = (p_nxge_class_pt_cfg_t)&nxge->class_config; 2682 class->mac_host_info[slot].rdctbl = (uint8_t)rdc_tbl; 2683 2684 mac_rdc.value = 0; 2685 mac_rdc.bits.w0.rdc_tbl_num = rdc_tbl; 2686 mac_rdc.bits.w0.mac_pref = class->mac_host_info[slot].mpr_npr; 2687 /* <mpr_npr> had better be 1! */ 2688 2689 /* Program the RDC table. */ 2690 if ((npi_mac_hostinfo_entry(nxge->npi_handle, OP_SET, 2691 nxge->function_num, slot, &mac_rdc)) != NPI_SUCCESS) { 2692 mutex_exit(nxge->genlock); 2693 (void) nxge_m_mmac_remove(nxge, vr->slot); 2694 return (EIO); 2695 } 2696 2697 if (nxge->mac.portnum != XMAC_PORT_0 && 2698 nxge->mac.portnum != XMAC_PORT_1) 2699 slot++; 2700 2701 /* (Re-)enable the MAC address. */ 2702 (void) npi_mac_altaddr_enable( 2703 nxge->npi_handle, nxge->mac.portnum, slot); 2704 2705 bcopy(macaddr, vr->altmac, sizeof (vr->altmac)); 2706 2707 /* 2708 * Update mmac 2709 */ 2710 bcopy(addr, mmac_info->mac_pool[vr->slot].addr, ETHERADDRL); 2711 mmac_info->mac_pool[vr->slot].flags |= MMAC_SLOT_USED; 2712 mmac_info->mac_pool[vr->slot].flags &= ~MMAC_VENDOR_ADDR; 2713 mmac_info->naddrfree--; 2714 nxge_mmac_kstat_update(nxge, vr->slot, B_FALSE); 2715 2716 mutex_exit(nxge->genlock); 2717 return (0); 2718 } 2719 2720 /* 2721 * nxge_hio_hostinfo_uninit 2722 * 2723 * Uninitialize an alternate MAC address. 2724 * 2725 * Arguments: 2726 * nxge 2727 * vr The Virtualization Region 2728 * 2729 * Notes: 2730 * 1. Remove the VR's alternate MAC address. 2731 * 1. Free (unbind) the RDC table allocated to this VR. 2732 * 2733 * Context: 2734 * Service domain 2735 * 2736 * Side Effects: 2737 * nxge->class_config.mac_host_info[slot].rdctbl 2738 * 2739 */ 2740 void 2741 nxge_hio_hostinfo_uninit( 2742 nxge_t *nxge, 2743 nxge_hio_vr_t *vr) 2744 { 2745 nxge_class_pt_cfg_t *class; 2746 2747 (void) npi_mac_altaddr_disable( 2748 nxge->npi_handle, nxge->mac.portnum, vr->slot); 2749 2750 /* Set this variable to its default. */ 2751 class = (p_nxge_class_pt_cfg_t)&nxge->class_config; 2752 class->mac_host_info[vr->slot].rdctbl = 2753 nxge->pt_config.hw_config.def_mac_rxdma_grpid; 2754 2755 (void) nxge_m_mmac_remove(nxge, vr->slot); 2756 vr->slot = -1; 2757 2758 (void) nxge_fzc_rdc_tbl_unbind(nxge, vr->rdc_tbl); 2759 vr->rdc_tbl = -1; 2760 } 2761 2762 /* Initialize the RxMAC sub-block */ 2763 2764 nxge_status_t 2765 nxge_rx_mac_init(p_nxge_t nxgep) 2766 { 2767 npi_attr_t ap; 2768 uint32_t i; 2769 uint16_t hashtab_e; 2770 p_hash_filter_t hash_filter; 2771 nxge_port_t portt; 2772 uint8_t portn; 2773 npi_handle_t handle; 2774 npi_status_t rs = NPI_SUCCESS; 2775 uint16_t *addr16p; 2776 uint16_t addr0, addr1, addr2; 2777 xmac_rx_config_t xconfig; 2778 bmac_rx_config_t bconfig; 2779 2780 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 2781 2782 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_init: port<%d>\n", 2783 portn)); 2784 handle = nxgep->npi_handle; 2785 portt = nxgep->mac.porttype; 2786 2787 addr16p = (uint16_t *)nxgep->ouraddr.ether_addr_octet; 2788 addr0 = ntohs(addr16p[2]); 2789 addr1 = ntohs(addr16p[1]); 2790 addr2 = ntohs(addr16p[0]); 2791 SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR, addr0, addr1, addr2, 2792 rs); 2793 2794 if (rs != NPI_SUCCESS) 2795 goto fail; 2796 SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR_FILTER, 0, 0, 0, rs); 2797 if (rs != NPI_SUCCESS) 2798 goto fail; 2799 SET_MAC_ATTR2(handle, ap, portn, MAC_PORT_ADDR_FILTER_MASK, 0, 0, rs); 2800 if (rs != NPI_SUCCESS) 2801 goto fail; 2802 2803 /* 2804 * Load the multicast hash filter bits. 2805 */ 2806 hash_filter = nxgep->hash_filter; 2807 for (i = 0; i < MAC_MAX_HASH_ENTRY; i++) { 2808 if (hash_filter != NULL) { 2809 hashtab_e = (uint16_t)hash_filter->hash_filter_regs[ 2810 (NMCFILTER_REGS - 1) - i]; 2811 } else { 2812 hashtab_e = 0; 2813 } 2814 2815 if ((rs = npi_mac_hashtab_entry(handle, OP_SET, portn, i, 2816 (uint16_t *)&hashtab_e)) != NPI_SUCCESS) 2817 goto fail; 2818 } 2819 2820 if (portt == PORT_TYPE_XMAC) { 2821 if ((rs = npi_xmac_rx_iconfig(handle, INIT, portn, 2822 0)) != NPI_SUCCESS) 2823 goto fail; 2824 nxgep->mac.rx_iconfig = NXGE_XMAC_RX_INTRS; 2825 2826 (void) nxge_fflp_init_hostinfo(nxgep); 2827 2828 xconfig = CFG_XMAC_RX_ERRCHK | CFG_XMAC_RX_CRC_CHK | 2829 CFG_XMAC_RX | CFG_XMAC_RX_CODE_VIO_CHK & 2830 ~CFG_XMAC_RX_STRIP_CRC; 2831 2832 if (nxgep->filter.all_phys_cnt != 0) 2833 xconfig |= CFG_XMAC_RX_PROMISCUOUS; 2834 2835 if (nxgep->filter.all_multicast_cnt != 0) 2836 xconfig |= CFG_XMAC_RX_PROMISCUOUSGROUP; 2837 2838 xconfig |= CFG_XMAC_RX_HASH_FILTER; 2839 2840 if ((rs = npi_xmac_rx_config(handle, INIT, portn, 2841 xconfig)) != NPI_SUCCESS) 2842 goto fail; 2843 nxgep->mac.rx_config = xconfig; 2844 2845 /* Comparison of mac unique address is always enabled on XMAC */ 2846 2847 if ((rs = npi_xmac_zap_rx_counters(handle, portn)) 2848 != NPI_SUCCESS) 2849 goto fail; 2850 } else { 2851 (void) nxge_fflp_init_hostinfo(nxgep); 2852 2853 if (npi_bmac_rx_iconfig(nxgep->npi_handle, INIT, portn, 2854 0) != NPI_SUCCESS) 2855 goto fail; 2856 nxgep->mac.rx_iconfig = NXGE_BMAC_RX_INTRS; 2857 2858 bconfig = CFG_BMAC_RX_DISCARD_ON_ERR | CFG_BMAC_RX & 2859 ~CFG_BMAC_RX_STRIP_CRC; 2860 2861 if (nxgep->filter.all_phys_cnt != 0) 2862 bconfig |= CFG_BMAC_RX_PROMISCUOUS; 2863 2864 if (nxgep->filter.all_multicast_cnt != 0) 2865 bconfig |= CFG_BMAC_RX_PROMISCUOUSGROUP; 2866 2867 bconfig |= CFG_BMAC_RX_HASH_FILTER; 2868 if ((rs = npi_bmac_rx_config(handle, INIT, portn, 2869 bconfig)) != NPI_SUCCESS) 2870 goto fail; 2871 nxgep->mac.rx_config = bconfig; 2872 2873 /* Always enable comparison of mac unique address */ 2874 if ((rs = npi_mac_altaddr_enable(handle, portn, 0)) 2875 != NPI_SUCCESS) 2876 goto fail; 2877 } 2878 2879 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_init: port<%d>\n", 2880 portn)); 2881 2882 return (NXGE_OK); 2883 2884 fail: 2885 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2886 "nxge_rx_mac_init: Failed to Initialize port<%d> RxMAC", 2887 portn)); 2888 2889 return (NXGE_ERROR | rs); 2890 } 2891 2892 /* Enable TXMAC */ 2893 2894 nxge_status_t 2895 nxge_tx_mac_enable(p_nxge_t nxgep) 2896 { 2897 npi_handle_t handle; 2898 npi_status_t rs = NPI_SUCCESS; 2899 nxge_status_t status = NXGE_OK; 2900 2901 handle = nxgep->npi_handle; 2902 2903 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_enable: port<%d>", 2904 nxgep->mac.portnum)); 2905 2906 if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK) 2907 goto fail; 2908 2909 /* based on speed */ 2910 nxgep->msg_min = ETHERMIN; 2911 2912 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 2913 if ((rs = npi_xmac_tx_config(handle, ENABLE, nxgep->mac.portnum, 2914 CFG_XMAC_TX)) != NPI_SUCCESS) 2915 goto fail; 2916 } else { 2917 if ((rs = npi_bmac_tx_config(handle, ENABLE, nxgep->mac.portnum, 2918 CFG_BMAC_TX)) != NPI_SUCCESS) 2919 goto fail; 2920 } 2921 2922 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_enable: port<%d>", 2923 nxgep->mac.portnum)); 2924 2925 return (NXGE_OK); 2926 fail: 2927 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2928 "nxgep_tx_mac_enable: Failed to enable port<%d> TxMAC", 2929 nxgep->mac.portnum)); 2930 if (rs != NPI_SUCCESS) 2931 return (NXGE_ERROR | rs); 2932 else 2933 return (status); 2934 } 2935 2936 /* Disable TXMAC */ 2937 2938 nxge_status_t 2939 nxge_tx_mac_disable(p_nxge_t nxgep) 2940 { 2941 npi_handle_t handle; 2942 npi_status_t rs = NPI_SUCCESS; 2943 2944 if (isLDOMguest(nxgep)) 2945 return (NXGE_OK); 2946 2947 handle = nxgep->npi_handle; 2948 2949 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_disable: port<%d>", 2950 nxgep->mac.portnum)); 2951 2952 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 2953 if ((rs = npi_xmac_tx_config(handle, DISABLE, 2954 nxgep->mac.portnum, CFG_XMAC_TX)) != NPI_SUCCESS) 2955 goto fail; 2956 } else { 2957 if ((rs = npi_bmac_tx_config(handle, DISABLE, 2958 nxgep->mac.portnum, CFG_BMAC_TX)) != NPI_SUCCESS) 2959 goto fail; 2960 } 2961 2962 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_disable: port<%d>", 2963 nxgep->mac.portnum)); 2964 return (NXGE_OK); 2965 fail: 2966 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2967 "nxge_tx_mac_disable: Failed to disable port<%d> TxMAC", 2968 nxgep->mac.portnum)); 2969 return (NXGE_ERROR | rs); 2970 } 2971 2972 /* Enable RXMAC */ 2973 2974 nxge_status_t 2975 nxge_rx_mac_enable(p_nxge_t nxgep) 2976 { 2977 npi_handle_t handle; 2978 uint8_t portn; 2979 npi_status_t rs = NPI_SUCCESS; 2980 nxge_status_t status = NXGE_OK; 2981 2982 /* This is a service-domain-only activity. */ 2983 if (isLDOMguest(nxgep)) 2984 return (status); 2985 2986 handle = nxgep->npi_handle; 2987 portn = nxgep->mac.portnum; 2988 2989 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_enable: port<%d>", 2990 portn)); 2991 2992 if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK) 2993 goto fail; 2994 2995 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 2996 if ((rs = npi_xmac_rx_config(handle, ENABLE, portn, 2997 CFG_XMAC_RX)) != NPI_SUCCESS) 2998 goto fail; 2999 } else { 3000 if ((rs = npi_bmac_rx_config(handle, ENABLE, portn, 3001 CFG_BMAC_RX)) != NPI_SUCCESS) 3002 goto fail; 3003 } 3004 3005 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3006 "<== nxge_rx_mac_enable: port<%d>", portn)); 3007 3008 return (NXGE_OK); 3009 fail: 3010 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3011 "nxgep_rx_mac_enable: Failed to enable port<%d> RxMAC", portn)); 3012 3013 if (rs != NPI_SUCCESS) 3014 return (NXGE_ERROR | rs); 3015 else 3016 return (status); 3017 } 3018 3019 /* Disable RXMAC */ 3020 3021 nxge_status_t 3022 nxge_rx_mac_disable(p_nxge_t nxgep) 3023 { 3024 npi_handle_t handle; 3025 uint8_t portn; 3026 npi_status_t rs = NPI_SUCCESS; 3027 3028 /* If we are a guest domain driver, don't bother. */ 3029 if (isLDOMguest(nxgep)) 3030 return (NXGE_OK); 3031 3032 handle = nxgep->npi_handle; 3033 portn = nxgep->mac.portnum; 3034 3035 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_disable: port<%d>", 3036 portn)); 3037 3038 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 3039 if ((rs = npi_xmac_rx_config(handle, DISABLE, portn, 3040 CFG_XMAC_RX)) != NPI_SUCCESS) 3041 goto fail; 3042 } else { 3043 if ((rs = npi_bmac_rx_config(handle, DISABLE, portn, 3044 CFG_BMAC_RX)) != NPI_SUCCESS) 3045 goto fail; 3046 } 3047 3048 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_disable: port<%d>", 3049 portn)); 3050 return (NXGE_OK); 3051 fail: 3052 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3053 "nxgep_rx_mac_disable: ", 3054 "Failed to disable port<%d> RxMAC", 3055 portn)); 3056 3057 return (NXGE_ERROR | rs); 3058 } 3059 3060 /* Reset TXMAC */ 3061 3062 nxge_status_t 3063 nxge_tx_mac_reset(p_nxge_t nxgep) 3064 { 3065 npi_handle_t handle; 3066 uint8_t portn; 3067 npi_status_t rs = NPI_SUCCESS; 3068 3069 handle = nxgep->npi_handle; 3070 portn = nxgep->mac.portnum; 3071 3072 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_reset: port<%d>", 3073 portn)); 3074 3075 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 3076 if ((rs = npi_xmac_reset(handle, portn, XTX_MAC_RESET_ALL)) 3077 != NPI_SUCCESS) 3078 goto fail; 3079 } else { 3080 if ((rs = npi_bmac_reset(handle, portn, TX_MAC_RESET)) 3081 != NPI_SUCCESS) 3082 goto fail; 3083 } 3084 3085 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_reset: port<%d>", 3086 portn)); 3087 3088 return (NXGE_OK); 3089 fail: 3090 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3091 "nxge_tx_mac_reset: Failed to Reset TxMAC port<%d>", 3092 portn)); 3093 3094 return (NXGE_ERROR | rs); 3095 } 3096 3097 /* Reset RXMAC */ 3098 3099 nxge_status_t 3100 nxge_rx_mac_reset(p_nxge_t nxgep) 3101 { 3102 npi_handle_t handle; 3103 uint8_t portn; 3104 npi_status_t rs = NPI_SUCCESS; 3105 3106 handle = nxgep->npi_handle; 3107 portn = nxgep->mac.portnum; 3108 3109 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_reset: port<%d>", 3110 portn)); 3111 3112 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 3113 if ((rs = npi_xmac_reset(handle, portn, XRX_MAC_RESET_ALL)) 3114 != NPI_SUCCESS) 3115 goto fail; 3116 } else { 3117 if ((rs = npi_bmac_reset(handle, portn, RX_MAC_RESET)) 3118 != NPI_SUCCESS) 3119 goto fail; 3120 } 3121 3122 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_reset: port<%d>", 3123 portn)); 3124 3125 return (NXGE_OK); 3126 fail: 3127 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3128 "nxge_rx_mac_reset: Failed to Reset RxMAC port<%d>", 3129 portn)); 3130 return (NXGE_ERROR | rs); 3131 } 3132 3133 /* 10G fiber link interrupt start routine */ 3134 3135 static nxge_status_t 3136 nxge_10G_link_intr_start(p_nxge_t nxgep) 3137 { 3138 npi_status_t rs = NPI_SUCCESS; 3139 uint8_t portn = nxgep->mac.portnum; 3140 3141 rs = npi_xmac_xpcs_link_intr_enable(nxgep->npi_handle, portn); 3142 3143 if (rs != NPI_SUCCESS) 3144 return (NXGE_ERROR | rs); 3145 else 3146 return (NXGE_OK); 3147 } 3148 3149 /* 10G fiber link interrupt stop routine */ 3150 3151 static nxge_status_t 3152 nxge_10G_link_intr_stop(p_nxge_t nxgep) 3153 { 3154 npi_status_t rs = NPI_SUCCESS; 3155 uint8_t portn = nxgep->mac.portnum; 3156 3157 rs = npi_xmac_xpcs_link_intr_disable(nxgep->npi_handle, portn); 3158 3159 if (rs != NPI_SUCCESS) 3160 return (NXGE_ERROR | rs); 3161 else 3162 return (NXGE_OK); 3163 } 3164 3165 /* 1G fiber link interrupt start routine */ 3166 3167 static nxge_status_t 3168 nxge_1G_fiber_link_intr_start(p_nxge_t nxgep) 3169 { 3170 npi_status_t rs = NPI_SUCCESS; 3171 uint8_t portn = nxgep->mac.portnum; 3172 3173 rs = npi_mac_pcs_link_intr_enable(nxgep->npi_handle, portn); 3174 if (rs != NPI_SUCCESS) 3175 return (NXGE_ERROR | rs); 3176 else 3177 return (NXGE_OK); 3178 } 3179 3180 /* 1G fiber link interrupt stop routine */ 3181 3182 static nxge_status_t 3183 nxge_1G_fiber_link_intr_stop(p_nxge_t nxgep) 3184 { 3185 npi_status_t rs = NPI_SUCCESS; 3186 uint8_t portn = nxgep->mac.portnum; 3187 3188 rs = npi_mac_pcs_link_intr_disable(nxgep->npi_handle, portn); 3189 3190 if (rs != NPI_SUCCESS) 3191 return (NXGE_ERROR | rs); 3192 else 3193 return (NXGE_OK); 3194 } 3195 3196 /* 1G copper link interrupt start routine */ 3197 3198 static nxge_status_t 3199 nxge_1G_copper_link_intr_start(p_nxge_t nxgep) 3200 { 3201 npi_status_t rs = NPI_SUCCESS; 3202 uint8_t portn = nxgep->mac.portnum; 3203 3204 rs = npi_mac_mif_link_intr_enable(nxgep->npi_handle, portn, 3205 MII_STATUS, MII_STATUS_LINKUP); 3206 3207 if (rs != NPI_SUCCESS) 3208 return (NXGE_ERROR | rs); 3209 else 3210 return (NXGE_OK); 3211 } 3212 3213 /* 1G copper link interrupt stop routine */ 3214 3215 static nxge_status_t 3216 nxge_1G_copper_link_intr_stop(p_nxge_t nxgep) 3217 { 3218 npi_status_t rs = NPI_SUCCESS; 3219 uint8_t portn = nxgep->mac.portnum; 3220 3221 rs = npi_mac_mif_link_intr_disable(nxgep->npi_handle, portn); 3222 3223 if (rs != NPI_SUCCESS) 3224 return (NXGE_ERROR | rs); 3225 else 3226 return (NXGE_OK); 3227 } 3228 3229 /* Enable/Disable Link Status change interrupt */ 3230 3231 nxge_status_t 3232 nxge_link_intr(p_nxge_t nxgep, link_intr_enable_t enable) 3233 { 3234 uint8_t portn; 3235 nxge_status_t status = NXGE_OK; 3236 3237 portn = nxgep->mac.portnum; 3238 3239 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_intr: port<%d>", portn)); 3240 if (!nxgep->xcvr.link_intr_stop || !nxgep->xcvr.link_intr_start) 3241 return (NXGE_OK); 3242 3243 if (enable == LINK_INTR_START) 3244 status = nxgep->xcvr.link_intr_start(nxgep); 3245 else if (enable == LINK_INTR_STOP) 3246 status = nxgep->xcvr.link_intr_stop(nxgep); 3247 if (status != NXGE_OK) 3248 goto fail; 3249 3250 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_intr: port<%d>", portn)); 3251 3252 return (NXGE_OK); 3253 fail: 3254 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3255 "nxge_link_intr: Failed to set port<%d> mif intr mode", 3256 portn)); 3257 3258 return (status); 3259 } 3260 3261 /* Initialize 1G Fiber / Copper transceiver using Clause 22 */ 3262 3263 nxge_status_t 3264 nxge_mii_xcvr_init(p_nxge_t nxgep) 3265 { 3266 p_nxge_param_t param_arr; 3267 p_nxge_stats_t statsp; 3268 uint8_t xcvr_portn; 3269 p_mii_regs_t mii_regs; 3270 mii_bmcr_t bmcr; 3271 mii_bmsr_t bmsr; 3272 mii_anar_t anar; 3273 mii_gcr_t gcr; 3274 mii_esr_t esr; 3275 mii_aux_ctl_t bcm5464r_aux; 3276 int status = NXGE_OK; 3277 3278 uint_t delay; 3279 3280 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_init")); 3281 3282 param_arr = nxgep->param_arr; 3283 statsp = nxgep->statsp; 3284 xcvr_portn = statsp->mac_stats.xcvr_portn; 3285 3286 mii_regs = NULL; 3287 3288 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3289 "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value)); 3290 3291 /* 3292 * The mif phy mode may be connected to either a copper link 3293 * or fiber link. Read the mode control register to get the fiber 3294 * configuration if it is hard-wired to fiber link. 3295 */ 3296 (void) nxge_mii_get_link_mode(nxgep); 3297 if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) { 3298 return (nxge_mii_xcvr_fiber_init(nxgep)); 3299 } 3300 3301 /* 3302 * Reset the transceiver. 3303 */ 3304 delay = 0; 3305 bmcr.value = 0; 3306 bmcr.bits.reset = 1; 3307 if ((status = nxge_mii_write(nxgep, xcvr_portn, 3308 #if defined(__i386) 3309 (uint8_t)(uint32_t)&mii_regs->bmcr, bmcr.value)) != NXGE_OK) 3310 #else 3311 (uint8_t)(uint64_t)&mii_regs->bmcr, bmcr.value)) != NXGE_OK) 3312 #endif 3313 goto fail; 3314 do { 3315 drv_usecwait(500); 3316 if ((status = nxge_mii_read(nxgep, xcvr_portn, 3317 #if defined(__i386) 3318 (uint8_t)(uint32_t)&mii_regs->bmcr, &bmcr.value)) 3319 #else 3320 (uint8_t)(uint64_t)&mii_regs->bmcr, &bmcr.value)) 3321 #endif 3322 != NXGE_OK) 3323 goto fail; 3324 delay++; 3325 } while ((bmcr.bits.reset) && (delay < 1000)); 3326 if (delay == 1000) { 3327 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed.")); 3328 goto fail; 3329 } 3330 3331 if ((status = nxge_mii_read(nxgep, xcvr_portn, 3332 #if defined(__i386) 3333 (uint8_t)(uint32_t)(&mii_regs->bmsr), 3334 #else 3335 (uint8_t)(uint64_t)(&mii_regs->bmsr), 3336 #endif 3337 &bmsr.value)) != NXGE_OK) 3338 goto fail; 3339 3340 param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able; 3341 param_arr[param_anar_100T4].value &= bmsr.bits.link_100T4; 3342 param_arr[param_anar_100fdx].value &= bmsr.bits.link_100fdx; 3343 param_arr[param_anar_100hdx].value = 0; 3344 param_arr[param_anar_10fdx].value &= bmsr.bits.link_10fdx; 3345 param_arr[param_anar_10hdx].value = 0; 3346 3347 /* 3348 * Initialize the xcvr statistics. 3349 */ 3350 statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able; 3351 statsp->mac_stats.cap_100T4 = bmsr.bits.link_100T4; 3352 statsp->mac_stats.cap_100fdx = bmsr.bits.link_100fdx; 3353 statsp->mac_stats.cap_100hdx = 0; 3354 statsp->mac_stats.cap_10fdx = bmsr.bits.link_10fdx; 3355 statsp->mac_stats.cap_10hdx = 0; 3356 statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value; 3357 statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value; 3358 3359 /* 3360 * Initialise the xcvr advertised capability statistics. 3361 */ 3362 statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value; 3363 statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 3364 statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 3365 statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value; 3366 statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value; 3367 statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value; 3368 statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value; 3369 statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value; 3370 statsp->mac_stats.adv_cap_asmpause = 3371 param_arr[param_anar_asmpause].value; 3372 statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value; 3373 3374 3375 /* 3376 * Check for extended status just in case we're 3377 * running a Gigibit phy. 3378 */ 3379 if (bmsr.bits.extend_status) { 3380 if ((status = nxge_mii_read(nxgep, xcvr_portn, 3381 #if defined(__i386) 3382 (uint8_t)(uint32_t)(&mii_regs->esr), &esr.value)) 3383 #else 3384 (uint8_t)(uint64_t)(&mii_regs->esr), &esr.value)) 3385 #endif 3386 != NXGE_OK) 3387 goto fail; 3388 param_arr[param_anar_1000fdx].value &= 3389 esr.bits.link_1000fdx; 3390 param_arr[param_anar_1000hdx].value = 0; 3391 3392 statsp->mac_stats.cap_1000fdx = 3393 (esr.bits.link_1000Xfdx || 3394 esr.bits.link_1000fdx); 3395 statsp->mac_stats.cap_1000hdx = 0; 3396 } else { 3397 param_arr[param_anar_1000fdx].value = 0; 3398 param_arr[param_anar_1000hdx].value = 0; 3399 } 3400 3401 /* 3402 * Initialize 1G Statistics once the capability is established. 3403 */ 3404 statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 3405 statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 3406 3407 /* 3408 * Initialise the link statistics. 3409 */ 3410 statsp->mac_stats.link_T4 = 0; 3411 statsp->mac_stats.link_asmpause = 0; 3412 statsp->mac_stats.link_pause = 0; 3413 statsp->mac_stats.link_speed = 0; 3414 statsp->mac_stats.link_duplex = 0; 3415 statsp->mac_stats.link_up = 0; 3416 3417 /* 3418 * Switch off Auto-negotiation, 100M and full duplex. 3419 */ 3420 bmcr.value = 0; 3421 if ((status = nxge_mii_write(nxgep, xcvr_portn, 3422 #if defined(__i386) 3423 (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 3424 #else 3425 (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 3426 #endif 3427 goto fail; 3428 3429 if ((statsp->port_stats.lb_mode == nxge_lb_phy) || 3430 (statsp->port_stats.lb_mode == nxge_lb_phy1000)) { 3431 bmcr.bits.loopback = 1; 3432 bmcr.bits.enable_autoneg = 0; 3433 if (statsp->port_stats.lb_mode == nxge_lb_phy1000) 3434 bmcr.bits.speed_1000_sel = 1; 3435 bmcr.bits.duplex_mode = 1; 3436 param_arr[param_autoneg].value = 0; 3437 } else { 3438 bmcr.bits.loopback = 0; 3439 } 3440 3441 if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) || 3442 (statsp->port_stats.lb_mode == nxge_lb_ext100) || 3443 (statsp->port_stats.lb_mode == nxge_lb_ext10)) { 3444 param_arr[param_autoneg].value = 0; 3445 bcm5464r_aux.value = 0; 3446 bcm5464r_aux.bits.ext_lb = 1; 3447 bcm5464r_aux.bits.write_1 = 1; 3448 if ((status = nxge_mii_write(nxgep, xcvr_portn, 3449 BCM5464R_AUX_CTL, bcm5464r_aux.value)) 3450 != NXGE_OK) 3451 goto fail; 3452 } 3453 3454 if (param_arr[param_autoneg].value) { 3455 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3456 "Restarting Auto-negotiation.")); 3457 /* 3458 * Setup our Auto-negotiation advertisement register. 3459 */ 3460 anar.value = 0; 3461 anar.bits.selector = 1; 3462 anar.bits.cap_100T4 = param_arr[param_anar_100T4].value; 3463 anar.bits.cap_100fdx = param_arr[param_anar_100fdx].value; 3464 anar.bits.cap_100hdx = param_arr[param_anar_100hdx].value; 3465 anar.bits.cap_10fdx = param_arr[param_anar_10fdx].value; 3466 anar.bits.cap_10hdx = param_arr[param_anar_10hdx].value; 3467 anar.bits.cap_asmpause = 0; 3468 anar.bits.cap_pause = 0; 3469 if (param_arr[param_anar_1000fdx].value || 3470 param_arr[param_anar_100fdx].value || 3471 param_arr[param_anar_10fdx].value) { 3472 anar.bits.cap_asmpause = statsp->mac_stats.cap_asmpause; 3473 anar.bits.cap_pause = statsp->mac_stats.cap_pause; 3474 } 3475 3476 if ((status = nxge_mii_write(nxgep, xcvr_portn, 3477 #if defined(__i386) 3478 (uint8_t)(uint32_t)(&mii_regs->anar), anar.value)) 3479 #else 3480 (uint8_t)(uint64_t)(&mii_regs->anar), anar.value)) 3481 #endif 3482 != NXGE_OK) 3483 goto fail; 3484 if (bmsr.bits.extend_status) { 3485 gcr.value = 0; 3486 gcr.bits.ms_mode_en = 3487 param_arr[param_master_cfg_enable].value; 3488 gcr.bits.master = 3489 param_arr[param_master_cfg_value].value; 3490 gcr.bits.link_1000fdx = 3491 param_arr[param_anar_1000fdx].value; 3492 gcr.bits.link_1000hdx = 3493 param_arr[param_anar_1000hdx].value; 3494 if ((status = nxge_mii_write(nxgep, xcvr_portn, 3495 #if defined(__i386) 3496 (uint8_t)(uint32_t)(&mii_regs->gcr), gcr.value)) 3497 #else 3498 (uint8_t)(uint64_t)(&mii_regs->gcr), gcr.value)) 3499 #endif 3500 != NXGE_OK) 3501 goto fail; 3502 } 3503 3504 bmcr.bits.enable_autoneg = 1; 3505 bmcr.bits.restart_autoneg = 1; 3506 3507 } else { 3508 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode.")); 3509 bmcr.bits.speed_1000_sel = 3510 param_arr[param_anar_1000fdx].value | 3511 param_arr[param_anar_1000hdx].value; 3512 bmcr.bits.speed_sel = (~bmcr.bits.speed_1000_sel) & 3513 (param_arr[param_anar_100fdx].value | 3514 param_arr[param_anar_100hdx].value); 3515 if (bmcr.bits.speed_1000_sel) { 3516 statsp->mac_stats.link_speed = 1000; 3517 gcr.value = 0; 3518 gcr.bits.ms_mode_en = 3519 param_arr[param_master_cfg_enable].value; 3520 gcr.bits.master = 3521 param_arr[param_master_cfg_value].value; 3522 if ((status = nxge_mii_write(nxgep, xcvr_portn, 3523 #if defined(__i386) 3524 (uint8_t)(uint32_t)(&mii_regs->gcr), 3525 #else 3526 (uint8_t)(uint64_t)(&mii_regs->gcr), 3527 #endif 3528 gcr.value)) 3529 != NXGE_OK) 3530 goto fail; 3531 if (param_arr[param_anar_1000fdx].value) { 3532 bmcr.bits.duplex_mode = 1; 3533 statsp->mac_stats.link_duplex = 2; 3534 } else 3535 statsp->mac_stats.link_duplex = 1; 3536 } else if (bmcr.bits.speed_sel) { 3537 statsp->mac_stats.link_speed = 100; 3538 if (param_arr[param_anar_100fdx].value) { 3539 bmcr.bits.duplex_mode = 1; 3540 statsp->mac_stats.link_duplex = 2; 3541 } else 3542 statsp->mac_stats.link_duplex = 1; 3543 } else { 3544 statsp->mac_stats.link_speed = 10; 3545 if (param_arr[param_anar_10fdx].value) { 3546 bmcr.bits.duplex_mode = 1; 3547 statsp->mac_stats.link_duplex = 2; 3548 } else 3549 statsp->mac_stats.link_duplex = 1; 3550 } 3551 if (statsp->mac_stats.link_duplex != 1) { 3552 statsp->mac_stats.link_asmpause = 3553 statsp->mac_stats.cap_asmpause; 3554 statsp->mac_stats.link_pause = 3555 statsp->mac_stats.cap_pause; 3556 } 3557 3558 if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) || 3559 (statsp->port_stats.lb_mode == nxge_lb_ext100) || 3560 (statsp->port_stats.lb_mode == nxge_lb_ext10)) { 3561 if (statsp->port_stats.lb_mode == nxge_lb_ext1000) { 3562 /* BCM5464R 1000mbps external loopback mode */ 3563 gcr.value = 0; 3564 gcr.bits.ms_mode_en = 1; 3565 gcr.bits.master = 1; 3566 if ((status = nxge_mii_write(nxgep, xcvr_portn, 3567 #if defined(__i386) 3568 (uint8_t)(uint32_t)(&mii_regs->gcr), 3569 #else 3570 (uint8_t)(uint64_t)(&mii_regs->gcr), 3571 #endif 3572 gcr.value)) 3573 != NXGE_OK) 3574 goto fail; 3575 bmcr.value = 0; 3576 bmcr.bits.speed_1000_sel = 1; 3577 statsp->mac_stats.link_speed = 1000; 3578 } else if (statsp->port_stats.lb_mode 3579 == nxge_lb_ext100) { 3580 /* BCM5464R 100mbps external loopback mode */ 3581 bmcr.value = 0; 3582 bmcr.bits.speed_sel = 1; 3583 bmcr.bits.duplex_mode = 1; 3584 statsp->mac_stats.link_speed = 100; 3585 } else if (statsp->port_stats.lb_mode 3586 == nxge_lb_ext10) { 3587 /* BCM5464R 10mbps external loopback mode */ 3588 bmcr.value = 0; 3589 bmcr.bits.duplex_mode = 1; 3590 statsp->mac_stats.link_speed = 10; 3591 } 3592 } 3593 } 3594 3595 if ((status = nxge_mii_write(nxgep, xcvr_portn, 3596 #if defined(__i386) 3597 (uint8_t)(uint32_t)(&mii_regs->bmcr), 3598 #else 3599 (uint8_t)(uint64_t)(&mii_regs->bmcr), 3600 #endif 3601 bmcr.value)) != NXGE_OK) 3602 goto fail; 3603 3604 if ((status = nxge_mii_read(nxgep, xcvr_portn, 3605 #if defined(__i386) 3606 (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK) 3607 #else 3608 (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK) 3609 #endif 3610 goto fail; 3611 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "bmcr = 0x%04X", bmcr.value)); 3612 3613 /* 3614 * Initialize the xcvr status kept in the context structure. 3615 */ 3616 nxgep->soft_bmsr.value = 0; 3617 3618 if ((status = nxge_mii_read(nxgep, xcvr_portn, 3619 #if defined(__i386) 3620 (uint8_t)(uint32_t)(&mii_regs->bmsr), 3621 #else 3622 (uint8_t)(uint64_t)(&mii_regs->bmsr), 3623 #endif 3624 &nxgep->bmsr.value)) != NXGE_OK) 3625 goto fail; 3626 3627 statsp->mac_stats.xcvr_inits++; 3628 nxgep->bmsr.value = 0; 3629 3630 fail: 3631 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3632 "<== nxge_mii_xcvr_init status 0x%x", status)); 3633 return (status); 3634 } 3635 3636 nxge_status_t 3637 nxge_mii_xcvr_fiber_init(p_nxge_t nxgep) 3638 { 3639 p_nxge_param_t param_arr; 3640 p_nxge_stats_t statsp; 3641 uint8_t xcvr_portn; 3642 p_mii_regs_t mii_regs; 3643 mii_bmcr_t bmcr; 3644 mii_bmsr_t bmsr; 3645 mii_gcr_t gcr; 3646 mii_esr_t esr; 3647 mii_aux_ctl_t bcm5464r_aux; 3648 int status = NXGE_OK; 3649 3650 uint_t delay; 3651 3652 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_fiber_init")); 3653 3654 param_arr = nxgep->param_arr; 3655 statsp = nxgep->statsp; 3656 xcvr_portn = statsp->mac_stats.xcvr_portn; 3657 3658 mii_regs = NULL; 3659 3660 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3661 "nxge_mii_xcvr_fiber_init: " 3662 "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value)); 3663 3664 /* 3665 * Reset the transceiver. 3666 */ 3667 delay = 0; 3668 bmcr.value = 0; 3669 bmcr.bits.reset = 1; 3670 3671 #if defined(__i386) 3672 3673 if ((status = nxge_mii_write(nxgep, xcvr_portn, 3674 (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 3675 goto fail; 3676 #else 3677 if ((status = nxge_mii_write(nxgep, xcvr_portn, 3678 (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 3679 goto fail; 3680 #endif 3681 do { 3682 drv_usecwait(500); 3683 #if defined(__i386) 3684 if ((status = nxge_mii_read(nxgep, xcvr_portn, 3685 (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) 3686 != NXGE_OK) 3687 goto fail; 3688 #else 3689 if ((status = nxge_mii_read(nxgep, xcvr_portn, 3690 (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) 3691 != NXGE_OK) 3692 goto fail; 3693 #endif 3694 delay++; 3695 } while ((bmcr.bits.reset) && (delay < 1000)); 3696 if (delay == 1000) { 3697 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed.")); 3698 goto fail; 3699 } 3700 3701 #if defined(__i386) 3702 if ((status = nxge_mii_read(nxgep, xcvr_portn, 3703 (uint8_t)(uint32_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK) 3704 goto fail; 3705 #else 3706 if ((status = nxge_mii_read(nxgep, xcvr_portn, 3707 (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK) 3708 goto fail; 3709 #endif 3710 3711 param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able; 3712 param_arr[param_anar_100T4].value = 0; 3713 param_arr[param_anar_100fdx].value = 0; 3714 param_arr[param_anar_100hdx].value = 0; 3715 param_arr[param_anar_10fdx].value = 0; 3716 param_arr[param_anar_10hdx].value = 0; 3717 3718 /* 3719 * Initialize the xcvr statistics. 3720 */ 3721 statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able; 3722 statsp->mac_stats.cap_100T4 = 0; 3723 statsp->mac_stats.cap_100fdx = 0; 3724 statsp->mac_stats.cap_100hdx = 0; 3725 statsp->mac_stats.cap_10fdx = 0; 3726 statsp->mac_stats.cap_10hdx = 0; 3727 statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value; 3728 statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value; 3729 3730 /* 3731 * Initialize the xcvr advertised capability statistics. 3732 */ 3733 statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value; 3734 statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 3735 statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 3736 statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value; 3737 statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value; 3738 statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value; 3739 statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value; 3740 statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value; 3741 statsp->mac_stats.adv_cap_asmpause = 3742 param_arr[param_anar_asmpause].value; 3743 statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value; 3744 3745 /* 3746 * Check for extended status just in case we're 3747 * running a Gigibit phy. 3748 */ 3749 if (bmsr.bits.extend_status) { 3750 #if defined(__i386) 3751 if ((status = nxge_mii_read(nxgep, xcvr_portn, 3752 (uint8_t)(uint32_t)(&mii_regs->esr), &esr.value)) != 3753 NXGE_OK) 3754 goto fail; 3755 #else 3756 if ((status = nxge_mii_read(nxgep, xcvr_portn, 3757 (uint8_t)(uint64_t)(&mii_regs->esr), &esr.value)) != 3758 NXGE_OK) 3759 goto fail; 3760 #endif 3761 param_arr[param_anar_1000fdx].value &= 3762 esr.bits.link_1000fdx; 3763 param_arr[param_anar_1000hdx].value = 0; 3764 3765 statsp->mac_stats.cap_1000fdx = 3766 (esr.bits.link_1000Xfdx || esr.bits.link_1000fdx); 3767 statsp->mac_stats.cap_1000hdx = 0; 3768 } else { 3769 param_arr[param_anar_1000fdx].value = 0; 3770 param_arr[param_anar_1000hdx].value = 0; 3771 } 3772 3773 /* 3774 * Initialize 1G Statistics once the capability is established. 3775 */ 3776 statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 3777 statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 3778 3779 /* 3780 * Initialize the link statistics. 3781 */ 3782 statsp->mac_stats.link_T4 = 0; 3783 statsp->mac_stats.link_asmpause = 0; 3784 statsp->mac_stats.link_pause = 0; 3785 statsp->mac_stats.link_speed = 0; 3786 statsp->mac_stats.link_duplex = 0; 3787 statsp->mac_stats.link_up = 0; 3788 3789 /* 3790 * Switch off Auto-negotiation, 100M and full duplex. 3791 */ 3792 bmcr.value = 0; 3793 #if defined(__i386) 3794 if ((status = nxge_mii_write(nxgep, xcvr_portn, 3795 (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 3796 goto fail; 3797 #else 3798 if ((status = nxge_mii_write(nxgep, xcvr_portn, 3799 (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 3800 goto fail; 3801 #endif 3802 3803 if ((statsp->port_stats.lb_mode == nxge_lb_phy) || 3804 (statsp->port_stats.lb_mode == nxge_lb_phy1000)) { 3805 bmcr.bits.loopback = 1; 3806 bmcr.bits.enable_autoneg = 0; 3807 if (statsp->port_stats.lb_mode == nxge_lb_phy1000) 3808 bmcr.bits.speed_1000_sel = 1; 3809 bmcr.bits.duplex_mode = 1; 3810 param_arr[param_autoneg].value = 0; 3811 } else { 3812 bmcr.bits.loopback = 0; 3813 } 3814 3815 if (statsp->port_stats.lb_mode == nxge_lb_ext1000) { 3816 param_arr[param_autoneg].value = 0; 3817 bcm5464r_aux.value = 0; 3818 bcm5464r_aux.bits.ext_lb = 1; 3819 bcm5464r_aux.bits.write_1 = 1; 3820 if ((status = nxge_mii_write(nxgep, xcvr_portn, 3821 BCM5464R_AUX_CTL, bcm5464r_aux.value)) != NXGE_OK) 3822 goto fail; 3823 } 3824 3825 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode.")); 3826 bmcr.bits.speed_1000_sel = 1; 3827 bmcr.bits.speed_sel = 0; 3828 bmcr.bits.duplex_mode = 1; 3829 statsp->mac_stats.link_speed = 1000; 3830 statsp->mac_stats.link_duplex = 2; 3831 3832 if ((statsp->port_stats.lb_mode == nxge_lb_ext1000)) { 3833 /* BCM5464R 1000mbps external loopback mode */ 3834 gcr.value = 0; 3835 gcr.bits.ms_mode_en = 1; 3836 gcr.bits.master = 1; 3837 #if defined(__i386) 3838 if ((status = nxge_mii_write(nxgep, xcvr_portn, 3839 (uint8_t)(uint32_t)(&mii_regs->gcr), 3840 gcr.value)) != NXGE_OK) 3841 goto fail; 3842 #else 3843 if ((status = nxge_mii_write(nxgep, xcvr_portn, 3844 (uint8_t)(uint64_t)(&mii_regs->gcr), 3845 gcr.value)) != NXGE_OK) 3846 goto fail; 3847 #endif 3848 bmcr.value = 0; 3849 bmcr.bits.speed_1000_sel = 1; 3850 statsp->mac_stats.link_speed = 1000; 3851 } 3852 3853 #if defined(__i386) 3854 if ((status = nxge_mii_write(nxgep, xcvr_portn, 3855 (uint8_t)(uint32_t)(&mii_regs->bmcr), 3856 bmcr.value)) != NXGE_OK) 3857 goto fail; 3858 #else 3859 if ((status = nxge_mii_write(nxgep, xcvr_portn, 3860 (uint8_t)(uint64_t)(&mii_regs->bmcr), 3861 bmcr.value)) != NXGE_OK) 3862 goto fail; 3863 #endif 3864 3865 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3866 "nxge_mii_xcvr_fiber_init: value wrote bmcr = 0x%x", 3867 bmcr.value)); 3868 3869 #if defined(__i386) 3870 if ((status = nxge_mii_read(nxgep, xcvr_portn, 3871 (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK) 3872 goto fail; 3873 #else 3874 if ((status = nxge_mii_read(nxgep, xcvr_portn, 3875 (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK) 3876 goto fail; 3877 #endif 3878 3879 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3880 "nxge_mii_xcvr_fiber_init: read bmcr = 0x%04X", bmcr.value)); 3881 3882 /* 3883 * Initialize the xcvr status kept in the context structure. 3884 */ 3885 nxgep->soft_bmsr.value = 0; 3886 #if defined(__i386) 3887 if ((status = nxge_mii_read(nxgep, xcvr_portn, 3888 (uint8_t)(uint32_t)(&mii_regs->bmsr), 3889 &nxgep->bmsr.value)) != NXGE_OK) 3890 goto fail; 3891 #else 3892 if ((status = nxge_mii_read(nxgep, xcvr_portn, 3893 (uint8_t)(uint64_t)(&mii_regs->bmsr), 3894 &nxgep->bmsr.value)) != NXGE_OK) 3895 goto fail; 3896 #endif 3897 3898 statsp->mac_stats.xcvr_inits++; 3899 nxgep->bmsr.value = 0; 3900 3901 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3902 "<== nxge_mii_xcvr_fiber_init status 0x%x", status)); 3903 return (status); 3904 3905 fail: 3906 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3907 "<== nxge_mii_xcvr_fiber_init status 0x%x", status)); 3908 return (status); 3909 } 3910 3911 /* Read from a MII compliant register */ 3912 3913 nxge_status_t 3914 nxge_mii_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg, 3915 uint16_t *value) 3916 { 3917 npi_status_t rs = NPI_SUCCESS; 3918 3919 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_read: xcvr_port<%d>" 3920 "xcvr_reg<%d>", xcvr_portn, xcvr_reg)); 3921 3922 MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 3923 3924 if ((nxgep->mac.portmode == PORT_1G_COPPER) || 3925 (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) { 3926 if ((rs = npi_mac_mif_mii_read(nxgep->npi_handle, 3927 xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 3928 goto fail; 3929 } else if ((nxgep->mac.portmode == PORT_1G_FIBER) || 3930 (nxgep->mac.portmode == PORT_1G_SERDES)) { 3931 if ((rs = npi_mac_pcs_mii_read(nxgep->npi_handle, 3932 xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 3933 goto fail; 3934 } else 3935 goto fail; 3936 3937 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 3938 3939 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_read: xcvr_port<%d>" 3940 "xcvr_reg<%d> value=0x%x", 3941 xcvr_portn, xcvr_reg, *value)); 3942 return (NXGE_OK); 3943 fail: 3944 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 3945 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3946 "nxge_mii_read: Failed to read mii on xcvr %d", 3947 xcvr_portn)); 3948 3949 return (NXGE_ERROR | rs); 3950 } 3951 3952 /* Write to a MII compliant Register */ 3953 3954 nxge_status_t 3955 nxge_mii_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg, 3956 uint16_t value) 3957 { 3958 npi_status_t rs = NPI_SUCCESS; 3959 3960 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_write: xcvr_port<%d>" 3961 "xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg, 3962 value)); 3963 3964 MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 3965 3966 if ((nxgep->mac.portmode == PORT_1G_COPPER) || 3967 (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) { 3968 if ((rs = npi_mac_mif_mii_write(nxgep->npi_handle, 3969 xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 3970 goto fail; 3971 } else if ((nxgep->mac.portmode == PORT_1G_FIBER) || 3972 (nxgep->mac.portmode == PORT_1G_SERDES)) { 3973 if ((rs = npi_mac_pcs_mii_write(nxgep->npi_handle, 3974 xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 3975 goto fail; 3976 } else 3977 goto fail; 3978 3979 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 3980 3981 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_write: xcvr_port<%d>" 3982 "xcvr_reg<%d>", xcvr_portn, xcvr_reg)); 3983 return (NXGE_OK); 3984 fail: 3985 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 3986 3987 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3988 "nxge_mii_write: Failed to write mii on xcvr %d", 3989 xcvr_portn)); 3990 3991 return (NXGE_ERROR | rs); 3992 } 3993 3994 /* Perform read from Clause45 serdes / transceiver device */ 3995 3996 nxge_status_t 3997 nxge_mdio_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device, 3998 uint16_t xcvr_reg, uint16_t *value) 3999 { 4000 npi_status_t rs = NPI_SUCCESS; 4001 4002 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_read: xcvr_port<%d>", 4003 xcvr_portn)); 4004 4005 MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 4006 4007 if ((rs = npi_mac_mif_mdio_read(nxgep->npi_handle, 4008 xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS) 4009 goto fail; 4010 4011 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 4012 4013 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_read: xcvr_port<%d>", 4014 xcvr_portn)); 4015 return (NXGE_OK); 4016 fail: 4017 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 4018 4019 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4020 "nxge_mdio_read: Failed to read mdio on xcvr %d", 4021 xcvr_portn)); 4022 4023 return (NXGE_ERROR | rs); 4024 } 4025 4026 /* Perform write to Clause45 serdes / transceiver device */ 4027 4028 nxge_status_t 4029 nxge_mdio_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device, 4030 uint16_t xcvr_reg, uint16_t value) 4031 { 4032 npi_status_t rs = NPI_SUCCESS; 4033 4034 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_write: xcvr_port<%d>", 4035 xcvr_portn)); 4036 4037 MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 4038 4039 if ((rs = npi_mac_mif_mdio_write(nxgep->npi_handle, 4040 xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS) 4041 goto fail; 4042 4043 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 4044 4045 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_write: xcvr_port<%d>", 4046 xcvr_portn)); 4047 return (NXGE_OK); 4048 fail: 4049 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 4050 4051 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4052 "nxge_mdio_write: Failed to write mdio on xcvr %d", 4053 xcvr_portn)); 4054 4055 return (NXGE_ERROR | rs); 4056 } 4057 4058 4059 /* Check MII to see if there is any link status change */ 4060 4061 nxge_status_t 4062 nxge_mii_check(p_nxge_t nxgep, mii_bmsr_t bmsr, mii_bmsr_t bmsr_ints, 4063 nxge_link_state_t *link_up) 4064 { 4065 p_nxge_param_t param_arr; 4066 p_nxge_stats_t statsp; 4067 p_mii_regs_t mii_regs; 4068 p_mii_bmsr_t soft_bmsr; 4069 mii_anar_t anar; 4070 mii_anlpar_t anlpar; 4071 mii_anar_t an_common; 4072 mii_aner_t aner; 4073 mii_gsr_t gsr; 4074 nxge_status_t status = NXGE_OK; 4075 4076 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_check")); 4077 4078 mii_regs = NULL; 4079 param_arr = nxgep->param_arr; 4080 statsp = nxgep->statsp; 4081 soft_bmsr = &nxgep->soft_bmsr; 4082 *link_up = LINK_NO_CHANGE; 4083 4084 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4085 "==> nxge_mii_check bmsr 0x%x bmsr_int 0x%x", 4086 bmsr.value, bmsr_ints.value)); 4087 4088 if (bmsr_ints.bits.link_status) { 4089 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4090 "==> nxge_mii_check (link up) bmsr 0x%x bmsr_int 0x%x", 4091 bmsr.value, bmsr_ints.value)); 4092 if (bmsr.bits.link_status) { 4093 soft_bmsr->bits.link_status = 1; 4094 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4095 "==> nxge_mii_check (link up) soft bmsr 0x%x bmsr_int " 4096 "0x%x", bmsr.value, bmsr_ints.value)); 4097 } else { 4098 statsp->mac_stats.link_up = 0; 4099 soft_bmsr->bits.link_status = 0; 4100 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4101 "Link down cable problem")); 4102 *link_up = LINK_IS_DOWN; 4103 } 4104 } 4105 4106 if (nxgep->mac.portmode == PORT_1G_COPPER && 4107 param_arr[param_autoneg].value) { 4108 if (bmsr_ints.bits.auto_neg_complete) { 4109 if (bmsr.bits.auto_neg_complete) 4110 soft_bmsr->bits.auto_neg_complete = 1; 4111 else 4112 soft_bmsr->bits.auto_neg_complete = 0; 4113 } 4114 if (soft_bmsr->bits.link_status == 0) { 4115 statsp->mac_stats.link_T4 = 0; 4116 statsp->mac_stats.link_speed = 0; 4117 statsp->mac_stats.link_duplex = 0; 4118 statsp->mac_stats.link_asmpause = 0; 4119 statsp->mac_stats.link_pause = 0; 4120 statsp->mac_stats.lp_cap_autoneg = 0; 4121 statsp->mac_stats.lp_cap_100T4 = 0; 4122 statsp->mac_stats.lp_cap_1000fdx = 0; 4123 statsp->mac_stats.lp_cap_1000hdx = 0; 4124 statsp->mac_stats.lp_cap_100fdx = 0; 4125 statsp->mac_stats.lp_cap_100hdx = 0; 4126 statsp->mac_stats.lp_cap_10fdx = 0; 4127 statsp->mac_stats.lp_cap_10hdx = 0; 4128 statsp->mac_stats.lp_cap_10gfdx = 0; 4129 statsp->mac_stats.lp_cap_10ghdx = 0; 4130 statsp->mac_stats.lp_cap_asmpause = 0; 4131 statsp->mac_stats.lp_cap_pause = 0; 4132 } 4133 } else 4134 soft_bmsr->bits.auto_neg_complete = 1; 4135 4136 if ((bmsr_ints.bits.link_status || 4137 bmsr_ints.bits.auto_neg_complete) && 4138 soft_bmsr->bits.link_status && 4139 soft_bmsr->bits.auto_neg_complete) { 4140 statsp->mac_stats.link_up = 1; 4141 4142 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4143 "==> nxge_mii_check " 4144 "(auto negotiation complete or link up) " 4145 "soft bmsr 0x%x bmsr_int 0x%x", 4146 bmsr.value, bmsr_ints.value)); 4147 4148 if (nxgep->mac.portmode == PORT_1G_COPPER && 4149 param_arr[param_autoneg].value) { 4150 if ((status = nxge_mii_read(nxgep, 4151 statsp->mac_stats.xcvr_portn, 4152 #if defined(__i386) 4153 (uint8_t)(uint32_t)(&mii_regs->anar), 4154 #else 4155 (uint8_t)(uint64_t)(&mii_regs->anar), 4156 #endif 4157 &anar.value)) != NXGE_OK) 4158 goto fail; 4159 if ((status = nxge_mii_read(nxgep, 4160 statsp->mac_stats.xcvr_portn, 4161 #if defined(__i386) 4162 (uint8_t)(uint32_t)(&mii_regs->anlpar), 4163 #else 4164 (uint8_t)(uint64_t)(&mii_regs->anlpar), 4165 #endif 4166 &anlpar.value)) != NXGE_OK) 4167 goto fail; 4168 if ((status = nxge_mii_read(nxgep, 4169 statsp->mac_stats.xcvr_portn, 4170 #if defined(__i386) 4171 (uint8_t)(uint32_t)(&mii_regs->aner), 4172 #else 4173 (uint8_t)(uint64_t)(&mii_regs->aner), 4174 #endif 4175 &aner.value)) != NXGE_OK) 4176 goto fail; 4177 statsp->mac_stats.lp_cap_autoneg = aner.bits.lp_an_able; 4178 statsp->mac_stats.lp_cap_100T4 = anlpar.bits.cap_100T4; 4179 statsp->mac_stats.lp_cap_100fdx = 4180 anlpar.bits.cap_100fdx; 4181 statsp->mac_stats.lp_cap_100hdx = 4182 anlpar.bits.cap_100hdx; 4183 statsp->mac_stats.lp_cap_10fdx = anlpar.bits.cap_10fdx; 4184 statsp->mac_stats.lp_cap_10hdx = anlpar.bits.cap_10hdx; 4185 statsp->mac_stats.lp_cap_asmpause = 4186 anlpar.bits.cap_asmpause; 4187 statsp->mac_stats.lp_cap_pause = anlpar.bits.cap_pause; 4188 an_common.value = anar.value & anlpar.value; 4189 if (param_arr[param_anar_1000fdx].value || 4190 param_arr[param_anar_1000hdx].value) { 4191 if ((status = nxge_mii_read(nxgep, 4192 statsp->mac_stats.xcvr_portn, 4193 #if defined(__i386) 4194 (uint8_t)(uint32_t)(&mii_regs->gsr), 4195 #else 4196 (uint8_t)(uint64_t)(&mii_regs->gsr), 4197 #endif 4198 &gsr.value)) 4199 != NXGE_OK) 4200 goto fail; 4201 statsp->mac_stats.lp_cap_1000fdx = 4202 gsr.bits.link_1000fdx; 4203 statsp->mac_stats.lp_cap_1000hdx = 4204 gsr.bits.link_1000hdx; 4205 if (param_arr[param_anar_1000fdx].value && 4206 gsr.bits.link_1000fdx) { 4207 statsp->mac_stats.link_speed = 1000; 4208 statsp->mac_stats.link_duplex = 2; 4209 } else if ( 4210 param_arr[param_anar_1000hdx].value && 4211 gsr.bits.link_1000hdx) { 4212 statsp->mac_stats.link_speed = 1000; 4213 statsp->mac_stats.link_duplex = 1; 4214 } 4215 } 4216 if ((an_common.value != 0) && 4217 !(statsp->mac_stats.link_speed)) { 4218 if (an_common.bits.cap_100T4) { 4219 statsp->mac_stats.link_T4 = 1; 4220 statsp->mac_stats.link_speed = 100; 4221 statsp->mac_stats.link_duplex = 1; 4222 } else if (an_common.bits.cap_100fdx) { 4223 statsp->mac_stats.link_speed = 100; 4224 statsp->mac_stats.link_duplex = 2; 4225 } else if (an_common.bits.cap_100hdx) { 4226 statsp->mac_stats.link_speed = 100; 4227 statsp->mac_stats.link_duplex = 1; 4228 } else if (an_common.bits.cap_10fdx) { 4229 statsp->mac_stats.link_speed = 10; 4230 statsp->mac_stats.link_duplex = 2; 4231 } else if (an_common.bits.cap_10hdx) { 4232 statsp->mac_stats.link_speed = 10; 4233 statsp->mac_stats.link_duplex = 1; 4234 } else { 4235 goto fail; 4236 } 4237 } 4238 if (statsp->mac_stats.link_duplex != 1) { 4239 statsp->mac_stats.link_asmpause = 4240 an_common.bits.cap_asmpause; 4241 if (statsp->mac_stats.link_asmpause) 4242 if ((statsp->mac_stats.cap_pause == 0) && 4243 (statsp->mac_stats.lp_cap_pause 4244 == 1)) 4245 statsp->mac_stats.link_pause 4246 = 0; 4247 else 4248 statsp->mac_stats.link_pause 4249 = 1; 4250 else 4251 statsp->mac_stats.link_pause = 4252 an_common.bits.cap_pause; 4253 } 4254 } else if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) { 4255 statsp->mac_stats.link_speed = 1000; 4256 statsp->mac_stats.link_duplex = 2; 4257 } 4258 *link_up = LINK_IS_UP; 4259 } 4260 4261 if (nxgep->link_notify) { 4262 *link_up = ((statsp->mac_stats.link_up) ? LINK_IS_UP : 4263 LINK_IS_DOWN); 4264 nxgep->link_notify = B_FALSE; 4265 } 4266 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mii_check")); 4267 return (NXGE_OK); 4268 fail: 4269 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4270 "nxge_mii_check: Unable to check MII")); 4271 return (status); 4272 } 4273 4274 /* Check PCS to see if there is any link status change */ 4275 nxge_status_t 4276 nxge_pcs_check(p_nxge_t nxgep, uint8_t portn, nxge_link_state_t *link_up) 4277 { 4278 p_nxge_stats_t statsp; 4279 nxge_status_t status = NXGE_OK; 4280 boolean_t linkup; 4281 4282 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_check")); 4283 4284 statsp = nxgep->statsp; 4285 *link_up = LINK_NO_CHANGE; 4286 4287 (void) npi_mac_get_link_status(nxgep->npi_handle, portn, &linkup); 4288 if (linkup) { 4289 if (nxgep->link_notify || 4290 nxgep->statsp->mac_stats.link_up == 0) { 4291 statsp->mac_stats.link_up = 1; 4292 statsp->mac_stats.link_speed = 1000; 4293 statsp->mac_stats.link_duplex = 2; 4294 *link_up = LINK_IS_UP; 4295 nxgep->link_notify = B_FALSE; 4296 } 4297 } else { 4298 if (nxgep->link_notify || 4299 nxgep->statsp->mac_stats.link_up == 1) { 4300 statsp->mac_stats.link_up = 0; 4301 statsp->mac_stats.link_speed = 0; 4302 statsp->mac_stats.link_duplex = 0; 4303 *link_up = LINK_IS_DOWN; 4304 nxgep->link_notify = B_FALSE; 4305 } 4306 } 4307 4308 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_check")); 4309 return (NXGE_OK); 4310 fail: 4311 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4312 "nxge_pcs_check: Unable to check PCS")); 4313 return (status); 4314 } 4315 4316 /* Add a multicast address entry into the HW hash table */ 4317 4318 nxge_status_t 4319 nxge_add_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp) 4320 { 4321 uint32_t mchash; 4322 p_hash_filter_t hash_filter; 4323 uint16_t hash_bit; 4324 boolean_t rx_init = B_FALSE; 4325 uint_t j; 4326 nxge_status_t status = NXGE_OK; 4327 4328 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_add_mcast_addr")); 4329 4330 RW_ENTER_WRITER(&nxgep->filter_lock); 4331 mchash = crc32_mchash(addrp); 4332 if (nxgep->hash_filter == NULL) { 4333 NXGE_DEBUG_MSG((NULL, STR_CTL, 4334 "Allocating hash filter storage.")); 4335 nxgep->hash_filter = KMEM_ZALLOC(sizeof (hash_filter_t), 4336 KM_SLEEP); 4337 } 4338 hash_filter = nxgep->hash_filter; 4339 j = mchash / HASH_REG_WIDTH; 4340 hash_bit = (1 << (mchash % HASH_REG_WIDTH)); 4341 hash_filter->hash_filter_regs[j] |= hash_bit; 4342 hash_filter->hash_bit_ref_cnt[mchash]++; 4343 if (hash_filter->hash_bit_ref_cnt[mchash] == 1) { 4344 hash_filter->hash_ref_cnt++; 4345 rx_init = B_TRUE; 4346 } 4347 if (rx_init) { 4348 if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 4349 goto fail; 4350 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 4351 goto fail; 4352 } 4353 4354 RW_EXIT(&nxgep->filter_lock); 4355 4356 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_add_mcast_addr")); 4357 4358 return (NXGE_OK); 4359 fail: 4360 RW_EXIT(&nxgep->filter_lock); 4361 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_add_mcast_addr: " 4362 "Unable to add multicast address")); 4363 return (status); 4364 } 4365 4366 /* Remove a multicast address entry from the HW hash table */ 4367 4368 nxge_status_t 4369 nxge_del_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp) 4370 { 4371 uint32_t mchash; 4372 p_hash_filter_t hash_filter; 4373 uint16_t hash_bit; 4374 boolean_t rx_init = B_FALSE; 4375 uint_t j; 4376 nxge_status_t status = NXGE_OK; 4377 4378 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_del_mcast_addr")); 4379 RW_ENTER_WRITER(&nxgep->filter_lock); 4380 mchash = crc32_mchash(addrp); 4381 if (nxgep->hash_filter == NULL) { 4382 NXGE_DEBUG_MSG((NULL, STR_CTL, 4383 "Hash filter already de_allocated.")); 4384 RW_EXIT(&nxgep->filter_lock); 4385 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr")); 4386 return (NXGE_OK); 4387 } 4388 hash_filter = nxgep->hash_filter; 4389 hash_filter->hash_bit_ref_cnt[mchash]--; 4390 if (hash_filter->hash_bit_ref_cnt[mchash] == 0) { 4391 j = mchash / HASH_REG_WIDTH; 4392 hash_bit = (1 << (mchash % HASH_REG_WIDTH)); 4393 hash_filter->hash_filter_regs[j] &= ~hash_bit; 4394 hash_filter->hash_ref_cnt--; 4395 rx_init = B_TRUE; 4396 } 4397 if (hash_filter->hash_ref_cnt == 0) { 4398 NXGE_DEBUG_MSG((NULL, STR_CTL, 4399 "De-allocating hash filter storage.")); 4400 KMEM_FREE(hash_filter, sizeof (hash_filter_t)); 4401 nxgep->hash_filter = NULL; 4402 } 4403 4404 if (rx_init) { 4405 if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 4406 goto fail; 4407 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 4408 goto fail; 4409 } 4410 RW_EXIT(&nxgep->filter_lock); 4411 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr")); 4412 4413 return (NXGE_OK); 4414 fail: 4415 RW_EXIT(&nxgep->filter_lock); 4416 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_del_mcast_addr: " 4417 "Unable to remove multicast address")); 4418 4419 return (status); 4420 } 4421 4422 /* Set MAC address into MAC address HW registers */ 4423 4424 nxge_status_t 4425 nxge_set_mac_addr(p_nxge_t nxgep, struct ether_addr *addrp) 4426 { 4427 nxge_status_t status = NXGE_OK; 4428 4429 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_mac_addr")); 4430 4431 MUTEX_ENTER(&nxgep->ouraddr_lock); 4432 /* 4433 * Exit if the address is same as ouraddr or multicast or broadcast 4434 */ 4435 if (((addrp->ether_addr_octet[0] & 01) == 1) || 4436 (ether_cmp(addrp, ðerbroadcastaddr) == 0) || 4437 (ether_cmp(addrp, &nxgep->ouraddr) == 0)) { 4438 goto nxge_set_mac_addr_exit; 4439 } 4440 nxgep->ouraddr = *addrp; 4441 /* 4442 * Set new interface local address and re-init device. 4443 * This is destructive to any other streams attached 4444 * to this device. 4445 */ 4446 RW_ENTER_WRITER(&nxgep->filter_lock); 4447 if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 4448 goto fail; 4449 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 4450 goto fail; 4451 4452 RW_EXIT(&nxgep->filter_lock); 4453 MUTEX_EXIT(&nxgep->ouraddr_lock); 4454 goto nxge_set_mac_addr_end; 4455 nxge_set_mac_addr_exit: 4456 MUTEX_EXIT(&nxgep->ouraddr_lock); 4457 nxge_set_mac_addr_end: 4458 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_mac_addr")); 4459 4460 return (NXGE_OK); 4461 fail: 4462 MUTEX_EXIT(&nxgep->ouraddr_lock); 4463 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_mac_addr: " 4464 "Unable to set mac address")); 4465 return (status); 4466 } 4467 4468 static 4469 check_link_state_t 4470 nxge_check_link_stop( 4471 nxge_t *nxge) 4472 { 4473 /* If the poll has been cancelled, return STOP. */ 4474 MUTEX_ENTER(&nxge->poll_lock); 4475 if (nxge->suspended || nxge->poll_state == LINK_MONITOR_STOPPING) { 4476 nxge->poll_state = LINK_MONITOR_STOP; 4477 nxge->nxge_link_poll_timerid = 0; 4478 cv_broadcast(&nxge->poll_cv); 4479 MUTEX_EXIT(&nxge->poll_lock); 4480 4481 NXGE_DEBUG_MSG((nxge, MAC_CTL, 4482 "nxge_check_%s_link(port<%d>) stopped.", 4483 nxge->mac.portmode == PORT_10G_FIBER ? "10g" : "mii", 4484 nxge->mac.portnum)); 4485 return (CHECK_LINK_STOP); 4486 } 4487 MUTEX_EXIT(&nxge->poll_lock); 4488 4489 return (CHECK_LINK_RESCHEDULE); 4490 } 4491 4492 /* Check status of MII (MIF or PCS) link */ 4493 4494 static nxge_status_t 4495 nxge_check_mii_link(p_nxge_t nxgep) 4496 { 4497 mii_bmsr_t bmsr_ints, bmsr_data; 4498 mii_anlpar_t anlpar; 4499 mii_gsr_t gsr; 4500 p_mii_regs_t mii_regs; 4501 nxge_status_t status = NXGE_OK; 4502 uint8_t portn; 4503 nxge_link_state_t link_up; 4504 4505 if (nxgep->nxge_magic != NXGE_MAGIC) 4506 return (NXGE_ERROR); 4507 4508 if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 4509 return (NXGE_OK); 4510 4511 portn = nxgep->mac.portnum; 4512 4513 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_mii_link port<%d>", 4514 portn)); 4515 4516 mii_regs = NULL; 4517 4518 RW_ENTER_WRITER(&nxgep->filter_lock); 4519 4520 if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10) 4521 goto nxge_check_mii_link_exit; 4522 4523 switch (nxgep->mac.portmode) { 4524 default: 4525 bmsr_data.value = 0; 4526 if ((status = nxge_mii_read(nxgep, 4527 nxgep->statsp->mac_stats.xcvr_portn, 4528 #if defined(__i386) 4529 (uint8_t)(uint32_t)(&mii_regs->bmsr), 4530 #else 4531 (uint8_t)(uint64_t)(&mii_regs->bmsr), 4532 #endif 4533 &bmsr_data.value)) != NXGE_OK) { 4534 goto fail; 4535 } 4536 4537 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4538 "==> nxge_check_mii_link port<0x%x> " 4539 "RIGHT AFTER READ bmsr_data 0x%x (nxgep->bmsr 0x%x ", 4540 portn, bmsr_data.value, nxgep->bmsr.value)); 4541 4542 if (nxgep->param_arr[param_autoneg].value) { 4543 if ((status = nxge_mii_read(nxgep, 4544 nxgep->statsp->mac_stats.xcvr_portn, 4545 #if defined(__i386) 4546 (uint8_t)(uint32_t)(&mii_regs->gsr), 4547 #else 4548 (uint8_t)(uint64_t)(&mii_regs->gsr), 4549 #endif 4550 &gsr.value)) != NXGE_OK) 4551 goto fail; 4552 if ((status = nxge_mii_read(nxgep, 4553 nxgep->statsp->mac_stats.xcvr_portn, 4554 #if defined(__i386) 4555 (uint8_t)(uint32_t)(&mii_regs->anlpar), 4556 #else 4557 (uint8_t)(uint64_t)(&mii_regs->anlpar), 4558 #endif 4559 &anlpar.value)) != NXGE_OK) 4560 goto fail; 4561 if (nxgep->mac.portmode != PORT_1G_RGMII_FIBER) { 4562 4563 if (nxgep->statsp->mac_stats.link_up && 4564 ((nxgep->statsp->mac_stats.lp_cap_1000fdx ^ 4565 gsr.bits.link_1000fdx) || 4566 (nxgep->statsp->mac_stats.lp_cap_1000hdx ^ 4567 gsr.bits.link_1000hdx) || 4568 (nxgep->statsp->mac_stats.lp_cap_100T4 ^ 4569 anlpar.bits.cap_100T4) || 4570 (nxgep->statsp->mac_stats.lp_cap_100fdx ^ 4571 anlpar.bits.cap_100fdx) || 4572 (nxgep->statsp->mac_stats.lp_cap_100hdx ^ 4573 anlpar.bits.cap_100hdx) || 4574 (nxgep->statsp->mac_stats.lp_cap_10fdx ^ 4575 anlpar.bits.cap_10fdx) || 4576 (nxgep->statsp->mac_stats.lp_cap_10hdx ^ 4577 anlpar.bits.cap_10hdx))) { 4578 bmsr_data.bits.link_status = 0; 4579 } 4580 } 4581 } 4582 4583 /* Workaround for link down issue */ 4584 if (bmsr_data.value == 0) { 4585 cmn_err(CE_NOTE, "!LINK DEBUG: Read zero bmsr\n"); 4586 goto nxge_check_mii_link_exit; 4587 } 4588 4589 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4590 "==> nxge_check_mii_link port<0x%x> :" 4591 "BEFORE BMSR ^ nxgep->bmsr 0x%x bmsr_data 0x%x", 4592 portn, nxgep->bmsr.value, bmsr_data.value)); 4593 4594 bmsr_ints.value = nxgep->bmsr.value ^ bmsr_data.value; 4595 nxgep->bmsr.value = bmsr_data.value; 4596 4597 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4598 "==> nxge_check_mii_link port<0x%x> CALLING " 4599 "bmsr_data 0x%x bmsr_ints.value 0x%x", 4600 portn, bmsr_data.value, bmsr_ints.value)); 4601 4602 if ((status = nxge_mii_check(nxgep, bmsr_data, bmsr_ints, 4603 &link_up)) != NXGE_OK) { 4604 goto fail; 4605 } 4606 break; 4607 4608 case PORT_1G_SERDES: 4609 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4610 "==> nxge_check_mii_link port<%d> (SERDES)", portn)); 4611 if ((status = nxge_pcs_check(nxgep, portn, &link_up)) 4612 != NXGE_OK) { 4613 goto fail; 4614 } 4615 break; 4616 } 4617 4618 nxge_check_mii_link_exit: 4619 RW_EXIT(&nxgep->filter_lock); 4620 if (link_up == LINK_IS_UP) { 4621 nxge_link_is_up(nxgep); 4622 } else if (link_up == LINK_IS_DOWN) { 4623 nxge_link_is_down(nxgep); 4624 } 4625 4626 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 4627 4628 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_mii_link port<%d>", 4629 portn)); 4630 return (NXGE_OK); 4631 4632 fail: 4633 RW_EXIT(&nxgep->filter_lock); 4634 4635 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 4636 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4637 "nxge_check_mii_link: Failed to check link port<%d>", 4638 portn)); 4639 return (status); 4640 } 4641 4642 4643 /*ARGSUSED*/ 4644 static nxge_status_t 4645 nxge_check_10g_link(p_nxge_t nxgep) 4646 { 4647 uint8_t portn; 4648 nxge_status_t status = NXGE_OK; 4649 boolean_t link_up; 4650 uint32_t val; 4651 npi_status_t rs; 4652 4653 if (nxgep->nxge_magic != NXGE_MAGIC) 4654 return (NXGE_ERROR); 4655 4656 if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 4657 return (NXGE_OK); 4658 4659 portn = nxgep->mac.portnum; 4660 val = 0; 4661 rs = NPI_SUCCESS; 4662 4663 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_10g_link port<%d>", 4664 portn)); 4665 4666 switch (nxgep->mac.portmode) { 4667 default: 4668 /* 4669 * Check if the phy is present in case of hot swappable phy 4670 */ 4671 if (nxgep->hot_swappable_phy) { 4672 boolean_t phy_present_now = B_FALSE; 4673 4674 /* 4675 * If this is the 2nd Goa port, then check 2 addresses 4676 * to take care of the Goa NEM card requirements. 4677 */ 4678 if (portn == 1) { 4679 if (nxge_is_phy_present(nxgep, 4680 BCM8706_ALT_GOA_PORT1_ADDR, 4681 BCM8706_DEV_ID, BCM_PHY_ID_MASK)) { 4682 phy_present_now = B_TRUE; 4683 nxgep->xcvr_addr = 4684 BCM8706_ALT_GOA_PORT1_ADDR; 4685 goto phy_check_done; 4686 } 4687 } 4688 if (nxge_is_phy_present(nxgep, 4689 (BCM8706_GOA_PORT_ADDR_BASE) + portn, 4690 BCM8706_DEV_ID, BCM_PHY_ID_MASK)) { 4691 nxgep->xcvr_addr = 4692 (BCM8706_GOA_PORT_ADDR_BASE) + portn; 4693 phy_present_now = B_TRUE; 4694 } 4695 4696 phy_check_done: 4697 if (nxgep->phy_absent) { 4698 if (phy_present_now) { 4699 /* 4700 * Detect, Initialize phy and do link up 4701 * set xcvr vals, link_init, nxge_init 4702 */ 4703 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4704 "Hot swappable phy DETECTED!!")); 4705 nxgep->phy_absent = B_FALSE; 4706 (void) nxge_xcvr_find(nxgep); 4707 (void) nxge_link_init(nxgep); 4708 if (!(nxgep->drv_state & 4709 STATE_HW_INITIALIZED)) { 4710 status = nxge_init(nxgep); 4711 if (status != NXGE_OK) { 4712 NXGE_ERROR_MSG((nxgep, 4713 NXGE_ERR_CTL, 4714 "Hot swappable " 4715 "phy present, but" 4716 " driver init" 4717 " failed...")); 4718 goto fail; 4719 } 4720 } 4721 } 4722 4723 goto start_link_check; 4724 4725 } else if (!phy_present_now) { 4726 /* 4727 * Phy gone, bring link down reset xcvr vals 4728 */ 4729 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4730 "Hot swappable phy REMOVED!!")); 4731 nxgep->phy_absent = B_TRUE; 4732 nxgep->statsp->mac_stats.link_up = 0; 4733 nxgep->statsp->mac_stats.link_speed = 0; 4734 nxgep->statsp->mac_stats.link_duplex = 0; 4735 nxge_link_is_down(nxgep); 4736 nxgep->link_notify = B_FALSE; 4737 4738 (void) nxge_xcvr_find(nxgep); 4739 4740 goto start_link_check; 4741 4742 } 4743 } 4744 if (nxgep->chip_id == MRVL88X201X_CHIP_ID) { 4745 status = nxge_mrvl88x2011_link(nxgep, &link_up); 4746 } else { 4747 status = nxge_check_bcm8704_link(nxgep, &link_up); 4748 } 4749 if (status != NXGE_OK) 4750 goto fail; 4751 break; 4752 case PORT_10G_SERDES: 4753 rs = npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 4754 XPCS_REG_STATUS, &val); 4755 if (rs != 0) 4756 goto fail; 4757 4758 link_up = B_FALSE; 4759 if (val & XPCS_STATUS_LANE_ALIGN) { 4760 link_up = B_TRUE; 4761 } 4762 4763 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4764 "==> nxge_check_10g_link port<%d> " 4765 "XPCS_REG_STATUS2 0x%x link_up %d", 4766 portn, val, link_up)); 4767 4768 break; 4769 } 4770 4771 if (link_up) { 4772 if (nxgep->link_notify || 4773 nxgep->statsp->mac_stats.link_up == 0) { 4774 if (nxge_10g_link_led_on(nxgep) != NXGE_OK) 4775 goto fail; 4776 nxgep->statsp->mac_stats.link_up = 1; 4777 nxgep->statsp->mac_stats.link_speed = 10000; 4778 nxgep->statsp->mac_stats.link_duplex = 2; 4779 4780 nxge_link_is_up(nxgep); 4781 nxgep->link_notify = B_FALSE; 4782 } 4783 } else { 4784 if (nxgep->link_notify || 4785 nxgep->statsp->mac_stats.link_up == 1) { 4786 if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 4787 goto fail; 4788 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4789 "Link down cable problem")); 4790 nxgep->statsp->mac_stats.link_up = 0; 4791 nxgep->statsp->mac_stats.link_speed = 0; 4792 nxgep->statsp->mac_stats.link_duplex = 0; 4793 4794 nxge_link_is_down(nxgep); 4795 nxgep->link_notify = B_FALSE; 4796 } 4797 } 4798 4799 start_link_check: 4800 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 4801 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_10g_link port<%d>", 4802 portn)); 4803 return (NXGE_OK); 4804 4805 fail: 4806 (void) nxge_check_link_stop(nxgep); 4807 4808 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4809 "nxge_check_10g_link: Failed to check link port<%d>", 4810 portn)); 4811 return (status); 4812 } 4813 4814 4815 /* Declare link down */ 4816 4817 void 4818 nxge_link_is_down(p_nxge_t nxgep) 4819 { 4820 p_nxge_stats_t statsp; 4821 char link_stat_msg[64]; 4822 4823 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_down")); 4824 4825 statsp = nxgep->statsp; 4826 (void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is down", 4827 statsp->mac_stats.xcvr_portn); 4828 4829 if (nxge_no_msg == B_FALSE) { 4830 NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg)); 4831 } 4832 4833 mac_link_update(nxgep->mach, LINK_STATE_DOWN); 4834 4835 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_down")); 4836 } 4837 4838 /* Declare link up */ 4839 4840 void 4841 nxge_link_is_up(p_nxge_t nxgep) 4842 { 4843 p_nxge_stats_t statsp; 4844 char link_stat_msg[64]; 4845 uint32_t val; 4846 4847 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_up")); 4848 4849 statsp = nxgep->statsp; 4850 (void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is up %d Mbps ", 4851 statsp->mac_stats.xcvr_portn, 4852 statsp->mac_stats.link_speed); 4853 4854 if (statsp->mac_stats.link_T4) 4855 (void) strcat(link_stat_msg, "T4"); 4856 else if (statsp->mac_stats.link_duplex == 2) 4857 (void) strcat(link_stat_msg, "full duplex"); 4858 else 4859 (void) strcat(link_stat_msg, "half duplex"); 4860 4861 (void) nxge_xif_init(nxgep); 4862 4863 /* Clean up symbol errors incurred during link transition */ 4864 if ((nxgep->mac.portmode == PORT_10G_FIBER) || 4865 (nxgep->mac.portmode == PORT_10G_SERDES)) { 4866 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 4867 XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val); 4868 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 4869 XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val); 4870 } 4871 4872 if (nxge_no_msg == B_FALSE) { 4873 NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg)); 4874 } 4875 4876 mac_link_update(nxgep->mach, LINK_STATE_UP); 4877 4878 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_up")); 4879 } 4880 4881 /* 4882 * Calculate the bit in the multicast address filter 4883 * that selects the given * address. 4884 * Note: For GEM, the last 8-bits are used. 4885 */ 4886 uint32_t 4887 crc32_mchash(p_ether_addr_t addr) 4888 { 4889 uint8_t *cp; 4890 uint32_t crc; 4891 uint32_t c; 4892 int byte; 4893 int bit; 4894 4895 cp = (uint8_t *)addr; 4896 crc = (uint32_t)0xffffffff; 4897 for (byte = 0; byte < 6; byte++) { 4898 c = (uint32_t)cp[byte]; 4899 for (bit = 0; bit < 8; bit++) { 4900 if ((c & 0x1) ^ (crc & 0x1)) 4901 crc = (crc >> 1)^0xedb88320; 4902 else 4903 crc = (crc >> 1); 4904 c >>= 1; 4905 } 4906 } 4907 return ((~crc) >> (32 - HASH_BITS)); 4908 } 4909 4910 /* Reset serdes */ 4911 4912 nxge_status_t 4913 nxge_serdes_reset(p_nxge_t nxgep) 4914 { 4915 npi_handle_t handle; 4916 4917 handle = nxgep->npi_handle; 4918 4919 ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0 | ESR_RESET_1); 4920 drv_usecwait(500); 4921 ESR_REG_WR(handle, ESR_CONFIG_REG, 0); 4922 4923 return (NXGE_OK); 4924 } 4925 4926 /* Monitor link status using interrupt or polling */ 4927 nxge_status_t 4928 nxge_link_monitor(p_nxge_t nxgep, link_mon_enable_t enable) 4929 { 4930 nxge_status_t status = NXGE_OK; 4931 4932 /* If we are a guest domain driver, don't bother. */ 4933 if (isLDOMguest(nxgep)) 4934 return (status); 4935 4936 /* 4937 * Return immediately if this is an imaginary XMAC port. 4938 * (At least, we don't have 4-port XMAC cards yet.) 4939 */ 4940 if ((nxgep->mac.portmode == PORT_10G_FIBER || 4941 nxgep->mac.portmode == PORT_10G_SERDES) && 4942 (nxgep->mac.portnum > 1)) 4943 return (NXGE_OK); 4944 4945 if (nxgep->statsp == NULL) { 4946 /* stats has not been allocated. */ 4947 return (NXGE_OK); 4948 } 4949 /* Don't check link if we're in internal loopback mode */ 4950 if (nxgep->statsp->port_stats.lb_mode >= nxge_lb_serdes10g) 4951 return (NXGE_OK); 4952 4953 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4954 "==> nxge_link_monitor port<%d> enable=%d", 4955 nxgep->mac.portnum, enable)); 4956 if (enable == LINK_MONITOR_START) { 4957 if (nxgep->mac.linkchkmode == LINKCHK_INTR) { 4958 if ((status = nxge_link_intr(nxgep, LINK_INTR_START)) 4959 != NXGE_OK) 4960 goto fail; 4961 } else { 4962 timeout_id_t timerid; 4963 4964 if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 4965 return (NXGE_OK); 4966 4967 if (nxgep->xcvr.check_link) { 4968 timerid = timeout( 4969 (fptrv_t)(nxgep->xcvr.check_link), 4970 nxgep, 4971 drv_usectohz(LINK_MONITOR_PERIOD)); 4972 MUTEX_ENTER(&nxgep->poll_lock); 4973 nxgep->nxge_link_poll_timerid = timerid; 4974 MUTEX_EXIT(&nxgep->poll_lock); 4975 } else { 4976 return (NXGE_ERROR); 4977 } 4978 } 4979 } else { 4980 if (nxgep->mac.linkchkmode == LINKCHK_INTR) { 4981 if ((status = nxge_link_intr(nxgep, LINK_INTR_STOP)) 4982 != NXGE_OK) 4983 goto fail; 4984 } else { 4985 clock_t rv; 4986 4987 MUTEX_ENTER(&nxgep->poll_lock); 4988 4989 /* If <timerid> == 0, the link monitor has */ 4990 /* never been started, or just now stopped. */ 4991 if (nxgep->nxge_link_poll_timerid == 0) { 4992 MUTEX_EXIT(&nxgep->poll_lock); 4993 return (NXGE_OK); 4994 } 4995 4996 nxgep->poll_state = LINK_MONITOR_STOPPING; 4997 rv = cv_timedwait(&nxgep->poll_cv, 4998 &nxgep->poll_lock, 4999 ddi_get_lbolt() + 5000 drv_usectohz(LM_WAIT_MULTIPLIER * 5001 LINK_MONITOR_PERIOD)); 5002 if (rv == -1) { 5003 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5004 "==> stopping port %d: " 5005 "cv_timedwait(%d) timed out", 5006 nxgep->mac.portnum, nxgep->poll_state)); 5007 nxgep->poll_state = LINK_MONITOR_STOP; 5008 nxgep->nxge_link_poll_timerid = 0; 5009 } 5010 5011 MUTEX_EXIT(&nxgep->poll_lock); 5012 } 5013 } 5014 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5015 "<== nxge_link_monitor port<%d> enable=%d", 5016 nxgep->mac.portnum, enable)); 5017 5018 return (NXGE_OK); 5019 fail: 5020 return (status); 5021 } 5022 5023 /* Set promiscous mode */ 5024 5025 nxge_status_t 5026 nxge_set_promisc(p_nxge_t nxgep, boolean_t on) 5027 { 5028 nxge_status_t status = NXGE_OK; 5029 5030 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_promisc: on %d", on)); 5031 5032 nxgep->filter.all_phys_cnt = ((on) ? 1 : 0); 5033 5034 RW_ENTER_WRITER(&nxgep->filter_lock); 5035 5036 if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) { 5037 goto fail; 5038 } 5039 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) { 5040 goto fail; 5041 } 5042 5043 RW_EXIT(&nxgep->filter_lock); 5044 5045 if (on) 5046 nxgep->statsp->mac_stats.promisc = B_TRUE; 5047 else 5048 nxgep->statsp->mac_stats.promisc = B_FALSE; 5049 5050 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_promisc")); 5051 5052 return (NXGE_OK); 5053 fail: 5054 RW_EXIT(&nxgep->filter_lock); 5055 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_promisc: " 5056 "Unable to set promisc (%d)", on)); 5057 5058 return (status); 5059 } 5060 5061 /*ARGSUSED*/ 5062 uint_t 5063 nxge_mif_intr(void *arg1, void *arg2) 5064 { 5065 #ifdef NXGE_DEBUG 5066 p_nxge_t nxgep = (p_nxge_t)arg2; 5067 #endif 5068 #if NXGE_MIF 5069 p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1; 5070 uint32_t status; 5071 npi_handle_t handle; 5072 uint8_t portn; 5073 p_nxge_stats_t statsp; 5074 #endif 5075 5076 #ifdef NXGE_MIF 5077 if (arg2 == NULL || (void *)ldvp->nxgep != arg2) { 5078 nxgep = ldvp->nxgep; 5079 } 5080 nxgep = ldvp->nxgep; 5081 #endif 5082 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mif_intr")); 5083 5084 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr")); 5085 return (DDI_INTR_CLAIMED); 5086 5087 mif_intr_fail: 5088 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr")); 5089 return (DDI_INTR_UNCLAIMED); 5090 } 5091 5092 /*ARGSUSED*/ 5093 uint_t 5094 nxge_mac_intr(void *arg1, void *arg2) 5095 { 5096 p_nxge_t nxgep = (p_nxge_t)arg2; 5097 p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1; 5098 p_nxge_ldg_t ldgp; 5099 uint32_t status; 5100 npi_handle_t handle; 5101 uint8_t portn; 5102 p_nxge_stats_t statsp; 5103 npi_status_t rs = NPI_SUCCESS; 5104 5105 if (arg2 == NULL || (void *)ldvp->nxgep != arg2) { 5106 nxgep = ldvp->nxgep; 5107 } 5108 5109 ldgp = ldvp->ldgp; 5110 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mac_intr: " 5111 "group %d", ldgp->ldg)); 5112 5113 handle = NXGE_DEV_NPI_HANDLE(nxgep); 5114 /* 5115 * This interrupt handler is for a specific 5116 * mac port. 5117 */ 5118 statsp = (p_nxge_stats_t)nxgep->statsp; 5119 portn = nxgep->mac.portnum; 5120 5121 NXGE_DEBUG_MSG((nxgep, INT_CTL, 5122 "==> nxge_mac_intr: reading mac stats: port<%d>", portn)); 5123 5124 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 5125 rs = npi_xmac_tx_get_istatus(handle, portn, 5126 (xmac_tx_iconfig_t *)&status); 5127 if (rs != NPI_SUCCESS) 5128 goto npi_fail; 5129 if (status & ICFG_XMAC_TX_ALL) { 5130 if (status & ICFG_XMAC_TX_UNDERRUN) { 5131 statsp->xmac_stats.tx_underflow_err++; 5132 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 5133 NXGE_FM_EREPORT_TXMAC_UNDERFLOW); 5134 } 5135 if (status & ICFG_XMAC_TX_MAX_PACKET_ERR) { 5136 statsp->xmac_stats.tx_maxpktsize_err++; 5137 /* 5138 * Do not send FMA ereport because this 5139 * error does not indicate HW failure. 5140 */ 5141 } 5142 if (status & ICFG_XMAC_TX_OVERFLOW) { 5143 statsp->xmac_stats.tx_overflow_err++; 5144 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 5145 NXGE_FM_EREPORT_TXMAC_OVERFLOW); 5146 } 5147 if (status & ICFG_XMAC_TX_FIFO_XFR_ERR) { 5148 statsp->xmac_stats.tx_fifo_xfr_err++; 5149 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 5150 NXGE_FM_EREPORT_TXMAC_TXFIFO_XFR_ERR); 5151 } 5152 if (status & ICFG_XMAC_TX_BYTE_CNT_EXP) { 5153 statsp->xmac_stats.tx_byte_cnt += 5154 XTXMAC_BYTE_CNT_MASK; 5155 } 5156 if (status & ICFG_XMAC_TX_FRAME_CNT_EXP) { 5157 statsp->xmac_stats.tx_frame_cnt += 5158 XTXMAC_FRM_CNT_MASK; 5159 } 5160 } 5161 5162 rs = npi_xmac_rx_get_istatus(handle, portn, 5163 (xmac_rx_iconfig_t *)&status); 5164 if (rs != NPI_SUCCESS) 5165 goto npi_fail; 5166 if (status & ICFG_XMAC_RX_ALL) { 5167 if (status & ICFG_XMAC_RX_OVERFLOW) 5168 statsp->xmac_stats.rx_overflow_err++; 5169 if (status & ICFG_XMAC_RX_UNDERFLOW) { 5170 statsp->xmac_stats.rx_underflow_err++; 5171 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 5172 NXGE_FM_EREPORT_RXMAC_UNDERFLOW); 5173 } 5174 /* 5175 * Do not send FMA ereport for the following 3 errors 5176 * because they do not indicate HW failures. 5177 */ 5178 if (status & ICFG_XMAC_RX_CRC_ERR_CNT_EXP) { 5179 statsp->xmac_stats.rx_crc_err_cnt += 5180 XRXMAC_CRC_ER_CNT_MASK; 5181 } 5182 if (status & ICFG_XMAC_RX_LEN_ERR_CNT_EXP) { 5183 statsp->xmac_stats.rx_len_err_cnt += 5184 MAC_LEN_ER_CNT_MASK; 5185 } 5186 if (status & ICFG_XMAC_RX_VIOL_ERR_CNT_EXP) { 5187 statsp->xmac_stats.rx_viol_err_cnt += 5188 XRXMAC_CD_VIO_CNT_MASK; 5189 } 5190 if (status & ICFG_XMAC_RX_OCT_CNT_EXP) { 5191 statsp->xmac_stats.rx_byte_cnt += 5192 XRXMAC_BT_CNT_MASK; 5193 } 5194 if (status & ICFG_XMAC_RX_HST_CNT1_EXP) { 5195 statsp->xmac_stats.rx_hist1_cnt += 5196 XRXMAC_HIST_CNT1_MASK; 5197 } 5198 if (status & ICFG_XMAC_RX_HST_CNT2_EXP) { 5199 statsp->xmac_stats.rx_hist2_cnt += 5200 XRXMAC_HIST_CNT2_MASK; 5201 } 5202 if (status & ICFG_XMAC_RX_HST_CNT3_EXP) { 5203 statsp->xmac_stats.rx_hist3_cnt += 5204 XRXMAC_HIST_CNT3_MASK; 5205 } 5206 if (status & ICFG_XMAC_RX_HST_CNT4_EXP) { 5207 statsp->xmac_stats.rx_hist4_cnt += 5208 XRXMAC_HIST_CNT4_MASK; 5209 } 5210 if (status & ICFG_XMAC_RX_HST_CNT5_EXP) { 5211 statsp->xmac_stats.rx_hist5_cnt += 5212 XRXMAC_HIST_CNT5_MASK; 5213 } 5214 if (status & ICFG_XMAC_RX_HST_CNT6_EXP) { 5215 statsp->xmac_stats.rx_hist6_cnt += 5216 XRXMAC_HIST_CNT6_MASK; 5217 } 5218 if (status & ICFG_XMAC_RX_BCAST_CNT_EXP) { 5219 statsp->xmac_stats.rx_broadcast_cnt += 5220 XRXMAC_BC_FRM_CNT_MASK; 5221 } 5222 if (status & ICFG_XMAC_RX_MCAST_CNT_EXP) { 5223 statsp->xmac_stats.rx_mult_cnt += 5224 XRXMAC_MC_FRM_CNT_MASK; 5225 } 5226 /* 5227 * Do not send FMA ereport for the following 3 errors 5228 * because they do not indicate HW failures. 5229 */ 5230 if (status & ICFG_XMAC_RX_FRAG_CNT_EXP) { 5231 statsp->xmac_stats.rx_frag_cnt += 5232 XRXMAC_FRAG_CNT_MASK; 5233 } 5234 if (status & ICFG_XMAC_RX_ALIGNERR_CNT_EXP) { 5235 statsp->xmac_stats.rx_frame_align_err_cnt += 5236 XRXMAC_AL_ER_CNT_MASK; 5237 } 5238 if (status & ICFG_XMAC_RX_LINK_FLT_CNT_EXP) { 5239 statsp->xmac_stats.rx_linkfault_err_cnt += 5240 XMAC_LINK_FLT_CNT_MASK; 5241 } 5242 if (status & ICFG_XMAC_RX_REMOTE_FLT_DET) { 5243 statsp->xmac_stats.rx_remotefault_err++; 5244 } 5245 if (status & ICFG_XMAC_RX_LOCAL_FLT_DET) { 5246 statsp->xmac_stats.rx_localfault_err++; 5247 } 5248 } 5249 5250 rs = npi_xmac_ctl_get_istatus(handle, portn, 5251 (xmac_ctl_iconfig_t *)&status); 5252 if (rs != NPI_SUCCESS) 5253 goto npi_fail; 5254 if (status & ICFG_XMAC_CTRL_ALL) { 5255 if (status & ICFG_XMAC_CTRL_PAUSE_RCVD) 5256 statsp->xmac_stats.rx_pause_cnt++; 5257 if (status & ICFG_XMAC_CTRL_PAUSE_STATE) 5258 statsp->xmac_stats.tx_pause_state++; 5259 if (status & ICFG_XMAC_CTRL_NOPAUSE_STATE) 5260 statsp->xmac_stats.tx_nopause_state++; 5261 } 5262 } else if (nxgep->mac.porttype == PORT_TYPE_BMAC) { 5263 rs = npi_bmac_tx_get_istatus(handle, portn, 5264 (bmac_tx_iconfig_t *)&status); 5265 if (rs != NPI_SUCCESS) 5266 goto npi_fail; 5267 if (status & ICFG_BMAC_TX_ALL) { 5268 if (status & ICFG_BMAC_TX_UNDERFLOW) { 5269 statsp->bmac_stats.tx_underrun_err++; 5270 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 5271 NXGE_FM_EREPORT_TXMAC_UNDERFLOW); 5272 } 5273 if (status & ICFG_BMAC_TX_MAXPKTSZ_ERR) { 5274 statsp->bmac_stats.tx_max_pkt_err++; 5275 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 5276 NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR); 5277 } 5278 if (status & ICFG_BMAC_TX_BYTE_CNT_EXP) { 5279 statsp->bmac_stats.tx_byte_cnt += 5280 BTXMAC_BYTE_CNT_MASK; 5281 } 5282 if (status & ICFG_BMAC_TX_FRAME_CNT_EXP) { 5283 statsp->bmac_stats.tx_frame_cnt += 5284 BTXMAC_FRM_CNT_MASK; 5285 } 5286 } 5287 5288 rs = npi_bmac_rx_get_istatus(handle, portn, 5289 (bmac_rx_iconfig_t *)&status); 5290 if (rs != NPI_SUCCESS) 5291 goto npi_fail; 5292 if (status & ICFG_BMAC_RX_ALL) { 5293 if (status & ICFG_BMAC_RX_OVERFLOW) { 5294 statsp->bmac_stats.rx_overflow_err++; 5295 } 5296 if (status & ICFG_BMAC_RX_FRAME_CNT_EXP) { 5297 statsp->bmac_stats.rx_frame_cnt += 5298 RXMAC_FRM_CNT_MASK; 5299 } 5300 if (status & ICFG_BMAC_RX_CRC_ERR_CNT_EXP) { 5301 statsp->bmac_stats.rx_crc_err_cnt += 5302 BMAC_CRC_ER_CNT_MASK; 5303 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 5304 NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP); 5305 } 5306 if (status & ICFG_BMAC_RX_LEN_ERR_CNT_EXP) { 5307 statsp->bmac_stats.rx_len_err_cnt += 5308 MAC_LEN_ER_CNT_MASK; 5309 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 5310 NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP); 5311 } 5312 if (status & ICFG_BMAC_RX_VIOL_ERR_CNT_EXP) 5313 statsp->bmac_stats.rx_viol_err_cnt += 5314 BMAC_CD_VIO_CNT_MASK; 5315 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 5316 NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP); 5317 } 5318 if (status & ICFG_BMAC_RX_BYTE_CNT_EXP) { 5319 statsp->bmac_stats.rx_byte_cnt += 5320 BRXMAC_BYTE_CNT_MASK; 5321 } 5322 if (status & ICFG_BMAC_RX_ALIGNERR_CNT_EXP) { 5323 statsp->bmac_stats.rx_align_err_cnt += 5324 BMAC_AL_ER_CNT_MASK; 5325 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 5326 NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP); 5327 } 5328 5329 rs = npi_bmac_ctl_get_istatus(handle, portn, 5330 (bmac_ctl_iconfig_t *)&status); 5331 if (rs != NPI_SUCCESS) 5332 goto npi_fail; 5333 5334 if (status & ICFG_BMAC_CTL_ALL) { 5335 if (status & ICFG_BMAC_CTL_RCVPAUSE) 5336 statsp->bmac_stats.rx_pause_cnt++; 5337 if (status & ICFG_BMAC_CTL_INPAUSE_ST) 5338 statsp->bmac_stats.tx_pause_state++; 5339 if (status & ICFG_BMAC_CTL_INNOTPAUSE_ST) 5340 statsp->bmac_stats.tx_nopause_state++; 5341 } 5342 } 5343 5344 if (ldgp->nldvs == 1) { 5345 (void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg, 5346 B_TRUE, ldgp->ldg_timer); 5347 } 5348 5349 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mac_intr")); 5350 return (DDI_INTR_CLAIMED); 5351 5352 npi_fail: 5353 NXGE_ERROR_MSG((nxgep, INT_CTL, "<== nxge_mac_intr")); 5354 return (DDI_INTR_UNCLAIMED); 5355 } 5356 5357 nxge_status_t 5358 nxge_check_bcm8704_link(p_nxge_t nxgep, boolean_t *link_up) 5359 { 5360 uint8_t phy_port_addr; 5361 nxge_status_t status = NXGE_OK; 5362 boolean_t rx_sig_ok; 5363 boolean_t pcs_blk_lock; 5364 boolean_t link_align; 5365 uint16_t val1, val2, val3; 5366 #ifdef NXGE_DEBUG_SYMBOL_ERR 5367 uint16_t val_debug; 5368 uint16_t val; 5369 #endif 5370 5371 phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn; 5372 5373 #ifdef NXGE_DEBUG_SYMBOL_ERR 5374 /* Check Device 3 Register Device 3 0xC809 */ 5375 (void) nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0xC809, &val_debug); 5376 if ((val_debug & ~0x200) != 0) { 5377 cmn_err(CE_NOTE, "!Port%d BCM8704 Dev3 Reg 0xc809 = 0x%x\n", 5378 nxgep->mac.portnum, val_debug); 5379 (void) nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, 5380 &val_debug); 5381 cmn_err(CE_NOTE, "!Port%d BCM8704 Dev4 Reg 0x18 = 0x%x\n", 5382 nxgep->mac.portnum, val_debug); 5383 } 5384 5385 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 5386 XPCS_REG_DESCWERR_COUNTER, &val); 5387 if (val != 0) 5388 cmn_err(CE_NOTE, "!XPCS DESCWERR = 0x%x\n", val); 5389 5390 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 5391 XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val); 5392 if (val != 0) 5393 cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L0_1 = 0x%x\n", val); 5394 5395 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 5396 XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val); 5397 if (val != 0) 5398 cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L2_3 = 0x%x\n", val); 5399 #endif 5400 5401 /* Check from BCM8704 if 10G link is up or down */ 5402 5403 /* Check Device 1 Register 0xA bit0 */ 5404 status = nxge_mdio_read(nxgep, phy_port_addr, 5405 BCM8704_PMA_PMD_DEV_ADDR, 5406 BCM8704_PMD_RECEIVE_SIG_DETECT, 5407 &val1); 5408 if (status != NXGE_OK) 5409 goto fail; 5410 rx_sig_ok = ((val1 & GLOB_PMD_RX_SIG_OK) ? B_TRUE : B_FALSE); 5411 5412 /* Check Device 3 Register 0x20 bit0 */ 5413 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 5414 BCM8704_PCS_DEV_ADDR, 5415 BCM8704_10GBASE_R_PCS_STATUS_REG, 5416 &val2)) != NPI_SUCCESS) 5417 goto fail; 5418 pcs_blk_lock = ((val2 & PCS_10GBASE_R_PCS_BLK_LOCK) ? B_TRUE : B_FALSE); 5419 5420 /* Check Device 4 Register 0x18 bit12 */ 5421 status = nxge_mdio_read(nxgep, phy_port_addr, 5422 BCM8704_PHYXS_ADDR, 5423 BCM8704_PHYXS_XGXS_LANE_STATUS_REG, 5424 &val3); 5425 if (status != NXGE_OK) 5426 goto fail; 5427 5428 switch (nxgep->chip_id) { 5429 case BCM8704_CHIP_ID: 5430 link_align = (val3 == (XGXS_LANE_ALIGN_STATUS | 5431 XGXS_LANE3_SYNC | XGXS_LANE2_SYNC | XGXS_LANE1_SYNC | 5432 XGXS_LANE0_SYNC | 0x400)) ? B_TRUE : B_FALSE; 5433 break; 5434 case BCM8706_CHIP_ID: 5435 link_align = ((val3 & XGXS_LANE_ALIGN_STATUS) && 5436 (val3 & XGXS_LANE3_SYNC) && (val3 & XGXS_LANE2_SYNC) && 5437 (val3 & XGXS_LANE1_SYNC) && (val3 & XGXS_LANE0_SYNC)) ? 5438 B_TRUE : B_FALSE; 5439 break; 5440 default: 5441 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_check_bcm8704_link:" 5442 "Unknown chip ID [0x%x]", nxgep->chip_id)); 5443 goto fail; 5444 } 5445 5446 5447 #ifdef NXGE_DEBUG_ALIGN_ERR 5448 /* Temp workaround for link down issue */ 5449 if (pcs_blk_lock == B_FALSE) { 5450 if (val2 != 0x4) { 5451 pcs_blk_lock = B_TRUE; 5452 cmn_err(CE_NOTE, 5453 "!LINK DEBUG: port%d PHY Dev3 " 5454 "Reg 0x20 = 0x%x\n", 5455 nxgep->mac.portnum, val2); 5456 } 5457 } 5458 5459 if (link_align == B_FALSE) { 5460 if (val3 != 0x140f) { 5461 link_align = B_TRUE; 5462 cmn_err(CE_NOTE, 5463 "!LINK DEBUG: port%d PHY Dev4 " 5464 "Reg 0x18 = 0x%x\n", 5465 nxgep->mac.portnum, val3); 5466 } 5467 } 5468 5469 if (rx_sig_ok == B_FALSE) { 5470 if ((val2 == 0) || (val3 == 0)) { 5471 rx_sig_ok = B_TRUE; 5472 cmn_err(CE_NOTE, 5473 "!LINK DEBUG: port %d Dev3 or Dev4 read zero\n", 5474 nxgep->mac.portnum); 5475 } 5476 } 5477 #endif 5478 5479 *link_up = ((rx_sig_ok == B_TRUE) && (pcs_blk_lock == B_TRUE) && 5480 (link_align == B_TRUE)) ? B_TRUE : B_FALSE; 5481 5482 return (NXGE_OK); 5483 fail: 5484 return (status); 5485 } 5486 5487 static nxge_status_t 5488 nxge_mrvl88x2011_link(p_nxge_t nxgep, boolean_t *link_up) 5489 { 5490 uint8_t phy; 5491 nxge_status_t status = NXGE_OK; 5492 boolean_t pma_status; 5493 boolean_t pcs_status; 5494 boolean_t xgxs_status; 5495 uint16_t val; 5496 5497 phy = nxgep->statsp->mac_stats.xcvr_portn; 5498 5499 MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR, 5500 MRVL_88X2011_10G_PMD_STAT_2, &val); 5501 5502 *link_up = B_FALSE; 5503 5504 /* Check from Marvell 88X2011 if 10G link is up or down */ 5505 5506 /* Check PMA/PMD Register: 1.0001.2 == 1 */ 5507 MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR, 5508 MRVL_88X2011_PMA_PMD_STAT_1, &val); 5509 5510 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5511 "nxge_check_mrvl88x2011_link: pmd=0x%x", val)); 5512 5513 pma_status = ((val & MRVL_88X2011_LNK_STATUS_OK) ? B_TRUE : B_FALSE); 5514 5515 /* Check PMC Register : 3.0001.2 == 1: read twice */ 5516 MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR, 5517 MRVL_88X2011_PMA_PMD_STAT_1, &val); 5518 MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR, 5519 MRVL_88X2011_PMA_PMD_STAT_1, &val); 5520 5521 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5522 "nxge_check_mrvl88x2011_link: pcs=0x%x", val)); 5523 5524 pcs_status = ((val & MRVL_88X2011_LNK_STATUS_OK) ? B_TRUE : B_FALSE); 5525 5526 /* Check XGXS Register : 4.0018.[0-3,12] */ 5527 MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV4_ADDR, 5528 MRVL_88X2011_10G_XGXS_LANE_STAT, &val); 5529 5530 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5531 "nxge_check_mrvl88x2011_link: xgxs=0x%x", val)); 5532 5533 xgxs_status = (val == (XGXS_LANE_ALIGN_STATUS | XGXS_LANE3_SYNC | 5534 XGXS_LANE2_SYNC | XGXS_LANE1_SYNC | 5535 XGXS_LANE0_SYNC | XGXS_PATTERN_TEST_ABILITY | 5536 XGXS_LANE_STAT_MAGIC)) ? B_TRUE : B_FALSE; 5537 5538 *link_up = (pma_status && pcs_status && xgxs_status) ? 5539 B_TRUE : B_FALSE; 5540 5541 fail: 5542 5543 if (*link_up == B_FALSE) { 5544 /* PCS OFF */ 5545 nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_CTL_OFF); 5546 } else { 5547 /* PCS Activity */ 5548 nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_CTL_PCS_ACT); 5549 } 5550 5551 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5552 " <== nxge_check_mrvl88x2011_link: up=%d", *link_up)); 5553 5554 return (status); 5555 } 5556 5557 nxge_status_t 5558 nxge_10g_link_led_on(p_nxge_t nxgep) 5559 { 5560 if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_TRUE) 5561 != NPI_SUCCESS) 5562 return (NXGE_ERROR); 5563 else 5564 return (NXGE_OK); 5565 } 5566 5567 nxge_status_t 5568 nxge_10g_link_led_off(p_nxge_t nxgep) 5569 { 5570 if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_FALSE) 5571 != NPI_SUCCESS) 5572 return (NXGE_ERROR); 5573 else 5574 return (NXGE_OK); 5575 } 5576 5577 static boolean_t 5578 nxge_is_phy_present(p_nxge_t nxgep, int addr, uint32_t id, uint32_t mask) 5579 { 5580 uint32_t pma_pmd_id = 0; 5581 uint32_t pcs_id = 0; 5582 uint32_t phy_id = 0; 5583 5584 pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, addr); 5585 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5586 "nxge_is_phy_present: pma_pmd_id[0x%x]", pma_pmd_id)); 5587 if ((pma_pmd_id & mask) == (id & mask)) 5588 goto found_phy; 5589 pcs_id = nxge_get_cl45_pcs_id(nxgep, addr); 5590 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5591 "nxge_is_phy_present: pcs_id[0x%x]", pcs_id)); 5592 if ((pcs_id & mask) == (id & mask)) 5593 goto found_phy; 5594 phy_id = nxge_get_cl22_phy_id(nxgep, addr); 5595 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5596 "nxge_is_phy_present: phy_id[0x%x]", phy_id)); 5597 if ((phy_id & mask) == (id & mask)) 5598 goto found_phy; 5599 5600 return (B_FALSE); 5601 5602 found_phy: 5603 return (B_TRUE); 5604 } 5605 5606 /* Check if the given id read using the given MDIO Clause is supported */ 5607 5608 static boolean_t 5609 nxge_is_supported_phy(uint32_t id, uint8_t type) 5610 { 5611 int i; 5612 int cl45_arr_len = NUM_CLAUSE_45_IDS; 5613 int cl22_arr_len = NUM_CLAUSE_22_IDS; 5614 boolean_t found = B_FALSE; 5615 5616 switch (type) { 5617 case CLAUSE_45_TYPE: 5618 for (i = 0; i < cl45_arr_len; i++) { 5619 if ((nxge_supported_cl45_ids[i] & BCM_PHY_ID_MASK) == 5620 (id & BCM_PHY_ID_MASK)) { 5621 found = B_TRUE; 5622 break; 5623 } 5624 } 5625 break; 5626 case CLAUSE_22_TYPE: 5627 for (i = 0; i < cl22_arr_len; i++) { 5628 if ((nxge_supported_cl22_ids[i] & BCM_PHY_ID_MASK) == 5629 (id & BCM_PHY_ID_MASK)) { 5630 found = B_TRUE; 5631 break; 5632 } 5633 } 5634 break; 5635 default: 5636 break; 5637 } 5638 5639 return (found); 5640 } 5641 5642 static uint32_t 5643 nxge_get_cl45_pma_pmd_id(p_nxge_t nxgep, int phy_port) 5644 { 5645 uint16_t val1 = 0; 5646 uint16_t val2 = 0; 5647 uint32_t pma_pmd_dev_id = 0; 5648 npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep); 5649 5650 MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 5651 (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR, 5652 NXGE_DEV_ID_REG_1, &val1); 5653 (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR, 5654 NXGE_DEV_ID_REG_2, &val2); 5655 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 5656 5657 pma_pmd_dev_id = val1; 5658 pma_pmd_dev_id = (pma_pmd_dev_id << 16); 5659 pma_pmd_dev_id |= val2; 5660 5661 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PMA/PMD " 5662 "devid[0x%llx]", phy_port, pma_pmd_dev_id)); 5663 5664 return (pma_pmd_dev_id); 5665 } 5666 5667 static uint32_t 5668 nxge_get_cl45_pcs_id(p_nxge_t nxgep, int phy_port) 5669 { 5670 uint16_t val1 = 0; 5671 uint16_t val2 = 0; 5672 uint32_t pcs_dev_id = 0; 5673 npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep); 5674 5675 MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 5676 (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR, 5677 NXGE_DEV_ID_REG_1, &val1); 5678 (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR, 5679 NXGE_DEV_ID_REG_2, &val2); 5680 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 5681 5682 pcs_dev_id = val1; 5683 pcs_dev_id = (pcs_dev_id << 16); 5684 pcs_dev_id |= val2; 5685 5686 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS " 5687 "devid[0x%llx]", phy_port, pcs_dev_id)); 5688 5689 return (pcs_dev_id); 5690 } 5691 5692 static uint32_t 5693 nxge_get_cl22_phy_id(p_nxge_t nxgep, int phy_port) 5694 { 5695 uint16_t val1 = 0; 5696 uint16_t val2 = 0; 5697 uint32_t phy_id = 0; 5698 npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep); 5699 npi_status_t npi_status = NPI_SUCCESS; 5700 5701 MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 5702 npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_1, 5703 &val1); 5704 if (npi_status != NPI_SUCCESS) { 5705 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] " 5706 "clause 22 read to reg 2 failed!!!")); 5707 goto exit; 5708 } 5709 npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_2, 5710 &val2); 5711 if (npi_status != 0) { 5712 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] " 5713 "clause 22 read to reg 3 failed!!!")); 5714 goto exit; 5715 } 5716 phy_id = val1; 5717 phy_id = (phy_id << 16); 5718 phy_id |= val2; 5719 5720 exit: 5721 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 5722 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID [0x%llx]", 5723 phy_port, phy_id)); 5724 5725 return (phy_id); 5726 } 5727 5728 /* 5729 * Scan the PHY ports 0 through 31 to get the PHY ID using Clause 22 MDIO 5730 * read and the PMA/PMD device ID and the PCS device ID using Clause 45 MDIO 5731 * read. Then use the values obtained to determine the phy type of each port 5732 * and the Neptune type. 5733 */ 5734 5735 nxge_status_t 5736 nxge_scan_ports_phy(p_nxge_t nxgep, p_nxge_hw_list_t hw_p) 5737 { 5738 int i, j, l; 5739 uint32_t pma_pmd_dev_id = 0; 5740 uint32_t pcs_dev_id = 0; 5741 uint32_t phy_id = 0; 5742 uint32_t port_pma_pmd_dev_id[NXGE_PORTS_NEPTUNE]; 5743 uint32_t port_pcs_dev_id[NXGE_PORTS_NEPTUNE]; 5744 uint32_t port_phy_id[NXGE_PORTS_NEPTUNE]; 5745 uint8_t pma_pmd_dev_fd[NXGE_MAX_PHY_PORTS]; 5746 uint8_t pcs_dev_fd[NXGE_MAX_PHY_PORTS]; 5747 uint8_t phy_fd_arr[NXGE_MAX_PHY_PORTS]; 5748 uint8_t port_fd_arr[NXGE_MAX_PHY_PORTS]; 5749 uint8_t total_port_fd, total_phy_fd; 5750 nxge_status_t status = NXGE_OK; 5751 5752 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_scan_ports_phy: ")); 5753 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5754 "==> nxge_scan_ports_phy: nxge niu_type[0x%x]", 5755 nxgep->niu_type)); 5756 5757 if (isLDOMguest(nxgep)) { 5758 hw_p->niu_type = NIU_TYPE_NONE; 5759 hw_p->platform_type = P_NEPTUNE_NONE; 5760 return (NXGE_OK); 5761 } 5762 5763 j = l = 0; 5764 total_port_fd = total_phy_fd = 0; 5765 /* 5766 * Clause 45 and Clause 22 port/phy addresses 0 through 7 are reserved 5767 * for on chip serdes usages. 5768 */ 5769 for (i = NXGE_EXT_PHY_PORT_ST; i < NXGE_MAX_PHY_PORTS; i++) { 5770 5771 pma_pmd_dev_id = nxge_get_cl45_pma_pmd_id(nxgep, i); 5772 5773 if (nxge_is_supported_phy(pma_pmd_dev_id, CLAUSE_45_TYPE)) { 5774 pma_pmd_dev_fd[i] = 1; 5775 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] " 5776 "PMA/PMD dev %x found", i, pma_pmd_dev_id)); 5777 if (j < NXGE_PORTS_NEPTUNE) { 5778 port_pma_pmd_dev_id[j] = pma_pmd_dev_id & 5779 BCM_PHY_ID_MASK; 5780 port_fd_arr[j] = (uint8_t)i; 5781 j++; 5782 } 5783 } else { 5784 pma_pmd_dev_fd[i] = 0; 5785 } 5786 5787 pcs_dev_id = nxge_get_cl45_pcs_id(nxgep, i); 5788 5789 if (nxge_is_supported_phy(pcs_dev_id, CLAUSE_45_TYPE)) { 5790 pcs_dev_fd[i] = 1; 5791 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS " 5792 "dev %x found", i, pcs_dev_id)); 5793 if (pma_pmd_dev_fd[i] == 1) { 5794 port_pcs_dev_id[j - 1] = pcs_dev_id & 5795 BCM_PHY_ID_MASK; 5796 } else { 5797 if (j < NXGE_PORTS_NEPTUNE) { 5798 port_pcs_dev_id[j] = pcs_dev_id & 5799 BCM_PHY_ID_MASK; 5800 port_fd_arr[j] = (uint8_t)i; 5801 j++; 5802 } 5803 } 5804 } else { 5805 pcs_dev_fd[i] = 0; 5806 } 5807 5808 if (pcs_dev_fd[i] || pma_pmd_dev_fd[i]) { 5809 total_port_fd ++; 5810 } 5811 5812 phy_id = nxge_get_cl22_phy_id(nxgep, i); 5813 5814 if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) { 5815 total_phy_fd ++; 5816 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID" 5817 "%x found", i, phy_id)); 5818 if (l < NXGE_PORTS_NEPTUNE) { 5819 port_phy_id[l] = phy_id & BCM_PHY_ID_MASK; 5820 phy_fd_arr[l] = (uint8_t)i; 5821 l++; 5822 } 5823 } 5824 } 5825 5826 switch (total_port_fd) { 5827 case 2: 5828 switch (total_phy_fd) { 5829 case 2: 5830 /* 2 10G, 2 1G RGMII Fiber */ 5831 if ((((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) && 5832 (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) || 5833 ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) && 5834 (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) && 5835 ((port_phy_id[0] == PHY_BCM5482_FAMILY) && 5836 (port_phy_id[1] == PHY_BCM5482_FAMILY))) { 5837 5838 hw_p->platform_type = 5839 P_NEPTUNE_GENERIC; 5840 5841 hw_p->niu_type = NEPTUNE_2_10GF_2_1GRF; 5842 5843 hw_p->xcvr_addr[0] = port_fd_arr[0]; 5844 hw_p->xcvr_addr[1] = port_fd_arr[1]; 5845 hw_p->xcvr_addr[2] = phy_fd_arr[0]; 5846 hw_p->xcvr_addr[3] = phy_fd_arr[1]; 5847 5848 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5849 "ARTM card with 2 10G, 2 1G")); 5850 } else { 5851 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5852 "Unsupported neptune type 1")); 5853 goto error_exit; 5854 } 5855 break; 5856 5857 case 1: 5858 /* TODO - 2 10G, 1 1G */ 5859 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5860 "Unsupported neptune type 2 10G, 1 1G")); 5861 goto error_exit; 5862 case 0: 5863 /* 2 10G */ 5864 if (((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) && 5865 (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) || 5866 ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) && 5867 (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY)) || 5868 ((port_pcs_dev_id[0] == MARVELL_88X201X_PHY_ID) && 5869 (port_pcs_dev_id[1] == MARVELL_88X201X_PHY_ID)) || 5870 ((port_pma_pmd_dev_id[0] == 5871 MARVELL_88X201X_PHY_ID) && 5872 (port_pma_pmd_dev_id[1] == 5873 MARVELL_88X201X_PHY_ID))) { 5874 5875 /* 5876 * Check the first phy port address against 5877 * the known phy start addresses to determine 5878 * the platform type. 5879 */ 5880 5881 switch (port_fd_arr[0]) { 5882 case BCM8704_NEPTUNE_PORT_ADDR_BASE: 5883 /* 5884 * The Marvell case also falls into 5885 * this case as 5886 * MRVL88X2011_NEPTUNE_PORT_ADDR_BASE 5887 * == BCM8704_NEPTUNE_PORT_ADDR_BASE. 5888 * This is OK for the 2 10G case. 5889 */ 5890 hw_p->niu_type = NEPTUNE_2_10GF; 5891 hw_p->platform_type = 5892 P_NEPTUNE_ATLAS_2PORT; 5893 break; 5894 case BCM8706_GOA_PORT_ADDR_BASE: 5895 if (hw_p->platform_type != 5896 P_NEPTUNE_NIU) { 5897 hw_p->platform_type = 5898 P_NEPTUNE_GENERIC; 5899 hw_p->niu_type = 5900 NEPTUNE_2_10GF; 5901 } 5902 break; 5903 default: 5904 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5905 "Unsupported neptune type 2 - 1")); 5906 goto error_exit; 5907 } 5908 5909 for (i = 0; i < 2; i++) { 5910 hw_p->xcvr_addr[i] = port_fd_arr[i]; 5911 } 5912 } else { 5913 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5914 "Unsupported neptune type 2")); 5915 goto error_exit; 5916 } 5917 break; 5918 case 4: 5919 /* Maramba with 2 XAUI */ 5920 if ((((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) && 5921 (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) || 5922 ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) && 5923 (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) && 5924 ((port_phy_id[0] == PHY_BCM5464R_FAMILY) && 5925 (port_phy_id[1] == PHY_BCM5464R_FAMILY) && 5926 (port_phy_id[2] == PHY_BCM5464R_FAMILY) && 5927 (port_phy_id[3] == PHY_BCM5464R_FAMILY))) { 5928 5929 /* 5930 * Check the first phy port address against 5931 * the known phy start addresses to determine 5932 * the platform type. 5933 */ 5934 switch (phy_fd_arr[0]) { 5935 case BCM5464_MARAMBA_P0_PORT_ADDR_BASE: 5936 hw_p->platform_type = 5937 P_NEPTUNE_MARAMBA_P0; 5938 break; 5939 case BCM5464_MARAMBA_P1_PORT_ADDR_BASE: 5940 hw_p->platform_type = 5941 P_NEPTUNE_MARAMBA_P1; 5942 break; 5943 default: 5944 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5945 "Unknown port %d...Cannot " 5946 "determine platform type", i)); 5947 goto error_exit; 5948 } 5949 5950 hw_p->niu_type = NEPTUNE_2_10GF_2_1GC; 5951 5952 hw_p->xcvr_addr[0] = port_fd_arr[0]; 5953 hw_p->xcvr_addr[1] = port_fd_arr[1]; 5954 hw_p->xcvr_addr[2] = phy_fd_arr[2]; 5955 hw_p->xcvr_addr[3] = phy_fd_arr[3]; 5956 5957 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5958 "Maramba with 2 XAUI")); 5959 } else { 5960 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5961 "Unsupported neptune type 3")); 5962 goto error_exit; 5963 } 5964 break; 5965 default: 5966 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5967 "Unsupported neptune type 5")); 5968 goto error_exit; 5969 } 5970 break; 5971 case 1: 5972 switch (total_phy_fd) { 5973 case 3: 5974 /* 5975 * TODO 3 1G, 1 10G mode. 5976 * Differentiate between 1_1G_1_10G_2_1G and 5977 * 1_10G_3_1G 5978 */ 5979 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5980 "Unsupported neptune type 7")); 5981 goto error_exit; 5982 case 2: 5983 /* 5984 * TODO 2 1G, 1 10G mode. 5985 * Differentiate between 1_1G_1_10G_1_1G and 5986 * 1_10G_2_1G 5987 */ 5988 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5989 "Unsupported neptune type 8")); 5990 goto error_exit; 5991 case 1: 5992 /* 5993 * TODO 1 1G, 1 10G mode. 5994 * Differentiate between 1_1G_1_10G and 5995 * 1_10G_1_1G 5996 */ 5997 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5998 "Unsupported neptune type 9")); 5999 goto error_exit; 6000 case 0: 6001 /* 1 10G mode, N2 with 1 XAUI */ 6002 if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY || 6003 port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) { 6004 6005 /* 6006 * Check the first phy port address against 6007 * the known phy start addresses to determine 6008 * the platform type. 6009 */ 6010 6011 switch (port_fd_arr[0]) { 6012 case BCM8704_N2_PORT_ADDR_BASE: 6013 case (BCM8704_N2_PORT_ADDR_BASE + 1): 6014 case BCM8706_ALT_GOA_PORT1_ADDR: 6015 if (hw_p->platform_type != 6016 P_NEPTUNE_NIU) { 6017 hw_p->platform_type = 6018 P_NEPTUNE_GENERIC; 6019 hw_p->niu_type = 6020 NEPTUNE_2_10GF; 6021 } 6022 break; 6023 default: 6024 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6025 "Unsupported neptune type 10")); 6026 goto error_exit; 6027 } 6028 /* 6029 * For GOA, which is a hot swappable PHY, the 6030 * phy address to function number mapping 6031 * should be preserved, i.e., addr 16 is 6032 * assigned to function 0 and 20 to function 1 6033 * But for Huron XAUI, the assignment should 6034 * be by function number, i.e., whichever 6035 * function number attaches should be 6036 * assigned the available PHY (this is required 6037 * primarily to support pre-production Huron 6038 * boards where function 0 is mapped to addr 17 6039 */ 6040 if (port_fd_arr[0] == 6041 BCM8706_ALT_GOA_PORT1_ADDR) { 6042 hw_p->xcvr_addr[1] = port_fd_arr[0]; 6043 } else { 6044 hw_p->xcvr_addr[nxgep->function_num] = 6045 port_fd_arr[0]; 6046 } 6047 } else { 6048 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6049 "Unsupported neptune type 10 - 1")); 6050 goto error_exit; 6051 } 6052 break; 6053 case 4: 6054 /* Maramba with 1 XAUI */ 6055 if ((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) || 6056 (port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY)) { 6057 6058 /* 6059 * Check the first phy port address against 6060 * the known phy start addresses to determine 6061 * the platform type. 6062 */ 6063 switch (phy_fd_arr[0]) { 6064 case BCM5464_MARAMBA_P0_PORT_ADDR_BASE: 6065 hw_p->platform_type = 6066 P_NEPTUNE_MARAMBA_P0; 6067 break; 6068 case BCM5464_MARAMBA_P1_PORT_ADDR_BASE: 6069 hw_p->platform_type = 6070 P_NEPTUNE_MARAMBA_P1; 6071 break; 6072 default: 6073 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6074 "Unknown port %d...Cannot " 6075 "determine platform type 10 - 2", 6076 i)); 6077 goto error_exit; 6078 } 6079 6080 /* 6081 * Check the BCM8704 address to determine 6082 * if XAUI is in port 0 or port 1. 6083 */ 6084 switch (port_fd_arr[0]) { 6085 case BCM8704_MARAMBA_PORT_ADDR_BASE: 6086 hw_p->niu_type = NEPTUNE_1_10GF_3_1GC; 6087 hw_p->xcvr_addr[0] = port_fd_arr[0]; 6088 for (i = 1; i < NXGE_MAX_PORTS; i++) { 6089 hw_p->xcvr_addr[i] = 6090 phy_fd_arr[i]; 6091 } 6092 break; 6093 case (BCM8704_MARAMBA_PORT_ADDR_BASE + 1): 6094 hw_p->niu_type = 6095 NEPTUNE_1_1GC_1_10GF_2_1GC; 6096 hw_p->xcvr_addr[0] = phy_fd_arr[0]; 6097 hw_p->xcvr_addr[1] = port_fd_arr[0]; 6098 hw_p->xcvr_addr[2] = phy_fd_arr[2]; 6099 hw_p->xcvr_addr[3] = phy_fd_arr[3]; 6100 break; 6101 default: 6102 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6103 "Unsupported neptune type 11")); 6104 goto error_exit; 6105 } 6106 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6107 "Maramba with 1 XAUI")); 6108 } else { 6109 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6110 "Unsupported neptune type 12")); 6111 goto error_exit; 6112 } 6113 break; 6114 default: 6115 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6116 "Unsupported neptune type 13")); 6117 goto error_exit; 6118 } 6119 break; 6120 case 0: 6121 switch (total_phy_fd) { 6122 case 4: 6123 if ((port_phy_id[0] == PHY_BCM5464R_FAMILY) && 6124 (port_phy_id[1] == PHY_BCM5464R_FAMILY) && 6125 (port_phy_id[2] == PHY_BCM5464R_FAMILY) && 6126 (port_phy_id[3] == PHY_BCM5464R_FAMILY)) { 6127 6128 /* 6129 * Check the first phy port address against 6130 * the known phy start addresses to determine 6131 * the platform type. 6132 */ 6133 switch (phy_fd_arr[0]) { 6134 case BCM5464_MARAMBA_P1_PORT_ADDR_BASE: 6135 hw_p->platform_type = 6136 P_NEPTUNE_MARAMBA_P1; 6137 break; 6138 case BCM5464_NEPTUNE_PORT_ADDR_BASE: 6139 hw_p->platform_type = 6140 P_NEPTUNE_ATLAS_4PORT; 6141 break; 6142 default: 6143 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6144 "Unknown port %d...Cannot " 6145 "determine platform type", i)); 6146 goto error_exit; 6147 } 6148 hw_p->niu_type = NEPTUNE_4_1GC; 6149 for (i = 0; i < NXGE_MAX_PORTS; i++) { 6150 hw_p->xcvr_addr[i] = phy_fd_arr[i]; 6151 } 6152 } else { 6153 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6154 "Unsupported neptune type 14")); 6155 goto error_exit; 6156 } 6157 break; 6158 case 3: 6159 /* TODO 3 1G mode */ 6160 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6161 "Unsupported neptune type 15")); 6162 goto error_exit; 6163 case 2: 6164 /* TODO 2 1G mode */ 6165 if ((port_phy_id[0] == PHY_BCM5482_FAMILY) && 6166 (port_phy_id[1] == PHY_BCM5482_FAMILY)) { 6167 hw_p->platform_type = P_NEPTUNE_GENERIC; 6168 hw_p->niu_type = NEPTUNE_2_1GRF; 6169 hw_p->xcvr_addr[2] = phy_fd_arr[0]; 6170 hw_p->xcvr_addr[3] = phy_fd_arr[1]; 6171 } else { 6172 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6173 "Unsupported neptune type 16")); 6174 goto error_exit; 6175 } 6176 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6177 "2 RGMII Fiber ports - RTM")); 6178 break; 6179 6180 case 1: 6181 /* TODO 1 1G mode */ 6182 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6183 "Unsupported neptune type 17")); 6184 goto error_exit; 6185 default: 6186 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6187 "Unsupported neptune type 18, total phy fd %d", 6188 total_phy_fd)); 6189 goto error_exit; 6190 } 6191 break; 6192 default: 6193 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6194 "Unsupported neptune type 19")); 6195 goto error_exit; 6196 } 6197 6198 scan_exit: 6199 6200 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_scan_ports_phy, " 6201 "niu type [0x%x]\n", hw_p->niu_type)); 6202 return (status); 6203 6204 error_exit: 6205 return (NXGE_ERROR); 6206 } 6207 6208 boolean_t 6209 nxge_is_valid_local_mac(ether_addr_st mac_addr) 6210 { 6211 if ((mac_addr.ether_addr_octet[0] & 0x01) || 6212 (ether_cmp(&mac_addr, ðerbroadcastaddr) == 0) || 6213 (ether_cmp(&mac_addr, ðerzeroaddr) == 0)) 6214 return (B_FALSE); 6215 else 6216 return (B_TRUE); 6217 } 6218 6219 static void 6220 nxge_bcm5464_link_led_off(p_nxge_t nxgep) { 6221 6222 npi_status_t rs = NPI_SUCCESS; 6223 uint8_t xcvr_portn; 6224 uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 6225 6226 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_bcm5464_link_led_off")); 6227 6228 if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P1) { 6229 xcvr_portn = BCM5464_MARAMBA_P1_PORT_ADDR_BASE; 6230 } else if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P0) { 6231 xcvr_portn = BCM5464_MARAMBA_P0_PORT_ADDR_BASE; 6232 } 6233 /* 6234 * For Altas 4-1G copper, Xcvr port numbers are 6235 * swapped with ethernet port number. This is 6236 * designed for better signal integrity in routing. 6237 */ 6238 switch (portn) { 6239 case 0: 6240 xcvr_portn += 3; 6241 break; 6242 case 1: 6243 xcvr_portn += 2; 6244 break; 6245 case 2: 6246 xcvr_portn += 1; 6247 break; 6248 case 3: 6249 default: 6250 break; 6251 } 6252 6253 MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 6254 rs = npi_mac_mif_mii_write(nxgep->npi_handle, 6255 xcvr_portn, BCM5464R_MISC, 0xb4ee); 6256 if (rs != NPI_SUCCESS) { 6257 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6258 "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write " 6259 "returned error 0x[%x]", rs)); 6260 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 6261 return; 6262 } 6263 6264 rs = npi_mac_mif_mii_write(nxgep->npi_handle, 6265 xcvr_portn, BCM5464R_MISC, 0xb8ee); 6266 if (rs != NPI_SUCCESS) { 6267 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6268 "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write " 6269 "returned error 0x[%x]", rs)); 6270 } 6271 6272 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 6273 } 6274 6275 static nxge_status_t 6276 nxge_mii_get_link_mode(p_nxge_t nxgep) 6277 { 6278 p_nxge_stats_t statsp; 6279 uint8_t xcvr_portn; 6280 p_mii_regs_t mii_regs; 6281 mii_mode_control_stat_t mode; 6282 int status = NXGE_OK; 6283 6284 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_get_link_mode")); 6285 6286 statsp = nxgep->statsp; 6287 xcvr_portn = statsp->mac_stats.xcvr_portn; 6288 mii_regs = NULL; 6289 mode.value = 0; 6290 mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG; 6291 #if defined(__i386) 6292 if ((status = nxge_mii_write(nxgep, xcvr_portn, 6293 (uint8_t)(uint32_t)(&mii_regs->shadow), 6294 mode.value)) != NXGE_OK) { 6295 goto fail; 6296 #else 6297 if ((status = nxge_mii_write(nxgep, xcvr_portn, 6298 (uint8_t)(uint64_t)(&mii_regs->shadow), 6299 mode.value)) != NXGE_OK) { 6300 goto fail; 6301 #endif 6302 } 6303 #if defined(__i386) 6304 if ((status = nxge_mii_read(nxgep, xcvr_portn, 6305 (uint8_t)(uint32_t)(&mii_regs->shadow), 6306 &mode.value)) != NXGE_OK) { 6307 goto fail; 6308 } 6309 #else 6310 if ((status = nxge_mii_read(nxgep, xcvr_portn, 6311 (uint8_t)(uint64_t)(&mii_regs->shadow), 6312 &mode.value)) != NXGE_OK) { 6313 goto fail; 6314 } 6315 #endif 6316 6317 if (mode.bits.mode == NXGE_MODE_SELECT_FIBER) { 6318 nxgep->mac.portmode = PORT_1G_RGMII_FIBER; 6319 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6320 "nxge_mii_get_link_mode: fiber mode")); 6321 } 6322 6323 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6324 "nxge_mii_get_link_mode: " 6325 "(address 0x%x) port 0x%x mode value 0x%x link mode 0x%x", 6326 NXGE_MII_MODE_CONTROL_REG, xcvr_portn, 6327 mode.value, nxgep->mac.portmode)); 6328 6329 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6330 "<== nxge_mii_get_link_mode")); 6331 return (status); 6332 fail: 6333 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6334 "<== nxge_mii_get_link_mode (failed)")); 6335 return (NXGE_ERROR); 6336 } 6337 6338 nxge_status_t 6339 nxge_mac_set_framesize(p_nxge_t nxgep) 6340 { 6341 npi_attr_t ap; 6342 uint8_t portn; 6343 npi_handle_t handle; 6344 npi_status_t rs = NPI_SUCCESS; 6345 6346 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_set_framesize")); 6347 6348 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 6349 handle = nxgep->npi_handle; 6350 6351 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6352 "==> nxge_mac_sec_framesize: port<%d> " 6353 "min framesize %d max framesize %d ", 6354 portn, 6355 nxgep->mac.minframesize, 6356 nxgep->mac.maxframesize)); 6357 6358 SET_MAC_ATTR2(handle, ap, portn, 6359 MAC_PORT_FRAME_SIZE, 6360 nxgep->mac.minframesize, 6361 nxgep->mac.maxframesize, 6362 rs); 6363 if (rs != NPI_SUCCESS) { 6364 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6365 "<== nxge_mac_set_framesize: failed to configure " 6366 "max/min frame size port %d", portn)); 6367 6368 return (NXGE_ERROR | rs); 6369 } 6370 6371 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6372 "<== nxge_mac_set_framesize: port<%d>", portn)); 6373 6374 return (NXGE_OK); 6375 } 6376 6377 #ifdef NXGE_DEBUG 6378 static void 6379 nxge_mii_dump(p_nxge_t nxgep) 6380 { 6381 p_nxge_stats_t statsp; 6382 uint8_t xcvr_portn; 6383 p_mii_regs_t mii_regs; 6384 mii_bmcr_t bmcr; 6385 mii_bmsr_t bmsr; 6386 mii_idr1_t idr1; 6387 mii_idr2_t idr2; 6388 mii_mode_control_stat_t mode; 6389 p_nxge_param_t param_arr; 6390 6391 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "==> nxge_mii_dump")); 6392 6393 statsp = nxgep->statsp; 6394 xcvr_portn = statsp->mac_stats.xcvr_portn; 6395 6396 mii_regs = NULL; 6397 6398 #if defined(__i386) 6399 (void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn, 6400 (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value); 6401 #else 6402 (void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn, 6403 (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value); 6404 #endif 6405 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6406 "nxge_mii_dump: bmcr (0) xcvr 0x%x value 0x%x", 6407 xcvr_portn, bmcr.value)); 6408 6409 #if defined(__i386) 6410 (void) nxge_mii_read(nxgep, 6411 nxgep->statsp->mac_stats.xcvr_portn, 6412 (uint8_t)(uint32_t)(&mii_regs->bmsr), &bmsr.value); 6413 #else 6414 (void) nxge_mii_read(nxgep, 6415 nxgep->statsp->mac_stats.xcvr_portn, 6416 (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value); 6417 #endif 6418 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6419 "nxge_mii_dump: bmsr (1) xcvr 0x%x value 0x%x", 6420 xcvr_portn, bmsr.value)); 6421 6422 #if defined(__i386) 6423 (void) nxge_mii_read(nxgep, 6424 nxgep->statsp->mac_stats.xcvr_portn, 6425 (uint8_t)(uint32_t)(&mii_regs->idr1), &idr1.value); 6426 #else 6427 (void) nxge_mii_read(nxgep, 6428 nxgep->statsp->mac_stats.xcvr_portn, 6429 (uint8_t)(uint64_t)(&mii_regs->idr1), &idr1.value); 6430 #endif 6431 6432 6433 #if defined(__i386) 6434 (void) nxge_mii_read(nxgep, 6435 nxgep->statsp->mac_stats.xcvr_portn, 6436 (uint8_t)(uint32_t)(&mii_regs->idr2), &idr2.value); 6437 #else 6438 (void) nxge_mii_read(nxgep, 6439 nxgep->statsp->mac_stats.xcvr_portn, 6440 (uint8_t)(uint64_t)(&mii_regs->idr2), &idr2.value); 6441 #endif 6442 6443 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6444 "nxge_mii_dump: idr1 (2) xcvr 0x%x value 0x%x", 6445 xcvr_portn, idr1.value)); 6446 6447 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6448 "nxge_mii_dump: idr2 (3) xcvr 0x%x value 0x%x", 6449 xcvr_portn, idr2.value)); 6450 6451 mode.value = 0; 6452 mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG; 6453 6454 #if defined(__i386) 6455 (void) nxge_mii_write(nxgep, xcvr_portn, 6456 (uint8_t)(uint32_t)(&mii_regs->shadow), mode.value); 6457 6458 (void) nxge_mii_read(nxgep, xcvr_portn, 6459 (uint8_t)(uint32_t)(&mii_regs->shadow), &mode.value); 6460 #else 6461 (void) nxge_mii_write(nxgep, xcvr_portn, 6462 (uint8_t)(uint64_t)(&mii_regs->shadow), mode.value); 6463 6464 (void) nxge_mii_read(nxgep, xcvr_portn, 6465 (uint8_t)(uint64_t)(&mii_regs->shadow), &mode.value); 6466 #endif 6467 6468 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6469 "nxge_mii_dump: mode control xcvr 0x%x value 0x%x", 6470 xcvr_portn, mode.value)); 6471 } 6472 #endif 6473