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