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