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