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