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