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