1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #include <sys/nxge/nxge_impl.h> 27 #include <sys/nxge/nxge_mac.h> 28 #include <sys/nxge/nxge_hio.h> 29 30 #define LINK_MONITOR_PERIOD (1000 * 1000) 31 #define LM_WAIT_MULTIPLIER 8 32 33 #define SERDES_RDY_WT_INTERVAL 50 34 #define MAX_SERDES_RDY_RETRIES 10 35 36 #define TN1010_SPEED_1G 1 37 #define TN1010_SPEED_10G 0 38 #define TN1010_AN_IN_PROG 0 /* Auto negotiation in progress */ 39 #define TN1010_AN_COMPLETE 1 40 #define TN1010_AN_RSVD 2 41 #define TN1010_AN_FAILED 3 42 43 extern uint32_t nxge_no_link_notify; 44 extern boolean_t nxge_no_msg; 45 extern uint32_t nxge_lb_dbg; 46 extern uint32_t nxge_jumbo_mtu; 47 48 typedef enum { 49 CHECK_LINK_RESCHEDULE, 50 CHECK_LINK_STOP 51 } check_link_state_t; 52 53 static check_link_state_t nxge_check_link_stop(nxge_t *); 54 55 /* 56 * Ethernet broadcast address definition. 57 */ 58 static ether_addr_st etherbroadcastaddr = 59 {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}; 60 /* 61 * Ethernet zero address definition. 62 */ 63 static ether_addr_st etherzeroaddr = 64 {{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; 65 /* 66 * Supported chip types 67 */ 68 static uint32_t nxge_supported_cl45_ids[] = { 69 BCM8704_DEV_ID, 70 MARVELL_88X_201X_DEV_ID, 71 BCM8706_DEV_ID, 72 TN1010_DEV_ID 73 }; 74 75 static uint32_t nxge_supported_cl22_ids[] = { 76 BCM5464R_PHY_ID, 77 BCM5482_PHY_ID 78 }; 79 80 #define NUM_CLAUSE_45_IDS (sizeof (nxge_supported_cl45_ids) / \ 81 sizeof (uint32_t)) 82 #define NUM_CLAUSE_22_IDS (sizeof (nxge_supported_cl22_ids) / \ 83 sizeof (uint32_t)) 84 /* 85 * static functions 86 */ 87 static uint32_t nxge_get_cl45_pma_pmd_id(p_nxge_t, int); 88 static uint32_t nxge_get_cl45_pcs_id(p_nxge_t, int); 89 static uint32_t nxge_get_cl22_phy_id(p_nxge_t, int); 90 static boolean_t nxge_is_supported_phy(uint32_t, uint8_t); 91 static boolean_t nxge_is_phy_present(p_nxge_t, int, uint32_t, uint32_t); 92 static nxge_status_t nxge_n2_serdes_init(p_nxge_t); 93 static nxge_status_t nxge_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_ERROR_MSG((nxgep, NXGE_ERR_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_ERROR_MSG((nxgep, NXGE_ERR_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 3344 /* Initialize the RxMAC sub-block */ 3345 3346 nxge_status_t 3347 nxge_rx_mac_init(p_nxge_t nxgep) 3348 { 3349 npi_attr_t ap; 3350 uint32_t i; 3351 uint16_t hashtab_e; 3352 p_hash_filter_t hash_filter; 3353 nxge_port_t portt; 3354 uint8_t portn; 3355 npi_handle_t handle; 3356 npi_status_t rs = NPI_SUCCESS; 3357 uint16_t *addr16p; 3358 uint16_t addr0, addr1, addr2; 3359 xmac_rx_config_t xconfig; 3360 bmac_rx_config_t bconfig; 3361 3362 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 3363 3364 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_init: port<%d>\n", 3365 portn)); 3366 handle = nxgep->npi_handle; 3367 portt = nxgep->mac.porttype; 3368 3369 addr16p = (uint16_t *)nxgep->ouraddr.ether_addr_octet; 3370 addr0 = ntohs(addr16p[2]); 3371 addr1 = ntohs(addr16p[1]); 3372 addr2 = ntohs(addr16p[0]); 3373 SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR, addr0, addr1, addr2, 3374 rs); 3375 3376 if (rs != NPI_SUCCESS) 3377 goto fail; 3378 SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR_FILTER, 0, 0, 0, rs); 3379 if (rs != NPI_SUCCESS) 3380 goto fail; 3381 SET_MAC_ATTR2(handle, ap, portn, MAC_PORT_ADDR_FILTER_MASK, 0, 0, rs); 3382 if (rs != NPI_SUCCESS) 3383 goto fail; 3384 3385 /* 3386 * Load the multicast hash filter bits. 3387 */ 3388 hash_filter = nxgep->hash_filter; 3389 for (i = 0; i < MAC_MAX_HASH_ENTRY; i++) { 3390 if (hash_filter != NULL) { 3391 hashtab_e = (uint16_t)hash_filter->hash_filter_regs[ 3392 (NMCFILTER_REGS - 1) - i]; 3393 } else { 3394 hashtab_e = 0; 3395 } 3396 3397 if ((rs = npi_mac_hashtab_entry(handle, OP_SET, portn, i, 3398 (uint16_t *)&hashtab_e)) != NPI_SUCCESS) 3399 goto fail; 3400 } 3401 3402 if (portt == PORT_TYPE_XMAC) { 3403 if ((rs = npi_xmac_rx_iconfig(handle, INIT, portn, 3404 0)) != NPI_SUCCESS) 3405 goto fail; 3406 nxgep->mac.rx_iconfig = NXGE_XMAC_RX_INTRS; 3407 3408 (void) nxge_fflp_init_hostinfo(nxgep); 3409 3410 xconfig = CFG_XMAC_RX_ERRCHK | CFG_XMAC_RX_CRC_CHK | 3411 CFG_XMAC_RX | CFG_XMAC_RX_CODE_VIO_CHK & 3412 ~CFG_XMAC_RX_STRIP_CRC; 3413 3414 if (nxgep->filter.all_phys_cnt != 0) 3415 xconfig |= CFG_XMAC_RX_PROMISCUOUS; 3416 3417 if (nxgep->filter.all_multicast_cnt != 0) 3418 xconfig |= CFG_XMAC_RX_PROMISCUOUSGROUP; 3419 3420 xconfig |= CFG_XMAC_RX_HASH_FILTER; 3421 3422 if ((rs = npi_xmac_rx_config(handle, INIT, portn, 3423 xconfig)) != NPI_SUCCESS) 3424 goto fail; 3425 nxgep->mac.rx_config = xconfig; 3426 3427 /* Comparison of mac unique address is always enabled on XMAC */ 3428 3429 if ((rs = npi_xmac_zap_rx_counters(handle, portn)) 3430 != NPI_SUCCESS) 3431 goto fail; 3432 } else { 3433 (void) nxge_fflp_init_hostinfo(nxgep); 3434 3435 if (npi_bmac_rx_iconfig(nxgep->npi_handle, INIT, portn, 3436 0) != NPI_SUCCESS) 3437 goto fail; 3438 nxgep->mac.rx_iconfig = NXGE_BMAC_RX_INTRS; 3439 3440 bconfig = CFG_BMAC_RX_DISCARD_ON_ERR | CFG_BMAC_RX & 3441 ~CFG_BMAC_RX_STRIP_CRC; 3442 3443 if (nxgep->filter.all_phys_cnt != 0) 3444 bconfig |= CFG_BMAC_RX_PROMISCUOUS; 3445 3446 if (nxgep->filter.all_multicast_cnt != 0) 3447 bconfig |= CFG_BMAC_RX_PROMISCUOUSGROUP; 3448 3449 bconfig |= CFG_BMAC_RX_HASH_FILTER; 3450 if ((rs = npi_bmac_rx_config(handle, INIT, portn, 3451 bconfig)) != NPI_SUCCESS) 3452 goto fail; 3453 nxgep->mac.rx_config = bconfig; 3454 3455 /* Always enable comparison of mac unique address */ 3456 if ((rs = npi_mac_altaddr_enable(handle, portn, 0)) 3457 != NPI_SUCCESS) 3458 goto fail; 3459 } 3460 3461 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_init: port<%d>\n", 3462 portn)); 3463 3464 return (NXGE_OK); 3465 3466 fail: 3467 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3468 "nxge_rx_mac_init: Failed to Initialize port<%d> RxMAC", portn)); 3469 3470 return (NXGE_ERROR | rs); 3471 } 3472 3473 /* Enable TXMAC */ 3474 3475 nxge_status_t 3476 nxge_tx_mac_enable(p_nxge_t nxgep) 3477 { 3478 npi_handle_t handle; 3479 npi_status_t rs = NPI_SUCCESS; 3480 nxge_status_t status = NXGE_OK; 3481 3482 handle = nxgep->npi_handle; 3483 3484 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_enable: port<%d>", 3485 nxgep->mac.portnum)); 3486 3487 if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK) 3488 goto fail; 3489 3490 /* based on speed */ 3491 nxgep->msg_min = ETHERMIN; 3492 3493 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 3494 if ((rs = npi_xmac_tx_config(handle, ENABLE, nxgep->mac.portnum, 3495 CFG_XMAC_TX)) != NPI_SUCCESS) 3496 goto fail; 3497 } else { 3498 if ((rs = npi_bmac_tx_config(handle, ENABLE, nxgep->mac.portnum, 3499 CFG_BMAC_TX)) != NPI_SUCCESS) 3500 goto fail; 3501 } 3502 3503 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_enable: port<%d>", 3504 nxgep->mac.portnum)); 3505 3506 return (NXGE_OK); 3507 fail: 3508 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3509 "nxgep_tx_mac_enable: Failed to enable port<%d> TxMAC", 3510 nxgep->mac.portnum)); 3511 if (rs != NPI_SUCCESS) 3512 return (NXGE_ERROR | rs); 3513 else 3514 return (status); 3515 } 3516 3517 /* Disable TXMAC */ 3518 3519 nxge_status_t 3520 nxge_tx_mac_disable(p_nxge_t nxgep) 3521 { 3522 npi_handle_t handle; 3523 npi_status_t rs = NPI_SUCCESS; 3524 3525 if (isLDOMguest(nxgep)) 3526 return (NXGE_OK); 3527 3528 handle = nxgep->npi_handle; 3529 3530 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_disable: port<%d>", 3531 nxgep->mac.portnum)); 3532 3533 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 3534 if ((rs = npi_xmac_tx_config(handle, DISABLE, 3535 nxgep->mac.portnum, CFG_XMAC_TX)) != NPI_SUCCESS) 3536 goto fail; 3537 } else { 3538 if ((rs = npi_bmac_tx_config(handle, DISABLE, 3539 nxgep->mac.portnum, CFG_BMAC_TX)) != NPI_SUCCESS) 3540 goto fail; 3541 } 3542 3543 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_disable: port<%d>", 3544 nxgep->mac.portnum)); 3545 return (NXGE_OK); 3546 fail: 3547 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3548 "nxge_tx_mac_disable: Failed to disable port<%d> TxMAC", 3549 nxgep->mac.portnum)); 3550 return (NXGE_ERROR | rs); 3551 } 3552 3553 /* Enable RXMAC */ 3554 3555 nxge_status_t 3556 nxge_rx_mac_enable(p_nxge_t nxgep) 3557 { 3558 npi_handle_t handle; 3559 uint8_t portn; 3560 npi_status_t rs = NPI_SUCCESS; 3561 nxge_status_t status = NXGE_OK; 3562 3563 /* This is a service-domain-only activity. */ 3564 if (isLDOMguest(nxgep)) 3565 return (status); 3566 3567 handle = nxgep->npi_handle; 3568 portn = nxgep->mac.portnum; 3569 3570 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_enable: port<%d>", 3571 portn)); 3572 3573 if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK) 3574 goto fail; 3575 3576 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 3577 if ((rs = npi_xmac_rx_config(handle, ENABLE, portn, 3578 CFG_XMAC_RX)) != NPI_SUCCESS) 3579 goto fail; 3580 } else { 3581 if ((rs = npi_bmac_rx_config(handle, ENABLE, portn, 3582 CFG_BMAC_RX)) != NPI_SUCCESS) 3583 goto fail; 3584 } 3585 3586 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3587 "<== nxge_rx_mac_enable: port<%d>", portn)); 3588 3589 return (NXGE_OK); 3590 fail: 3591 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3592 "nxgep_rx_mac_enable: Failed to enable port<%d> RxMAC", portn)); 3593 3594 if (rs != NPI_SUCCESS) 3595 return (NXGE_ERROR | rs); 3596 else 3597 return (status); 3598 } 3599 3600 /* Disable RXMAC */ 3601 3602 nxge_status_t 3603 nxge_rx_mac_disable(p_nxge_t nxgep) 3604 { 3605 npi_handle_t handle; 3606 uint8_t portn; 3607 npi_status_t rs = NPI_SUCCESS; 3608 3609 /* If we are a guest domain driver, don't bother. */ 3610 if (isLDOMguest(nxgep)) 3611 return (NXGE_OK); 3612 3613 handle = nxgep->npi_handle; 3614 portn = nxgep->mac.portnum; 3615 3616 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_disable: port<%d>", 3617 portn)); 3618 3619 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 3620 if ((rs = npi_xmac_rx_config(handle, DISABLE, portn, 3621 CFG_XMAC_RX)) != NPI_SUCCESS) 3622 goto fail; 3623 } else { 3624 if ((rs = npi_bmac_rx_config(handle, DISABLE, portn, 3625 CFG_BMAC_RX)) != NPI_SUCCESS) 3626 goto fail; 3627 } 3628 3629 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_disable: port<%d>", 3630 portn)); 3631 return (NXGE_OK); 3632 fail: 3633 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3634 "nxgep_rx_mac_disable: Failed to disable port<%d> RxMAC", portn)); 3635 3636 return (NXGE_ERROR | rs); 3637 } 3638 3639 /* Reset TXMAC */ 3640 3641 nxge_status_t 3642 nxge_tx_mac_reset(p_nxge_t nxgep) 3643 { 3644 npi_handle_t handle; 3645 uint8_t portn; 3646 npi_status_t rs = NPI_SUCCESS; 3647 3648 handle = nxgep->npi_handle; 3649 portn = nxgep->mac.portnum; 3650 3651 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_reset: port<%d>", 3652 portn)); 3653 3654 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 3655 if ((rs = npi_xmac_reset(handle, portn, XTX_MAC_RESET_ALL)) 3656 != NPI_SUCCESS) 3657 goto fail; 3658 } else { 3659 if ((rs = npi_bmac_reset(handle, portn, TX_MAC_RESET)) 3660 != NPI_SUCCESS) 3661 goto fail; 3662 } 3663 3664 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_reset: port<%d>", 3665 portn)); 3666 3667 return (NXGE_OK); 3668 fail: 3669 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3670 "nxge_tx_mac_reset: Failed to Reset TxMAC port<%d>", portn)); 3671 3672 return (NXGE_ERROR | rs); 3673 } 3674 3675 /* Reset RXMAC */ 3676 3677 nxge_status_t 3678 nxge_rx_mac_reset(p_nxge_t nxgep) 3679 { 3680 npi_handle_t handle; 3681 uint8_t portn; 3682 npi_status_t rs = NPI_SUCCESS; 3683 3684 handle = nxgep->npi_handle; 3685 portn = nxgep->mac.portnum; 3686 3687 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_reset: port<%d>", 3688 portn)); 3689 3690 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 3691 if ((rs = npi_xmac_reset(handle, portn, XRX_MAC_RESET_ALL)) 3692 != NPI_SUCCESS) 3693 goto fail; 3694 } else { 3695 if ((rs = npi_bmac_reset(handle, portn, RX_MAC_RESET)) 3696 != NPI_SUCCESS) 3697 goto fail; 3698 } 3699 3700 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_reset: port<%d>", 3701 portn)); 3702 3703 return (NXGE_OK); 3704 fail: 3705 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3706 "nxge_rx_mac_reset: Failed to Reset RxMAC port<%d>", portn)); 3707 return (NXGE_ERROR | rs); 3708 } 3709 3710 /* 10G fiber link interrupt start routine */ 3711 3712 static nxge_status_t 3713 nxge_10G_link_intr_start(p_nxge_t nxgep) 3714 { 3715 npi_status_t rs = NPI_SUCCESS; 3716 uint8_t portn = nxgep->mac.portnum; 3717 3718 rs = npi_xmac_xpcs_link_intr_enable(nxgep->npi_handle, portn); 3719 3720 if (rs != NPI_SUCCESS) 3721 return (NXGE_ERROR | rs); 3722 else 3723 return (NXGE_OK); 3724 } 3725 3726 /* 10G fiber link interrupt stop routine */ 3727 3728 static nxge_status_t 3729 nxge_10G_link_intr_stop(p_nxge_t nxgep) 3730 { 3731 npi_status_t rs = NPI_SUCCESS; 3732 uint8_t portn = nxgep->mac.portnum; 3733 3734 rs = npi_xmac_xpcs_link_intr_disable(nxgep->npi_handle, portn); 3735 3736 if (rs != NPI_SUCCESS) 3737 return (NXGE_ERROR | rs); 3738 else 3739 return (NXGE_OK); 3740 } 3741 3742 /* 1G fiber link interrupt start routine */ 3743 3744 static nxge_status_t 3745 nxge_1G_fiber_link_intr_start(p_nxge_t nxgep) 3746 { 3747 npi_status_t rs = NPI_SUCCESS; 3748 uint8_t portn = nxgep->mac.portnum; 3749 3750 rs = npi_mac_pcs_link_intr_enable(nxgep->npi_handle, portn); 3751 if (rs != NPI_SUCCESS) 3752 return (NXGE_ERROR | rs); 3753 else 3754 return (NXGE_OK); 3755 } 3756 3757 /* 1G fiber link interrupt stop routine */ 3758 3759 static nxge_status_t 3760 nxge_1G_fiber_link_intr_stop(p_nxge_t nxgep) 3761 { 3762 npi_status_t rs = NPI_SUCCESS; 3763 uint8_t portn = nxgep->mac.portnum; 3764 3765 rs = npi_mac_pcs_link_intr_disable(nxgep->npi_handle, portn); 3766 3767 if (rs != NPI_SUCCESS) 3768 return (NXGE_ERROR | rs); 3769 else 3770 return (NXGE_OK); 3771 } 3772 3773 /* 1G copper link interrupt start routine */ 3774 3775 static nxge_status_t 3776 nxge_1G_copper_link_intr_start(p_nxge_t nxgep) 3777 { 3778 npi_status_t rs = NPI_SUCCESS; 3779 uint8_t portn = nxgep->mac.portnum; 3780 3781 rs = npi_mac_mif_link_intr_enable(nxgep->npi_handle, portn, 3782 MII_STATUS, MII_STATUS_LINKUP); 3783 3784 if (rs != NPI_SUCCESS) 3785 return (NXGE_ERROR | rs); 3786 else 3787 return (NXGE_OK); 3788 } 3789 3790 /* 1G copper link interrupt stop routine */ 3791 3792 static nxge_status_t 3793 nxge_1G_copper_link_intr_stop(p_nxge_t nxgep) 3794 { 3795 npi_status_t rs = NPI_SUCCESS; 3796 uint8_t portn = nxgep->mac.portnum; 3797 3798 rs = npi_mac_mif_link_intr_disable(nxgep->npi_handle, portn); 3799 3800 if (rs != NPI_SUCCESS) 3801 return (NXGE_ERROR | rs); 3802 else 3803 return (NXGE_OK); 3804 } 3805 3806 /* Enable/Disable Link Status change interrupt */ 3807 3808 nxge_status_t 3809 nxge_link_intr(p_nxge_t nxgep, link_intr_enable_t enable) 3810 { 3811 uint8_t portn; 3812 nxge_status_t status = NXGE_OK; 3813 3814 portn = nxgep->mac.portnum; 3815 3816 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_intr: port<%d>", portn)); 3817 if (!nxgep->xcvr.link_intr_stop || !nxgep->xcvr.link_intr_start) 3818 return (NXGE_OK); 3819 3820 if (enable == LINK_INTR_START) 3821 status = nxgep->xcvr.link_intr_start(nxgep); 3822 else if (enable == LINK_INTR_STOP) 3823 status = nxgep->xcvr.link_intr_stop(nxgep); 3824 if (status != NXGE_OK) 3825 goto fail; 3826 3827 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_intr: port<%d>", portn)); 3828 3829 return (NXGE_OK); 3830 fail: 3831 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3832 "nxge_link_intr: Failed to set port<%d> mif intr mode", portn)); 3833 3834 return (status); 3835 } 3836 3837 /* Initialize 1G Fiber / Copper transceiver using Clause 22 */ 3838 3839 nxge_status_t 3840 nxge_mii_xcvr_init(p_nxge_t nxgep) 3841 { 3842 p_nxge_param_t param_arr; 3843 p_nxge_stats_t statsp; 3844 uint8_t xcvr_portn; 3845 p_mii_regs_t mii_regs; 3846 mii_bmcr_t bmcr; 3847 mii_bmsr_t bmsr; 3848 mii_anar_t anar; 3849 mii_gcr_t gcr; 3850 mii_esr_t esr; 3851 mii_aux_ctl_t bcm5464r_aux; 3852 int status = NXGE_OK; 3853 3854 uint_t delay; 3855 3856 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_init")); 3857 3858 param_arr = nxgep->param_arr; 3859 statsp = nxgep->statsp; 3860 xcvr_portn = statsp->mac_stats.xcvr_portn; 3861 3862 mii_regs = NULL; 3863 3864 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3865 "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value)); 3866 3867 /* 3868 * The mif phy mode may be connected to either a copper link 3869 * or fiber link. Read the mode control register to get the fiber 3870 * configuration if it is hard-wired to fiber link. 3871 */ 3872 (void) nxge_mii_get_link_mode(nxgep); 3873 if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) { 3874 return (nxge_mii_xcvr_fiber_init(nxgep)); 3875 } 3876 3877 /* 3878 * Reset the transceiver. 3879 */ 3880 delay = 0; 3881 bmcr.value = 0; 3882 bmcr.bits.reset = 1; 3883 if ((status = nxge_mii_write(nxgep, xcvr_portn, 3884 #if defined(__i386) 3885 (uint8_t)(uint32_t)&mii_regs->bmcr, 3886 #else 3887 (uint8_t)(uint64_t)&mii_regs->bmcr, 3888 #endif 3889 bmcr.value)) != NXGE_OK) 3890 goto fail; 3891 do { 3892 drv_usecwait(500); 3893 if ((status = nxge_mii_read(nxgep, xcvr_portn, 3894 #if defined(__i386) 3895 (uint8_t)(uint32_t)&mii_regs->bmcr, 3896 #else 3897 (uint8_t)(uint64_t)&mii_regs->bmcr, 3898 #endif 3899 &bmcr.value)) != NXGE_OK) 3900 goto fail; 3901 delay++; 3902 } while ((bmcr.bits.reset) && (delay < 1000)); 3903 if (delay == 1000) { 3904 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed.")); 3905 goto fail; 3906 } 3907 3908 if ((status = nxge_mii_read(nxgep, xcvr_portn, 3909 #if defined(__i386) 3910 (uint8_t)(uint32_t)(&mii_regs->bmsr), 3911 #else 3912 (uint8_t)(uint64_t)(&mii_regs->bmsr), 3913 #endif 3914 &bmsr.value)) != NXGE_OK) 3915 goto fail; 3916 3917 param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able; 3918 param_arr[param_anar_100T4].value &= bmsr.bits.link_100T4; 3919 param_arr[param_anar_100fdx].value &= bmsr.bits.link_100fdx; 3920 param_arr[param_anar_100hdx].value = 0; 3921 param_arr[param_anar_10fdx].value &= bmsr.bits.link_10fdx; 3922 param_arr[param_anar_10hdx].value = 0; 3923 3924 /* 3925 * Initialize the xcvr statistics. 3926 */ 3927 statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able; 3928 statsp->mac_stats.cap_100T4 = bmsr.bits.link_100T4; 3929 statsp->mac_stats.cap_100fdx = bmsr.bits.link_100fdx; 3930 statsp->mac_stats.cap_100hdx = 0; 3931 statsp->mac_stats.cap_10fdx = bmsr.bits.link_10fdx; 3932 statsp->mac_stats.cap_10hdx = 0; 3933 statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value; 3934 statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value; 3935 3936 /* 3937 * Initialize the xcvr advertised capability statistics. 3938 */ 3939 statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value; 3940 statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 3941 statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 3942 statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value; 3943 statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value; 3944 statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value; 3945 statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value; 3946 statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value; 3947 statsp->mac_stats.adv_cap_asmpause = 3948 param_arr[param_anar_asmpause].value; 3949 statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value; 3950 3951 3952 /* 3953 * Check for extended status just in case we're 3954 * running a Gigibit phy. 3955 */ 3956 if (bmsr.bits.extend_status) { 3957 if ((status = nxge_mii_read(nxgep, xcvr_portn, 3958 #if defined(__i386) 3959 (uint8_t)(uint32_t)(&mii_regs->esr), 3960 #else 3961 (uint8_t)(uint64_t)(&mii_regs->esr), 3962 #endif 3963 &esr.value)) != NXGE_OK) 3964 goto fail; 3965 param_arr[param_anar_1000fdx].value &= esr.bits.link_1000fdx; 3966 param_arr[param_anar_1000hdx].value = 0; 3967 3968 statsp->mac_stats.cap_1000fdx = 3969 (esr.bits.link_1000Xfdx || esr.bits.link_1000fdx); 3970 statsp->mac_stats.cap_1000hdx = 0; 3971 } else { 3972 param_arr[param_anar_1000fdx].value = 0; 3973 param_arr[param_anar_1000hdx].value = 0; 3974 } 3975 3976 /* 3977 * Initialize 1G Statistics once the capability is established. 3978 */ 3979 statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 3980 statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 3981 3982 /* 3983 * Initialize the link statistics. 3984 */ 3985 statsp->mac_stats.link_T4 = 0; 3986 statsp->mac_stats.link_asmpause = 0; 3987 statsp->mac_stats.link_pause = 0; 3988 statsp->mac_stats.link_speed = 0; 3989 statsp->mac_stats.link_duplex = 0; 3990 statsp->mac_stats.link_up = 0; 3991 3992 /* 3993 * Switch off Auto-negotiation, 100M and full duplex. 3994 */ 3995 bmcr.value = 0; 3996 if ((status = nxge_mii_write(nxgep, xcvr_portn, 3997 #if defined(__i386) 3998 (uint8_t)(uint32_t)(&mii_regs->bmcr), 3999 #else 4000 (uint8_t)(uint64_t)(&mii_regs->bmcr), 4001 #endif 4002 bmcr.value)) != NXGE_OK) 4003 goto fail; 4004 4005 if ((statsp->port_stats.lb_mode == nxge_lb_phy) || 4006 (statsp->port_stats.lb_mode == nxge_lb_phy1000)) { 4007 bmcr.bits.loopback = 1; 4008 bmcr.bits.enable_autoneg = 0; 4009 if (statsp->port_stats.lb_mode == nxge_lb_phy1000) 4010 bmcr.bits.speed_1000_sel = 1; 4011 bmcr.bits.duplex_mode = 1; 4012 param_arr[param_autoneg].value = 0; 4013 } else { 4014 bmcr.bits.loopback = 0; 4015 } 4016 4017 if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) || 4018 (statsp->port_stats.lb_mode == nxge_lb_ext100) || 4019 (statsp->port_stats.lb_mode == nxge_lb_ext10)) { 4020 param_arr[param_autoneg].value = 0; 4021 bcm5464r_aux.value = 0; 4022 bcm5464r_aux.bits.ext_lb = 1; 4023 bcm5464r_aux.bits.write_1 = 1; 4024 if ((status = nxge_mii_write(nxgep, xcvr_portn, 4025 BCM5464R_AUX_CTL, bcm5464r_aux.value)) != NXGE_OK) 4026 goto fail; 4027 } 4028 4029 /* If auto-negotiation is desired */ 4030 if (param_arr[param_autoneg].value) { 4031 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4032 "Restarting Auto-negotiation.")); 4033 /* 4034 * Setup our Auto-negotiation advertisement register. 4035 */ 4036 anar.value = 0; 4037 anar.bits.selector = 1; 4038 anar.bits.cap_100T4 = param_arr[param_anar_100T4].value; 4039 anar.bits.cap_100fdx = param_arr[param_anar_100fdx].value; 4040 anar.bits.cap_100hdx = param_arr[param_anar_100hdx].value; 4041 anar.bits.cap_10fdx = param_arr[param_anar_10fdx].value; 4042 anar.bits.cap_10hdx = param_arr[param_anar_10hdx].value; 4043 anar.bits.cap_asmpause = 0; 4044 anar.bits.cap_pause = 0; 4045 if (param_arr[param_anar_1000fdx].value || 4046 param_arr[param_anar_100fdx].value || 4047 param_arr[param_anar_10fdx].value) { 4048 anar.bits.cap_asmpause = statsp->mac_stats.cap_asmpause; 4049 anar.bits.cap_pause = statsp->mac_stats.cap_pause; 4050 } 4051 4052 /* Write to the auto-negotiation advertisement register */ 4053 if ((status = nxge_mii_write(nxgep, xcvr_portn, 4054 #if defined(__i386) 4055 (uint8_t)(uint32_t)(&mii_regs->anar), 4056 #else 4057 (uint8_t)(uint64_t)(&mii_regs->anar), 4058 #endif 4059 anar.value)) != NXGE_OK) 4060 goto fail; 4061 if (bmsr.bits.extend_status) { 4062 gcr.value = 0; 4063 gcr.bits.ms_mode_en = 4064 param_arr[param_master_cfg_enable].value; 4065 gcr.bits.master = 4066 param_arr[param_master_cfg_value].value; 4067 gcr.bits.link_1000fdx = 4068 param_arr[param_anar_1000fdx].value; 4069 gcr.bits.link_1000hdx = 4070 param_arr[param_anar_1000hdx].value; 4071 if ((status = nxge_mii_write(nxgep, xcvr_portn, 4072 #if defined(__i386) 4073 (uint8_t)(uint32_t)(&mii_regs->gcr), 4074 #else 4075 (uint8_t)(uint64_t)(&mii_regs->gcr), 4076 #endif 4077 gcr.value)) != NXGE_OK) 4078 goto fail; 4079 } 4080 4081 bmcr.bits.enable_autoneg = 1; 4082 bmcr.bits.restart_autoneg = 1; 4083 4084 } else { 4085 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode.")); 4086 bmcr.bits.speed_1000_sel = 4087 param_arr[param_anar_1000fdx].value | 4088 param_arr[param_anar_1000hdx].value; 4089 bmcr.bits.speed_sel = (~bmcr.bits.speed_1000_sel) & 4090 (param_arr[param_anar_100fdx].value | 4091 param_arr[param_anar_100hdx].value); 4092 4093 /* Force to 1G */ 4094 if (bmcr.bits.speed_1000_sel) { 4095 statsp->mac_stats.link_speed = 1000; 4096 gcr.value = 0; 4097 gcr.bits.ms_mode_en = 4098 param_arr[param_master_cfg_enable].value; 4099 gcr.bits.master = 4100 param_arr[param_master_cfg_value].value; 4101 if ((status = nxge_mii_write(nxgep, xcvr_portn, 4102 #if defined(__i386) 4103 (uint8_t)(uint32_t)(&mii_regs->gcr), 4104 #else 4105 (uint8_t)(uint64_t)(&mii_regs->gcr), 4106 #endif 4107 gcr.value)) != NXGE_OK) 4108 goto fail; 4109 if (param_arr[param_anar_1000fdx].value) { 4110 bmcr.bits.duplex_mode = 1; 4111 statsp->mac_stats.link_duplex = 2; 4112 } else 4113 statsp->mac_stats.link_duplex = 1; 4114 4115 /* Force to 100M */ 4116 } else if (bmcr.bits.speed_sel) { 4117 statsp->mac_stats.link_speed = 100; 4118 if (param_arr[param_anar_100fdx].value) { 4119 bmcr.bits.duplex_mode = 1; 4120 statsp->mac_stats.link_duplex = 2; 4121 } else 4122 statsp->mac_stats.link_duplex = 1; 4123 4124 /* Force to 10M */ 4125 } else { 4126 statsp->mac_stats.link_speed = 10; 4127 if (param_arr[param_anar_10fdx].value) { 4128 bmcr.bits.duplex_mode = 1; 4129 statsp->mac_stats.link_duplex = 2; 4130 } else 4131 statsp->mac_stats.link_duplex = 1; 4132 } 4133 if (statsp->mac_stats.link_duplex != 1) { 4134 statsp->mac_stats.link_asmpause = 4135 statsp->mac_stats.cap_asmpause; 4136 statsp->mac_stats.link_pause = 4137 statsp->mac_stats.cap_pause; 4138 } 4139 4140 if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) || 4141 (statsp->port_stats.lb_mode == nxge_lb_ext100) || 4142 (statsp->port_stats.lb_mode == nxge_lb_ext10)) { 4143 if (statsp->port_stats.lb_mode == nxge_lb_ext1000) { 4144 /* BCM5464R 1000mbps external loopback mode */ 4145 gcr.value = 0; 4146 gcr.bits.ms_mode_en = 1; 4147 gcr.bits.master = 1; 4148 if ((status = nxge_mii_write(nxgep, xcvr_portn, 4149 #if defined(__i386) 4150 (uint8_t)(uint32_t)(&mii_regs->gcr), 4151 #else 4152 (uint8_t)(uint64_t)(&mii_regs->gcr), 4153 #endif 4154 gcr.value)) != NXGE_OK) 4155 goto fail; 4156 bmcr.value = 0; 4157 bmcr.bits.speed_1000_sel = 1; 4158 statsp->mac_stats.link_speed = 1000; 4159 } else if (statsp->port_stats.lb_mode 4160 == nxge_lb_ext100) { 4161 /* BCM5464R 100mbps external loopback mode */ 4162 bmcr.value = 0; 4163 bmcr.bits.speed_sel = 1; 4164 bmcr.bits.duplex_mode = 1; 4165 statsp->mac_stats.link_speed = 100; 4166 } else if (statsp->port_stats.lb_mode 4167 == nxge_lb_ext10) { 4168 /* BCM5464R 10mbps external loopback mode */ 4169 bmcr.value = 0; 4170 bmcr.bits.duplex_mode = 1; 4171 statsp->mac_stats.link_speed = 10; 4172 } 4173 } 4174 } 4175 4176 if ((status = nxge_mii_write(nxgep, xcvr_portn, 4177 #if defined(__i386) 4178 (uint8_t)(uint32_t)(&mii_regs->bmcr), 4179 #else 4180 (uint8_t)(uint64_t)(&mii_regs->bmcr), 4181 #endif 4182 bmcr.value)) != NXGE_OK) 4183 goto fail; 4184 4185 if ((status = nxge_mii_read(nxgep, xcvr_portn, 4186 #if defined(__i386) 4187 (uint8_t)(uint32_t)(&mii_regs->bmcr), 4188 #else 4189 (uint8_t)(uint64_t)(&mii_regs->bmcr), 4190 #endif 4191 &bmcr.value)) != NXGE_OK) 4192 goto fail; 4193 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "bmcr = 0x%04X", bmcr.value)); 4194 4195 /* 4196 * Initialize the xcvr status kept in the context structure. 4197 */ 4198 nxgep->soft_bmsr.value = 0; 4199 4200 if ((status = nxge_mii_read(nxgep, xcvr_portn, 4201 #if defined(__i386) 4202 (uint8_t)(uint32_t)(&mii_regs->bmsr), 4203 #else 4204 (uint8_t)(uint64_t)(&mii_regs->bmsr), 4205 #endif 4206 &nxgep->bmsr.value)) != NXGE_OK) 4207 goto fail; 4208 4209 statsp->mac_stats.xcvr_inits++; 4210 nxgep->bmsr.value = 0; 4211 4212 fail: 4213 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4214 "<== nxge_mii_xcvr_init status 0x%x", status)); 4215 return (status); 4216 } 4217 4218 nxge_status_t 4219 nxge_mii_xcvr_fiber_init(p_nxge_t nxgep) 4220 { 4221 p_nxge_param_t param_arr; 4222 p_nxge_stats_t statsp; 4223 uint8_t xcvr_portn; 4224 p_mii_regs_t mii_regs; 4225 mii_bmcr_t bmcr; 4226 mii_bmsr_t bmsr; 4227 mii_gcr_t gcr; 4228 mii_esr_t esr; 4229 mii_aux_ctl_t bcm5464r_aux; 4230 int status = NXGE_OK; 4231 4232 uint_t delay; 4233 4234 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_fiber_init")); 4235 4236 param_arr = nxgep->param_arr; 4237 statsp = nxgep->statsp; 4238 xcvr_portn = statsp->mac_stats.xcvr_portn; 4239 4240 mii_regs = NULL; 4241 4242 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4243 "nxge_mii_xcvr_fiber_init: " 4244 "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value)); 4245 4246 /* 4247 * Reset the transceiver. 4248 */ 4249 delay = 0; 4250 bmcr.value = 0; 4251 bmcr.bits.reset = 1; 4252 4253 #if defined(__i386) 4254 4255 if ((status = nxge_mii_write(nxgep, xcvr_portn, 4256 (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 4257 goto fail; 4258 #else 4259 if ((status = nxge_mii_write(nxgep, xcvr_portn, 4260 (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 4261 goto fail; 4262 #endif 4263 do { 4264 drv_usecwait(500); 4265 #if defined(__i386) 4266 if ((status = nxge_mii_read(nxgep, xcvr_portn, 4267 (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) 4268 != NXGE_OK) 4269 goto fail; 4270 #else 4271 if ((status = nxge_mii_read(nxgep, xcvr_portn, 4272 (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) 4273 != NXGE_OK) 4274 goto fail; 4275 #endif 4276 delay++; 4277 } while ((bmcr.bits.reset) && (delay < 1000)); 4278 if (delay == 1000) { 4279 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed.")); 4280 goto fail; 4281 } 4282 4283 #if defined(__i386) 4284 if ((status = nxge_mii_read(nxgep, xcvr_portn, 4285 (uint8_t)(uint32_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK) 4286 goto fail; 4287 #else 4288 if ((status = nxge_mii_read(nxgep, xcvr_portn, 4289 (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value)) != NXGE_OK) 4290 goto fail; 4291 #endif 4292 4293 param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able; 4294 param_arr[param_anar_100T4].value = 0; 4295 param_arr[param_anar_100fdx].value = 0; 4296 param_arr[param_anar_100hdx].value = 0; 4297 param_arr[param_anar_10fdx].value = 0; 4298 param_arr[param_anar_10hdx].value = 0; 4299 4300 /* 4301 * Initialize the xcvr statistics. 4302 */ 4303 statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able; 4304 statsp->mac_stats.cap_100T4 = 0; 4305 statsp->mac_stats.cap_100fdx = 0; 4306 statsp->mac_stats.cap_100hdx = 0; 4307 statsp->mac_stats.cap_10fdx = 0; 4308 statsp->mac_stats.cap_10hdx = 0; 4309 statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value; 4310 statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value; 4311 4312 /* 4313 * Initialize the xcvr advertised capability statistics. 4314 */ 4315 statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value; 4316 statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 4317 statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 4318 statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value; 4319 statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value; 4320 statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value; 4321 statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value; 4322 statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value; 4323 statsp->mac_stats.adv_cap_asmpause = 4324 param_arr[param_anar_asmpause].value; 4325 statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value; 4326 4327 /* 4328 * Check for extended status just in case we're 4329 * running a Gigibit phy. 4330 */ 4331 if (bmsr.bits.extend_status) { 4332 #if defined(__i386) 4333 if ((status = nxge_mii_read(nxgep, xcvr_portn, 4334 (uint8_t)(uint32_t)(&mii_regs->esr), &esr.value)) != 4335 NXGE_OK) 4336 goto fail; 4337 #else 4338 if ((status = nxge_mii_read(nxgep, xcvr_portn, 4339 (uint8_t)(uint64_t)(&mii_regs->esr), &esr.value)) != 4340 NXGE_OK) 4341 goto fail; 4342 #endif 4343 param_arr[param_anar_1000fdx].value &= 4344 esr.bits.link_1000fdx; 4345 param_arr[param_anar_1000hdx].value = 0; 4346 4347 statsp->mac_stats.cap_1000fdx = 4348 (esr.bits.link_1000Xfdx || esr.bits.link_1000fdx); 4349 statsp->mac_stats.cap_1000hdx = 0; 4350 } else { 4351 param_arr[param_anar_1000fdx].value = 0; 4352 param_arr[param_anar_1000hdx].value = 0; 4353 } 4354 4355 /* 4356 * Initialize 1G Statistics once the capability is established. 4357 */ 4358 statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 4359 statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 4360 4361 /* 4362 * Initialize the link statistics. 4363 */ 4364 statsp->mac_stats.link_T4 = 0; 4365 statsp->mac_stats.link_asmpause = 0; 4366 statsp->mac_stats.link_pause = 0; 4367 statsp->mac_stats.link_speed = 0; 4368 statsp->mac_stats.link_duplex = 0; 4369 statsp->mac_stats.link_up = 0; 4370 4371 /* 4372 * Switch off Auto-negotiation, 100M and full duplex. 4373 */ 4374 bmcr.value = 0; 4375 #if defined(__i386) 4376 if ((status = nxge_mii_write(nxgep, xcvr_portn, 4377 (uint8_t)(uint32_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 4378 goto fail; 4379 #else 4380 if ((status = nxge_mii_write(nxgep, xcvr_portn, 4381 (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 4382 goto fail; 4383 #endif 4384 4385 if ((statsp->port_stats.lb_mode == nxge_lb_phy) || 4386 (statsp->port_stats.lb_mode == nxge_lb_phy1000)) { 4387 bmcr.bits.loopback = 1; 4388 bmcr.bits.enable_autoneg = 0; 4389 if (statsp->port_stats.lb_mode == nxge_lb_phy1000) 4390 bmcr.bits.speed_1000_sel = 1; 4391 bmcr.bits.duplex_mode = 1; 4392 param_arr[param_autoneg].value = 0; 4393 } else { 4394 bmcr.bits.loopback = 0; 4395 } 4396 4397 if (statsp->port_stats.lb_mode == nxge_lb_ext1000) { 4398 param_arr[param_autoneg].value = 0; 4399 bcm5464r_aux.value = 0; 4400 bcm5464r_aux.bits.ext_lb = 1; 4401 bcm5464r_aux.bits.write_1 = 1; 4402 if ((status = nxge_mii_write(nxgep, xcvr_portn, 4403 BCM5464R_AUX_CTL, bcm5464r_aux.value)) != NXGE_OK) 4404 goto fail; 4405 } 4406 4407 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode.")); 4408 bmcr.bits.speed_1000_sel = 1; 4409 bmcr.bits.speed_sel = 0; 4410 bmcr.bits.duplex_mode = 1; 4411 statsp->mac_stats.link_speed = 1000; 4412 statsp->mac_stats.link_duplex = 2; 4413 4414 if ((statsp->port_stats.lb_mode == nxge_lb_ext1000)) { 4415 /* BCM5464R 1000mbps external loopback mode */ 4416 gcr.value = 0; 4417 gcr.bits.ms_mode_en = 1; 4418 gcr.bits.master = 1; 4419 #if defined(__i386) 4420 if ((status = nxge_mii_write(nxgep, xcvr_portn, 4421 (uint8_t)(uint32_t)(&mii_regs->gcr), 4422 gcr.value)) != NXGE_OK) 4423 goto fail; 4424 #else 4425 if ((status = nxge_mii_write(nxgep, xcvr_portn, 4426 (uint8_t)(uint64_t)(&mii_regs->gcr), 4427 gcr.value)) != NXGE_OK) 4428 goto fail; 4429 #endif 4430 bmcr.value = 0; 4431 bmcr.bits.speed_1000_sel = 1; 4432 statsp->mac_stats.link_speed = 1000; 4433 } 4434 4435 #if defined(__i386) 4436 if ((status = nxge_mii_write(nxgep, xcvr_portn, 4437 (uint8_t)(uint32_t)(&mii_regs->bmcr), 4438 bmcr.value)) != NXGE_OK) 4439 goto fail; 4440 #else 4441 if ((status = nxge_mii_write(nxgep, xcvr_portn, 4442 (uint8_t)(uint64_t)(&mii_regs->bmcr), 4443 bmcr.value)) != NXGE_OK) 4444 goto fail; 4445 #endif 4446 4447 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4448 "nxge_mii_xcvr_fiber_init: value wrote bmcr = 0x%x", 4449 bmcr.value)); 4450 4451 #if defined(__i386) 4452 if ((status = nxge_mii_read(nxgep, xcvr_portn, 4453 (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK) 4454 goto fail; 4455 #else 4456 if ((status = nxge_mii_read(nxgep, xcvr_portn, 4457 (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK) 4458 goto fail; 4459 #endif 4460 4461 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4462 "nxge_mii_xcvr_fiber_init: read bmcr = 0x%04X", bmcr.value)); 4463 4464 /* 4465 * Initialize the xcvr status kept in the context structure. 4466 */ 4467 nxgep->soft_bmsr.value = 0; 4468 #if defined(__i386) 4469 if ((status = nxge_mii_read(nxgep, xcvr_portn, 4470 (uint8_t)(uint32_t)(&mii_regs->bmsr), 4471 &nxgep->bmsr.value)) != NXGE_OK) 4472 goto fail; 4473 #else 4474 if ((status = nxge_mii_read(nxgep, xcvr_portn, 4475 (uint8_t)(uint64_t)(&mii_regs->bmsr), 4476 &nxgep->bmsr.value)) != NXGE_OK) 4477 goto fail; 4478 #endif 4479 4480 statsp->mac_stats.xcvr_inits++; 4481 nxgep->bmsr.value = 0; 4482 4483 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4484 "<== nxge_mii_xcvr_fiber_init status 0x%x", status)); 4485 return (status); 4486 4487 fail: 4488 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4489 "<== nxge_mii_xcvr_fiber_init status 0x%x", status)); 4490 return (status); 4491 } 4492 4493 /* Read from a MII compliant register */ 4494 4495 nxge_status_t 4496 nxge_mii_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg, 4497 uint16_t *value) 4498 { 4499 npi_status_t rs = NPI_SUCCESS; 4500 4501 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_read: xcvr_port<%d>" 4502 "xcvr_reg<%d>", xcvr_portn, xcvr_reg)); 4503 4504 MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 4505 4506 if ((nxgep->mac.portmode == PORT_1G_COPPER) || 4507 (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) { 4508 if ((rs = npi_mac_mif_mii_read(nxgep->npi_handle, 4509 xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 4510 goto fail; 4511 } else if ((nxgep->mac.portmode == PORT_1G_FIBER) || 4512 (nxgep->mac.portmode == PORT_1G_SERDES)) { 4513 if ((rs = npi_mac_pcs_mii_read(nxgep->npi_handle, 4514 xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 4515 goto fail; 4516 } else 4517 goto fail; 4518 4519 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 4520 4521 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_read: xcvr_port<%d>" 4522 "xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg, *value)); 4523 return (NXGE_OK); 4524 fail: 4525 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 4526 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4527 "nxge_mii_read: Failed to read mii on xcvr %d", xcvr_portn)); 4528 4529 return (NXGE_ERROR | rs); 4530 } 4531 4532 /* Write to a MII compliant Register */ 4533 4534 nxge_status_t 4535 nxge_mii_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg, 4536 uint16_t value) 4537 { 4538 npi_status_t rs = NPI_SUCCESS; 4539 4540 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_write: xcvr_port<%d>" 4541 "xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg, value)); 4542 4543 MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 4544 4545 if ((nxgep->mac.portmode == PORT_1G_COPPER) || 4546 (nxgep->mac.portmode == PORT_1G_RGMII_FIBER)) { 4547 if ((rs = npi_mac_mif_mii_write(nxgep->npi_handle, 4548 xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 4549 goto fail; 4550 } else if ((nxgep->mac.portmode == PORT_1G_FIBER) || 4551 (nxgep->mac.portmode == PORT_1G_SERDES)) { 4552 if ((rs = npi_mac_pcs_mii_write(nxgep->npi_handle, 4553 xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 4554 goto fail; 4555 } else 4556 goto fail; 4557 4558 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 4559 4560 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_write: xcvr_port<%d>" 4561 "xcvr_reg<%d>", xcvr_portn, xcvr_reg)); 4562 return (NXGE_OK); 4563 fail: 4564 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 4565 4566 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4567 "nxge_mii_write: Failed to write mii on xcvr %d", xcvr_portn)); 4568 4569 return (NXGE_ERROR | rs); 4570 } 4571 4572 /* 4573 * Perform write to Clause45 serdes / transceiver device 4574 * Arguments: 4575 * xcvr_portn: The IEEE 802.3 Clause45 PHYAD, it is the same as port 4576 * number if nxge_mdio_write is used for accessing the 4577 * internal LSIL serdes. Otherwise PHYAD is different 4578 * for different platforms. 4579 * device: With each PHYAD, the driver can use MDIO to control 4580 * multiple devices inside the PHY, here "device" is an 4581 * MMD (MDIO managable device). 4582 * xcvr_reg: Each device has multiple registers. xcvr_reg specifies 4583 * the register which the driver will write value to. 4584 * value: The register value will be filled in. 4585 */ 4586 nxge_status_t 4587 nxge_mdio_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device, 4588 uint16_t xcvr_reg, uint16_t *value) 4589 { 4590 npi_status_t rs = NPI_SUCCESS; 4591 4592 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_read: xcvr_port<%d>", 4593 xcvr_portn)); 4594 4595 MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 4596 4597 if ((rs = npi_mac_mif_mdio_read(nxgep->npi_handle, 4598 xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS) 4599 goto fail; 4600 4601 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 4602 4603 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_read: xcvr_port<%d>", 4604 xcvr_portn)); 4605 return (NXGE_OK); 4606 fail: 4607 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 4608 4609 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4610 "nxge_mdio_read: Failed to read mdio on xcvr %d", xcvr_portn)); 4611 4612 return (NXGE_ERROR | rs); 4613 } 4614 4615 /* Perform write to Clause45 serdes / transceiver device */ 4616 4617 nxge_status_t 4618 nxge_mdio_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device, 4619 uint16_t xcvr_reg, uint16_t value) 4620 { 4621 npi_status_t rs = NPI_SUCCESS; 4622 4623 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_write: xcvr_port<%d>", 4624 xcvr_portn)); 4625 4626 MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 4627 4628 if ((rs = npi_mac_mif_mdio_write(nxgep->npi_handle, 4629 xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS) 4630 goto fail; 4631 4632 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 4633 4634 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_write: xcvr_port<%d>", 4635 xcvr_portn)); 4636 return (NXGE_OK); 4637 fail: 4638 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 4639 4640 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4641 "nxge_mdio_write: Failed to write mdio on xcvr %d", xcvr_portn)); 4642 4643 return (NXGE_ERROR | rs); 4644 } 4645 4646 4647 /* Check MII to see if there is any link status change */ 4648 4649 nxge_status_t 4650 nxge_mii_check(p_nxge_t nxgep, mii_bmsr_t bmsr, mii_bmsr_t bmsr_ints, 4651 nxge_link_state_t *link_up) 4652 { 4653 p_nxge_param_t param_arr; 4654 p_nxge_stats_t statsp; 4655 p_mii_regs_t mii_regs; 4656 p_mii_bmsr_t soft_bmsr; 4657 mii_anar_t anar; 4658 mii_anlpar_t anlpar; 4659 mii_anar_t an_common; 4660 mii_aner_t aner; 4661 mii_gsr_t gsr; 4662 nxge_status_t status = NXGE_OK; 4663 4664 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_check")); 4665 4666 mii_regs = NULL; 4667 param_arr = nxgep->param_arr; 4668 statsp = nxgep->statsp; 4669 soft_bmsr = &nxgep->soft_bmsr; 4670 *link_up = LINK_NO_CHANGE; 4671 4672 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4673 "==> nxge_mii_check bmsr 0x%x bmsr_int 0x%x", 4674 bmsr.value, bmsr_ints.value)); 4675 4676 if (bmsr_ints.bits.link_status) { 4677 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4678 "==> nxge_mii_check (link up) bmsr 0x%x bmsr_int 0x%x", 4679 bmsr.value, bmsr_ints.value)); 4680 if (bmsr.bits.link_status) { 4681 soft_bmsr->bits.link_status = 1; 4682 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4683 "==> nxge_mii_check (link up) soft bmsr 0x%x bmsr_int " 4684 "0x%x", bmsr.value, bmsr_ints.value)); 4685 } else { 4686 statsp->mac_stats.link_up = 0; 4687 soft_bmsr->bits.link_status = 0; 4688 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4689 "Link down cable problem")); 4690 *link_up = LINK_IS_DOWN; 4691 } 4692 } 4693 4694 if (nxgep->mac.portmode == PORT_1G_COPPER && 4695 param_arr[param_autoneg].value) { 4696 if (bmsr_ints.bits.auto_neg_complete) { 4697 if (bmsr.bits.auto_neg_complete) 4698 soft_bmsr->bits.auto_neg_complete = 1; 4699 else 4700 soft_bmsr->bits.auto_neg_complete = 0; 4701 } 4702 if (soft_bmsr->bits.link_status == 0) { 4703 statsp->mac_stats.link_T4 = 0; 4704 statsp->mac_stats.link_speed = 0; 4705 statsp->mac_stats.link_duplex = 0; 4706 statsp->mac_stats.link_asmpause = 0; 4707 statsp->mac_stats.link_pause = 0; 4708 statsp->mac_stats.lp_cap_autoneg = 0; 4709 statsp->mac_stats.lp_cap_100T4 = 0; 4710 statsp->mac_stats.lp_cap_1000fdx = 0; 4711 statsp->mac_stats.lp_cap_1000hdx = 0; 4712 statsp->mac_stats.lp_cap_100fdx = 0; 4713 statsp->mac_stats.lp_cap_100hdx = 0; 4714 statsp->mac_stats.lp_cap_10fdx = 0; 4715 statsp->mac_stats.lp_cap_10hdx = 0; 4716 statsp->mac_stats.lp_cap_10gfdx = 0; 4717 statsp->mac_stats.lp_cap_10ghdx = 0; 4718 statsp->mac_stats.lp_cap_asmpause = 0; 4719 statsp->mac_stats.lp_cap_pause = 0; 4720 } 4721 } else 4722 soft_bmsr->bits.auto_neg_complete = 1; 4723 4724 if ((bmsr_ints.bits.link_status || 4725 bmsr_ints.bits.auto_neg_complete) && 4726 soft_bmsr->bits.link_status && 4727 soft_bmsr->bits.auto_neg_complete) { 4728 statsp->mac_stats.link_up = 1; 4729 4730 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4731 "==> nxge_mii_check " 4732 "(auto negotiation complete or link up) " 4733 "soft bmsr 0x%x bmsr_int 0x%x", 4734 bmsr.value, bmsr_ints.value)); 4735 4736 if (nxgep->mac.portmode == PORT_1G_COPPER && 4737 param_arr[param_autoneg].value) { 4738 if ((status = nxge_mii_read(nxgep, 4739 statsp->mac_stats.xcvr_portn, 4740 #if defined(__i386) 4741 (uint8_t)(uint32_t)(&mii_regs->anar), 4742 #else 4743 (uint8_t)(uint64_t)(&mii_regs->anar), 4744 #endif 4745 &anar.value)) != NXGE_OK) 4746 goto fail; 4747 if ((status = nxge_mii_read(nxgep, 4748 statsp->mac_stats.xcvr_portn, 4749 #if defined(__i386) 4750 (uint8_t)(uint32_t)(&mii_regs->anlpar), 4751 #else 4752 (uint8_t)(uint64_t)(&mii_regs->anlpar), 4753 #endif 4754 &anlpar.value)) != NXGE_OK) 4755 goto fail; 4756 if ((status = nxge_mii_read(nxgep, 4757 statsp->mac_stats.xcvr_portn, 4758 #if defined(__i386) 4759 (uint8_t)(uint32_t)(&mii_regs->aner), 4760 #else 4761 (uint8_t)(uint64_t)(&mii_regs->aner), 4762 #endif 4763 &aner.value)) != NXGE_OK) 4764 goto fail; 4765 statsp->mac_stats.lp_cap_autoneg = aner.bits.lp_an_able; 4766 statsp->mac_stats.lp_cap_100T4 = anlpar.bits.cap_100T4; 4767 statsp->mac_stats.lp_cap_100fdx = 4768 anlpar.bits.cap_100fdx; 4769 statsp->mac_stats.lp_cap_100hdx = 4770 anlpar.bits.cap_100hdx; 4771 statsp->mac_stats.lp_cap_10fdx = anlpar.bits.cap_10fdx; 4772 statsp->mac_stats.lp_cap_10hdx = anlpar.bits.cap_10hdx; 4773 statsp->mac_stats.lp_cap_asmpause = 4774 anlpar.bits.cap_asmpause; 4775 statsp->mac_stats.lp_cap_pause = anlpar.bits.cap_pause; 4776 an_common.value = anar.value & anlpar.value; 4777 if (param_arr[param_anar_1000fdx].value || 4778 param_arr[param_anar_1000hdx].value) { 4779 if ((status = nxge_mii_read(nxgep, 4780 statsp->mac_stats.xcvr_portn, 4781 #if defined(__i386) 4782 (uint8_t)(uint32_t)(&mii_regs->gsr), 4783 #else 4784 (uint8_t)(uint64_t)(&mii_regs->gsr), 4785 #endif 4786 &gsr.value)) != NXGE_OK) 4787 goto fail; 4788 statsp->mac_stats.lp_cap_1000fdx = 4789 gsr.bits.link_1000fdx; 4790 statsp->mac_stats.lp_cap_1000hdx = 4791 gsr.bits.link_1000hdx; 4792 if (param_arr[param_anar_1000fdx].value && 4793 gsr.bits.link_1000fdx) { 4794 statsp->mac_stats.link_speed = 1000; 4795 statsp->mac_stats.link_duplex = 2; 4796 } else if ( 4797 param_arr[param_anar_1000hdx].value && 4798 gsr.bits.link_1000hdx) { 4799 statsp->mac_stats.link_speed = 1000; 4800 statsp->mac_stats.link_duplex = 1; 4801 } 4802 } 4803 if ((an_common.value != 0) && 4804 !(statsp->mac_stats.link_speed)) { 4805 if (an_common.bits.cap_100T4) { 4806 statsp->mac_stats.link_T4 = 1; 4807 statsp->mac_stats.link_speed = 100; 4808 statsp->mac_stats.link_duplex = 1; 4809 } else if (an_common.bits.cap_100fdx) { 4810 statsp->mac_stats.link_speed = 100; 4811 statsp->mac_stats.link_duplex = 2; 4812 } else if (an_common.bits.cap_100hdx) { 4813 statsp->mac_stats.link_speed = 100; 4814 statsp->mac_stats.link_duplex = 1; 4815 } else if (an_common.bits.cap_10fdx) { 4816 statsp->mac_stats.link_speed = 10; 4817 statsp->mac_stats.link_duplex = 2; 4818 } else if (an_common.bits.cap_10hdx) { 4819 statsp->mac_stats.link_speed = 10; 4820 statsp->mac_stats.link_duplex = 1; 4821 } else { 4822 goto fail; 4823 } 4824 } 4825 if (statsp->mac_stats.link_duplex != 1) { 4826 int link_pause; 4827 int cp, lcp; 4828 4829 statsp->mac_stats.link_asmpause = 4830 an_common.bits.cap_asmpause; 4831 cp = statsp->mac_stats.cap_pause; 4832 lcp = statsp->mac_stats.lp_cap_pause; 4833 if (statsp->mac_stats.link_asmpause) { 4834 if ((cp == 0) && (lcp == 1)) { 4835 link_pause = 0; 4836 } else { 4837 link_pause = 1; 4838 } 4839 } else { 4840 link_pause = an_common.bits.cap_pause; 4841 } 4842 statsp->mac_stats.link_pause = link_pause; 4843 } 4844 } else if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) { 4845 statsp->mac_stats.link_speed = 1000; 4846 statsp->mac_stats.link_duplex = 2; 4847 } 4848 *link_up = LINK_IS_UP; 4849 } 4850 4851 if (nxgep->link_notify) { 4852 *link_up = ((statsp->mac_stats.link_up) ? LINK_IS_UP : 4853 LINK_IS_DOWN); 4854 nxgep->link_notify = B_FALSE; 4855 } 4856 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mii_check")); 4857 return (NXGE_OK); 4858 fail: 4859 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4860 "nxge_mii_check: Unable to check MII")); 4861 return (status); 4862 } 4863 4864 /* 4865 * Check PCS to see if there is any link status change. 4866 * This function is called by PORT_1G_SERDES only. 4867 */ 4868 void 4869 nxge_pcs_check(p_nxge_t nxgep, uint8_t portn, nxge_link_state_t *link_up) 4870 { 4871 p_nxge_stats_t statsp; 4872 boolean_t linkup; 4873 4874 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_check")); 4875 4876 statsp = nxgep->statsp; 4877 *link_up = LINK_NO_CHANGE; 4878 4879 (void) npi_mac_get_link_status(nxgep->npi_handle, portn, &linkup); 4880 if (linkup) { 4881 if (nxgep->link_notify || 4882 nxgep->statsp->mac_stats.link_up == 0) { 4883 statsp->mac_stats.link_up = 1; 4884 statsp->mac_stats.link_speed = 1000; 4885 statsp->mac_stats.link_duplex = 2; 4886 *link_up = LINK_IS_UP; 4887 nxgep->link_notify = B_FALSE; 4888 } 4889 } else { 4890 if (nxgep->link_notify || 4891 nxgep->statsp->mac_stats.link_up == 1) { 4892 statsp->mac_stats.link_up = 0; 4893 statsp->mac_stats.link_speed = 0; 4894 statsp->mac_stats.link_duplex = 0; 4895 *link_up = LINK_IS_DOWN; 4896 nxgep->link_notify = B_FALSE; 4897 } 4898 } 4899 4900 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_check")); 4901 } 4902 4903 /* Add a multicast address entry into the HW hash table */ 4904 4905 nxge_status_t 4906 nxge_add_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp) 4907 { 4908 uint32_t mchash; 4909 p_hash_filter_t hash_filter; 4910 uint16_t hash_bit; 4911 boolean_t rx_init = B_FALSE; 4912 uint_t j; 4913 nxge_status_t status = NXGE_OK; 4914 4915 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_add_mcast_addr")); 4916 4917 RW_ENTER_WRITER(&nxgep->filter_lock); 4918 mchash = crc32_mchash(addrp); 4919 if (nxgep->hash_filter == NULL) { 4920 NXGE_DEBUG_MSG((NULL, STR_CTL, 4921 "Allocating hash filter storage.")); 4922 nxgep->hash_filter = KMEM_ZALLOC(sizeof (hash_filter_t), 4923 KM_SLEEP); 4924 } 4925 hash_filter = nxgep->hash_filter; 4926 j = mchash / HASH_REG_WIDTH; 4927 hash_bit = (1 << (mchash % HASH_REG_WIDTH)); 4928 hash_filter->hash_filter_regs[j] |= hash_bit; 4929 hash_filter->hash_bit_ref_cnt[mchash]++; 4930 if (hash_filter->hash_bit_ref_cnt[mchash] == 1) { 4931 hash_filter->hash_ref_cnt++; 4932 rx_init = B_TRUE; 4933 } 4934 if (rx_init) { 4935 if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 4936 goto fail; 4937 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 4938 goto fail; 4939 } 4940 4941 RW_EXIT(&nxgep->filter_lock); 4942 4943 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_add_mcast_addr")); 4944 4945 return (NXGE_OK); 4946 fail: 4947 RW_EXIT(&nxgep->filter_lock); 4948 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_add_mcast_addr: " 4949 "Unable to add multicast address")); 4950 return (status); 4951 } 4952 4953 /* Remove a multicast address entry from the HW hash table */ 4954 4955 nxge_status_t 4956 nxge_del_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp) 4957 { 4958 uint32_t mchash; 4959 p_hash_filter_t hash_filter; 4960 uint16_t hash_bit; 4961 boolean_t rx_init = B_FALSE; 4962 uint_t j; 4963 nxge_status_t status = NXGE_OK; 4964 4965 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_del_mcast_addr")); 4966 RW_ENTER_WRITER(&nxgep->filter_lock); 4967 mchash = crc32_mchash(addrp); 4968 if (nxgep->hash_filter == NULL) { 4969 NXGE_DEBUG_MSG((NULL, STR_CTL, 4970 "Hash filter already de_allocated.")); 4971 RW_EXIT(&nxgep->filter_lock); 4972 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr")); 4973 return (NXGE_OK); 4974 } 4975 hash_filter = nxgep->hash_filter; 4976 hash_filter->hash_bit_ref_cnt[mchash]--; 4977 if (hash_filter->hash_bit_ref_cnt[mchash] == 0) { 4978 j = mchash / HASH_REG_WIDTH; 4979 hash_bit = (1 << (mchash % HASH_REG_WIDTH)); 4980 hash_filter->hash_filter_regs[j] &= ~hash_bit; 4981 hash_filter->hash_ref_cnt--; 4982 rx_init = B_TRUE; 4983 } 4984 if (hash_filter->hash_ref_cnt == 0) { 4985 NXGE_DEBUG_MSG((NULL, STR_CTL, 4986 "De-allocating hash filter storage.")); 4987 KMEM_FREE(hash_filter, sizeof (hash_filter_t)); 4988 nxgep->hash_filter = NULL; 4989 } 4990 4991 if (rx_init) { 4992 if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 4993 goto fail; 4994 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 4995 goto fail; 4996 } 4997 RW_EXIT(&nxgep->filter_lock); 4998 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr")); 4999 5000 return (NXGE_OK); 5001 fail: 5002 RW_EXIT(&nxgep->filter_lock); 5003 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_del_mcast_addr: " 5004 "Unable to remove multicast address")); 5005 5006 return (status); 5007 } 5008 5009 /* Set MAC address into MAC address HW registers */ 5010 5011 nxge_status_t 5012 nxge_set_mac_addr(p_nxge_t nxgep, struct ether_addr *addrp) 5013 { 5014 nxge_status_t status = NXGE_OK; 5015 5016 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_mac_addr")); 5017 5018 MUTEX_ENTER(&nxgep->ouraddr_lock); 5019 /* 5020 * Exit if the address is same as ouraddr or multicast or broadcast 5021 */ 5022 if (((addrp->ether_addr_octet[0] & 01) == 1) || 5023 (ether_cmp(addrp, ðerbroadcastaddr) == 0) || 5024 (ether_cmp(addrp, &nxgep->ouraddr) == 0)) { 5025 goto nxge_set_mac_addr_exit; 5026 } 5027 nxgep->ouraddr = *addrp; 5028 /* 5029 * Set new interface local address and re-init device. 5030 * This is destructive to any other streams attached 5031 * to this device. 5032 */ 5033 RW_ENTER_WRITER(&nxgep->filter_lock); 5034 if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 5035 goto fail; 5036 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 5037 goto fail; 5038 5039 RW_EXIT(&nxgep->filter_lock); 5040 MUTEX_EXIT(&nxgep->ouraddr_lock); 5041 goto nxge_set_mac_addr_end; 5042 nxge_set_mac_addr_exit: 5043 MUTEX_EXIT(&nxgep->ouraddr_lock); 5044 nxge_set_mac_addr_end: 5045 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_mac_addr")); 5046 5047 return (NXGE_OK); 5048 fail: 5049 MUTEX_EXIT(&nxgep->ouraddr_lock); 5050 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_mac_addr: " 5051 "Unable to set mac address")); 5052 return (status); 5053 } 5054 5055 static 5056 check_link_state_t 5057 nxge_check_link_stop(nxge_t *nxge) 5058 { 5059 /* If the poll has been cancelled, return STOP. */ 5060 MUTEX_ENTER(&nxge->poll_lock); 5061 if (nxge->suspended || nxge->poll_state == LINK_MONITOR_STOPPING) { 5062 nxge->poll_state = LINK_MONITOR_STOP; 5063 nxge->nxge_link_poll_timerid = 0; 5064 cv_broadcast(&nxge->poll_cv); 5065 MUTEX_EXIT(&nxge->poll_lock); 5066 5067 NXGE_DEBUG_MSG((nxge, MAC_CTL, 5068 "nxge_check_%s_link(port<%d>) stopped.", 5069 nxge->mac.portmode == PORT_10G_FIBER ? "10g" : "mii", 5070 nxge->mac.portnum)); 5071 return (CHECK_LINK_STOP); 5072 } 5073 MUTEX_EXIT(&nxge->poll_lock); 5074 5075 return (CHECK_LINK_RESCHEDULE); 5076 } 5077 5078 /* 5079 * Check status of MII (MIF or PCS) link. 5080 * This function is called once per second, that is because this function 5081 * calls nxge_link_monitor with LINK_MONITOR_START, which starts a timer to 5082 * call this function recursively. 5083 */ 5084 static nxge_status_t 5085 nxge_check_mii_link(p_nxge_t nxgep) 5086 { 5087 mii_bmsr_t bmsr_ints, bmsr_data; 5088 mii_anlpar_t anlpar; 5089 mii_gsr_t gsr; 5090 p_mii_regs_t mii_regs; 5091 nxge_status_t status = NXGE_OK; 5092 uint8_t portn; 5093 nxge_link_state_t link_up; 5094 5095 if (nxgep->nxge_magic != NXGE_MAGIC) 5096 return (NXGE_ERROR); 5097 5098 if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 5099 return (NXGE_OK); 5100 5101 portn = nxgep->mac.portnum; 5102 5103 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_mii_link port<%d>", 5104 portn)); 5105 5106 mii_regs = NULL; 5107 5108 RW_ENTER_WRITER(&nxgep->filter_lock); 5109 5110 if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10) 5111 goto nxge_check_mii_link_exit; 5112 5113 switch (nxgep->mac.portmode) { 5114 default: 5115 bmsr_data.value = 0; 5116 if ((status = nxge_mii_read(nxgep, 5117 nxgep->statsp->mac_stats.xcvr_portn, 5118 #if defined(__i386) 5119 (uint8_t)(uint32_t)(&mii_regs->bmsr), 5120 #else 5121 (uint8_t)(uint64_t)(&mii_regs->bmsr), 5122 #endif 5123 &bmsr_data.value)) != NXGE_OK) { 5124 goto fail; 5125 } 5126 5127 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5128 "==> nxge_check_mii_link port<0x%x> " 5129 "RIGHT AFTER READ bmsr_data 0x%x (nxgep->bmsr 0x%x ", 5130 portn, bmsr_data.value, nxgep->bmsr.value)); 5131 5132 if (nxgep->param_arr[param_autoneg].value) { 5133 if ((status = nxge_mii_read(nxgep, 5134 nxgep->statsp->mac_stats.xcvr_portn, 5135 #if defined(__i386) 5136 (uint8_t)(uint32_t)(&mii_regs->gsr), 5137 #else 5138 (uint8_t)(uint64_t)(&mii_regs->gsr), 5139 #endif 5140 &gsr.value)) != NXGE_OK) 5141 goto fail; 5142 if ((status = nxge_mii_read(nxgep, 5143 nxgep->statsp->mac_stats.xcvr_portn, 5144 #if defined(__i386) 5145 (uint8_t)(uint32_t)(&mii_regs->anlpar), 5146 #else 5147 (uint8_t)(uint64_t)(&mii_regs->anlpar), 5148 #endif 5149 &anlpar.value)) != NXGE_OK) 5150 goto fail; 5151 if (nxgep->mac.portmode != PORT_1G_RGMII_FIBER) { 5152 5153 if (nxgep->statsp->mac_stats.link_up && 5154 ((nxgep->statsp->mac_stats.lp_cap_1000fdx ^ 5155 gsr.bits.link_1000fdx) || 5156 (nxgep->statsp->mac_stats.lp_cap_1000hdx ^ 5157 gsr.bits.link_1000hdx) || 5158 (nxgep->statsp->mac_stats.lp_cap_100T4 ^ 5159 anlpar.bits.cap_100T4) || 5160 (nxgep->statsp->mac_stats.lp_cap_100fdx ^ 5161 anlpar.bits.cap_100fdx) || 5162 (nxgep->statsp->mac_stats.lp_cap_100hdx ^ 5163 anlpar.bits.cap_100hdx) || 5164 (nxgep->statsp->mac_stats.lp_cap_10fdx ^ 5165 anlpar.bits.cap_10fdx) || 5166 (nxgep->statsp->mac_stats.lp_cap_10hdx ^ 5167 anlpar.bits.cap_10hdx))) { 5168 bmsr_data.bits.link_status = 0; 5169 } 5170 } 5171 } 5172 5173 /* Workaround for link down issue */ 5174 if (bmsr_data.value == 0) { 5175 cmn_err(CE_NOTE, "!LINK DEBUG: Read zero bmsr\n"); 5176 goto nxge_check_mii_link_exit; 5177 } 5178 5179 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5180 "==> nxge_check_mii_link port<0x%x> :" 5181 "BEFORE BMSR ^ nxgep->bmsr 0x%x bmsr_data 0x%x", 5182 portn, nxgep->bmsr.value, bmsr_data.value)); 5183 5184 bmsr_ints.value = nxgep->bmsr.value ^ bmsr_data.value; 5185 nxgep->bmsr.value = bmsr_data.value; 5186 5187 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5188 "==> nxge_check_mii_link port<0x%x> CALLING " 5189 "bmsr_data 0x%x bmsr_ints.value 0x%x", 5190 portn, bmsr_data.value, bmsr_ints.value)); 5191 5192 if ((status = nxge_mii_check(nxgep, bmsr_data, bmsr_ints, 5193 &link_up)) != NXGE_OK) { 5194 goto fail; 5195 } 5196 break; 5197 5198 case PORT_1G_SERDES: 5199 /* 5200 * Above default is for all cases except PORT_1G_SERDES. 5201 * The default case gets information from the PHY, but a 5202 * nxge whose portmode equals PORT_1G_SERDES does not 5203 * have a PHY. 5204 */ 5205 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5206 "==> nxge_check_mii_link port<%d> (SERDES)", portn)); 5207 nxge_pcs_check(nxgep, portn, &link_up); 5208 break; 5209 } 5210 5211 nxge_check_mii_link_exit: 5212 RW_EXIT(&nxgep->filter_lock); 5213 if (link_up == LINK_IS_UP) { 5214 nxge_link_is_up(nxgep); 5215 } else if (link_up == LINK_IS_DOWN) { 5216 nxge_link_is_down(nxgep); 5217 } 5218 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 5219 5220 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_mii_link port<%d>", 5221 portn)); 5222 return (NXGE_OK); 5223 5224 fail: 5225 RW_EXIT(&nxgep->filter_lock); 5226 5227 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 5228 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5229 "nxge_check_mii_link: Failed to check link port<%d>", portn)); 5230 return (status); 5231 } 5232 5233 /*ARGSUSED*/ 5234 static nxge_status_t 5235 nxge_check_10g_link(p_nxge_t nxgep) 5236 { 5237 uint8_t portn; 5238 nxge_status_t status = NXGE_OK; 5239 boolean_t link_up; 5240 uint32_t val; 5241 npi_status_t rs; 5242 5243 if (nxgep->nxge_magic != NXGE_MAGIC) 5244 return (NXGE_ERROR); 5245 5246 if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 5247 return (NXGE_OK); 5248 5249 portn = nxgep->mac.portnum; 5250 val = 0; 5251 rs = NPI_SUCCESS; 5252 5253 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_10g_link port<%d>", 5254 portn)); 5255 5256 switch (nxgep->mac.portmode) { 5257 default: 5258 /* 5259 * Check if the phy is present in case of hot swappable phy 5260 */ 5261 if (nxgep->hot_swappable_phy) { 5262 boolean_t phy_present_now = B_FALSE; 5263 5264 /* 5265 * If this is the 2nd Goa port, then check 2 addresses 5266 * to take care of the Goa NEM card requirements. 5267 */ 5268 if (portn == 1) { 5269 if (nxge_is_phy_present(nxgep, 5270 ALT_GOA_CLAUSE45_PORT1_ADDR, 5271 BCM8706_DEV_ID, BCM_PHY_ID_MASK)) { 5272 phy_present_now = B_TRUE; 5273 nxgep->xcvr_addr = 5274 ALT_GOA_CLAUSE45_PORT1_ADDR; 5275 goto phy_check_done; 5276 } 5277 } 5278 if (nxge_is_phy_present(nxgep, 5279 (GOA_CLAUSE45_PORT_ADDR_BASE) + portn, 5280 BCM8706_DEV_ID, BCM_PHY_ID_MASK)) { 5281 nxgep->xcvr_addr = 5282 (GOA_CLAUSE45_PORT_ADDR_BASE) + portn; 5283 phy_present_now = B_TRUE; 5284 } 5285 5286 phy_check_done: 5287 /* Check back-to-back XAUI connect to detect Opus NEM */ 5288 rs = npi_xmac_xpcs_read(nxgep->npi_handle, 5289 nxgep->mac.portnum, XPCS_REG_STATUS, &val); 5290 if (rs != 0) 5291 goto fail; 5292 5293 link_up = B_FALSE; 5294 if (val & XPCS_STATUS_LANE_ALIGN) { 5295 link_up = B_TRUE; 5296 } 5297 5298 if (nxgep->phy_absent) { 5299 if (phy_present_now) { 5300 /* 5301 * Detect, Initialize phy and do link up 5302 * set xcvr vals, link_init, nxge_init 5303 */ 5304 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5305 "Hot swappable phy DETECTED!!")); 5306 nxgep->phy_absent = B_FALSE; 5307 (void) nxge_xcvr_find(nxgep); 5308 (void) nxge_link_init(nxgep); 5309 if (!(nxgep->drv_state & 5310 STATE_HW_INITIALIZED)) { 5311 status = nxge_init(nxgep); 5312 if (status != NXGE_OK) { 5313 NXGE_ERROR_MSG((nxgep, 5314 NXGE_ERR_CTL, 5315 "Hot swappable " 5316 "phy present, but" 5317 " driver init" 5318 " failed...")); 5319 goto fail; 5320 } 5321 } 5322 } else if (link_up) { /* XAUI linkup, no PHY */ 5323 /* 5324 * This is the back-to-back XAUI 5325 * connect case for Opus NEM. 5326 */ 5327 nxgep->statsp->mac_stats.xcvr_inuse = 5328 XPCS_XCVR; 5329 nxgep->mac.portmode = PORT_10G_SERDES; 5330 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5331 "HSP 10G Serdes DETECTED!!")); 5332 break; 5333 } 5334 5335 goto start_link_check; 5336 5337 } else if (!phy_present_now) { 5338 /* 5339 * Phy gone, bring link down reset xcvr vals 5340 */ 5341 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5342 "Hot swappable phy REMOVED!!")); 5343 nxgep->phy_absent = B_TRUE; 5344 nxgep->statsp->mac_stats.link_up = 0; 5345 nxgep->statsp->mac_stats.link_speed = 0; 5346 nxgep->statsp->mac_stats.link_duplex = 0; 5347 nxge_link_is_down(nxgep); 5348 nxgep->link_notify = B_FALSE; 5349 5350 (void) nxge_xcvr_find(nxgep); 5351 5352 goto start_link_check; 5353 5354 } 5355 } 5356 if (nxgep->chip_id == MRVL88X201X_CHIP_ID) { 5357 status = nxge_check_mrvl88x2011_link(nxgep, &link_up); 5358 } else { 5359 status = nxge_check_bcm8704_link(nxgep, &link_up); 5360 } 5361 if (status != NXGE_OK) 5362 goto fail; 5363 break; 5364 case PORT_10G_SERDES: 5365 rs = npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 5366 XPCS_REG_STATUS, &val); 5367 if (rs != 0) 5368 goto fail; 5369 5370 link_up = B_FALSE; 5371 if (val & XPCS_STATUS_LANE_ALIGN) { 5372 link_up = B_TRUE; 5373 } 5374 5375 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5376 "==> nxge_check_10g_link port<%d> " 5377 "XPCS_REG_STATUS2 0x%x link_up %d", 5378 portn, val, link_up)); 5379 5380 break; 5381 } 5382 5383 if (link_up) { 5384 if (nxgep->link_notify || 5385 nxgep->statsp->mac_stats.link_up == 0) { 5386 if (nxge_10g_link_led_on(nxgep) != NXGE_OK) 5387 goto fail; 5388 nxgep->statsp->mac_stats.link_up = 1; 5389 nxgep->statsp->mac_stats.link_speed = 10000; 5390 nxgep->statsp->mac_stats.link_duplex = 2; 5391 5392 nxge_link_is_up(nxgep); 5393 nxgep->link_notify = B_FALSE; 5394 } 5395 } else { 5396 if (nxgep->link_notify || 5397 nxgep->statsp->mac_stats.link_up == 1) { 5398 if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 5399 goto fail; 5400 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5401 "Link down cable problem")); 5402 nxgep->statsp->mac_stats.link_up = 0; 5403 nxgep->statsp->mac_stats.link_speed = 0; 5404 nxgep->statsp->mac_stats.link_duplex = 0; 5405 5406 nxge_link_is_down(nxgep); 5407 nxgep->link_notify = B_FALSE; 5408 5409 if (nxgep->mac.portmode == PORT_10G_SERDES) { 5410 /* 5411 * NEM was unplugged, set up xcvr table 5412 * to find another xcvr in the future. 5413 */ 5414 (void) nxge_xcvr_find(nxgep); 5415 } 5416 } 5417 } 5418 5419 start_link_check: 5420 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 5421 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_10g_link port<%d>", 5422 portn)); 5423 return (NXGE_OK); 5424 5425 fail: 5426 (void) nxge_check_link_stop(nxgep); 5427 5428 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5429 "nxge_check_10g_link: Failed to check link port<%d>", 5430 portn)); 5431 return (status); 5432 } 5433 5434 5435 /* Declare link down */ 5436 5437 void 5438 nxge_link_is_down(p_nxge_t nxgep) 5439 { 5440 p_nxge_stats_t statsp; 5441 char link_stat_msg[64]; 5442 5443 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_down")); 5444 5445 statsp = nxgep->statsp; 5446 (void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is down", 5447 statsp->mac_stats.xcvr_portn); 5448 5449 if (nxge_no_msg == B_FALSE) { 5450 NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg)); 5451 } 5452 5453 mac_link_update(nxgep->mach, LINK_STATE_DOWN); 5454 5455 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_down")); 5456 } 5457 5458 /* Declare link up */ 5459 5460 void 5461 nxge_link_is_up(p_nxge_t nxgep) 5462 { 5463 p_nxge_stats_t statsp; 5464 char link_stat_msg[64]; 5465 uint32_t val; 5466 5467 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_up")); 5468 5469 statsp = nxgep->statsp; 5470 (void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is up %d Mbps ", 5471 statsp->mac_stats.xcvr_portn, 5472 statsp->mac_stats.link_speed); 5473 5474 if (statsp->mac_stats.link_T4) 5475 (void) strcat(link_stat_msg, "T4"); 5476 else if (statsp->mac_stats.link_duplex == 2) 5477 (void) strcat(link_stat_msg, "full duplex"); 5478 else 5479 (void) strcat(link_stat_msg, "half duplex"); 5480 5481 5482 /* Clean up symbol errors incurred during link transition */ 5483 if ((nxgep->mac.portmode == PORT_10G_FIBER) || 5484 (nxgep->mac.portmode == PORT_10G_SERDES)) { 5485 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 5486 XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val); 5487 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 5488 XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val); 5489 } 5490 5491 /* 5492 * If the driver was plumbed without a link (therefore auto-negotiation 5493 * could not complete), the driver will detect a link up when a cable 5494 * conneting to a link partner is plugged into the port. By the time 5495 * link-up is detected, auto-negotiation should have completed (The 5496 * TN1010 tries to contact a link partner every 8~24ms). Here we re- 5497 * configure the Neptune/NIU according to the newly negotiated speed. 5498 * This is necessary only for the TN1010 basad device because only the 5499 * TN1010 supports dual speeds. 5500 */ 5501 if (nxgep->mac.portmode == PORT_1G_TN1010 || 5502 nxgep->mac.portmode == PORT_10G_TN1010) { 5503 5504 (void) nxge_set_tn1010_param(nxgep); 5505 5506 /* 5507 * nxge_xcvr_find calls nxge_get_xcvr_type (which sets 5508 * nxgep->portmode) and nxge_setup_xcvr_table (which sets 5509 * the nxgep->xcvr to the proper nxge_xcvr_table_t struct). 5510 */ 5511 if (nxge_xcvr_find(nxgep) != NXGE_OK) { 5512 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5513 "nxge_link_is_up: nxge_xcvr_find failed")); 5514 } 5515 5516 /* nxge_link_init calls nxge_xcvr_init and nxge_serdes_init */ 5517 if (nxge_link_init(nxgep) != NXGE_OK) { 5518 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5519 "nxge_link_is_up: nxge_link_init failed")); 5520 } 5521 5522 /* 5523 * nxge_mac_init calls many subroutines including 5524 * nxge_xif_init which sets XGMII or GMII mode 5525 */ 5526 if (nxge_mac_init(nxgep) != NXGE_OK) { 5527 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5528 "nxge_link_is_up: nxge_mac_init failed")); 5529 } 5530 } else { 5531 (void) nxge_xif_init(nxgep); 5532 } 5533 5534 if (nxge_no_msg == B_FALSE) { 5535 NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg)); 5536 } 5537 5538 mac_link_update(nxgep->mach, LINK_STATE_UP); 5539 5540 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_up")); 5541 } 5542 5543 #ifdef NXGE_DEBUG 5544 /* Dump all TN1010 Status registers */ 5545 static void 5546 nxge_dump_tn1010_status_regs(p_nxge_t nxgep) 5547 { 5548 uint16_t val; 5549 5550 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 5551 TN1010_PMA_PMD_DEV_ADDR, 1, &val); 5552 cmn_err(CE_NOTE, "PMA status1 = 0x%x", val); 5553 5554 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 5555 TN1010_PMA_PMD_DEV_ADDR, 8, &val); 5556 cmn_err(CE_NOTE, "PMA status2 = 0x%x", val); 5557 5558 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 5559 TN1010_PMA_PMD_DEV_ADDR, 129, &val); 5560 cmn_err(CE_NOTE, "10BASET-T status = 0x%x", val); 5561 5562 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 5563 TN1010_PCS_DEV_ADDR, 1, &val); 5564 cmn_err(CE_NOTE, "PCS status1 = 0x%x", val); 5565 5566 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 5567 TN1010_PCS_DEV_ADDR, 8, &val); 5568 cmn_err(CE_NOTE, "PCS status2 = 0x%x", val); 5569 5570 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 5571 TN1010_PCS_DEV_ADDR, 32, &val); 5572 cmn_err(CE_NOTE, "10GBASE-R status1 = 0x%x", val); 5573 5574 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 5575 TN1010_PCS_DEV_ADDR, 33, &val); 5576 cmn_err(CE_NOTE, "10GBASE-R Status2 = 0x%x", val); 5577 5578 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 5579 TN1010_PHYXS_DEV_ADDR, 1, &val); 5580 cmn_err(CE_NOTE, "PHYXS status1 = 0x%x", val); 5581 5582 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 5583 TN1010_PHYXS_DEV_ADDR, 8, &val); 5584 cmn_err(CE_NOTE, "PHYXS status2 = 0x%x", val); 5585 5586 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 5587 TN1010_PHYXS_DEV_ADDR, 24, &val); 5588 cmn_err(CE_NOTE, "XGXS Lane status = 0x%x", val); 5589 5590 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 5591 TN1010_AUTONEG_DEV_ADDR, 1, &val); 5592 cmn_err(CE_NOTE, "Autoneg status = 0x%x", val); 5593 5594 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 5595 TN1010_AUTONEG_DEV_ADDR, 33, &val); 5596 cmn_err(CE_NOTE, "10Gbase-T An status = 0x%x", val); 5597 5598 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 5599 TN1010_VENDOR_MMD1_DEV_ADDR, 1, &val); 5600 cmn_err(CE_NOTE, "TN1010 status = 0x%x", val); 5601 5602 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 5603 TN1010_VENDOR_MMD1_DEV_ADDR, 8, &val); 5604 cmn_err(CE_NOTE, "Device status = 0x%x", val); 5605 5606 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 5607 TN1010_VENDOR_MMD1_DEV_ADDR, 16, &val); 5608 cmn_err(CE_NOTE, "DDR status = 0x%x", val); 5609 5610 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 5611 TN1010_VENDOR_MMD1_DEV_ADDR, 17, &val); 5612 cmn_err(CE_NOTE, "DDR fault status = 0x%x", val); 5613 5614 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 5615 TN1010_VENDOR_MMD1_DEV_ADDR, 11, &val); 5616 cmn_err(CE_NOTE, "Firmware Revision = 0x%x Major = 0x%x Minor = 0x%x", 5617 val, (val & 0xFF00) >> 8, val & 0x00FF); 5618 } 5619 #endif 5620 5621 /* 5622 * Calculate the bit in the multicast address filter 5623 * that selects the given * address. 5624 * Note: For GEM, the last 8-bits are used. 5625 */ 5626 uint32_t 5627 crc32_mchash(p_ether_addr_t addr) 5628 { 5629 uint8_t *cp; 5630 uint32_t crc; 5631 uint32_t c; 5632 int byte; 5633 int bit; 5634 5635 cp = (uint8_t *)addr; 5636 crc = (uint32_t)0xffffffff; 5637 for (byte = 0; byte < 6; byte++) { 5638 c = (uint32_t)cp[byte]; 5639 for (bit = 0; bit < 8; bit++) { 5640 if ((c & 0x1) ^ (crc & 0x1)) 5641 crc = (crc >> 1)^0xedb88320; 5642 else 5643 crc = (crc >> 1); 5644 c >>= 1; 5645 } 5646 } 5647 return ((~crc) >> (32 - HASH_BITS)); 5648 } 5649 5650 /* Reset serdes */ 5651 5652 nxge_status_t 5653 nxge_serdes_reset(p_nxge_t nxgep) 5654 { 5655 npi_handle_t handle; 5656 5657 handle = nxgep->npi_handle; 5658 5659 ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0 | ESR_RESET_1); 5660 drv_usecwait(500); 5661 ESR_REG_WR(handle, ESR_CONFIG_REG, 0); 5662 5663 return (NXGE_OK); 5664 } 5665 5666 /* 5667 * This function monitors link status using interrupt or polling. 5668 * It calls nxgep->xcvr.check_link, a member function of 5669 * nxge_xcvr_table_t. But nxgep->xcvr.check_link calls this 5670 * function back, that is why the check_link routine is 5671 * executed periodically. 5672 */ 5673 nxge_status_t 5674 nxge_link_monitor(p_nxge_t nxgep, link_mon_enable_t enable) 5675 { 5676 nxge_status_t status = NXGE_OK; 5677 5678 /* If we are a guest domain driver, don't bother. */ 5679 if (isLDOMguest(nxgep)) 5680 return (status); 5681 5682 /* 5683 * Return immediately if this is an imaginary XMAC port. 5684 * (At least, we don't have 4-port XMAC cards yet.) 5685 */ 5686 if ((nxgep->mac.portmode == PORT_10G_FIBER || 5687 nxgep->mac.portmode == PORT_10G_SERDES) && 5688 (nxgep->mac.portnum > 1)) 5689 return (NXGE_OK); 5690 5691 if (nxgep->statsp == NULL) { 5692 /* stats has not been allocated. */ 5693 return (NXGE_OK); 5694 } 5695 /* Don't check link if we're in internal loopback mode */ 5696 if (nxgep->statsp->port_stats.lb_mode >= nxge_lb_serdes10g) 5697 return (NXGE_OK); 5698 5699 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5700 "==> nxge_link_monitor port<%d> enable=%d", 5701 nxgep->mac.portnum, enable)); 5702 if (enable == LINK_MONITOR_START) { 5703 if (nxgep->mac.linkchkmode == LINKCHK_INTR) { 5704 if ((status = nxge_link_intr(nxgep, LINK_INTR_START)) 5705 != NXGE_OK) 5706 goto fail; 5707 } else { 5708 timeout_id_t timerid; 5709 /* 5710 * check_link_stop means "Stop the link check", so 5711 * we return without starting the timer. 5712 */ 5713 if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 5714 return (NXGE_OK); 5715 5716 /* 5717 * Otherwise fire the timer for the nxge to check 5718 * the link using the check_link function 5719 * of the nxge_xcvr_table and pass "nxgep" as the 5720 * argument to the check_link function. 5721 */ 5722 if (nxgep->xcvr.check_link) { 5723 timerid = timeout( 5724 (fptrv_t)(nxgep->xcvr.check_link), 5725 nxgep, 5726 drv_usectohz(LINK_MONITOR_PERIOD)); 5727 MUTEX_ENTER(&nxgep->poll_lock); 5728 nxgep->nxge_link_poll_timerid = timerid; 5729 MUTEX_EXIT(&nxgep->poll_lock); 5730 } else { 5731 return (NXGE_ERROR); 5732 } 5733 } 5734 } else { 5735 if (nxgep->mac.linkchkmode == LINKCHK_INTR) { 5736 if ((status = nxge_link_intr(nxgep, LINK_INTR_STOP)) 5737 != NXGE_OK) 5738 goto fail; 5739 } else { 5740 clock_t rv; 5741 5742 MUTEX_ENTER(&nxgep->poll_lock); 5743 5744 /* If <timerid> == 0, the link monitor has */ 5745 /* never been started, or just now stopped. */ 5746 if (nxgep->nxge_link_poll_timerid == 0) { 5747 MUTEX_EXIT(&nxgep->poll_lock); 5748 return (NXGE_OK); 5749 } 5750 5751 nxgep->poll_state = LINK_MONITOR_STOPPING; 5752 rv = cv_reltimedwait(&nxgep->poll_cv, &nxgep->poll_lock, 5753 drv_usectohz(LM_WAIT_MULTIPLIER * 5754 LINK_MONITOR_PERIOD), TR_CLOCK_TICK); 5755 if (rv == -1) { 5756 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5757 "==> stopping port %d: " 5758 "cv_timedwait(%d) timed out", 5759 nxgep->mac.portnum, nxgep->poll_state)); 5760 nxgep->poll_state = LINK_MONITOR_STOP; 5761 nxgep->nxge_link_poll_timerid = 0; 5762 } 5763 5764 MUTEX_EXIT(&nxgep->poll_lock); 5765 } 5766 } 5767 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5768 "<== nxge_link_monitor port<%d> enable=%d", 5769 nxgep->mac.portnum, enable)); 5770 5771 return (NXGE_OK); 5772 fail: 5773 return (status); 5774 5775 } 5776 5777 nxge_status_t 5778 nxge_check_tn1010_link(p_nxge_t nxgep) 5779 { 5780 nxge_status_t status = NXGE_OK; 5781 nxge_link_state_t link_up; 5782 5783 if (nxgep->nxge_magic != NXGE_MAGIC) { 5784 /* magic is 0 if driver is not attached */ 5785 return (NXGE_ERROR); 5786 } 5787 5788 /* Link has been stopped, no need to continue */ 5789 if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) { 5790 return (NXGE_OK); 5791 } 5792 5793 if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10) 5794 goto nxge_check_tn1010_link_exit; 5795 5796 if ((status = nxge_tn1010_check(nxgep, &link_up)) != NXGE_OK) 5797 goto fail; 5798 5799 nxge_check_tn1010_link_exit: 5800 if (link_up == LINK_IS_UP) 5801 nxge_link_is_up(nxgep); 5802 else if (link_up == LINK_IS_DOWN) 5803 nxge_link_is_down(nxgep); 5804 5805 /* 5806 * nxge_link_monitor will call (nxgep->xcvr.check_link) 5807 * which could be THIS function. 5808 */ 5809 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 5810 5811 return (NXGE_OK); 5812 5813 fail: 5814 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 5815 5816 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5817 "nxge_check_tn1010_link: Failed to check link")); 5818 return (status); 5819 } 5820 5821 5822 /* 5823 * Fill variable "link_up" with either LINK_IS_UP or LINK_IS_DOWN. 5824 */ 5825 static nxge_status_t 5826 nxge_tn1010_check(p_nxge_t nxgep, nxge_link_state_t *link_up) 5827 { 5828 nxge_status_t status = NXGE_OK; 5829 p_nxge_stats_t statsp; 5830 uint8_t phy_port_addr, portn; 5831 uint16_t val; 5832 5833 *link_up = LINK_NO_CHANGE; 5834 5835 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 5836 phy_port_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 5837 statsp = nxgep->statsp; 5838 5839 /* Check if link is up */ 5840 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 5841 TN1010_AUTONEG_DEV_ADDR, TN1010_AUTONEG_STATUS_REG, &val)) 5842 != NXGE_OK) { 5843 goto fail; 5844 } 5845 /* 5846 * nxge_link_is_up has called nxge_set_tn1010_param and set 5847 * portmode and link_speed 5848 */ 5849 if (val & TN1010_AN_LINK_STAT_BIT) { 5850 if (nxgep->link_notify || 5851 nxgep->statsp->mac_stats.link_up == 0) { 5852 statsp->mac_stats.link_up = 1; 5853 statsp->mac_stats.link_duplex = 2; 5854 *link_up = LINK_IS_UP; 5855 nxgep->link_notify = B_FALSE; 5856 } 5857 } else { 5858 if (nxgep->link_notify || 5859 nxgep->statsp->mac_stats.link_up == 1) { 5860 statsp->mac_stats.link_up = 0; 5861 statsp->mac_stats.link_speed = 0; 5862 statsp->mac_stats.link_duplex = 0; 5863 *link_up = LINK_IS_DOWN; 5864 nxgep->link_notify = B_FALSE; 5865 } 5866 } 5867 return (NXGE_OK); 5868 5869 fail: 5870 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5871 "nxge_tn1010_check: Unable to check TN1010")); 5872 return (status); 5873 } 5874 5875 5876 /* Set promiscous mode */ 5877 5878 nxge_status_t 5879 nxge_set_promisc(p_nxge_t nxgep, boolean_t on) 5880 { 5881 nxge_status_t status = NXGE_OK; 5882 5883 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_promisc: on %d", on)); 5884 5885 nxgep->filter.all_phys_cnt = ((on) ? 1 : 0); 5886 5887 RW_ENTER_WRITER(&nxgep->filter_lock); 5888 5889 if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) { 5890 goto fail; 5891 } 5892 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) { 5893 goto fail; 5894 } 5895 5896 RW_EXIT(&nxgep->filter_lock); 5897 5898 if (on) 5899 nxgep->statsp->mac_stats.promisc = B_TRUE; 5900 else 5901 nxgep->statsp->mac_stats.promisc = B_FALSE; 5902 5903 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_promisc")); 5904 5905 return (NXGE_OK); 5906 fail: 5907 RW_EXIT(&nxgep->filter_lock); 5908 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_promisc: " 5909 "Unable to set promisc (%d)", on)); 5910 5911 return (status); 5912 } 5913 5914 /*ARGSUSED*/ 5915 uint_t 5916 nxge_mif_intr(void *arg1, void *arg2) 5917 { 5918 #ifdef NXGE_DEBUG 5919 p_nxge_t nxgep = (p_nxge_t)arg2; 5920 #endif 5921 #if NXGE_MIF 5922 p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1; 5923 uint32_t status; 5924 npi_handle_t handle; 5925 uint8_t portn; 5926 p_nxge_stats_t statsp; 5927 #endif 5928 5929 #ifdef NXGE_MIF 5930 if (arg2 == NULL || (void *)ldvp->nxgep != arg2) { 5931 nxgep = ldvp->nxgep; 5932 } 5933 nxgep = ldvp->nxgep; 5934 #endif 5935 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mif_intr")); 5936 5937 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr")); 5938 return (DDI_INTR_CLAIMED); 5939 5940 mif_intr_fail: 5941 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr")); 5942 return (DDI_INTR_UNCLAIMED); 5943 } 5944 5945 /*ARGSUSED*/ 5946 uint_t 5947 nxge_mac_intr(void *arg1, void *arg2) 5948 { 5949 p_nxge_t nxgep = (p_nxge_t)arg2; 5950 p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1; 5951 p_nxge_ldg_t ldgp; 5952 uint32_t status; 5953 npi_handle_t handle; 5954 uint8_t portn; 5955 p_nxge_stats_t statsp; 5956 npi_status_t rs = NPI_SUCCESS; 5957 5958 if (arg2 == NULL || (void *)ldvp->nxgep != arg2) { 5959 nxgep = ldvp->nxgep; 5960 } 5961 5962 ldgp = ldvp->ldgp; 5963 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mac_intr: " 5964 "group %d", ldgp->ldg)); 5965 5966 handle = NXGE_DEV_NPI_HANDLE(nxgep); 5967 /* 5968 * This interrupt handler is for a specific 5969 * mac port. 5970 */ 5971 statsp = (p_nxge_stats_t)nxgep->statsp; 5972 portn = nxgep->mac.portnum; 5973 5974 NXGE_DEBUG_MSG((nxgep, INT_CTL, 5975 "==> nxge_mac_intr: reading mac stats: port<%d>", portn)); 5976 5977 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 5978 rs = npi_xmac_tx_get_istatus(handle, portn, 5979 (xmac_tx_iconfig_t *)&status); 5980 if (rs != NPI_SUCCESS) 5981 goto npi_fail; 5982 if (status & ICFG_XMAC_TX_ALL) { 5983 if (status & ICFG_XMAC_TX_UNDERRUN) { 5984 statsp->xmac_stats.tx_underflow_err++; 5985 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 5986 NXGE_FM_EREPORT_TXMAC_UNDERFLOW); 5987 } 5988 if (status & ICFG_XMAC_TX_MAX_PACKET_ERR) { 5989 statsp->xmac_stats.tx_maxpktsize_err++; 5990 /* 5991 * Do not send FMA ereport because this 5992 * error does not indicate HW failure. 5993 */ 5994 } 5995 if (status & ICFG_XMAC_TX_OVERFLOW) { 5996 statsp->xmac_stats.tx_overflow_err++; 5997 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 5998 NXGE_FM_EREPORT_TXMAC_OVERFLOW); 5999 } 6000 if (status & ICFG_XMAC_TX_FIFO_XFR_ERR) { 6001 statsp->xmac_stats.tx_fifo_xfr_err++; 6002 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 6003 NXGE_FM_EREPORT_TXMAC_TXFIFO_XFR_ERR); 6004 } 6005 if (status & ICFG_XMAC_TX_BYTE_CNT_EXP) { 6006 statsp->xmac_stats.tx_byte_cnt += 6007 XTXMAC_BYTE_CNT_MASK; 6008 } 6009 if (status & ICFG_XMAC_TX_FRAME_CNT_EXP) { 6010 statsp->xmac_stats.tx_frame_cnt += 6011 XTXMAC_FRM_CNT_MASK; 6012 } 6013 } 6014 6015 rs = npi_xmac_rx_get_istatus(handle, portn, 6016 (xmac_rx_iconfig_t *)&status); 6017 if (rs != NPI_SUCCESS) 6018 goto npi_fail; 6019 if (status & ICFG_XMAC_RX_ALL) { 6020 if (status & ICFG_XMAC_RX_OVERFLOW) 6021 statsp->xmac_stats.rx_overflow_err++; 6022 if (status & ICFG_XMAC_RX_UNDERFLOW) { 6023 statsp->xmac_stats.rx_underflow_err++; 6024 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 6025 NXGE_FM_EREPORT_RXMAC_UNDERFLOW); 6026 } 6027 /* 6028 * Do not send FMA ereport for the following 3 errors 6029 * because they do not indicate HW failures. 6030 */ 6031 if (status & ICFG_XMAC_RX_CRC_ERR_CNT_EXP) { 6032 statsp->xmac_stats.rx_crc_err_cnt += 6033 XRXMAC_CRC_ER_CNT_MASK; 6034 } 6035 if (status & ICFG_XMAC_RX_LEN_ERR_CNT_EXP) { 6036 statsp->xmac_stats.rx_len_err_cnt += 6037 MAC_LEN_ER_CNT_MASK; 6038 } 6039 if (status & ICFG_XMAC_RX_VIOL_ERR_CNT_EXP) { 6040 statsp->xmac_stats.rx_viol_err_cnt += 6041 XRXMAC_CD_VIO_CNT_MASK; 6042 } 6043 if (status & ICFG_XMAC_RX_OCT_CNT_EXP) { 6044 statsp->xmac_stats.rx_byte_cnt += 6045 XRXMAC_BT_CNT_MASK; 6046 } 6047 if (status & ICFG_XMAC_RX_HST_CNT1_EXP) { 6048 statsp->xmac_stats.rx_hist1_cnt += 6049 XRXMAC_HIST_CNT1_MASK; 6050 } 6051 if (status & ICFG_XMAC_RX_HST_CNT2_EXP) { 6052 statsp->xmac_stats.rx_hist2_cnt += 6053 XRXMAC_HIST_CNT2_MASK; 6054 } 6055 if (status & ICFG_XMAC_RX_HST_CNT3_EXP) { 6056 statsp->xmac_stats.rx_hist3_cnt += 6057 XRXMAC_HIST_CNT3_MASK; 6058 } 6059 if (status & ICFG_XMAC_RX_HST_CNT4_EXP) { 6060 statsp->xmac_stats.rx_hist4_cnt += 6061 XRXMAC_HIST_CNT4_MASK; 6062 } 6063 if (status & ICFG_XMAC_RX_HST_CNT5_EXP) { 6064 statsp->xmac_stats.rx_hist5_cnt += 6065 XRXMAC_HIST_CNT5_MASK; 6066 } 6067 if (status & ICFG_XMAC_RX_HST_CNT6_EXP) { 6068 statsp->xmac_stats.rx_hist6_cnt += 6069 XRXMAC_HIST_CNT6_MASK; 6070 } 6071 if (status & ICFG_XMAC_RX_BCAST_CNT_EXP) { 6072 statsp->xmac_stats.rx_broadcast_cnt += 6073 XRXMAC_BC_FRM_CNT_MASK; 6074 } 6075 if (status & ICFG_XMAC_RX_MCAST_CNT_EXP) { 6076 statsp->xmac_stats.rx_mult_cnt += 6077 XRXMAC_MC_FRM_CNT_MASK; 6078 } 6079 /* 6080 * Do not send FMA ereport for the following 3 errors 6081 * because they do not indicate HW failures. 6082 */ 6083 if (status & ICFG_XMAC_RX_FRAG_CNT_EXP) { 6084 statsp->xmac_stats.rx_frag_cnt += 6085 XRXMAC_FRAG_CNT_MASK; 6086 } 6087 if (status & ICFG_XMAC_RX_ALIGNERR_CNT_EXP) { 6088 statsp->xmac_stats.rx_frame_align_err_cnt += 6089 XRXMAC_AL_ER_CNT_MASK; 6090 } 6091 if (status & ICFG_XMAC_RX_LINK_FLT_CNT_EXP) { 6092 statsp->xmac_stats.rx_linkfault_err_cnt += 6093 XMAC_LINK_FLT_CNT_MASK; 6094 } 6095 if (status & ICFG_XMAC_RX_REMOTE_FLT_DET) { 6096 statsp->xmac_stats.rx_remotefault_err++; 6097 } 6098 if (status & ICFG_XMAC_RX_LOCAL_FLT_DET) { 6099 statsp->xmac_stats.rx_localfault_err++; 6100 } 6101 } 6102 6103 rs = npi_xmac_ctl_get_istatus(handle, portn, 6104 (xmac_ctl_iconfig_t *)&status); 6105 if (rs != NPI_SUCCESS) 6106 goto npi_fail; 6107 if (status & ICFG_XMAC_CTRL_ALL) { 6108 if (status & ICFG_XMAC_CTRL_PAUSE_RCVD) 6109 statsp->xmac_stats.rx_pause_cnt++; 6110 if (status & ICFG_XMAC_CTRL_PAUSE_STATE) 6111 statsp->xmac_stats.tx_pause_state++; 6112 if (status & ICFG_XMAC_CTRL_NOPAUSE_STATE) 6113 statsp->xmac_stats.tx_nopause_state++; 6114 } 6115 } else if (nxgep->mac.porttype == PORT_TYPE_BMAC) { 6116 rs = npi_bmac_tx_get_istatus(handle, portn, 6117 (bmac_tx_iconfig_t *)&status); 6118 if (rs != NPI_SUCCESS) 6119 goto npi_fail; 6120 if (status & ICFG_BMAC_TX_ALL) { 6121 if (status & ICFG_BMAC_TX_UNDERFLOW) { 6122 statsp->bmac_stats.tx_underrun_err++; 6123 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 6124 NXGE_FM_EREPORT_TXMAC_UNDERFLOW); 6125 } 6126 if (status & ICFG_BMAC_TX_MAXPKTSZ_ERR) { 6127 statsp->bmac_stats.tx_max_pkt_err++; 6128 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 6129 NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR); 6130 } 6131 if (status & ICFG_BMAC_TX_BYTE_CNT_EXP) { 6132 statsp->bmac_stats.tx_byte_cnt += 6133 BTXMAC_BYTE_CNT_MASK; 6134 } 6135 if (status & ICFG_BMAC_TX_FRAME_CNT_EXP) { 6136 statsp->bmac_stats.tx_frame_cnt += 6137 BTXMAC_FRM_CNT_MASK; 6138 } 6139 } 6140 6141 rs = npi_bmac_rx_get_istatus(handle, portn, 6142 (bmac_rx_iconfig_t *)&status); 6143 if (rs != NPI_SUCCESS) 6144 goto npi_fail; 6145 if (status & ICFG_BMAC_RX_ALL) { 6146 if (status & ICFG_BMAC_RX_OVERFLOW) { 6147 statsp->bmac_stats.rx_overflow_err++; 6148 } 6149 if (status & ICFG_BMAC_RX_FRAME_CNT_EXP) { 6150 statsp->bmac_stats.rx_frame_cnt += 6151 RXMAC_FRM_CNT_MASK; 6152 } 6153 if (status & ICFG_BMAC_RX_CRC_ERR_CNT_EXP) { 6154 statsp->bmac_stats.rx_crc_err_cnt += 6155 BMAC_CRC_ER_CNT_MASK; 6156 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 6157 NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP); 6158 } 6159 if (status & ICFG_BMAC_RX_LEN_ERR_CNT_EXP) { 6160 statsp->bmac_stats.rx_len_err_cnt += 6161 MAC_LEN_ER_CNT_MASK; 6162 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 6163 NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP); 6164 } 6165 if (status & ICFG_BMAC_RX_VIOL_ERR_CNT_EXP) 6166 statsp->bmac_stats.rx_viol_err_cnt += 6167 BMAC_CD_VIO_CNT_MASK; 6168 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 6169 NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP); 6170 } 6171 if (status & ICFG_BMAC_RX_BYTE_CNT_EXP) { 6172 statsp->bmac_stats.rx_byte_cnt += 6173 BRXMAC_BYTE_CNT_MASK; 6174 } 6175 if (status & ICFG_BMAC_RX_ALIGNERR_CNT_EXP) { 6176 statsp->bmac_stats.rx_align_err_cnt += 6177 BMAC_AL_ER_CNT_MASK; 6178 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 6179 NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP); 6180 } 6181 6182 rs = npi_bmac_ctl_get_istatus(handle, portn, 6183 (bmac_ctl_iconfig_t *)&status); 6184 if (rs != NPI_SUCCESS) 6185 goto npi_fail; 6186 6187 if (status & ICFG_BMAC_CTL_ALL) { 6188 if (status & ICFG_BMAC_CTL_RCVPAUSE) 6189 statsp->bmac_stats.rx_pause_cnt++; 6190 if (status & ICFG_BMAC_CTL_INPAUSE_ST) 6191 statsp->bmac_stats.tx_pause_state++; 6192 if (status & ICFG_BMAC_CTL_INNOTPAUSE_ST) 6193 statsp->bmac_stats.tx_nopause_state++; 6194 } 6195 } 6196 6197 if (ldgp->nldvs == 1) { 6198 (void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg, 6199 B_TRUE, ldgp->ldg_timer); 6200 } 6201 6202 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mac_intr")); 6203 return (DDI_INTR_CLAIMED); 6204 6205 npi_fail: 6206 NXGE_ERROR_MSG((nxgep, INT_CTL, "<== nxge_mac_intr")); 6207 return (DDI_INTR_UNCLAIMED); 6208 } 6209 6210 nxge_status_t 6211 nxge_check_bcm8704_link(p_nxge_t nxgep, boolean_t *link_up) 6212 { 6213 uint8_t phy_port_addr; 6214 nxge_status_t status = NXGE_OK; 6215 boolean_t rx_sig_ok; 6216 boolean_t pcs_blk_lock; 6217 boolean_t link_align; 6218 uint16_t val1, val2, val3; 6219 #ifdef NXGE_DEBUG_SYMBOL_ERR 6220 uint16_t val_debug; 6221 uint32_t val; 6222 #endif 6223 6224 phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn; 6225 6226 #ifdef NXGE_DEBUG_SYMBOL_ERR 6227 /* Check Device 3 Register Device 3 0xC809 */ 6228 (void) nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0xC809, &val_debug); 6229 if ((val_debug & ~0x200) != 0) { 6230 cmn_err(CE_NOTE, "!Port%d BCM8704 Dev3 Reg 0xc809 = 0x%x\n", 6231 nxgep->mac.portnum, val_debug); 6232 (void) nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, 6233 &val_debug); 6234 cmn_err(CE_NOTE, "!Port%d BCM8704 Dev4 Reg 0x18 = 0x%x\n", 6235 nxgep->mac.portnum, val_debug); 6236 } 6237 6238 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 6239 XPCS_REG_DESCWERR_COUNTER, &val); 6240 if (val != 0) 6241 cmn_err(CE_NOTE, "!XPCS DESCWERR = 0x%x\n", val); 6242 6243 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 6244 XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val); 6245 if (val != 0) 6246 cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L0_1 = 0x%x\n", val); 6247 6248 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 6249 XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val); 6250 if (val != 0) 6251 cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L2_3 = 0x%x\n", val); 6252 #endif 6253 6254 /* Check from BCM8704 if 10G link is up or down */ 6255 6256 /* Check Device 1 Register 0xA bit0 */ 6257 status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PMA_PMD_DEV_ADDR, 6258 BCM8704_PMD_RECEIVE_SIG_DETECT, &val1); 6259 if (status != NXGE_OK) 6260 goto fail; 6261 rx_sig_ok = ((val1 & GLOB_PMD_RX_SIG_OK) ? B_TRUE : B_FALSE); 6262 6263 /* Check Device 3 Register 0x20 bit0 */ 6264 if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PCS_DEV_ADDR, 6265 BCM8704_10GBASE_R_PCS_STATUS_REG, &val2)) != NPI_SUCCESS) 6266 goto fail; 6267 pcs_blk_lock = ((val2 & PCS_10GBASE_R_PCS_BLK_LOCK) ? B_TRUE : B_FALSE); 6268 6269 /* Check Device 4 Register 0x18 bit12 */ 6270 status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 6271 BCM8704_PHYXS_XGXS_LANE_STATUS_REG, &val3); 6272 if (status != NXGE_OK) 6273 goto fail; 6274 6275 switch (nxgep->chip_id) { 6276 case BCM8704_CHIP_ID: 6277 link_align = (val3 == (XGXS_LANE_ALIGN_STATUS | 6278 XGXS_LANE3_SYNC | XGXS_LANE2_SYNC | XGXS_LANE1_SYNC | 6279 XGXS_LANE0_SYNC | 0x400)) ? B_TRUE : B_FALSE; 6280 break; 6281 case BCM8706_CHIP_ID: 6282 link_align = ((val3 & XGXS_LANE_ALIGN_STATUS) && 6283 (val3 & XGXS_LANE3_SYNC) && (val3 & XGXS_LANE2_SYNC) && 6284 (val3 & XGXS_LANE1_SYNC) && (val3 & XGXS_LANE0_SYNC)) ? 6285 B_TRUE : B_FALSE; 6286 break; 6287 default: 6288 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_check_bcm8704_link:" 6289 "Unknown chip ID [0x%x]", nxgep->chip_id)); 6290 goto fail; 6291 } 6292 6293 #ifdef NXGE_DEBUG_ALIGN_ERR 6294 /* Temp workaround for link down issue */ 6295 if (pcs_blk_lock == B_FALSE) { 6296 if (val2 != 0x4) { 6297 pcs_blk_lock = B_TRUE; 6298 cmn_err(CE_NOTE, "!LINK DEBUG: port%d PHY Dev3 " 6299 "Reg 0x20 = 0x%x\n", nxgep->mac.portnum, val2); 6300 } 6301 } 6302 6303 if (link_align == B_FALSE) { 6304 if (val3 != 0x140f) { 6305 link_align = B_TRUE; 6306 cmn_err(CE_NOTE, "!LINK DEBUG: port%d PHY Dev4 " 6307 "Reg 0x18 = 0x%x\n", nxgep->mac.portnum, val3); 6308 } 6309 } 6310 6311 if (rx_sig_ok == B_FALSE) { 6312 if ((val2 == 0) || (val3 == 0)) { 6313 rx_sig_ok = B_TRUE; 6314 cmn_err(CE_NOTE, 6315 "!LINK DEBUG: port %d Dev3 or Dev4 read zero\n", 6316 nxgep->mac.portnum); 6317 } 6318 } 6319 #endif 6320 6321 *link_up = ((rx_sig_ok == B_TRUE) && (pcs_blk_lock == B_TRUE) && 6322 (link_align == B_TRUE)) ? B_TRUE : B_FALSE; 6323 6324 return (NXGE_OK); 6325 fail: 6326 return (status); 6327 } 6328 6329 static nxge_status_t 6330 nxge_check_mrvl88x2011_link(p_nxge_t nxgep, boolean_t *link_up) 6331 { 6332 uint8_t phy; 6333 nxge_status_t status = NXGE_OK; 6334 boolean_t pma_status; 6335 boolean_t pcs_status; 6336 boolean_t xgxs_status; 6337 uint16_t val; 6338 6339 phy = nxgep->statsp->mac_stats.xcvr_portn; 6340 6341 MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR, 6342 MRVL_88X2011_10G_PMD_STAT_2, &val); 6343 6344 *link_up = B_FALSE; 6345 6346 /* Check from Marvell 88X2011 if 10G link is up or down */ 6347 6348 /* Check PMA/PMD Register: 1.0001.2 == 1 */ 6349 MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR, 6350 MRVL_88X2011_PMA_PMD_STAT_1, &val); 6351 6352 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6353 "nxge_check_mrvl88x2011_link: pmd=0x%x", val)); 6354 6355 pma_status = ((val & MRVL_88X2011_LNK_STATUS_OK) ? B_TRUE : B_FALSE); 6356 6357 /* Check PMC Register : 3.0001.2 == 1: read twice */ 6358 MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR, 6359 MRVL_88X2011_PMA_PMD_STAT_1, &val); 6360 MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR, 6361 MRVL_88X2011_PMA_PMD_STAT_1, &val); 6362 6363 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6364 "nxge_check_mrvl88x2011_link: pcs=0x%x", val)); 6365 6366 pcs_status = ((val & MRVL_88X2011_LNK_STATUS_OK) ? B_TRUE : B_FALSE); 6367 6368 /* Check XGXS Register : 4.0018.[0-3,12] */ 6369 MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV4_ADDR, 6370 MRVL_88X2011_10G_XGXS_LANE_STAT, &val); 6371 6372 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6373 "nxge_check_mrvl88x2011_link: xgxs=0x%x", val)); 6374 6375 xgxs_status = (val == (XGXS_LANE_ALIGN_STATUS | XGXS_LANE3_SYNC | 6376 XGXS_LANE2_SYNC | XGXS_LANE1_SYNC | 6377 XGXS_LANE0_SYNC | XGXS_PATTERN_TEST_ABILITY | 6378 XGXS_LANE_STAT_MAGIC)) ? B_TRUE : B_FALSE; 6379 6380 *link_up = (pma_status && pcs_status && xgxs_status) ? 6381 B_TRUE : B_FALSE; 6382 6383 fail: 6384 6385 if (*link_up == B_FALSE) { 6386 /* PCS OFF */ 6387 nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_CTL_OFF); 6388 } else { 6389 /* PCS Activity */ 6390 nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_CTL_PCS_ACT); 6391 } 6392 6393 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6394 " <== nxge_check_mrvl88x2011_link: up=%d", *link_up)); 6395 6396 return (status); 6397 } 6398 6399 nxge_status_t 6400 nxge_10g_link_led_on(p_nxge_t nxgep) 6401 { 6402 if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_TRUE) 6403 != NPI_SUCCESS) 6404 return (NXGE_ERROR); 6405 else 6406 return (NXGE_OK); 6407 } 6408 6409 nxge_status_t 6410 nxge_10g_link_led_off(p_nxge_t nxgep) 6411 { 6412 if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_FALSE) 6413 != NPI_SUCCESS) 6414 return (NXGE_ERROR); 6415 else 6416 return (NXGE_OK); 6417 } 6418 6419 static boolean_t 6420 nxge_is_phy_present(p_nxge_t nxgep, int addr, uint32_t id, uint32_t mask) 6421 { 6422 uint32_t pma_pmd_id = 0; 6423 uint32_t pcs_id = 0; 6424 uint32_t phy_id = 0; 6425 6426 pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, addr); 6427 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6428 "nxge_is_phy_present: pma_pmd_id[0x%x]", pma_pmd_id)); 6429 if ((pma_pmd_id & mask) == (id & mask)) 6430 goto found_phy; 6431 pcs_id = nxge_get_cl45_pcs_id(nxgep, addr); 6432 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6433 "nxge_is_phy_present: pcs_id[0x%x]", pcs_id)); 6434 if ((pcs_id & mask) == (id & mask)) 6435 goto found_phy; 6436 phy_id = nxge_get_cl22_phy_id(nxgep, addr); 6437 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6438 "nxge_is_phy_present: phy_id[0x%x]", phy_id)); 6439 if ((phy_id & mask) == (id & mask)) 6440 goto found_phy; 6441 6442 return (B_FALSE); 6443 6444 found_phy: 6445 return (B_TRUE); 6446 } 6447 6448 /* Check if the given id read using the given MDIO Clause is supported */ 6449 6450 static boolean_t 6451 nxge_is_supported_phy(uint32_t id, uint8_t type) 6452 { 6453 int i; 6454 boolean_t found = B_FALSE; 6455 6456 switch (type) { 6457 case CLAUSE_45_TYPE: 6458 for (i = 0; i < NUM_CLAUSE_45_IDS; i++) { 6459 if (((nxge_supported_cl45_ids[i] & BCM_PHY_ID_MASK) == 6460 (id & BCM_PHY_ID_MASK)) || 6461 (TN1010_DEV_ID == (id & TN1010_DEV_ID_MASK))) { 6462 found = B_TRUE; 6463 break; 6464 } 6465 } 6466 break; 6467 case CLAUSE_22_TYPE: 6468 for (i = 0; i < NUM_CLAUSE_22_IDS; i++) { 6469 if ((nxge_supported_cl22_ids[i] & BCM_PHY_ID_MASK) == 6470 (id & BCM_PHY_ID_MASK)) { 6471 found = B_TRUE; 6472 break; 6473 } 6474 } 6475 break; 6476 default: 6477 break; 6478 } 6479 6480 return (found); 6481 } 6482 6483 static uint32_t 6484 nxge_get_cl45_pma_pmd_id(p_nxge_t nxgep, int phy_port) 6485 { 6486 uint16_t val1 = 0; 6487 uint16_t val2 = 0; 6488 uint32_t pma_pmd_dev_id = 0; 6489 npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep); 6490 6491 MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 6492 (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR, 6493 NXGE_DEV_ID_REG_1, &val1); 6494 (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR, 6495 NXGE_DEV_ID_REG_2, &val2); 6496 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 6497 6498 /* Concatenate the Device ID stored in two registers. */ 6499 pma_pmd_dev_id = val1; 6500 pma_pmd_dev_id = (pma_pmd_dev_id << 16); 6501 pma_pmd_dev_id |= val2; 6502 6503 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PMA/PMD " 6504 "devid[0x%llx]", phy_port, pma_pmd_dev_id)); 6505 6506 return (pma_pmd_dev_id); 6507 } 6508 6509 static uint32_t 6510 nxge_get_cl45_pcs_id(p_nxge_t nxgep, int phy_port) 6511 { 6512 uint16_t val1 = 0; 6513 uint16_t val2 = 0; 6514 uint32_t pcs_dev_id = 0; 6515 npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep); 6516 6517 MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 6518 (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR, 6519 NXGE_DEV_ID_REG_1, &val1); 6520 (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR, 6521 NXGE_DEV_ID_REG_2, &val2); 6522 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 6523 6524 pcs_dev_id = val1; 6525 pcs_dev_id = (pcs_dev_id << 16); 6526 pcs_dev_id |= val2; 6527 6528 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS " 6529 "devid[0x%llx]", phy_port, pcs_dev_id)); 6530 6531 return (pcs_dev_id); 6532 } 6533 6534 static uint32_t 6535 nxge_get_cl22_phy_id(p_nxge_t nxgep, int phy_port) 6536 { 6537 uint16_t val1 = 0; 6538 uint16_t val2 = 0; 6539 uint32_t phy_id = 0; 6540 npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep); 6541 npi_status_t npi_status = NPI_SUCCESS; 6542 6543 MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 6544 npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_1, 6545 &val1); 6546 if (npi_status != NPI_SUCCESS) { 6547 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] " 6548 "clause 22 read to reg 2 failed!!!")); 6549 goto exit; 6550 } 6551 npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_2, 6552 &val2); 6553 if (npi_status != 0) { 6554 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] " 6555 "clause 22 read to reg 3 failed!!!")); 6556 goto exit; 6557 } 6558 phy_id = val1; 6559 phy_id = (phy_id << 16); 6560 phy_id |= val2; 6561 6562 exit: 6563 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 6564 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID [0x%llx]", 6565 phy_port, phy_id)); 6566 6567 return (phy_id); 6568 } 6569 6570 /* 6571 * Scan the PHY ports 0 through 31 to get the PHY ID using Clause 22 MDIO 6572 * read and the PMA/PMD device ID and the PCS device ID using Clause 45 MDIO 6573 * read. Then use the values obtained to determine the phy type of each port 6574 * and the Neptune type. 6575 * 6576 * This function sets hw_p->xcvr_addr[i] for future MDIO access and set 6577 * hw_p->niu_type for each nxge instance to figure out nxgep->mac.portmode 6578 * in case the portmode information is not available via OBP, nxge.conf, 6579 * VPD or SEEPROM. 6580 */ 6581 nxge_status_t 6582 nxge_scan_ports_phy(p_nxge_t nxgep, p_nxge_hw_list_t hw_p) 6583 { 6584 int i, j, l; 6585 uint32_t pma_pmd_dev_id = 0; 6586 uint32_t pcs_dev_id = 0; 6587 uint32_t phy_id = 0; 6588 uint32_t port_pma_pmd_dev_id[NXGE_PORTS_NEPTUNE]; 6589 uint32_t port_pcs_dev_id[NXGE_PORTS_NEPTUNE]; 6590 uint32_t port_phy_id[NXGE_PORTS_NEPTUNE]; 6591 uint8_t pma_pmd_dev_fd[NXGE_MAX_PHY_PORTS]; 6592 uint8_t pcs_dev_fd[NXGE_MAX_PHY_PORTS]; 6593 uint8_t phy_fd_arr[NXGE_MAX_PHY_PORTS]; 6594 uint8_t port_fd_arr[NXGE_MAX_PHY_PORTS]; 6595 uint8_t total_port_fd, total_phy_fd; 6596 uint8_t num_xaui; 6597 nxge_status_t status = NXGE_OK; 6598 6599 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_scan_ports_phy: ")); 6600 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6601 "==> nxge_scan_ports_phy: nxge niu_type[0x%x]", 6602 nxgep->niu_type)); 6603 6604 if (isLDOMguest(nxgep)) { 6605 hw_p->niu_type = NIU_TYPE_NONE; 6606 hw_p->platform_type = P_NEPTUNE_NONE; 6607 return (NXGE_OK); 6608 } 6609 6610 j = l = 0; 6611 total_port_fd = total_phy_fd = 0; 6612 /* 6613 * Clause 45 and Clause 22 port/phy addresses 0 through 5 are reserved 6614 * for on chip serdes usages. "i" in the following for loop starts at 6. 6615 */ 6616 for (i = NXGE_EXT_PHY_PORT_ST; i < NXGE_MAX_PHY_PORTS; i++) { 6617 6618 pma_pmd_dev_id = nxge_get_cl45_pma_pmd_id(nxgep, i); 6619 6620 if (nxge_is_supported_phy(pma_pmd_dev_id, CLAUSE_45_TYPE)) { 6621 pma_pmd_dev_fd[i] = 1; 6622 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] " 6623 "PMA/PMD dev %x found", i, pma_pmd_dev_id)); 6624 if (j < NXGE_PORTS_NEPTUNE) { 6625 if ((pma_pmd_dev_id & TN1010_DEV_ID_MASK) 6626 == TN1010_DEV_ID) { 6627 port_pma_pmd_dev_id[j] = TN1010_DEV_ID; 6628 } else { 6629 port_pma_pmd_dev_id[j] = 6630 pma_pmd_dev_id & BCM_PHY_ID_MASK; 6631 } 6632 port_fd_arr[j] = (uint8_t)i; 6633 j++; 6634 } 6635 } else { 6636 pma_pmd_dev_fd[i] = 0; 6637 } 6638 6639 pcs_dev_id = nxge_get_cl45_pcs_id(nxgep, i); 6640 6641 if (nxge_is_supported_phy(pcs_dev_id, CLAUSE_45_TYPE)) { 6642 pcs_dev_fd[i] = 1; 6643 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS " 6644 "dev %x found", i, pcs_dev_id)); 6645 if (pma_pmd_dev_fd[i] == 1) { 6646 if ((pcs_dev_id & TN1010_DEV_ID_MASK) 6647 == TN1010_DEV_ID) { 6648 port_pcs_dev_id[j - 1] = 6649 TN1010_DEV_ID; 6650 } else { 6651 port_pcs_dev_id[j - 1] = 6652 pcs_dev_id & 6653 BCM_PHY_ID_MASK; 6654 } 6655 } else { 6656 if (j < NXGE_PORTS_NEPTUNE) { 6657 if ((pcs_dev_id & TN1010_DEV_ID_MASK) 6658 == TN1010_DEV_ID) { 6659 port_pcs_dev_id[j] = 6660 TN1010_DEV_ID; 6661 } else { 6662 port_pcs_dev_id[j] = 6663 pcs_dev_id & 6664 BCM_PHY_ID_MASK; 6665 } 6666 port_fd_arr[j] = (uint8_t)i; 6667 j++; 6668 } 6669 } 6670 } else { 6671 pcs_dev_fd[i] = 0; 6672 } 6673 6674 if (pcs_dev_fd[i] || pma_pmd_dev_fd[i]) { 6675 total_port_fd ++; 6676 } 6677 6678 phy_id = nxge_get_cl22_phy_id(nxgep, i); 6679 if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) { 6680 total_phy_fd ++; 6681 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID" 6682 "%x found", i, phy_id)); 6683 if (l < NXGE_PORTS_NEPTUNE) { 6684 if ((phy_id & TN1010_DEV_ID_MASK) 6685 == TN1010_DEV_ID) { 6686 port_phy_id[l] = TN1010_DEV_ID; 6687 } else { 6688 port_phy_id[l] 6689 = phy_id & BCM_PHY_ID_MASK; 6690 } 6691 phy_fd_arr[l] = (uint8_t)i; 6692 l++; 6693 } 6694 } 6695 } 6696 6697 switch (total_port_fd) { 6698 case 2: 6699 switch (total_phy_fd) { 6700 case 2: 6701 /* 2 10G, 2 1G RGMII Fiber / copper */ 6702 if ((((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) && 6703 (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) || 6704 ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) && 6705 (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) && 6706 ((port_phy_id[0] == PHY_BCM5482_FAMILY) && 6707 (port_phy_id[1] == PHY_BCM5482_FAMILY))) { 6708 6709 switch (hw_p->platform_type) { 6710 case P_NEPTUNE_ROCK: 6711 hw_p->niu_type = NEPTUNE_2_10GF_2_1GC; 6712 /* 6713 * ROCK platform has assigned a lower 6714 * addr to port 1. (port 0 = 0x9 and 6715 * port 1 = 0x8). 6716 */ 6717 hw_p->xcvr_addr[1] = port_fd_arr[0]; 6718 hw_p->xcvr_addr[0] = port_fd_arr[1]; 6719 6720 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6721 "Rock with 2 10G, 2 1GC")); 6722 break; 6723 6724 case P_NEPTUNE_NONE: 6725 default: 6726 hw_p->platform_type = 6727 P_NEPTUNE_GENERIC; 6728 hw_p->niu_type = NEPTUNE_2_10GF_2_1GRF; 6729 6730 hw_p->xcvr_addr[0] = port_fd_arr[0]; 6731 hw_p->xcvr_addr[1] = port_fd_arr[1]; 6732 6733 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6734 "ARTM card with 2 10G, 2 1GF")); 6735 break; 6736 } 6737 6738 hw_p->xcvr_addr[2] = phy_fd_arr[0]; 6739 hw_p->xcvr_addr[3] = phy_fd_arr[1]; 6740 6741 } else { 6742 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6743 "Unsupported neptune type 1")); 6744 goto error_exit; 6745 } 6746 break; 6747 6748 case 1: 6749 /* TODO - 2 10G, 1 1G */ 6750 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6751 "Unsupported neptune type 2 10G, 1 1G")); 6752 goto error_exit; 6753 case 0: 6754 /* 6755 * 2 10G: 2XGF NIC, Marvell, Goa, Huron with 2 XAUI 6756 * cards, etc. 6757 */ 6758 if (((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) && 6759 (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) || 6760 ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) && 6761 (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY)) || 6762 ((port_pcs_dev_id[0] == MARVELL_88X201X_PHY_ID) && 6763 (port_pcs_dev_id[1] == MARVELL_88X201X_PHY_ID)) || 6764 ((port_pma_pmd_dev_id[0] == 6765 MARVELL_88X201X_PHY_ID) && 6766 (port_pma_pmd_dev_id[1] == 6767 MARVELL_88X201X_PHY_ID))) { 6768 6769 /* 6770 * Check the first phy port address against 6771 * the known phy start addresses to determine 6772 * the platform type. 6773 */ 6774 6775 switch (port_fd_arr[0]) { 6776 case NEPTUNE_CLAUSE45_PORT_ADDR_BASE: 6777 /* 6778 * The Marvell case also falls into 6779 * this case as 6780 * MRVL88X2011_NEPTUNE_PORT_ADDR_BASE 6781 * == NEPTUNE_CLAUSE45_PORT_ADDR_BASE. 6782 * This is OK for the 2 10G case. 6783 */ 6784 hw_p->niu_type = NEPTUNE_2_10GF; 6785 hw_p->platform_type = 6786 P_NEPTUNE_ATLAS_2PORT; 6787 break; 6788 case GOA_CLAUSE45_PORT_ADDR_BASE: 6789 if (hw_p->platform_type != 6790 P_NEPTUNE_NIU) { 6791 hw_p->platform_type = 6792 P_NEPTUNE_GENERIC; 6793 hw_p->niu_type = 6794 NEPTUNE_2_10GF; 6795 } 6796 break; 6797 default: 6798 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6799 "Unsupported neptune type 2 - 1")); 6800 goto error_exit; 6801 } 6802 6803 for (i = 0; i < 2; i++) { 6804 hw_p->xcvr_addr[i] = port_fd_arr[i]; 6805 } 6806 6807 /* Both XAUI slots have copper XAUI cards */ 6808 } else if ((((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 6809 == TN1010_DEV_ID) && 6810 ((port_pcs_dev_id[1] & TN1010_DEV_ID_MASK) 6811 == TN1010_DEV_ID)) || 6812 (((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK) 6813 == TN1010_DEV_ID) && 6814 ((port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK) 6815 == TN1010_DEV_ID))) { 6816 hw_p->niu_type = NEPTUNE_2_TN1010; 6817 hw_p->xcvr_addr[0] = port_fd_arr[0]; 6818 hw_p->xcvr_addr[1] = port_fd_arr[1]; 6819 6820 /* Slot0 has fiber XAUI, slot1 has copper XAUI */ 6821 } else if ((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY && 6822 (port_pcs_dev_id[1] & TN1010_DEV_ID_MASK) 6823 == TN1010_DEV_ID) || 6824 (port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY && 6825 (port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK) == 6826 TN1010_DEV_ID)) { 6827 hw_p->niu_type = NEPTUNE_1_10GF_1_TN1010; 6828 hw_p->xcvr_addr[0] = port_fd_arr[0]; 6829 hw_p->xcvr_addr[1] = port_fd_arr[1]; 6830 6831 /* Slot0 has copper XAUI, slot1 has fiber XAUI */ 6832 } else if ((port_pcs_dev_id[1] == PHY_BCM8704_FAMILY && 6833 (port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 6834 == TN1010_DEV_ID) || 6835 (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY && 6836 (port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK) 6837 == TN1010_DEV_ID)) { 6838 hw_p->niu_type = NEPTUNE_1_TN1010_1_10GF; 6839 hw_p->xcvr_addr[0] = port_fd_arr[0]; 6840 hw_p->xcvr_addr[1] = port_fd_arr[1]; 6841 6842 } else { 6843 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6844 "Unsupported neptune type 2")); 6845 goto error_exit; 6846 } 6847 break; 6848 6849 case 4: 6850 if (nxge_get_num_of_xaui( 6851 port_pma_pmd_dev_id, port_pcs_dev_id, 6852 port_phy_id, &num_xaui) == NXGE_ERROR) { 6853 goto error_exit; 6854 } 6855 if (num_xaui != 2) 6856 goto error_exit; 6857 6858 /* 6859 * Maramba with 2 XAUIs (either fiber or copper) 6860 * 6861 * Check the first phy port address against 6862 * the known phy start addresses to determine 6863 * the platform type. 6864 */ 6865 switch (phy_fd_arr[0]) { 6866 case MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE: 6867 hw_p->platform_type = 6868 P_NEPTUNE_MARAMBA_P0; 6869 break; 6870 case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE: 6871 hw_p->platform_type = 6872 P_NEPTUNE_MARAMBA_P1; 6873 break; 6874 default: 6875 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6876 "Unknown port %d...Cannot " 6877 "determine platform type", i)); 6878 goto error_exit; 6879 } 6880 6881 hw_p->xcvr_addr[0] = port_fd_arr[0]; 6882 hw_p->xcvr_addr[1] = port_fd_arr[1]; 6883 hw_p->xcvr_addr[2] = phy_fd_arr[2]; 6884 hw_p->xcvr_addr[3] = phy_fd_arr[3]; 6885 6886 /* slot0 has fiber XAUI, slot1 has Cu XAUI */ 6887 if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY && 6888 (port_pcs_dev_id[1] & TN1010_DEV_ID_MASK) 6889 == TN1010_DEV_ID) { 6890 hw_p->niu_type = NEPTUNE_1_10GF_1_TN1010_2_1GC; 6891 6892 /* slot0 has Cu XAUI, slot1 has fiber XAUI */ 6893 } else if (((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 6894 == TN1010_DEV_ID) && 6895 port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) { 6896 hw_p->niu_type = NEPTUNE_1_TN1010_1_10GF_2_1GC; 6897 6898 /* Both slots have fiber XAUI */ 6899 } else if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY && 6900 port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) { 6901 hw_p->niu_type = NEPTUNE_2_10GF_2_1GC; 6902 6903 /* Both slots have copper XAUI */ 6904 } else if (((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 6905 == TN1010_DEV_ID) && 6906 (port_pcs_dev_id[1] & TN1010_DEV_ID_MASK) 6907 == TN1010_DEV_ID) { 6908 hw_p->niu_type = NEPTUNE_2_TN1010_2_1GC; 6909 6910 } else { 6911 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6912 "Unsupported neptune type 3")); 6913 goto error_exit; 6914 } 6915 break; 6916 default: 6917 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6918 "Unsupported neptune type 5")); 6919 goto error_exit; 6920 } 6921 break; 6922 case 1: /* Only one clause45 port */ 6923 switch (total_phy_fd) { /* Number of clause22 ports */ 6924 case 3: 6925 /* 6926 * TODO 3 1G, 1 10G mode. 6927 * Differentiate between 1_1G_1_10G_2_1G and 6928 * 1_10G_3_1G 6929 */ 6930 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6931 "Unsupported neptune type 7")); 6932 goto error_exit; 6933 case 2: 6934 /* 6935 * TODO 2 1G, 1 10G mode. 6936 * Differentiate between 1_1G_1_10G_1_1G and 6937 * 1_10G_2_1G 6938 */ 6939 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6940 "Unsupported neptune type 8")); 6941 goto error_exit; 6942 case 1: 6943 /* 6944 * TODO 1 1G, 1 10G mode. 6945 * Differentiate between 1_1G_1_10G and 6946 * 1_10G_1_1G 6947 */ 6948 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6949 "Unsupported neptune type 9")); 6950 goto error_exit; 6951 case 0: /* N2 with 1 XAUI (fiber or copper) */ 6952 /* Fiber XAUI */ 6953 if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY || 6954 port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) { 6955 6956 /* 6957 * Check the first phy port address against 6958 * the known phy start addresses to determine 6959 * the platform type. 6960 */ 6961 6962 switch (port_fd_arr[0]) { 6963 case N2_CLAUSE45_PORT_ADDR_BASE: 6964 case (N2_CLAUSE45_PORT_ADDR_BASE + 1): 6965 case ALT_GOA_CLAUSE45_PORT1_ADDR: 6966 /* 6967 * If hw_p->platform_type == 6968 * P_NEPTUNE_NIU, then portmode 6969 * is already known, so there is 6970 * no need to figure out hw_p-> 6971 * platform_type because 6972 * platform_type is only for 6973 * figuring out portmode. 6974 */ 6975 if (hw_p->platform_type != 6976 P_NEPTUNE_NIU) { 6977 hw_p->platform_type = 6978 P_NEPTUNE_GENERIC; 6979 hw_p->niu_type = 6980 NEPTUNE_2_10GF; 6981 } 6982 break; 6983 default: 6984 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6985 "Unsupported neptune type 10")); 6986 goto error_exit; 6987 } 6988 /* 6989 * For GOA, which is a hot swappable PHY, the 6990 * phy address to function number mapping 6991 * should be preserved, i.e., addr 16 is 6992 * assigned to function 0 and 20 to function 1 6993 * But for Huron XAUI, the assignment should 6994 * be by function number, i.e., whichever 6995 * function number attaches should be 6996 * assigned the available PHY (this is required 6997 * primarily to support pre-production Huron 6998 * boards where function 0 is mapped to addr 17 6999 */ 7000 if (port_fd_arr[0] == 7001 ALT_GOA_CLAUSE45_PORT1_ADDR) { 7002 hw_p->xcvr_addr[1] = port_fd_arr[0]; 7003 } else { 7004 hw_p->xcvr_addr[nxgep->function_num] = 7005 port_fd_arr[0]; 7006 } 7007 7008 /* A 10G copper XAUI in either slot0 or slot1 */ 7009 } else if ((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 7010 == TN1010_DEV_ID || 7011 (port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK) 7012 == TN1010_DEV_ID) { 7013 switch (port_fd_arr[0]) { 7014 /* The XAUI is in slot0 */ 7015 case N2_CLAUSE45_PORT_ADDR_BASE: 7016 hw_p->niu_type = NEPTUNE_1_TN1010; 7017 break; 7018 7019 /* The XAUI is in slot1 */ 7020 case (N2_CLAUSE45_PORT_ADDR_BASE + 1): 7021 hw_p->niu_type 7022 = NEPTUNE_1_NONE_1_TN1010; 7023 break; 7024 default: 7025 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7026 "Unsupported XAUI port address")); 7027 goto error_exit; 7028 } 7029 hw_p->xcvr_addr[nxgep->function_num] 7030 = port_fd_arr[0]; 7031 7032 } else { 7033 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7034 "Unsupported PHY type")); 7035 goto error_exit; 7036 } 7037 break; 7038 case 4: /* Maramba always have 4 clause 45 ports */ 7039 7040 /* Maramba with 1 XAUI */ 7041 if ((port_pcs_dev_id[0] != PHY_BCM8704_FAMILY) && 7042 (port_pma_pmd_dev_id[0] != PHY_BCM8704_FAMILY) && 7043 ((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 7044 != TN1010_DEV_ID) && 7045 ((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK) 7046 != TN1010_DEV_ID)) { 7047 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7048 "Unsupported neptune type 12")); 7049 goto error_exit; 7050 } 7051 7052 /* 7053 * Check the first phy port address against 7054 * the known phy start addresses to determine 7055 * the platform type. 7056 */ 7057 switch (phy_fd_arr[0]) { 7058 case MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE: 7059 hw_p->platform_type = 7060 P_NEPTUNE_MARAMBA_P0; 7061 break; 7062 case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE: 7063 hw_p->platform_type = 7064 P_NEPTUNE_MARAMBA_P1; 7065 break; 7066 default: 7067 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7068 "Unknown port %d...Cannot " 7069 "determine platform type 10 - 2", 7070 i)); 7071 goto error_exit; 7072 } 7073 7074 /* 7075 * Check the clause45 address to determine 7076 * if XAUI is in port 0 or port 1. 7077 */ 7078 switch (port_fd_arr[0]) { 7079 case MARAMBA_CLAUSE45_PORT_ADDR_BASE: 7080 if (port_pcs_dev_id[0] 7081 == PHY_BCM8704_FAMILY || 7082 port_pma_pmd_dev_id[0] 7083 == PHY_BCM8704_FAMILY) { 7084 hw_p->niu_type 7085 = NEPTUNE_1_10GF_3_1GC; 7086 } else { 7087 hw_p->niu_type 7088 = NEPTUNE_1_TN1010_3_1GC; 7089 } 7090 hw_p->xcvr_addr[0] = port_fd_arr[0]; 7091 for (i = 1; i < NXGE_MAX_PORTS; i++) { 7092 hw_p->xcvr_addr[i] = 7093 phy_fd_arr[i]; 7094 } 7095 break; 7096 case (MARAMBA_CLAUSE45_PORT_ADDR_BASE + 1): 7097 if (port_pcs_dev_id[0] 7098 == PHY_BCM8704_FAMILY || 7099 port_pma_pmd_dev_id[0] 7100 == PHY_BCM8704_FAMILY) { 7101 hw_p->niu_type = 7102 NEPTUNE_1_1GC_1_10GF_2_1GC; 7103 } else { 7104 hw_p->niu_type = 7105 NEPTUNE_1_1GC_1_TN1010_2_1GC; 7106 } 7107 hw_p->xcvr_addr[0] = phy_fd_arr[0]; 7108 hw_p->xcvr_addr[1] = port_fd_arr[0]; 7109 hw_p->xcvr_addr[2] = phy_fd_arr[2]; 7110 hw_p->xcvr_addr[3] = phy_fd_arr[3]; 7111 break; 7112 default: 7113 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7114 "Unsupported neptune type 11")); 7115 goto error_exit; 7116 } 7117 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7118 "Maramba with 1 XAUI (fiber or copper)")); 7119 break; 7120 default: 7121 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7122 "Unsupported neptune type 13")); 7123 goto error_exit; 7124 } 7125 break; 7126 case 0: /* 4 ports Neptune based NIC */ 7127 switch (total_phy_fd) { 7128 case 4: 7129 if ((port_phy_id[0] == PHY_BCM5464R_FAMILY) && 7130 (port_phy_id[1] == PHY_BCM5464R_FAMILY) && 7131 (port_phy_id[2] == PHY_BCM5464R_FAMILY) && 7132 (port_phy_id[3] == PHY_BCM5464R_FAMILY)) { 7133 7134 /* 7135 * Check the first phy port address against 7136 * the known phy start addresses to determine 7137 * the platform type. 7138 */ 7139 switch (phy_fd_arr[0]) { 7140 case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE: 7141 hw_p->platform_type = 7142 P_NEPTUNE_MARAMBA_P1; 7143 break; 7144 case NEPTUNE_CLAUSE22_PORT_ADDR_BASE: 7145 hw_p->platform_type = 7146 P_NEPTUNE_ATLAS_4PORT; 7147 break; 7148 default: 7149 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7150 "Unknown port %d...Cannot " 7151 "determine platform type", i)); 7152 goto error_exit; 7153 } 7154 hw_p->niu_type = NEPTUNE_4_1GC; 7155 for (i = 0; i < NXGE_MAX_PORTS; i++) { 7156 hw_p->xcvr_addr[i] = phy_fd_arr[i]; 7157 } 7158 } else { 7159 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7160 "Unsupported neptune type 14")); 7161 goto error_exit; 7162 } 7163 break; 7164 case 3: 7165 /* TODO 3 1G mode */ 7166 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7167 "Unsupported neptune type 15")); 7168 goto error_exit; 7169 case 2: 7170 /* TODO 2 1G mode */ 7171 if ((port_phy_id[0] == PHY_BCM5482_FAMILY) && 7172 (port_phy_id[1] == PHY_BCM5482_FAMILY)) { 7173 hw_p->platform_type = P_NEPTUNE_GENERIC; 7174 hw_p->niu_type = NEPTUNE_2_1GRF; 7175 hw_p->xcvr_addr[2] = phy_fd_arr[0]; 7176 hw_p->xcvr_addr[3] = phy_fd_arr[1]; 7177 } else { 7178 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7179 "Unsupported neptune type 16")); 7180 goto error_exit; 7181 } 7182 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7183 "2 RGMII Fiber ports - RTM")); 7184 break; 7185 7186 case 1: 7187 /* TODO 1 1G mode */ 7188 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7189 "Unsupported neptune type 17")); 7190 goto error_exit; 7191 default: 7192 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7193 "Unsupported neptune type 18, total phy fd %d", 7194 total_phy_fd)); 7195 goto error_exit; 7196 } 7197 break; 7198 default: 7199 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7200 "Unsupported neptune type 19")); 7201 goto error_exit; 7202 } 7203 7204 scan_exit: 7205 7206 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_scan_ports_phy, " 7207 "niu type [0x%x]\n", hw_p->niu_type)); 7208 return (status); 7209 7210 error_exit: 7211 return (NXGE_ERROR); 7212 } 7213 7214 boolean_t 7215 nxge_is_valid_local_mac(ether_addr_st mac_addr) 7216 { 7217 if ((mac_addr.ether_addr_octet[0] & 0x01) || 7218 (ether_cmp(&mac_addr, ðerbroadcastaddr) == 0) || 7219 (ether_cmp(&mac_addr, ðerzeroaddr) == 0)) 7220 return (B_FALSE); 7221 else 7222 return (B_TRUE); 7223 } 7224 7225 static void 7226 nxge_bcm5464_link_led_off(p_nxge_t nxgep) { 7227 7228 npi_status_t rs = NPI_SUCCESS; 7229 uint8_t xcvr_portn; 7230 uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 7231 7232 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_bcm5464_link_led_off")); 7233 7234 if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P1) { 7235 xcvr_portn = MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE; 7236 } else if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P0) { 7237 xcvr_portn = MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE; 7238 } 7239 /* 7240 * For Altas 4-1G copper, Xcvr port numbers are 7241 * swapped with ethernet port number. This is 7242 * designed for better signal integrity in routing. 7243 */ 7244 switch (portn) { 7245 case 0: 7246 xcvr_portn += 3; 7247 break; 7248 case 1: 7249 xcvr_portn += 2; 7250 break; 7251 case 2: 7252 xcvr_portn += 1; 7253 break; 7254 case 3: 7255 default: 7256 break; 7257 } 7258 7259 MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 7260 rs = npi_mac_mif_mii_write(nxgep->npi_handle, 7261 xcvr_portn, BCM5464R_MISC, 0xb4ee); 7262 if (rs != NPI_SUCCESS) { 7263 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7264 "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write " 7265 "returned error 0x[%x]", rs)); 7266 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 7267 return; 7268 } 7269 7270 rs = npi_mac_mif_mii_write(nxgep->npi_handle, 7271 xcvr_portn, BCM5464R_MISC, 0xb8ee); 7272 if (rs != NPI_SUCCESS) { 7273 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7274 "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write " 7275 "returned error 0x[%x]", rs)); 7276 } 7277 7278 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 7279 } 7280 7281 static nxge_status_t 7282 nxge_mii_get_link_mode(p_nxge_t nxgep) 7283 { 7284 p_nxge_stats_t statsp; 7285 uint8_t xcvr_portn; 7286 p_mii_regs_t mii_regs; 7287 mii_mode_control_stat_t mode; 7288 int status = NXGE_OK; 7289 7290 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_get_link_mode")); 7291 7292 statsp = nxgep->statsp; 7293 xcvr_portn = statsp->mac_stats.xcvr_portn; 7294 mii_regs = NULL; 7295 mode.value = 0; 7296 mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG; 7297 #if defined(__i386) 7298 if ((status = nxge_mii_write(nxgep, xcvr_portn, 7299 (uint8_t)(uint32_t)(&mii_regs->shadow), 7300 mode.value)) != NXGE_OK) { 7301 goto fail; 7302 #else 7303 if ((status = nxge_mii_write(nxgep, xcvr_portn, 7304 (uint8_t)(uint64_t)(&mii_regs->shadow), 7305 mode.value)) != NXGE_OK) { 7306 goto fail; 7307 #endif 7308 } 7309 #if defined(__i386) 7310 if ((status = nxge_mii_read(nxgep, xcvr_portn, 7311 (uint8_t)(uint32_t)(&mii_regs->shadow), 7312 &mode.value)) != NXGE_OK) { 7313 goto fail; 7314 } 7315 #else 7316 if ((status = nxge_mii_read(nxgep, xcvr_portn, 7317 (uint8_t)(uint64_t)(&mii_regs->shadow), 7318 &mode.value)) != NXGE_OK) { 7319 goto fail; 7320 } 7321 #endif 7322 7323 if (mode.bits.mode == NXGE_MODE_SELECT_FIBER) { 7324 nxgep->mac.portmode = PORT_1G_RGMII_FIBER; 7325 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7326 "nxge_mii_get_link_mode: fiber mode")); 7327 } 7328 7329 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7330 "nxge_mii_get_link_mode: " 7331 "(address 0x%x) port 0x%x mode value 0x%x link mode 0x%x", 7332 NXGE_MII_MODE_CONTROL_REG, xcvr_portn, 7333 mode.value, nxgep->mac.portmode)); 7334 7335 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7336 "<== nxge_mii_get_link_mode")); 7337 return (status); 7338 fail: 7339 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7340 "<== nxge_mii_get_link_mode (failed)")); 7341 return (NXGE_ERROR); 7342 } 7343 7344 nxge_status_t 7345 nxge_mac_set_framesize(p_nxge_t nxgep) 7346 { 7347 npi_attr_t ap; 7348 uint8_t portn; 7349 npi_handle_t handle; 7350 npi_status_t rs = NPI_SUCCESS; 7351 7352 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_set_framesize")); 7353 7354 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 7355 handle = nxgep->npi_handle; 7356 7357 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7358 "==> nxge_mac_sec_framesize: port<%d> " 7359 "min framesize %d max framesize %d ", 7360 portn, 7361 nxgep->mac.minframesize, 7362 nxgep->mac.maxframesize)); 7363 7364 SET_MAC_ATTR2(handle, ap, portn, 7365 MAC_PORT_FRAME_SIZE, 7366 nxgep->mac.minframesize, 7367 nxgep->mac.maxframesize, 7368 rs); 7369 if (rs != NPI_SUCCESS) { 7370 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7371 "<== nxge_mac_set_framesize: failed to configure " 7372 "max/min frame size port %d", portn)); 7373 7374 return (NXGE_ERROR | rs); 7375 } 7376 7377 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7378 "<== nxge_mac_set_framesize: port<%d>", portn)); 7379 7380 return (NXGE_OK); 7381 } 7382 7383 static nxge_status_t 7384 nxge_get_num_of_xaui(uint32_t *port_pma_pmd_dev_id, 7385 uint32_t *port_pcs_dev_id, uint32_t *port_phy_id, uint8_t *num_xaui) 7386 { 7387 uint8_t i; 7388 7389 for (i = 0; i < 4; i++) { 7390 if (port_phy_id[i] != PHY_BCM5464R_FAMILY) 7391 return (NXGE_ERROR); 7392 } 7393 7394 *num_xaui = 0; 7395 if ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY && 7396 port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) || 7397 (((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK) 7398 == TN1010_DEV_ID) && 7399 ((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 7400 == TN1010_DEV_ID))) { 7401 (*num_xaui) ++; 7402 } 7403 if ((port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY && 7404 port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) || 7405 (((port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK) 7406 == TN1010_DEV_ID) && 7407 ((port_pcs_dev_id[1] & TN1010_DEV_ID_MASK) 7408 == TN1010_DEV_ID))) { 7409 (*num_xaui) ++; 7410 } 7411 return (NXGE_OK); 7412 } 7413 7414 /* 7415 * Instruction from Teranetics: Once you detect link is up, go 7416 * read Reg 30.1.4 for link speed: '1' for 1G and '0' for 10G. You 7417 * may want to qualify it by first checking Register 30.1.7:6 and 7418 * making sure it reads "01" (Auto-Neg Complete). 7419 * 7420 * If this function is called when the link is down or before auto- 7421 * negotiation has completed, then the speed of the PHY is not certain. 7422 * In such cases, this function returns 1G as the default speed with 7423 * NXGE_OK status instead of NXGE_ERROR. It is OK to initialize the 7424 * driver based on a default speed because this function will be called 7425 * again when the link comes up. Returning NXGE_ERROR, which may 7426 * cause brutal chain reaction in caller functions, is not necessary. 7427 */ 7428 static nxge_status_t 7429 nxge_get_tn1010_speed(p_nxge_t nxgep, uint16_t *speed) 7430 { 7431 uint8_t phy_port_addr, autoneg_stat, link_up; 7432 nxge_status_t status = NXGE_OK; 7433 uint16_t val; 7434 uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 7435 7436 /* Set default speed to 10G */ 7437 *speed = TN1010_SPEED_10G; 7438 7439 /* Set Clause 45 */ 7440 npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE); 7441 7442 phy_port_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 7443 7444 /* Check Device 1 Register 0xA bit0 for link up status */ 7445 status = nxge_mdio_read(nxgep, phy_port_addr, 7446 TN1010_AUTONEG_DEV_ADDR, TN1010_AUTONEG_STATUS_REG, &val); 7447 if (status != NXGE_OK) 7448 goto fail; 7449 7450 link_up = ((val & TN1010_AN_LINK_STAT_BIT) 7451 ? B_TRUE : B_FALSE); 7452 if (link_up == B_FALSE) { 7453 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7454 "nxge_get_tn1010_speed: link is down")); 7455 goto nxge_get_tn1010_speed_exit; 7456 } 7457 7458 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 7459 TN1010_VENDOR_MMD1_DEV_ADDR, TN1010_VENDOR_MMD1_STATUS_REG, 7460 &val)) != NXGE_OK) { 7461 goto fail; 7462 } 7463 autoneg_stat = (val & TN1010_VENDOR_MMD1_AN_STAT_BITS) >> 7464 TN1010_VENDOR_MMD1_AN_STAT_SHIFT; 7465 7466 /* 7467 * Return NXGE_OK even when we can not get a settled speed. In 7468 * such case, the speed reported should not be trusted but that 7469 * is OK, we will call this function periodically and will get 7470 * the correct speed after the link is up. 7471 */ 7472 switch (autoneg_stat) { 7473 case TN1010_AN_IN_PROG: 7474 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7475 "nxge_get_tn1010_speed: Auto-negotiation in progress")); 7476 break; 7477 case TN1010_AN_COMPLETE: 7478 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 7479 TN1010_VENDOR_MMD1_DEV_ADDR, 7480 TN1010_VENDOR_MMD1_STATUS_REG, 7481 &val)) != NXGE_OK) { 7482 goto fail; 7483 } 7484 *speed = (val & TN1010_VENDOR_MMD1_AN_SPEED_BIT) >> 7485 TN1010_VENDOR_MMD1_AN_SPEED_SHIFT; 7486 break; 7487 case TN1010_AN_RSVD: 7488 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7489 "nxge_get_tn1010_speed: Autoneg status undefined")); 7490 break; 7491 case TN1010_AN_FAILED: 7492 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7493 "nxge_get_tn1010_speed: Auto-negotiation failed")); 7494 break; 7495 default: 7496 break; 7497 } 7498 nxge_get_tn1010_speed_exit: 7499 return (NXGE_OK); 7500 fail: 7501 return (status); 7502 } 7503 7504 7505 /* 7506 * Teranetics TN1010 PHY chip supports both 1G and 10G modes, this function 7507 * figures out the speed of the PHY determined by the autonegotiation 7508 * process and sets the following 3 parameters, 7509 * nxgep->mac.portmode 7510 * nxgep->statsp->mac_stats.link_speed 7511 * nxgep->statsp->mac_stats.xcvr_inuse 7512 */ 7513 static nxge_status_t 7514 nxge_set_tn1010_param(p_nxge_t nxgep) 7515 { 7516 uint16_t speed; 7517 7518 if (nxge_get_tn1010_speed(nxgep, &speed) != NXGE_OK) { 7519 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7520 "nxge_set_tn1010_param: " 7521 "Failed to get TN1010 speed")); 7522 return (NXGE_ERROR); 7523 } 7524 if (speed == TN1010_SPEED_1G) { 7525 nxgep->mac.portmode = PORT_1G_TN1010; 7526 nxgep->statsp->mac_stats.link_speed = 1000; 7527 nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 7528 } else { 7529 nxgep->mac.portmode = PORT_10G_TN1010; 7530 nxgep->statsp->mac_stats.link_speed = 10000; 7531 nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 7532 } 7533 return (NXGE_OK); 7534 } 7535 7536 #ifdef NXGE_DEBUG 7537 static void 7538 nxge_mii_dump(p_nxge_t nxgep) 7539 { 7540 p_nxge_stats_t statsp; 7541 uint8_t xcvr_portn; 7542 p_mii_regs_t mii_regs; 7543 mii_bmcr_t bmcr; 7544 mii_bmsr_t bmsr; 7545 mii_idr1_t idr1; 7546 mii_idr2_t idr2; 7547 mii_mode_control_stat_t mode; 7548 p_nxge_param_t param_arr; 7549 7550 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "==> nxge_mii_dump")); 7551 7552 statsp = nxgep->statsp; 7553 xcvr_portn = statsp->mac_stats.xcvr_portn; 7554 7555 mii_regs = NULL; 7556 7557 #if defined(__i386) 7558 (void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn, 7559 (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value); 7560 #else 7561 (void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn, 7562 (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value); 7563 #endif 7564 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7565 "nxge_mii_dump: bmcr (0) xcvr 0x%x value 0x%x", 7566 xcvr_portn, bmcr.value)); 7567 7568 #if defined(__i386) 7569 (void) nxge_mii_read(nxgep, 7570 nxgep->statsp->mac_stats.xcvr_portn, 7571 (uint8_t)(uint32_t)(&mii_regs->bmsr), &bmsr.value); 7572 #else 7573 (void) nxge_mii_read(nxgep, 7574 nxgep->statsp->mac_stats.xcvr_portn, 7575 (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value); 7576 #endif 7577 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7578 "nxge_mii_dump: bmsr (1) xcvr 0x%x value 0x%x", 7579 xcvr_portn, bmsr.value)); 7580 7581 #if defined(__i386) 7582 (void) nxge_mii_read(nxgep, 7583 nxgep->statsp->mac_stats.xcvr_portn, 7584 (uint8_t)(uint32_t)(&mii_regs->idr1), &idr1.value); 7585 #else 7586 (void) nxge_mii_read(nxgep, 7587 nxgep->statsp->mac_stats.xcvr_portn, 7588 (uint8_t)(uint64_t)(&mii_regs->idr1), &idr1.value); 7589 #endif 7590 7591 7592 #if defined(__i386) 7593 (void) nxge_mii_read(nxgep, 7594 nxgep->statsp->mac_stats.xcvr_portn, 7595 (uint8_t)(uint32_t)(&mii_regs->idr2), &idr2.value); 7596 #else 7597 (void) nxge_mii_read(nxgep, 7598 nxgep->statsp->mac_stats.xcvr_portn, 7599 (uint8_t)(uint64_t)(&mii_regs->idr2), &idr2.value); 7600 #endif 7601 7602 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7603 "nxge_mii_dump: idr1 (2) xcvr 0x%x value 0x%x", 7604 xcvr_portn, idr1.value)); 7605 7606 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7607 "nxge_mii_dump: idr2 (3) xcvr 0x%x value 0x%x", 7608 xcvr_portn, idr2.value)); 7609 7610 mode.value = 0; 7611 mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG; 7612 7613 #if defined(__i386) 7614 (void) nxge_mii_write(nxgep, xcvr_portn, 7615 (uint8_t)(uint32_t)(&mii_regs->shadow), mode.value); 7616 7617 (void) nxge_mii_read(nxgep, xcvr_portn, 7618 (uint8_t)(uint32_t)(&mii_regs->shadow), &mode.value); 7619 #else 7620 (void) nxge_mii_write(nxgep, xcvr_portn, 7621 (uint8_t)(uint64_t)(&mii_regs->shadow), mode.value); 7622 7623 (void) nxge_mii_read(nxgep, xcvr_portn, 7624 (uint8_t)(uint64_t)(&mii_regs->shadow), &mode.value); 7625 #endif 7626 7627 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7628 "nxge_mii_dump: mode control xcvr 0x%x value 0x%x", 7629 xcvr_portn, mode.value)); 7630 } 7631 #endif 7632