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_DEBUG_MSG((nxgep, MAC_CTL, 2162 "nxge_neptune_10G_serdes_init: " 2163 "Serdes/signal for port<%d> not ready", portn)); 2164 goto done; 2165 } 2166 } else if (portn == 1) { 2167 /* Wait for serdes to be ready */ 2168 for (i = 0; i < MAX_SERDES_RDY_RETRIES; i++) { 2169 ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val); 2170 if ((val & ESR_SIG_P1_BITS_MASK) != 2171 (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1 | 2172 ESR_SIG_XSERDES_RDY_P1 | 2173 ESR_SIG_XDETECT_P1_CH3 | 2174 ESR_SIG_XDETECT_P1_CH2 | 2175 ESR_SIG_XDETECT_P1_CH1 | 2176 ESR_SIG_XDETECT_P1_CH0)) 2177 2178 NXGE_DELAY(SERDES_RDY_WT_INTERVAL); 2179 else 2180 break; 2181 } 2182 2183 if (i == MAX_SERDES_RDY_RETRIES) { 2184 /* 2185 * RDY signal stays low may due to the absent of the 2186 * external PHY, it is not an error condition. But still 2187 * print the message for the debugging purpose when link 2188 * stays down 2189 */ 2190 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2191 "nxge_neptune_10G_serdes_init: " 2192 "Serdes/signal for port<%d> not ready", portn)); 2193 goto done; 2194 } 2195 } 2196 2197 done: 2198 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2199 "<== nxge_neptune_10G_serdes_init port<%d>", portn)); 2200 2201 return (NXGE_OK); 2202 fail: 2203 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2204 "nxge_neptune_10G_serdes_init: " 2205 "Failed to initialize Neptune serdes for port<%d>", portn)); 2206 2207 return (status); 2208 } 2209 2210 /* Initialize Neptune Internal Serdes for 1G (Neptune only) */ 2211 2212 static nxge_status_t 2213 nxge_1G_serdes_init(p_nxge_t nxgep) 2214 { 2215 npi_handle_t handle; 2216 uint8_t portn; 2217 int chan; 2218 sr_rx_tx_ctrl_l_t rx_tx_ctrl_l; 2219 sr_rx_tx_ctrl_h_t rx_tx_ctrl_h; 2220 sr_glue_ctrl0_l_t glue_ctrl0_l; 2221 sr_glue_ctrl0_h_t glue_ctrl0_h; 2222 uint64_t val; 2223 uint16_t val16l; 2224 uint16_t val16h; 2225 nxge_status_t status = NXGE_OK; 2226 2227 portn = nxgep->mac.portnum; 2228 2229 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2230 "==> nxge_1G_serdes_init port<%d>", portn)); 2231 2232 handle = nxgep->npi_handle; 2233 2234 switch (portn) { 2235 case 0: 2236 /* Assert the reset register */ 2237 ESR_REG_RD(handle, ESR_RESET_REG, &val); 2238 val |= ESR_RESET_0; 2239 ESR_REG_WR(handle, ESR_RESET_REG, val); 2240 2241 /* Set the PLL register to 0x79 */ 2242 ESR_REG_WR(handle, ESR_0_PLL_CONFIG_REG, 2243 ESR_PLL_CFG_1G_SERDES); 2244 2245 /* Set the control register to 0x249249f */ 2246 ESR_REG_WR(handle, ESR_0_CONTROL_REG, ESR_CTL_1G_SERDES); 2247 2248 /* Set Serdes0 Internal Loopback if necessary */ 2249 if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) { 2250 /* Set pad loopback modes 0xaa */ 2251 ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 2252 ESR_TSTCFG_LBTEST_PAD); 2253 } else { 2254 ESR_REG_WR(handle, ESR_0_TEST_CONFIG_REG, 0); 2255 } 2256 2257 /* Deassert the reset register */ 2258 ESR_REG_RD(handle, ESR_RESET_REG, &val); 2259 val &= ~ESR_RESET_0; 2260 ESR_REG_WR(handle, ESR_RESET_REG, val); 2261 break; 2262 2263 case 1: 2264 /* Assert the reset register */ 2265 ESR_REG_RD(handle, ESR_RESET_REG, &val); 2266 val |= ESR_RESET_1; 2267 ESR_REG_WR(handle, ESR_RESET_REG, val); 2268 2269 /* Set PLL register to 0x79 */ 2270 ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG, 2271 ESR_PLL_CFG_1G_SERDES); 2272 2273 /* Set the control register to 0x249249f */ 2274 ESR_REG_WR(handle, ESR_1_CONTROL_REG, ESR_CTL_1G_SERDES); 2275 2276 /* Set Serdes1 Internal Loopback if necessary */ 2277 if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes1000) { 2278 /* Set pad loopback mode 0xaa */ 2279 ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 2280 ESR_TSTCFG_LBTEST_PAD); 2281 } else { 2282 ESR_REG_WR(handle, ESR_1_TEST_CONFIG_REG, 0); 2283 } 2284 2285 /* Deassert the reset register */ 2286 ESR_REG_RD(handle, ESR_RESET_REG, &val); 2287 val &= ~ESR_RESET_1; 2288 ESR_REG_WR(handle, ESR_RESET_REG, val); 2289 break; 2290 2291 default: 2292 /* Nothing to do here */ 2293 goto done; 2294 } 2295 2296 /* init TX RX channels */ 2297 for (chan = 0; chan < 4; chan++) { 2298 if ((status = nxge_mdio_read(nxgep, portn, 2299 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 2300 &rx_tx_ctrl_l.value)) != NXGE_OK) { 2301 goto fail; 2302 } 2303 if ((status = nxge_mdio_read(nxgep, portn, 2304 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 2305 &rx_tx_ctrl_h.value)) != NXGE_OK) { 2306 goto fail; 2307 } 2308 if ((status = nxge_mdio_read(nxgep, portn, 2309 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 2310 &glue_ctrl0_l.value)) != NXGE_OK) { 2311 goto fail; 2312 } 2313 if ((status = nxge_mdio_read(nxgep, portn, 2314 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 2315 &glue_ctrl0_h.value)) != NXGE_OK) { 2316 goto fail; 2317 } 2318 2319 rx_tx_ctrl_l.bits.enstretch = 1; 2320 rx_tx_ctrl_h.bits.vmuxlo = 2; 2321 rx_tx_ctrl_h.bits.vpulselo = 2; 2322 glue_ctrl0_l.bits.rxlosenable = 1; 2323 glue_ctrl0_l.bits.samplerate = 0xF; 2324 glue_ctrl0_l.bits.thresholdcount = 0xFF; 2325 glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES; 2326 if ((status = nxge_mdio_write(nxgep, portn, 2327 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 2328 rx_tx_ctrl_l.value)) != NXGE_OK) { 2329 goto fail; 2330 } 2331 if ((status = nxge_mdio_write(nxgep, portn, 2332 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 2333 rx_tx_ctrl_h.value)) != NXGE_OK) { 2334 goto fail; 2335 } 2336 if ((status = nxge_mdio_write(nxgep, portn, 2337 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 2338 glue_ctrl0_l.value)) != NXGE_OK) { 2339 goto fail; 2340 } 2341 if ((status = nxge_mdio_write(nxgep, portn, 2342 ESR_NEPTUNE_DEV_ADDR, ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 2343 glue_ctrl0_h.value)) != NXGE_OK) { 2344 goto fail; 2345 } 2346 } 2347 2348 if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2349 ESR_NEP_RX_POWER_CONTROL_L_ADDR(), 0xfff)) != NXGE_OK) { 2350 goto fail; 2351 } 2352 if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2353 ESR_NEP_RX_POWER_CONTROL_H_ADDR(), 0xfff)) != NXGE_OK) { 2354 goto fail; 2355 } 2356 if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2357 ESR_NEP_TX_POWER_CONTROL_L_ADDR(), 0x70)) != NXGE_OK) { 2358 goto fail; 2359 } 2360 if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2361 ESR_NEP_TX_POWER_CONTROL_H_ADDR(), 0xfff)) != NXGE_OK) { 2362 goto fail; 2363 } 2364 2365 /* Apply Tx core reset */ 2366 if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2367 ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0)) != NXGE_OK) { 2368 goto fail; 2369 } 2370 2371 if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2372 ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0xffff)) != 2373 NXGE_OK) { 2374 goto fail; 2375 } 2376 2377 NXGE_DELAY(200); 2378 2379 /* Apply Rx core reset */ 2380 if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2381 ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), (uint16_t)0xffff)) != 2382 NXGE_OK) { 2383 goto fail; 2384 } 2385 2386 NXGE_DELAY(200); 2387 if ((status = nxge_mdio_write(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2388 ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), (uint16_t)0)) != NXGE_OK) { 2389 goto fail; 2390 } 2391 2392 NXGE_DELAY(200); 2393 if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2394 ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), &val16l)) != NXGE_OK) { 2395 goto fail; 2396 } 2397 if ((status = nxge_mdio_read(nxgep, portn, ESR_NEPTUNE_DEV_ADDR, 2398 ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), &val16h)) != NXGE_OK) { 2399 goto fail; 2400 } 2401 if ((val16l != 0) || (val16h != 0)) { 2402 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2403 "Failed to reset port<%d> XAUI Serdes " 2404 "(val16l 0x%x val16h 0x%x)", portn, val16l, val16h)); 2405 status = NXGE_ERROR; 2406 goto fail; 2407 } 2408 2409 NXGE_DELAY(200); 2410 ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val); 2411 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2412 "nxge_neptune_serdes_init: read internal signal reg port<%d> " 2413 "val 0x%x", portn, val)); 2414 if (portn == 0) { 2415 if ((val & ESR_SIG_P0_BITS_MASK_1G) != 2416 (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0)) { 2417 /* 2418 * RDY signal stays low may due to the absent of the 2419 * external PHY, it is not an error condition. But still 2420 * print the message for the debugging purpose when link 2421 * stays down 2422 */ 2423 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2424 "nxge_neptune_1G_serdes_init: " 2425 "Serdes/signal for port<%d> not ready", portn)); 2426 goto done; 2427 } 2428 } else if (portn == 1) { 2429 if ((val & ESR_SIG_P1_BITS_MASK_1G) != 2430 (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1)) { 2431 /* 2432 * RDY signal stays low may due to the absent of the 2433 * external PHY, it is not an error condition. But still 2434 * print the message for the debugging purpose when link 2435 * stays down 2436 */ 2437 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2438 "nxge_neptune_1G_serdes_init: " 2439 "Serdes/signal for port<%d> not ready", portn)); 2440 goto done; 2441 2442 } 2443 } 2444 done: 2445 2446 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2447 "<== nxge_1G_serdes_init port<%d>", portn)); 2448 return (NXGE_OK); 2449 fail: 2450 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2451 "nxge_1G_serdes_init: " 2452 "Failed to initialize Neptune serdes for port<%d>", 2453 portn)); 2454 2455 return (status); 2456 } 2457 2458 /* Initialize the BCM 8704 xcvr */ 2459 2460 static nxge_status_t 2461 nxge_BCM8704_xcvr_init(p_nxge_t nxgep) 2462 { 2463 uint16_t val; 2464 #ifdef NXGE_DEBUG 2465 uint8_t portn; 2466 uint16_t val1; 2467 #endif 2468 uint8_t phy_port_addr; 2469 pmd_tx_control_t tx_ctl; 2470 control_t ctl; 2471 phyxs_control_t phyxs_ctl; 2472 pcs_control_t pcs_ctl; 2473 uint32_t delay = 0; 2474 optics_dcntr_t op_ctr; 2475 nxge_status_t status = NXGE_OK; 2476 #ifdef NXGE_DEBUG 2477 portn = nxgep->mac.portnum; 2478 #endif 2479 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8704_xcvr_init: port<%d>", 2480 portn)); 2481 2482 phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn; 2483 2484 /* Reset the transceiver */ 2485 if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 2486 BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK) 2487 goto fail; 2488 2489 phyxs_ctl.bits.reset = 1; 2490 if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 2491 BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK) 2492 goto fail; 2493 2494 do { 2495 drv_usecwait(500); 2496 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 2497 BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG, 2498 &phyxs_ctl.value)) != NXGE_OK) 2499 goto fail; 2500 delay++; 2501 } while ((phyxs_ctl.bits.reset) && (delay < 100)); 2502 if (delay == 100) { 2503 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: " 2504 "failed to reset Transceiver on port<%d>", portn)); 2505 status = NXGE_ERROR; 2506 goto fail; 2507 } 2508 2509 /* Set to 0x7FBF */ 2510 ctl.value = 0; 2511 ctl.bits.res1 = 0x3F; 2512 ctl.bits.optxon_lvl = 1; 2513 ctl.bits.oprxflt_lvl = 1; 2514 ctl.bits.optrxlos_lvl = 1; 2515 ctl.bits.optxflt_lvl = 1; 2516 ctl.bits.opprflt_lvl = 1; 2517 ctl.bits.obtmpflt_lvl = 1; 2518 ctl.bits.opbiasflt_lvl = 1; 2519 ctl.bits.optxrst_lvl = 1; 2520 if ((status = nxge_mdio_write(nxgep, phy_port_addr, 2521 BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, ctl.value)) 2522 != NXGE_OK) 2523 goto fail; 2524 2525 /* Set to 0x164 */ 2526 tx_ctl.value = 0; 2527 tx_ctl.bits.tsck_lpwren = 1; 2528 tx_ctl.bits.tx_dac_txck = 0x2; 2529 tx_ctl.bits.tx_dac_txd = 0x1; 2530 tx_ctl.bits.xfp_clken = 1; 2531 if ((status = nxge_mdio_write(nxgep, phy_port_addr, 2532 BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, 2533 tx_ctl.value)) != NXGE_OK) 2534 goto fail; 2535 /* 2536 * According to Broadcom's instruction, SW needs to read 2537 * back these registers twice after written. 2538 */ 2539 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 2540 BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val)) 2541 != NXGE_OK) 2542 goto fail; 2543 2544 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 2545 BCM8704_USER_DEV3_ADDR, BCM8704_USER_CONTROL_REG, &val)) 2546 != NXGE_OK) 2547 goto fail; 2548 2549 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 2550 BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val)) 2551 != NXGE_OK) 2552 goto fail; 2553 2554 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 2555 BCM8704_USER_DEV3_ADDR, BCM8704_USER_PMD_TX_CONTROL_REG, &val)) 2556 != NXGE_OK) 2557 goto fail; 2558 2559 /* Enable Tx and Rx LEDs to be driven by traffic */ 2560 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 2561 BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 2562 &op_ctr.value)) != NXGE_OK) 2563 goto fail; 2564 if (NXGE_IS_XAUI_PLATFORM(nxgep)) { 2565 op_ctr.bits.gpio_sel = 0x1; 2566 } else { 2567 op_ctr.bits.gpio_sel = 0x3; 2568 } 2569 if ((status = nxge_mdio_write(nxgep, phy_port_addr, 2570 BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 2571 op_ctr.value)) != NXGE_OK) 2572 goto fail; 2573 2574 NXGE_DELAY(1000000); 2575 2576 /* Set BCM8704 Internal Loopback mode if necessary */ 2577 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 2578 BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value)) 2579 != NXGE_OK) 2580 goto fail; 2581 if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g) 2582 pcs_ctl.bits.loopback = 1; 2583 else 2584 pcs_ctl.bits.loopback = 0; 2585 if ((status = nxge_mdio_write(nxgep, phy_port_addr, 2586 BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value)) 2587 != NXGE_OK) 2588 goto fail; 2589 2590 status = nxge_mdio_read(nxgep, phy_port_addr, 0x1, 0xA, &val); 2591 if (status != NXGE_OK) 2592 goto fail; 2593 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2594 "BCM8704 port<%d> Dev 1 Reg 0xA = 0x%x\n", portn, val)); 2595 status = nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0x20, &val); 2596 if (status != NXGE_OK) 2597 goto fail; 2598 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2599 "BCM8704 port<%d> Dev 3 Reg 0x20 = 0x%x\n", portn, val)); 2600 status = nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, &val); 2601 if (status != NXGE_OK) 2602 goto fail; 2603 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2604 "BCM8704 port<%d> Dev 4 Reg 0x18 = 0x%x\n", portn, val)); 2605 2606 #ifdef NXGE_DEBUG 2607 /* Diagnose link issue if link is not up */ 2608 status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_USER_DEV3_ADDR, 2609 BCM8704_USER_ANALOG_STATUS0_REG, 2610 &val); 2611 if (status != NXGE_OK) 2612 goto fail; 2613 2614 status = nxge_mdio_read(nxgep, phy_port_addr, 2615 BCM8704_USER_DEV3_ADDR, BCM8704_USER_ANALOG_STATUS0_REG, &val); 2616 if (status != NXGE_OK) 2617 goto fail; 2618 2619 status = nxge_mdio_read(nxgep, phy_port_addr, 2620 BCM8704_USER_DEV3_ADDR, BCM8704_USER_TX_ALARM_STATUS_REG, &val1); 2621 if (status != NXGE_OK) 2622 goto fail; 2623 2624 status = nxge_mdio_read(nxgep, phy_port_addr, 2625 BCM8704_USER_DEV3_ADDR, BCM8704_USER_TX_ALARM_STATUS_REG, &val1); 2626 if (status != NXGE_OK) 2627 goto fail; 2628 2629 if (val != 0x3FC) { 2630 if ((val == 0x43BC) && (val1 != 0)) { 2631 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2632 "Cable not connected to peer or bad" 2633 " cable on port<%d>\n", portn)); 2634 } else if (val == 0x639C) { 2635 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2636 "Optical module (XFP) is bad or absent" 2637 " on port<%d>\n", portn)); 2638 } 2639 } 2640 #endif 2641 2642 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8704_xcvr_init: port<%d>", 2643 portn)); 2644 return (NXGE_OK); 2645 2646 fail: 2647 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2648 "nxge_BCM8704_xcvr_init: failed to initialize transceiver for " 2649 "port<%d>", nxgep->mac.portnum)); 2650 return (NXGE_ERROR); 2651 } 2652 2653 /* Initialize the BCM 8706 Transceiver */ 2654 2655 static nxge_status_t 2656 nxge_BCM8706_xcvr_init(p_nxge_t nxgep) 2657 { 2658 uint8_t phy_port_addr; 2659 phyxs_control_t phyxs_ctl; 2660 pcs_control_t pcs_ctl; 2661 uint32_t delay = 0; 2662 optics_dcntr_t op_ctr; 2663 nxge_status_t status = NXGE_OK; 2664 #ifdef NXGE_DEBUG 2665 uint8_t portn = nxgep->mac.portnum; 2666 #endif 2667 2668 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8706_xcvr_init: port<%d>", 2669 portn)); 2670 2671 phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn; 2672 2673 /* Reset the transceiver */ 2674 if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 2675 BCM8704_PHYXS_CONTROL_REG, &phyxs_ctl.value)) != NXGE_OK) 2676 goto fail; 2677 2678 phyxs_ctl.bits.reset = 1; 2679 if ((status = nxge_mdio_write(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 2680 BCM8704_PHYXS_CONTROL_REG, phyxs_ctl.value)) != NXGE_OK) 2681 goto fail; 2682 do { 2683 drv_usecwait(500); 2684 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 2685 BCM8704_PHYXS_ADDR, BCM8704_PHYXS_CONTROL_REG, 2686 &phyxs_ctl.value)) != NXGE_OK) 2687 goto fail; 2688 delay++; 2689 } while ((phyxs_ctl.bits.reset) && (delay < 100)); 2690 2691 if (delay == 100) { 2692 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_xcvr_init: " 2693 "failed to reset Transceiver on port<%d>", portn)); 2694 status = NXGE_ERROR; 2695 goto fail; 2696 } 2697 2698 NXGE_DELAY(1000000); 2699 2700 /* Set BCM8706 Internal Loopback mode if necessary */ 2701 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 2702 BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, &pcs_ctl.value)) 2703 != NXGE_OK) 2704 goto fail; 2705 if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g) 2706 pcs_ctl.bits.loopback = 1; 2707 else 2708 pcs_ctl.bits.loopback = 0; 2709 if ((status = nxge_mdio_write(nxgep, phy_port_addr, 2710 BCM8704_PCS_DEV_ADDR, BCM8704_PCS_CONTROL_REG, pcs_ctl.value)) 2711 != NXGE_OK) 2712 goto fail; 2713 2714 /* Enable Tx and Rx LEDs to be driven by traffic */ 2715 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 2716 BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 2717 &op_ctr.value)) != NXGE_OK) 2718 goto fail; 2719 op_ctr.bits.gpio_sel = 0x3; 2720 op_ctr.bits.res2 = 0x1; 2721 2722 if ((status = nxge_mdio_write(nxgep, phy_port_addr, 2723 BCM8704_USER_DEV3_ADDR, BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 2724 op_ctr.value)) != NXGE_OK) 2725 goto fail; 2726 2727 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_BCM8706_xcvr_init: port<%d>", 2728 portn)); 2729 return (NXGE_OK); 2730 2731 fail: 2732 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2733 "nxge_BCM8706_xcvr_init: failed to initialize transceiver for " 2734 "port<%d>", nxgep->mac.portnum)); 2735 return (status); 2736 } 2737 2738 #define CHK_STAT(x) status = (x); if (status != NXGE_OK) goto fail 2739 2740 #define MRVL88X2011_RD(nxgep, port, d, r, p) \ 2741 CHK_STAT(nxge_mdio_read(nxgep, port, d, r, p)) 2742 2743 #define MRVL88X2011_WR(nxgep, port, d, r, p) \ 2744 CHK_STAT(nxge_mdio_write(nxgep, port, d, r, p)) 2745 2746 2747 static void 2748 nxge_mrvl88x2011_led_blink_rate(p_nxge_t nxgep, uint16_t rate) 2749 { 2750 uint16_t value; 2751 uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn; 2752 2753 if (nxge_mdio_read(nxgep, phy, MRVL_88X2011_USER_DEV2_ADDR, 2754 MRVL_88X2011_LED_BLINK_CTL, &value) == NXGE_OK) { 2755 value &= ~MRVL_88X2011_LED_BLK_MASK; 2756 value |= (rate << MRVL_88X2011_LED_BLK_SHIFT); 2757 (void) nxge_mdio_write(nxgep, phy, 2758 MRVL_88X2011_USER_DEV2_ADDR, MRVL_88X2011_LED_BLINK_CTL, 2759 value); 2760 } 2761 } 2762 2763 static nxge_status_t 2764 nxge_mrvl88x2011_setup_lb(p_nxge_t nxgep) 2765 { 2766 nxge_status_t status; 2767 pcs_control_t pcs_ctl; 2768 uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn; 2769 2770 MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR, 2771 MRVL_88X2011_PMA_PMD_CTL_1, &pcs_ctl.value); 2772 2773 if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g) 2774 pcs_ctl.bits.loopback = 1; 2775 else 2776 pcs_ctl.bits.loopback = 0; 2777 2778 MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR, 2779 MRVL_88X2011_PMA_PMD_CTL_1, pcs_ctl.value); 2780 2781 fail: 2782 return (status); 2783 } 2784 2785 2786 static void 2787 nxge_mrvl88x2011_led(p_nxge_t nxgep, uint16_t val) 2788 { 2789 uint16_t val2; 2790 uint8_t phy = nxgep->statsp->mac_stats.xcvr_portn; 2791 2792 val2 = MRVL_88X2011_LED(MRVL_88X2011_LED_ACT, val); 2793 val2 &= ~MRVL_88X2011_LED(MRVL_88X2011_LED_ACT, 2794 MRVL_88X2011_LED_CTL_MASK); 2795 val2 |= MRVL_88X2011_LED(MRVL_88X2011_LED_ACT, val); 2796 2797 if (nxge_mdio_write(nxgep, phy, MRVL_88X2011_USER_DEV2_ADDR, 2798 MRVL_88X2011_LED_8_TO_11_CTL, val2) != NXGE_OK) { 2799 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2800 "nxge_mrvl88x2011_led: nxge_mdio_write failed!!")); 2801 } 2802 } 2803 2804 2805 static nxge_status_t 2806 nxge_mrvl88x2011_xcvr_init(p_nxge_t nxgep) 2807 { 2808 uint8_t phy; 2809 nxge_status_t status; 2810 uint16_t clk; 2811 2812 phy = nxgep->statsp->mac_stats.xcvr_portn; 2813 2814 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2815 "==> nxge_mrvl88x2011_xcvr_init: port<%d> addr<0x%x>", 2816 nxgep->mac.portnum, phy)); 2817 2818 /* Set LED functions */ 2819 nxge_mrvl88x2011_led_blink_rate(nxgep, MRVL_88X2011_LED_BLK134MS); 2820 /* PCS activity */ 2821 nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_ACT); 2822 2823 MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR, 2824 MRVL_88X2011_GEN_CTL, &clk); 2825 clk |= MRVL_88X2011_ENA_XFPREFCLK; 2826 MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR, 2827 MRVL_88X2011_GEN_CTL, clk); 2828 2829 /* Set internal loopback mode if necessary */ 2830 2831 CHK_STAT(nxge_mrvl88x2011_setup_lb(nxgep)); 2832 2833 /* Enable PMD */ 2834 MRVL88X2011_WR(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR, 2835 MRVL_88X2011_10G_PMD_TX_DIS, MRVL_88X2011_ENA_PMDTX); 2836 2837 NXGE_DEBUG_MSG((nxgep, MAC_CTL, " nxge_mrvl88x2011_reset: OK")); 2838 2839 fail: 2840 return (status); 2841 } 2842 2843 2844 2845 /* Initialize the 10G Transceiver */ 2846 2847 static nxge_status_t 2848 nxge_10G_xcvr_init(p_nxge_t nxgep) 2849 { 2850 p_nxge_stats_t statsp; 2851 p_nxge_param_t param_arr = nxgep->param_arr; 2852 nxge_status_t status = NXGE_OK; 2853 #ifdef NXGE_DEBUG 2854 uint8_t portn = nxgep->mac.portnum; 2855 #endif 2856 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>", 2857 portn)); 2858 2859 statsp = nxgep->statsp; 2860 2861 /* Disable Link LEDs, with or without PHY */ 2862 if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 2863 goto done; 2864 2865 /* Skip MDIO, if PHY absent */ 2866 if (nxgep->mac.portmode == PORT_10G_SERDES || nxgep->phy_absent) { 2867 goto done; 2868 } 2869 2870 /* Set Clause 45 */ 2871 npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE); 2872 2873 switch (nxgep->chip_id) { 2874 case BCM8704_CHIP_ID: 2875 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_10G_xcvr_init: " 2876 "Chip ID 8704 [0x%x] for 10G xcvr", nxgep->chip_id)); 2877 status = nxge_BCM8704_xcvr_init(nxgep); 2878 break; 2879 case BCM8706_CHIP_ID: 2880 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_10G_xcvr_init: " 2881 "Chip ID 8706 [0x%x] for 10G xcvr", nxgep->chip_id)); 2882 status = nxge_BCM8706_xcvr_init(nxgep); 2883 break; 2884 case MRVL88X201X_CHIP_ID: 2885 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "nxge_10G_xcvr_init: " 2886 "Chip ID 8706 [0x%x] for 10G xcvr", nxgep->chip_id)); 2887 status = nxge_mrvl88x2011_xcvr_init(nxgep); 2888 break; 2889 default: 2890 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_xcvr_init: " 2891 "Unknown chip ID 0x%x for 10G xcvr addr[%d]", 2892 nxgep->chip_id, nxgep->statsp->mac_stats.xcvr_portn)); 2893 goto fail; 2894 } 2895 2896 if (status != NXGE_OK) { 2897 goto fail; 2898 } 2899 done: 2900 statsp->mac_stats.cap_10gfdx = 1; 2901 statsp->mac_stats.lp_cap_10gfdx = 1; 2902 statsp->mac_stats.adv_cap_asmpause = 2903 param_arr[param_anar_asmpause].value; 2904 statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value; 2905 2906 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_10G_xcvr_init: port<%d>", 2907 portn)); 2908 return (NXGE_OK); 2909 2910 fail: 2911 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2912 "nxge_10G_xcvr_init: failed to initialize transceiver for " 2913 "port<%d>", nxgep->mac.portnum)); 2914 return (NXGE_ERROR); 2915 } 2916 2917 /* Initialize the 1G copper (BCM 5464) Transceiver */ 2918 2919 static nxge_status_t 2920 nxge_1G_xcvr_init(p_nxge_t nxgep) 2921 { 2922 p_nxge_param_t param_arr = nxgep->param_arr; 2923 p_nxge_stats_t statsp = nxgep->statsp; 2924 nxge_status_t status = NXGE_OK; 2925 2926 if (nxgep->mac.portmode == PORT_1G_SERDES) { 2927 statsp->mac_stats.cap_1000fdx = 2928 param_arr[param_anar_1000fdx].value; 2929 goto done; 2930 } 2931 2932 /* Set Clause 22 */ 2933 npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_FALSE); 2934 2935 /* Set capability flags */ 2936 statsp->mac_stats.cap_1000fdx = param_arr[param_anar_1000fdx].value; 2937 if ((nxgep->mac.portmode == PORT_1G_COPPER) || 2938 (nxgep->mac.portmode == PORT_1G_FIBER)) { 2939 statsp->mac_stats.cap_100fdx = 2940 param_arr[param_anar_100fdx].value; 2941 statsp->mac_stats.cap_10fdx = 2942 param_arr[param_anar_10fdx].value; 2943 } 2944 2945 status = nxge_mii_xcvr_init(nxgep); 2946 done: 2947 return (status); 2948 } 2949 2950 /* 2951 * Although the Teranetics copper transceiver (TN1010) does not need 2952 * to be initialized by the driver for passing packets, this funtion 2953 * initializes the members of nxgep->statsp->mac_stats struct for 2954 * kstat based on the value of nxgep->statsp->ports_stats.lb_mode. 2955 * It also configures the TN1010 for PHY loopback to support SunVTS. 2956 * 2957 * TN1010 only has the option to disable advertisement for the 10G 2958 * mode. So we can set it to either Dual Mode or 1G Only mode but 2959 * can't set it to 10G Only mode. 2960 * 2961 * ndd -set command can set the following 6 speed/duplex related parameters. 2962 * 2963 * ---------------------------------------------------------------- 2964 * ndd -set /dev/nxgeX param n kstat nxge:X | grep param 2965 * ---------------------------------------------------------------- 2966 * adv_autoneg_cap kstat nxge:1 | grep adv_cap_autoneg 2967 * adv_10gfdx_cap 2968 * adv_1000fdx_cap kstat nxge:1 | grep adv_cap_1000fdx 2969 * adv_100fdx_cap kstat nxge:1 | grep adv_cap_100fdx 2970 * adv_10fdx_cap kstat nxge:1 | grep adv_cap_10fdx 2971 * adv_pause_cap kstat nxge:1 | grep adv_cap_pause 2972 * ---------------------------------------------------------------- 2973 */ 2974 static nxge_status_t 2975 nxge_tn1010_xcvr_init(p_nxge_t nxgep) 2976 { 2977 p_nxge_param_t param_arr; 2978 p_nxge_stats_t statsp; 2979 tn1010_pcs_ctrl_t tn1010_pcs_ctrl; 2980 uint16_t speed; 2981 uint8_t phy_port_addr; 2982 uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 2983 int status = NXGE_OK; 2984 2985 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_1G_tn1010_xcvr_init")); 2986 2987 param_arr = nxgep->param_arr; 2988 statsp = nxgep->statsp; 2989 2990 /* 2991 * Initialize the xcvr statistics which are NOT controlled by ndd 2992 */ 2993 statsp->mac_stats.cap_autoneg = 1; /* TN1010 autoneg is always on */ 2994 statsp->mac_stats.cap_100T4 = 0; 2995 2996 /* 2997 * Read the TN1010 link speed and initialize capabilities kstat. Note 2998 * that function nxge_check_tn1010_link repeatedly invoked by the 2999 * timer will update link_speed real time. 3000 */ 3001 if (nxge_get_tn1010_speed(nxgep, &speed) != NXGE_OK) { 3002 goto fail; 3003 } 3004 if (speed == TN1010_SPEED_1G) { 3005 statsp->mac_stats.cap_10gfdx = 0; 3006 } else { 3007 statsp->mac_stats.cap_10gfdx = 1; 3008 } 3009 3010 /* Whether we are in 1G or 10G mode, we always have the 1G capability */ 3011 statsp->mac_stats.cap_1000fdx = 1; 3012 3013 /* TN1010 is not able to operate in the following states */ 3014 statsp->mac_stats.cap_1000hdx = 0; 3015 statsp->mac_stats.cap_100fdx = 0; 3016 statsp->mac_stats.cap_100hdx = 0; 3017 statsp->mac_stats.cap_10fdx = 0; 3018 statsp->mac_stats.cap_10hdx = 0; 3019 3020 /* param_anar_pause can be modified by ndd -set */ 3021 statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value; 3022 3023 /* 3024 * The following 4 lines actually overwrites what ever the ndd command 3025 * has set. For example, by command 3026 * ndd -set /dev/nxge1 adv_autoneg_cap n (n = 0 or 1) 3027 * we could set param_arr[param_autoneg].value to n. However, because 3028 * here we assign constants to these parameters, whatever we set with 3029 * the "ndd -set" command will be replaced. So command 3030 * kstat nxge:X | grep param 3031 * will always show those constant values. In other words, the 3032 * "ndd -set" command can NOT change the values of these 4 parameters 3033 * even though the command appears to be successful. 3034 * 3035 * Note: TN1010 auto negotiation is always enabled. 3036 */ 3037 statsp->mac_stats.adv_cap_autoneg 3038 = param_arr[param_autoneg].value = 1; 3039 statsp->mac_stats.adv_cap_1000fdx 3040 = param_arr[param_anar_1000fdx].value = 1; 3041 statsp->mac_stats.adv_cap_100fdx 3042 = param_arr[param_anar_100fdx].value = 0; 3043 statsp->mac_stats.adv_cap_10fdx 3044 = param_arr[param_anar_10fdx].value = 0; 3045 3046 /* 3047 * The following 4 ndd params have type NXGE_PARAM_MAC_DONT_SHOW as 3048 * defined in nxge_param_arr[], therefore they are not seen by the 3049 * "ndd -get" command and can not be changed by ndd. We just set 3050 * them (both ndd param and kstat values) to constant 0 because TN1010 3051 * does not support those speeds. 3052 */ 3053 statsp->mac_stats.adv_cap_100T4 3054 = param_arr[param_anar_100T4].value = 0; 3055 statsp->mac_stats.adv_cap_1000hdx 3056 = param_arr[param_anar_1000hdx].value = 0; 3057 statsp->mac_stats.adv_cap_100hdx 3058 = param_arr[param_anar_100hdx].value = 0; 3059 statsp->mac_stats.adv_cap_10hdx 3060 = param_arr[param_anar_10hdx].value = 0; 3061 3062 /* 3063 * adv_cap_pause has type NXGE_PARAM_MAC_RW, so it can be modified 3064 * by ndd 3065 */ 3066 statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value; 3067 3068 /* 3069 * nxge_param_arr[] defines the adv_cap_asmpause with type 3070 * NXGE_PARAM_DONT_SHOW, therefore they are NOT seen by the 3071 * "ndd -get" command and can not be changed by ndd. Here we do not 3072 * assign a constant to it so the default value defined in 3073 * nxge_param_arr[] will be used to set the parameter and 3074 * will be shown by the kstat. 3075 */ 3076 statsp->mac_stats.adv_cap_asmpause 3077 = param_arr[param_anar_asmpause].value; 3078 3079 /* 3080 * Initialize the link statistics. 3081 */ 3082 statsp->mac_stats.link_T4 = 0; 3083 statsp->mac_stats.link_asmpause = 0; 3084 statsp->mac_stats.link_pause = 0; 3085 if (speed == TN1010_SPEED_1G) { 3086 statsp->mac_stats.link_speed = 1000; 3087 statsp->mac_stats.link_duplex = 2; /* Full duplex */ 3088 statsp->mac_stats.link_up = 1; 3089 } else { 3090 statsp->mac_stats.link_speed = 10000; 3091 statsp->mac_stats.link_duplex = 2; 3092 statsp->mac_stats.link_up = 1; 3093 } 3094 3095 /* 3096 * Because TN1010 does not have a link partner register, to 3097 * figure out the link partner's capabilities is tricky. Here we 3098 * just set the kstat based on our knowledge about the partner 3099 * (The partner must support auto-neg because auto-negotiation 3100 * has completed, it must support 1G or 10G because that is the 3101 * negotiated speed we are using.) 3102 * 3103 * Note: Current kstat does not show lp_cap_10gfdx and 3104 * lp_cap_10ghdx. 3105 */ 3106 if (speed == TN1010_SPEED_1G) { 3107 statsp->mac_stats.lp_cap_1000fdx = 1; 3108 statsp->mac_stats.lp_cap_10gfdx = 0; 3109 } else { 3110 statsp->mac_stats.lp_cap_1000fdx = 0; 3111 statsp->mac_stats.lp_cap_10gfdx = 1; 3112 } 3113 statsp->mac_stats.lp_cap_10ghdx = 0; 3114 statsp->mac_stats.lp_cap_1000hdx = 0; 3115 statsp->mac_stats.lp_cap_100fdx = 0; 3116 statsp->mac_stats.lp_cap_100hdx = 0; 3117 statsp->mac_stats.lp_cap_10fdx = 0; 3118 statsp->mac_stats.lp_cap_10hdx = 0; 3119 statsp->mac_stats.lp_cap_10gfdx = 0; 3120 statsp->mac_stats.lp_cap_10ghdx = 0; 3121 statsp->mac_stats.lp_cap_100T4 = 0; 3122 statsp->mac_stats.lp_cap_autoneg = 1; 3123 statsp->mac_stats.lp_cap_asmpause = 0; 3124 statsp->mac_stats.lp_cap_pause = 0; 3125 3126 /* Handle PHY loopback for SunVTS loopback test */ 3127 npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE); 3128 phy_port_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 3129 3130 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 3131 TN1010_PCS_DEV_ADDR, TN1010_PCS_CONTROL_REG, 3132 &tn1010_pcs_ctrl.value)) != NXGE_OK) { 3133 goto fail; 3134 } 3135 if ((statsp->port_stats.lb_mode == nxge_lb_phy1000) || 3136 (statsp->port_stats.lb_mode == nxge_lb_phy10g)) { 3137 tn1010_pcs_ctrl.bits.loopback = 1; 3138 } else { 3139 tn1010_pcs_ctrl.bits.loopback = 0; 3140 } 3141 if ((status = nxge_mdio_write(nxgep, phy_port_addr, 3142 TN1010_PCS_DEV_ADDR, TN1010_PCS_CONTROL_REG, 3143 tn1010_pcs_ctrl.value)) != NXGE_OK) { 3144 goto fail; 3145 } 3146 3147 statsp->mac_stats.xcvr_inits++; 3148 3149 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3150 "<== nxge_1G_tn1010_xcvr_init status 0x%x", status)); 3151 return (status); 3152 fail: 3153 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3154 "<== nxge_1G_tn1010_xcvr_init status 0x%x", status)); 3155 return (status); 3156 } 3157 3158 /* Initialize transceiver */ 3159 3160 nxge_status_t 3161 nxge_xcvr_init(p_nxge_t nxgep) 3162 { 3163 p_nxge_stats_t statsp; 3164 #ifdef NXGE_DEBUG 3165 uint8_t portn; 3166 #endif 3167 3168 nxge_status_t status = NXGE_OK; 3169 #ifdef NXGE_DEBUG 3170 portn = nxgep->mac.portnum; 3171 #endif 3172 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", portn)); 3173 statsp = nxgep->statsp; 3174 3175 /* 3176 * Initialize the xcvr statistics. nxgep->xcvr.xcvr_init will 3177 * modify mac_stats. 3178 */ 3179 statsp->mac_stats.cap_autoneg = 0; 3180 statsp->mac_stats.cap_100T4 = 0; 3181 statsp->mac_stats.cap_100fdx = 0; 3182 statsp->mac_stats.cap_100hdx = 0; 3183 statsp->mac_stats.cap_10fdx = 0; 3184 statsp->mac_stats.cap_10hdx = 0; 3185 statsp->mac_stats.cap_asmpause = 0; 3186 statsp->mac_stats.cap_pause = 0; 3187 statsp->mac_stats.cap_1000fdx = 0; 3188 statsp->mac_stats.cap_1000hdx = 0; 3189 statsp->mac_stats.cap_10gfdx = 0; 3190 statsp->mac_stats.cap_10ghdx = 0; 3191 3192 /* 3193 * Initialize the link statistics. 3194 */ 3195 statsp->mac_stats.link_T4 = 0; 3196 statsp->mac_stats.link_asmpause = 0; 3197 statsp->mac_stats.link_pause = 0; 3198 3199 if (nxgep->xcvr.xcvr_init) { 3200 status = nxgep->xcvr.xcvr_init(nxgep); 3201 if (status != NXGE_OK) 3202 goto fail; 3203 statsp->mac_stats.xcvr_inits++; 3204 } 3205 3206 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", 3207 portn)); 3208 return (NXGE_OK); 3209 3210 fail: 3211 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3212 "nxge_xcvr_init: failed to initialize transceiver for port<%d>", 3213 portn)); 3214 return (status); 3215 } 3216 3217 /* Look for transceiver type */ 3218 3219 nxge_status_t 3220 nxge_xcvr_find(p_nxge_t nxgep) 3221 { 3222 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_find: port<%d>", 3223 nxgep->mac.portnum)); 3224 3225 if (nxge_get_xcvr_type(nxgep) != NXGE_OK) 3226 return (NXGE_ERROR); 3227 3228 if (nxge_setup_xcvr_table(nxgep) != NXGE_OK) 3229 return (NXGE_ERROR); 3230 3231 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xcvr_find: xcvr_inuse = %d", 3232 nxgep->statsp->mac_stats.xcvr_inuse)); 3233 return (NXGE_OK); 3234 } 3235 3236 /* Initialize the TxMAC sub-block */ 3237 3238 nxge_status_t 3239 nxge_tx_mac_init(p_nxge_t nxgep) 3240 { 3241 npi_attr_t ap; 3242 uint8_t portn; 3243 nxge_port_mode_t portmode; 3244 nxge_port_t portt; 3245 npi_handle_t handle; 3246 npi_status_t rs = NPI_SUCCESS; 3247 3248 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 3249 portt = nxgep->mac.porttype; 3250 handle = nxgep->npi_handle; 3251 portmode = nxgep->mac.portmode; 3252 3253 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_init: port<%d>", 3254 portn)); 3255 /* Set Max and Min Frame Size */ 3256 /* 3257 * Use maxframesize to configure the hardware maxframe size 3258 * and minframesize to configure the hardware minframe size. 3259 */ 3260 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3261 "==> nxge_tx_mac_init: port<%d> " 3262 "min framesize %d max framesize %d ", 3263 nxgep->mac.minframesize, 3264 nxgep->mac.maxframesize, 3265 portn)); 3266 3267 SET_MAC_ATTR2(handle, ap, portn, 3268 MAC_PORT_FRAME_SIZE, 3269 nxgep->mac.minframesize, 3270 nxgep->mac.maxframesize, 3271 rs); 3272 if (rs != NPI_SUCCESS) 3273 goto fail; 3274 3275 if (portt == PORT_TYPE_XMAC) { 3276 if ((rs = npi_xmac_tx_iconfig(handle, INIT, portn, 3277 0)) != NPI_SUCCESS) 3278 goto fail; 3279 nxgep->mac.tx_iconfig = NXGE_XMAC_TX_INTRS; 3280 if ((portmode == PORT_10G_FIBER) || 3281 (portmode == PORT_10G_COPPER) || 3282 (portmode == PORT_10G_TN1010) || 3283 (portmode == PORT_HSP_MODE) || 3284 (portmode == PORT_10G_SERDES)) { 3285 SET_MAC_ATTR1(handle, ap, portn, XMAC_10G_PORT_IPG, 3286 XGMII_IPG_12_15, rs); 3287 if (rs != NPI_SUCCESS) 3288 goto fail; 3289 nxgep->mac.ipg[0] = XGMII_IPG_12_15; 3290 } else { 3291 SET_MAC_ATTR1(handle, ap, portn, XMAC_PORT_IPG, 3292 MII_GMII_IPG_12, rs); 3293 if (rs != NPI_SUCCESS) 3294 goto fail; 3295 nxgep->mac.ipg[0] = MII_GMII_IPG_12; 3296 } 3297 if ((rs = npi_xmac_tx_config(handle, INIT, portn, 3298 CFG_XMAC_TX_CRC | CFG_XMAC_TX)) != NPI_SUCCESS) 3299 goto fail; 3300 nxgep->mac.tx_config = CFG_XMAC_TX_CRC | CFG_XMAC_TX; 3301 nxgep->mac.maxburstsize = 0; /* not programmable */ 3302 nxgep->mac.ctrltype = 0; /* not programmable */ 3303 nxgep->mac.pa_size = 0; /* not programmable */ 3304 3305 if ((rs = npi_xmac_zap_tx_counters(handle, portn)) 3306 != NPI_SUCCESS) 3307 goto fail; 3308 3309 } else { 3310 if ((rs = npi_bmac_tx_iconfig(handle, INIT, portn, 3311 0)) != NPI_SUCCESS) 3312 goto fail; 3313 nxgep->mac.tx_iconfig = NXGE_BMAC_TX_INTRS; 3314 3315 SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_CTRL_TYPE, 0x8808, 3316 rs); 3317 if (rs != NPI_SUCCESS) 3318 goto fail; 3319 nxgep->mac.ctrltype = 0x8808; 3320 3321 SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_PA_SIZE, 0x7, rs); 3322 if (rs != NPI_SUCCESS) 3323 goto fail; 3324 nxgep->mac.pa_size = 0x7; 3325 3326 if ((rs = npi_bmac_tx_config(handle, INIT, portn, 3327 CFG_BMAC_TX_CRC | CFG_BMAC_TX)) != NPI_SUCCESS) 3328 goto fail; 3329 nxgep->mac.tx_config = CFG_BMAC_TX_CRC | CFG_BMAC_TX; 3330 } 3331 3332 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_init: port<%d>", 3333 portn)); 3334 3335 return (NXGE_OK); 3336 fail: 3337 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3338 "nxge_tx_mac_init: failed to initialize port<%d> TXMAC", portn)); 3339 3340 return (NXGE_ERROR | rs); 3341 } 3342 3343 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 /* Only status change will update *link_up */ 4687 if (statsp->mac_stats.link_up == 1) { 4688 *link_up = LINK_IS_DOWN; 4689 /* Will notify, turn off further msg */ 4690 nxgep->link_notify = B_FALSE; 4691 } 4692 statsp->mac_stats.link_up = 0; 4693 soft_bmsr->bits.link_status = 0; 4694 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4695 "Link down cable problem")); 4696 } 4697 } 4698 4699 if (nxgep->mac.portmode == PORT_1G_COPPER && 4700 param_arr[param_autoneg].value) { 4701 if (bmsr_ints.bits.auto_neg_complete) { 4702 if (bmsr.bits.auto_neg_complete) 4703 soft_bmsr->bits.auto_neg_complete = 1; 4704 else 4705 soft_bmsr->bits.auto_neg_complete = 0; 4706 } 4707 if (soft_bmsr->bits.link_status == 0) { 4708 statsp->mac_stats.link_T4 = 0; 4709 statsp->mac_stats.link_speed = 0; 4710 statsp->mac_stats.link_duplex = 0; 4711 statsp->mac_stats.link_asmpause = 0; 4712 statsp->mac_stats.link_pause = 0; 4713 statsp->mac_stats.lp_cap_autoneg = 0; 4714 statsp->mac_stats.lp_cap_100T4 = 0; 4715 statsp->mac_stats.lp_cap_1000fdx = 0; 4716 statsp->mac_stats.lp_cap_1000hdx = 0; 4717 statsp->mac_stats.lp_cap_100fdx = 0; 4718 statsp->mac_stats.lp_cap_100hdx = 0; 4719 statsp->mac_stats.lp_cap_10fdx = 0; 4720 statsp->mac_stats.lp_cap_10hdx = 0; 4721 statsp->mac_stats.lp_cap_10gfdx = 0; 4722 statsp->mac_stats.lp_cap_10ghdx = 0; 4723 statsp->mac_stats.lp_cap_asmpause = 0; 4724 statsp->mac_stats.lp_cap_pause = 0; 4725 } 4726 } else 4727 soft_bmsr->bits.auto_neg_complete = 1; 4728 4729 if ((bmsr_ints.bits.link_status || 4730 bmsr_ints.bits.auto_neg_complete) && 4731 soft_bmsr->bits.link_status && 4732 soft_bmsr->bits.auto_neg_complete) { 4733 if (statsp->mac_stats.link_up == 0) { 4734 *link_up = LINK_IS_UP; 4735 nxgep->link_notify = B_FALSE; 4736 } 4737 statsp->mac_stats.link_up = 1; 4738 4739 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 4740 "==> nxge_mii_check " 4741 "(auto negotiation complete or link up) " 4742 "soft bmsr 0x%x bmsr_int 0x%x", 4743 bmsr.value, bmsr_ints.value)); 4744 4745 if (nxgep->mac.portmode == PORT_1G_COPPER && 4746 param_arr[param_autoneg].value) { 4747 if ((status = nxge_mii_read(nxgep, 4748 statsp->mac_stats.xcvr_portn, 4749 #if defined(__i386) 4750 (uint8_t)(uint32_t)(&mii_regs->anar), 4751 #else 4752 (uint8_t)(uint64_t)(&mii_regs->anar), 4753 #endif 4754 &anar.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->anlpar), 4760 #else 4761 (uint8_t)(uint64_t)(&mii_regs->anlpar), 4762 #endif 4763 &anlpar.value)) != NXGE_OK) 4764 goto fail; 4765 if ((status = nxge_mii_read(nxgep, 4766 statsp->mac_stats.xcvr_portn, 4767 #if defined(__i386) 4768 (uint8_t)(uint32_t)(&mii_regs->aner), 4769 #else 4770 (uint8_t)(uint64_t)(&mii_regs->aner), 4771 #endif 4772 &aner.value)) != NXGE_OK) 4773 goto fail; 4774 statsp->mac_stats.lp_cap_autoneg = aner.bits.lp_an_able; 4775 statsp->mac_stats.lp_cap_100T4 = anlpar.bits.cap_100T4; 4776 statsp->mac_stats.lp_cap_100fdx = 4777 anlpar.bits.cap_100fdx; 4778 statsp->mac_stats.lp_cap_100hdx = 4779 anlpar.bits.cap_100hdx; 4780 statsp->mac_stats.lp_cap_10fdx = anlpar.bits.cap_10fdx; 4781 statsp->mac_stats.lp_cap_10hdx = anlpar.bits.cap_10hdx; 4782 statsp->mac_stats.lp_cap_asmpause = 4783 anlpar.bits.cap_asmpause; 4784 statsp->mac_stats.lp_cap_pause = anlpar.bits.cap_pause; 4785 an_common.value = anar.value & anlpar.value; 4786 if (param_arr[param_anar_1000fdx].value || 4787 param_arr[param_anar_1000hdx].value) { 4788 if ((status = nxge_mii_read(nxgep, 4789 statsp->mac_stats.xcvr_portn, 4790 #if defined(__i386) 4791 (uint8_t)(uint32_t)(&mii_regs->gsr), 4792 #else 4793 (uint8_t)(uint64_t)(&mii_regs->gsr), 4794 #endif 4795 &gsr.value)) != NXGE_OK) 4796 goto fail; 4797 statsp->mac_stats.lp_cap_1000fdx = 4798 gsr.bits.link_1000fdx; 4799 statsp->mac_stats.lp_cap_1000hdx = 4800 gsr.bits.link_1000hdx; 4801 if (param_arr[param_anar_1000fdx].value && 4802 gsr.bits.link_1000fdx) { 4803 statsp->mac_stats.link_speed = 1000; 4804 statsp->mac_stats.link_duplex = 2; 4805 } else if ( 4806 param_arr[param_anar_1000hdx].value && 4807 gsr.bits.link_1000hdx) { 4808 statsp->mac_stats.link_speed = 1000; 4809 statsp->mac_stats.link_duplex = 1; 4810 } 4811 } 4812 if ((an_common.value != 0) && 4813 !(statsp->mac_stats.link_speed)) { 4814 if (an_common.bits.cap_100T4) { 4815 statsp->mac_stats.link_T4 = 1; 4816 statsp->mac_stats.link_speed = 100; 4817 statsp->mac_stats.link_duplex = 1; 4818 } else if (an_common.bits.cap_100fdx) { 4819 statsp->mac_stats.link_speed = 100; 4820 statsp->mac_stats.link_duplex = 2; 4821 } else if (an_common.bits.cap_100hdx) { 4822 statsp->mac_stats.link_speed = 100; 4823 statsp->mac_stats.link_duplex = 1; 4824 } else if (an_common.bits.cap_10fdx) { 4825 statsp->mac_stats.link_speed = 10; 4826 statsp->mac_stats.link_duplex = 2; 4827 } else if (an_common.bits.cap_10hdx) { 4828 statsp->mac_stats.link_speed = 10; 4829 statsp->mac_stats.link_duplex = 1; 4830 } else { 4831 goto fail; 4832 } 4833 } 4834 if (statsp->mac_stats.link_duplex != 1) { 4835 int link_pause; 4836 int cp, lcp; 4837 4838 statsp->mac_stats.link_asmpause = 4839 an_common.bits.cap_asmpause; 4840 cp = statsp->mac_stats.cap_pause; 4841 lcp = statsp->mac_stats.lp_cap_pause; 4842 if (statsp->mac_stats.link_asmpause) { 4843 if ((cp == 0) && (lcp == 1)) { 4844 link_pause = 0; 4845 } else { 4846 link_pause = 1; 4847 } 4848 } else { 4849 link_pause = an_common.bits.cap_pause; 4850 } 4851 statsp->mac_stats.link_pause = link_pause; 4852 } 4853 } else if (nxgep->mac.portmode == PORT_1G_RGMII_FIBER) { 4854 statsp->mac_stats.link_speed = 1000; 4855 statsp->mac_stats.link_duplex = 2; 4856 } 4857 } 4858 /* Initial link_notify, delay link down msg */ 4859 if (nxgep->link_notify && nxgep->nxge_mac_state == NXGE_MAC_STARTED && 4860 (statsp->mac_stats.link_up == 1 || nxgep->link_check_count > 3)) { 4861 *link_up = ((statsp->mac_stats.link_up) ? LINK_IS_UP : 4862 LINK_IS_DOWN); 4863 nxgep->link_notify = B_FALSE; 4864 } 4865 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mii_check")); 4866 return (NXGE_OK); 4867 fail: 4868 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 4869 "nxge_mii_check: Unable to check MII")); 4870 return (status); 4871 } 4872 4873 /* 4874 * Check PCS to see if there is any link status change. 4875 * This function is called by PORT_1G_SERDES only. 4876 */ 4877 void 4878 nxge_pcs_check(p_nxge_t nxgep, uint8_t portn, nxge_link_state_t *link_up) 4879 { 4880 p_nxge_stats_t statsp; 4881 boolean_t linkup; 4882 4883 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_check")); 4884 4885 statsp = nxgep->statsp; 4886 *link_up = LINK_NO_CHANGE; 4887 4888 (void) npi_mac_get_link_status(nxgep->npi_handle, portn, &linkup); 4889 if (linkup) { 4890 if ((nxgep->link_notify && 4891 nxgep->nxge_mac_state == NXGE_MAC_STARTED) || 4892 nxgep->statsp->mac_stats.link_up == 0) { 4893 statsp->mac_stats.link_up = 1; 4894 statsp->mac_stats.link_speed = 1000; 4895 statsp->mac_stats.link_duplex = 2; 4896 *link_up = LINK_IS_UP; 4897 nxgep->link_notify = B_FALSE; 4898 } 4899 } else { 4900 if ((nxgep->link_notify && nxgep->link_check_count > 3 && 4901 nxgep->nxge_mac_state == NXGE_MAC_STARTED) || 4902 nxgep->statsp->mac_stats.link_up == 1) { 4903 statsp->mac_stats.link_up = 0; 4904 statsp->mac_stats.link_speed = 0; 4905 statsp->mac_stats.link_duplex = 0; 4906 *link_up = LINK_IS_DOWN; 4907 nxgep->link_notify = B_FALSE; 4908 } 4909 } 4910 4911 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_check")); 4912 } 4913 4914 /* Add a multicast address entry into the HW hash table */ 4915 4916 nxge_status_t 4917 nxge_add_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp) 4918 { 4919 uint32_t mchash; 4920 p_hash_filter_t hash_filter; 4921 uint16_t hash_bit; 4922 boolean_t rx_init = B_FALSE; 4923 uint_t j; 4924 nxge_status_t status = NXGE_OK; 4925 4926 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_add_mcast_addr")); 4927 4928 RW_ENTER_WRITER(&nxgep->filter_lock); 4929 mchash = crc32_mchash(addrp); 4930 if (nxgep->hash_filter == NULL) { 4931 NXGE_DEBUG_MSG((NULL, STR_CTL, 4932 "Allocating hash filter storage.")); 4933 nxgep->hash_filter = KMEM_ZALLOC(sizeof (hash_filter_t), 4934 KM_SLEEP); 4935 } 4936 hash_filter = nxgep->hash_filter; 4937 j = mchash / HASH_REG_WIDTH; 4938 hash_bit = (1 << (mchash % HASH_REG_WIDTH)); 4939 hash_filter->hash_filter_regs[j] |= hash_bit; 4940 hash_filter->hash_bit_ref_cnt[mchash]++; 4941 if (hash_filter->hash_bit_ref_cnt[mchash] == 1) { 4942 hash_filter->hash_ref_cnt++; 4943 rx_init = B_TRUE; 4944 } 4945 if (rx_init) { 4946 if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 4947 goto fail; 4948 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 4949 goto fail; 4950 } 4951 4952 RW_EXIT(&nxgep->filter_lock); 4953 4954 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_add_mcast_addr")); 4955 4956 return (NXGE_OK); 4957 fail: 4958 RW_EXIT(&nxgep->filter_lock); 4959 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_add_mcast_addr: " 4960 "Unable to add multicast address")); 4961 return (status); 4962 } 4963 4964 /* Remove a multicast address entry from the HW hash table */ 4965 4966 nxge_status_t 4967 nxge_del_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp) 4968 { 4969 uint32_t mchash; 4970 p_hash_filter_t hash_filter; 4971 uint16_t hash_bit; 4972 boolean_t rx_init = B_FALSE; 4973 uint_t j; 4974 nxge_status_t status = NXGE_OK; 4975 4976 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_del_mcast_addr")); 4977 RW_ENTER_WRITER(&nxgep->filter_lock); 4978 mchash = crc32_mchash(addrp); 4979 if (nxgep->hash_filter == NULL) { 4980 NXGE_DEBUG_MSG((NULL, STR_CTL, 4981 "Hash filter already de_allocated.")); 4982 RW_EXIT(&nxgep->filter_lock); 4983 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr")); 4984 return (NXGE_OK); 4985 } 4986 hash_filter = nxgep->hash_filter; 4987 hash_filter->hash_bit_ref_cnt[mchash]--; 4988 if (hash_filter->hash_bit_ref_cnt[mchash] == 0) { 4989 j = mchash / HASH_REG_WIDTH; 4990 hash_bit = (1 << (mchash % HASH_REG_WIDTH)); 4991 hash_filter->hash_filter_regs[j] &= ~hash_bit; 4992 hash_filter->hash_ref_cnt--; 4993 rx_init = B_TRUE; 4994 } 4995 if (hash_filter->hash_ref_cnt == 0) { 4996 NXGE_DEBUG_MSG((NULL, STR_CTL, 4997 "De-allocating hash filter storage.")); 4998 KMEM_FREE(hash_filter, sizeof (hash_filter_t)); 4999 nxgep->hash_filter = NULL; 5000 } 5001 5002 if (rx_init) { 5003 if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 5004 goto fail; 5005 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 5006 goto fail; 5007 } 5008 RW_EXIT(&nxgep->filter_lock); 5009 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr")); 5010 5011 return (NXGE_OK); 5012 fail: 5013 RW_EXIT(&nxgep->filter_lock); 5014 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_del_mcast_addr: " 5015 "Unable to remove multicast address")); 5016 5017 return (status); 5018 } 5019 5020 /* Set MAC address into MAC address HW registers */ 5021 5022 nxge_status_t 5023 nxge_set_mac_addr(p_nxge_t nxgep, struct ether_addr *addrp) 5024 { 5025 nxge_status_t status = NXGE_OK; 5026 5027 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_mac_addr")); 5028 5029 MUTEX_ENTER(&nxgep->ouraddr_lock); 5030 /* 5031 * Exit if the address is same as ouraddr or multicast or broadcast 5032 */ 5033 if (((addrp->ether_addr_octet[0] & 01) == 1) || 5034 (ether_cmp(addrp, ðerbroadcastaddr) == 0) || 5035 (ether_cmp(addrp, &nxgep->ouraddr) == 0)) { 5036 goto nxge_set_mac_addr_exit; 5037 } 5038 nxgep->ouraddr = *addrp; 5039 /* 5040 * Set new interface local address and re-init device. 5041 * This is destructive to any other streams attached 5042 * to this device. 5043 */ 5044 RW_ENTER_WRITER(&nxgep->filter_lock); 5045 if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 5046 goto fail; 5047 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 5048 goto fail; 5049 5050 RW_EXIT(&nxgep->filter_lock); 5051 MUTEX_EXIT(&nxgep->ouraddr_lock); 5052 goto nxge_set_mac_addr_end; 5053 nxge_set_mac_addr_exit: 5054 MUTEX_EXIT(&nxgep->ouraddr_lock); 5055 nxge_set_mac_addr_end: 5056 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_mac_addr")); 5057 5058 return (NXGE_OK); 5059 fail: 5060 MUTEX_EXIT(&nxgep->ouraddr_lock); 5061 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_mac_addr: " 5062 "Unable to set mac address")); 5063 return (status); 5064 } 5065 5066 static 5067 check_link_state_t 5068 nxge_check_link_stop(nxge_t *nxge) 5069 { 5070 /* If the poll has been cancelled, return STOP. */ 5071 MUTEX_ENTER(&nxge->poll_lock); 5072 if (nxge->suspended || nxge->poll_state == LINK_MONITOR_STOPPING) { 5073 nxge->poll_state = LINK_MONITOR_STOP; 5074 nxge->nxge_link_poll_timerid = 0; 5075 cv_broadcast(&nxge->poll_cv); 5076 MUTEX_EXIT(&nxge->poll_lock); 5077 5078 NXGE_DEBUG_MSG((nxge, MAC_CTL, 5079 "nxge_check_%s_link(port<%d>) stopped.", 5080 nxge->mac.portmode == PORT_10G_FIBER ? "10g" : "mii", 5081 nxge->mac.portnum)); 5082 return (CHECK_LINK_STOP); 5083 } 5084 MUTEX_EXIT(&nxge->poll_lock); 5085 5086 return (CHECK_LINK_RESCHEDULE); 5087 } 5088 5089 /* 5090 * Check status of MII (MIF or PCS) link. 5091 * This function is called once per second, that is because this function 5092 * calls nxge_link_monitor with LINK_MONITOR_START, which starts a timer to 5093 * call this function recursively. 5094 */ 5095 static nxge_status_t 5096 nxge_check_mii_link(p_nxge_t nxgep) 5097 { 5098 mii_bmsr_t bmsr_ints, bmsr_data; 5099 mii_anlpar_t anlpar; 5100 mii_gsr_t gsr; 5101 p_mii_regs_t mii_regs; 5102 nxge_status_t status = NXGE_OK; 5103 uint8_t portn; 5104 nxge_link_state_t link_up; 5105 5106 if (nxgep->nxge_magic != NXGE_MAGIC) 5107 return (NXGE_ERROR); 5108 5109 if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 5110 return (NXGE_OK); 5111 5112 portn = nxgep->mac.portnum; 5113 5114 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_mii_link port<%d>", 5115 portn)); 5116 5117 mii_regs = NULL; 5118 5119 RW_ENTER_WRITER(&nxgep->filter_lock); 5120 5121 if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10) 5122 goto nxge_check_mii_link_exit; 5123 5124 switch (nxgep->mac.portmode) { 5125 default: 5126 bmsr_data.value = 0; 5127 if ((status = nxge_mii_read(nxgep, 5128 nxgep->statsp->mac_stats.xcvr_portn, 5129 #if defined(__i386) 5130 (uint8_t)(uint32_t)(&mii_regs->bmsr), 5131 #else 5132 (uint8_t)(uint64_t)(&mii_regs->bmsr), 5133 #endif 5134 &bmsr_data.value)) != NXGE_OK) { 5135 goto fail; 5136 } 5137 5138 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5139 "==> nxge_check_mii_link port<0x%x> " 5140 "RIGHT AFTER READ bmsr_data 0x%x (nxgep->bmsr 0x%x ", 5141 portn, bmsr_data.value, nxgep->bmsr.value)); 5142 5143 if (nxgep->param_arr[param_autoneg].value) { 5144 if ((status = nxge_mii_read(nxgep, 5145 nxgep->statsp->mac_stats.xcvr_portn, 5146 #if defined(__i386) 5147 (uint8_t)(uint32_t)(&mii_regs->gsr), 5148 #else 5149 (uint8_t)(uint64_t)(&mii_regs->gsr), 5150 #endif 5151 &gsr.value)) != NXGE_OK) 5152 goto fail; 5153 if ((status = nxge_mii_read(nxgep, 5154 nxgep->statsp->mac_stats.xcvr_portn, 5155 #if defined(__i386) 5156 (uint8_t)(uint32_t)(&mii_regs->anlpar), 5157 #else 5158 (uint8_t)(uint64_t)(&mii_regs->anlpar), 5159 #endif 5160 &anlpar.value)) != NXGE_OK) 5161 goto fail; 5162 if (nxgep->mac.portmode != PORT_1G_RGMII_FIBER) { 5163 5164 if (nxgep->statsp->mac_stats.link_up && 5165 ((nxgep->statsp->mac_stats.lp_cap_1000fdx ^ 5166 gsr.bits.link_1000fdx) || 5167 (nxgep->statsp->mac_stats.lp_cap_1000hdx ^ 5168 gsr.bits.link_1000hdx) || 5169 (nxgep->statsp->mac_stats.lp_cap_100T4 ^ 5170 anlpar.bits.cap_100T4) || 5171 (nxgep->statsp->mac_stats.lp_cap_100fdx ^ 5172 anlpar.bits.cap_100fdx) || 5173 (nxgep->statsp->mac_stats.lp_cap_100hdx ^ 5174 anlpar.bits.cap_100hdx) || 5175 (nxgep->statsp->mac_stats.lp_cap_10fdx ^ 5176 anlpar.bits.cap_10fdx) || 5177 (nxgep->statsp->mac_stats.lp_cap_10hdx ^ 5178 anlpar.bits.cap_10hdx))) { 5179 bmsr_data.bits.link_status = 0; 5180 } 5181 } 5182 } 5183 5184 /* Workaround for link down issue */ 5185 if (bmsr_data.value == 0) { 5186 cmn_err(CE_NOTE, "!LINK DEBUG: Read zero bmsr\n"); 5187 goto nxge_check_mii_link_exit; 5188 } 5189 5190 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5191 "==> nxge_check_mii_link port<0x%x> :" 5192 "BEFORE BMSR ^ nxgep->bmsr 0x%x bmsr_data 0x%x", 5193 portn, nxgep->bmsr.value, bmsr_data.value)); 5194 5195 bmsr_ints.value = nxgep->bmsr.value ^ bmsr_data.value; 5196 nxgep->bmsr.value = bmsr_data.value; 5197 5198 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5199 "==> nxge_check_mii_link port<0x%x> CALLING " 5200 "bmsr_data 0x%x bmsr_ints.value 0x%x", 5201 portn, bmsr_data.value, bmsr_ints.value)); 5202 5203 if ((status = nxge_mii_check(nxgep, bmsr_data, bmsr_ints, 5204 &link_up)) != NXGE_OK) { 5205 goto fail; 5206 } 5207 break; 5208 5209 case PORT_1G_SERDES: 5210 /* 5211 * Above default is for all cases except PORT_1G_SERDES. 5212 * The default case gets information from the PHY, but a 5213 * nxge whose portmode equals PORT_1G_SERDES does not 5214 * have a PHY. 5215 */ 5216 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5217 "==> nxge_check_mii_link port<%d> (SERDES)", portn)); 5218 nxge_pcs_check(nxgep, portn, &link_up); 5219 break; 5220 } 5221 5222 nxge_check_mii_link_exit: 5223 RW_EXIT(&nxgep->filter_lock); 5224 if (link_up == LINK_IS_UP) { 5225 nxge_link_is_up(nxgep); 5226 } else if (link_up == LINK_IS_DOWN) { 5227 nxge_link_is_down(nxgep); 5228 } 5229 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 5230 5231 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_mii_link port<%d>", 5232 portn)); 5233 return (NXGE_OK); 5234 5235 fail: 5236 RW_EXIT(&nxgep->filter_lock); 5237 5238 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 5239 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5240 "nxge_check_mii_link: Failed to check link port<%d>", portn)); 5241 return (status); 5242 } 5243 5244 /*ARGSUSED*/ 5245 static nxge_status_t 5246 nxge_check_10g_link(p_nxge_t nxgep) 5247 { 5248 uint8_t portn; 5249 nxge_status_t status = NXGE_OK; 5250 boolean_t link_up; 5251 uint32_t val; 5252 npi_status_t rs; 5253 5254 if (nxgep->nxge_magic != NXGE_MAGIC) 5255 return (NXGE_ERROR); 5256 5257 if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 5258 return (NXGE_OK); 5259 5260 portn = nxgep->mac.portnum; 5261 val = 0; 5262 rs = NPI_SUCCESS; 5263 5264 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_10g_link port<%d>", 5265 portn)); 5266 5267 switch (nxgep->mac.portmode) { 5268 default: 5269 /* 5270 * Check if the phy is present in case of hot swappable phy 5271 */ 5272 if (nxgep->hot_swappable_phy) { 5273 boolean_t phy_present_now = B_FALSE; 5274 5275 /* 5276 * If this is the 2nd Goa port, then check 2 addresses 5277 * to take care of the Goa NEM card requirements. 5278 */ 5279 if (portn == 1) { 5280 if (nxge_is_phy_present(nxgep, 5281 ALT_GOA_CLAUSE45_PORT1_ADDR, 5282 BCM8706_DEV_ID, BCM_PHY_ID_MASK)) { 5283 phy_present_now = B_TRUE; 5284 nxgep->xcvr_addr = 5285 ALT_GOA_CLAUSE45_PORT1_ADDR; 5286 goto phy_check_done; 5287 } 5288 } 5289 if (nxge_is_phy_present(nxgep, 5290 (GOA_CLAUSE45_PORT_ADDR_BASE) + portn, 5291 BCM8706_DEV_ID, BCM_PHY_ID_MASK)) { 5292 nxgep->xcvr_addr = 5293 (GOA_CLAUSE45_PORT_ADDR_BASE) + portn; 5294 phy_present_now = B_TRUE; 5295 } 5296 5297 phy_check_done: 5298 /* Check back-to-back XAUI connect to detect Opus NEM */ 5299 rs = npi_xmac_xpcs_read(nxgep->npi_handle, 5300 nxgep->mac.portnum, XPCS_REG_STATUS, &val); 5301 if (rs != 0) 5302 goto fail; 5303 5304 link_up = B_FALSE; 5305 if (val & XPCS_STATUS_LANE_ALIGN) { 5306 link_up = B_TRUE; 5307 } 5308 5309 if (nxgep->phy_absent) { 5310 if (phy_present_now) { 5311 /* 5312 * Detect, Initialize phy and do link up 5313 * set xcvr vals, link_init, nxge_init 5314 */ 5315 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5316 "Hot swappable phy DETECTED!!")); 5317 nxgep->phy_absent = B_FALSE; 5318 (void) nxge_xcvr_find(nxgep); 5319 (void) nxge_link_init(nxgep); 5320 if (!(nxgep->drv_state & 5321 STATE_HW_INITIALIZED)) { 5322 status = nxge_init(nxgep); 5323 if (status != NXGE_OK) { 5324 NXGE_ERROR_MSG((nxgep, 5325 NXGE_ERR_CTL, 5326 "Hot swappable " 5327 "phy present, but" 5328 " driver init" 5329 " failed...")); 5330 goto fail; 5331 } 5332 } 5333 } else if (link_up) { /* XAUI linkup, no PHY */ 5334 /* 5335 * This is the back-to-back XAUI 5336 * connect case for Opus NEM. 5337 */ 5338 nxgep->statsp->mac_stats.xcvr_inuse = 5339 XPCS_XCVR; 5340 nxgep->mac.portmode = PORT_10G_SERDES; 5341 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5342 "HSP 10G Serdes DETECTED!!")); 5343 break; 5344 } 5345 5346 if (nxgep->link_notify && 5347 nxgep->link_check_count > 3 && 5348 nxgep->nxge_mac_state == NXGE_MAC_STARTED || 5349 nxgep->statsp->mac_stats.link_up == 1) { 5350 nxgep->statsp->mac_stats.link_up = 0; 5351 nxgep->statsp->mac_stats.link_speed = 0; 5352 nxgep->statsp->mac_stats.link_duplex = 5353 0; 5354 5355 nxge_link_is_down(nxgep); 5356 nxgep->link_notify = B_FALSE; 5357 } 5358 5359 goto start_link_check; 5360 5361 } else if (!phy_present_now) { 5362 /* 5363 * Phy gone, bring link down reset xcvr vals 5364 */ 5365 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5366 "Hot swappable phy REMOVED!!")); 5367 nxgep->phy_absent = B_TRUE; 5368 nxgep->statsp->mac_stats.link_up = 0; 5369 nxgep->statsp->mac_stats.link_speed = 0; 5370 nxgep->statsp->mac_stats.link_duplex = 0; 5371 nxge_link_is_down(nxgep); 5372 nxgep->link_notify = B_FALSE; 5373 5374 (void) nxge_xcvr_find(nxgep); 5375 5376 goto start_link_check; 5377 5378 } 5379 } 5380 if (nxgep->chip_id == MRVL88X201X_CHIP_ID) { 5381 status = nxge_check_mrvl88x2011_link(nxgep, &link_up); 5382 } else { 5383 status = nxge_check_bcm8704_link(nxgep, &link_up); 5384 } 5385 if (status != NXGE_OK) 5386 goto fail; 5387 break; 5388 case PORT_10G_SERDES: 5389 rs = npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 5390 XPCS_REG_STATUS, &val); 5391 if (rs != 0) 5392 goto fail; 5393 5394 link_up = B_FALSE; 5395 if (val & XPCS_STATUS_LANE_ALIGN) { 5396 link_up = B_TRUE; 5397 } 5398 5399 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5400 "==> nxge_check_10g_link port<%d> " 5401 "XPCS_REG_STATUS2 0x%x link_up %d", 5402 portn, val, link_up)); 5403 5404 break; 5405 } 5406 5407 if (link_up) { 5408 if ((nxgep->link_notify && 5409 nxgep->nxge_mac_state == NXGE_MAC_STARTED) || 5410 nxgep->statsp->mac_stats.link_up == 0) { 5411 if (nxge_10g_link_led_on(nxgep) != NXGE_OK) 5412 goto fail; 5413 nxgep->statsp->mac_stats.link_up = 1; 5414 nxgep->statsp->mac_stats.link_speed = 10000; 5415 nxgep->statsp->mac_stats.link_duplex = 2; 5416 5417 nxge_link_is_up(nxgep); 5418 nxgep->link_notify = B_FALSE; 5419 } 5420 } else { 5421 if ((nxgep->link_notify && nxgep->link_check_count > 3 && 5422 nxgep->nxge_mac_state == NXGE_MAC_STARTED) || 5423 nxgep->statsp->mac_stats.link_up == 1) { 5424 if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 5425 goto fail; 5426 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5427 "Link down cable problem")); 5428 nxgep->statsp->mac_stats.link_up = 0; 5429 nxgep->statsp->mac_stats.link_speed = 0; 5430 nxgep->statsp->mac_stats.link_duplex = 0; 5431 5432 nxge_link_is_down(nxgep); 5433 nxgep->link_notify = B_FALSE; 5434 5435 if (nxgep->mac.portmode == PORT_10G_SERDES) { 5436 /* 5437 * NEM was unplugged, set up xcvr table 5438 * to find another xcvr in the future. 5439 */ 5440 (void) nxge_xcvr_find(nxgep); 5441 } 5442 } 5443 } 5444 5445 start_link_check: 5446 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 5447 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_10g_link port<%d>", 5448 portn)); 5449 return (NXGE_OK); 5450 5451 fail: 5452 (void) nxge_check_link_stop(nxgep); 5453 5454 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5455 "nxge_check_10g_link: Failed to check link port<%d>", 5456 portn)); 5457 return (status); 5458 } 5459 5460 5461 /* Declare link down */ 5462 5463 void 5464 nxge_link_is_down(p_nxge_t nxgep) 5465 { 5466 p_nxge_stats_t statsp; 5467 char link_stat_msg[64]; 5468 5469 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_down")); 5470 5471 statsp = nxgep->statsp; 5472 (void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is down", 5473 statsp->mac_stats.xcvr_portn); 5474 5475 if (nxge_no_msg == B_FALSE) { 5476 NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg)); 5477 } 5478 5479 mac_link_update(nxgep->mach, LINK_STATE_DOWN); 5480 5481 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_down")); 5482 } 5483 5484 /* Declare link up */ 5485 5486 void 5487 nxge_link_is_up(p_nxge_t nxgep) 5488 { 5489 p_nxge_stats_t statsp; 5490 char link_stat_msg[64]; 5491 uint32_t val; 5492 5493 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_up")); 5494 5495 statsp = nxgep->statsp; 5496 (void) sprintf(link_stat_msg, "xcvr addr:0x%02x - link is up %d Mbps ", 5497 statsp->mac_stats.xcvr_portn, 5498 statsp->mac_stats.link_speed); 5499 5500 if (statsp->mac_stats.link_T4) 5501 (void) strcat(link_stat_msg, "T4"); 5502 else if (statsp->mac_stats.link_duplex == 2) 5503 (void) strcat(link_stat_msg, "full duplex"); 5504 else 5505 (void) strcat(link_stat_msg, "half duplex"); 5506 5507 5508 /* Clean up symbol errors incurred during link transition */ 5509 if ((nxgep->mac.portmode == PORT_10G_FIBER) || 5510 (nxgep->mac.portmode == PORT_10G_SERDES)) { 5511 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 5512 XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val); 5513 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 5514 XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val); 5515 } 5516 5517 /* 5518 * If the driver was plumbed without a link (therefore auto-negotiation 5519 * could not complete), the driver will detect a link up when a cable 5520 * conneting to a link partner is plugged into the port. By the time 5521 * link-up is detected, auto-negotiation should have completed (The 5522 * TN1010 tries to contact a link partner every 8~24ms). Here we re- 5523 * configure the Neptune/NIU according to the newly negotiated speed. 5524 * This is necessary only for the TN1010 basad device because only the 5525 * TN1010 supports dual speeds. 5526 */ 5527 if (nxgep->mac.portmode == PORT_1G_TN1010 || 5528 nxgep->mac.portmode == PORT_10G_TN1010) { 5529 5530 (void) nxge_set_tn1010_param(nxgep); 5531 5532 /* 5533 * nxge_xcvr_find calls nxge_get_xcvr_type (which sets 5534 * nxgep->portmode) and nxge_setup_xcvr_table (which sets 5535 * the nxgep->xcvr to the proper nxge_xcvr_table_t struct). 5536 */ 5537 if (nxge_xcvr_find(nxgep) != NXGE_OK) { 5538 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5539 "nxge_link_is_up: nxge_xcvr_find failed")); 5540 } 5541 5542 /* nxge_link_init calls nxge_xcvr_init and nxge_serdes_init */ 5543 if (nxge_link_init(nxgep) != NXGE_OK) { 5544 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5545 "nxge_link_is_up: nxge_link_init failed")); 5546 } 5547 5548 /* 5549 * nxge_mac_init calls many subroutines including 5550 * nxge_xif_init which sets XGMII or GMII mode 5551 */ 5552 if (nxge_mac_init(nxgep) != NXGE_OK) { 5553 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5554 "nxge_link_is_up: nxge_mac_init failed")); 5555 } 5556 } else { 5557 (void) nxge_xif_init(nxgep); 5558 } 5559 5560 if (nxge_no_msg == B_FALSE) { 5561 NXGE_ERROR_MSG((nxgep, NXGE_NOTE, "%s", link_stat_msg)); 5562 } 5563 5564 mac_link_update(nxgep->mach, LINK_STATE_UP); 5565 5566 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_up")); 5567 } 5568 5569 #ifdef NXGE_DEBUG 5570 /* Dump all TN1010 Status registers */ 5571 static void 5572 nxge_dump_tn1010_status_regs(p_nxge_t nxgep) 5573 { 5574 uint16_t val; 5575 5576 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 5577 TN1010_PMA_PMD_DEV_ADDR, 1, &val); 5578 cmn_err(CE_NOTE, "PMA status1 = 0x%x", val); 5579 5580 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 5581 TN1010_PMA_PMD_DEV_ADDR, 8, &val); 5582 cmn_err(CE_NOTE, "PMA status2 = 0x%x", val); 5583 5584 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 5585 TN1010_PMA_PMD_DEV_ADDR, 129, &val); 5586 cmn_err(CE_NOTE, "10BASET-T status = 0x%x", val); 5587 5588 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 5589 TN1010_PCS_DEV_ADDR, 1, &val); 5590 cmn_err(CE_NOTE, "PCS status1 = 0x%x", val); 5591 5592 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 5593 TN1010_PCS_DEV_ADDR, 8, &val); 5594 cmn_err(CE_NOTE, "PCS status2 = 0x%x", val); 5595 5596 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 5597 TN1010_PCS_DEV_ADDR, 32, &val); 5598 cmn_err(CE_NOTE, "10GBASE-R status1 = 0x%x", val); 5599 5600 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 5601 TN1010_PCS_DEV_ADDR, 33, &val); 5602 cmn_err(CE_NOTE, "10GBASE-R Status2 = 0x%x", val); 5603 5604 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 5605 TN1010_PHYXS_DEV_ADDR, 1, &val); 5606 cmn_err(CE_NOTE, "PHYXS status1 = 0x%x", val); 5607 5608 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 5609 TN1010_PHYXS_DEV_ADDR, 8, &val); 5610 cmn_err(CE_NOTE, "PHYXS status2 = 0x%x", val); 5611 5612 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 5613 TN1010_PHYXS_DEV_ADDR, 24, &val); 5614 cmn_err(CE_NOTE, "XGXS Lane status = 0x%x", val); 5615 5616 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 5617 TN1010_AUTONEG_DEV_ADDR, 1, &val); 5618 cmn_err(CE_NOTE, "Autoneg status = 0x%x", val); 5619 5620 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 5621 TN1010_AUTONEG_DEV_ADDR, 33, &val); 5622 cmn_err(CE_NOTE, "10Gbase-T An status = 0x%x", val); 5623 5624 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 5625 TN1010_VENDOR_MMD1_DEV_ADDR, 1, &val); 5626 cmn_err(CE_NOTE, "TN1010 status = 0x%x", val); 5627 5628 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 5629 TN1010_VENDOR_MMD1_DEV_ADDR, 8, &val); 5630 cmn_err(CE_NOTE, "Device status = 0x%x", val); 5631 5632 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 5633 TN1010_VENDOR_MMD1_DEV_ADDR, 16, &val); 5634 cmn_err(CE_NOTE, "DDR status = 0x%x", val); 5635 5636 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 5637 TN1010_VENDOR_MMD1_DEV_ADDR, 17, &val); 5638 cmn_err(CE_NOTE, "DDR fault status = 0x%x", val); 5639 5640 nxge_mdio_read(nxgep, nxgep->xcvr_addr, 5641 TN1010_VENDOR_MMD1_DEV_ADDR, 11, &val); 5642 cmn_err(CE_NOTE, "Firmware Revision = 0x%x Major = 0x%x Minor = 0x%x", 5643 val, (val & 0xFF00) >> 8, val & 0x00FF); 5644 } 5645 #endif 5646 5647 /* 5648 * Calculate the bit in the multicast address filter 5649 * that selects the given * address. 5650 * Note: For GEM, the last 8-bits are used. 5651 */ 5652 uint32_t 5653 crc32_mchash(p_ether_addr_t addr) 5654 { 5655 uint8_t *cp; 5656 uint32_t crc; 5657 uint32_t c; 5658 int byte; 5659 int bit; 5660 5661 cp = (uint8_t *)addr; 5662 crc = (uint32_t)0xffffffff; 5663 for (byte = 0; byte < 6; byte++) { 5664 c = (uint32_t)cp[byte]; 5665 for (bit = 0; bit < 8; bit++) { 5666 if ((c & 0x1) ^ (crc & 0x1)) 5667 crc = (crc >> 1)^0xedb88320; 5668 else 5669 crc = (crc >> 1); 5670 c >>= 1; 5671 } 5672 } 5673 return ((~crc) >> (32 - HASH_BITS)); 5674 } 5675 5676 /* Reset serdes */ 5677 5678 nxge_status_t 5679 nxge_serdes_reset(p_nxge_t nxgep) 5680 { 5681 npi_handle_t handle; 5682 5683 handle = nxgep->npi_handle; 5684 5685 ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0 | ESR_RESET_1); 5686 drv_usecwait(500); 5687 ESR_REG_WR(handle, ESR_CONFIG_REG, 0); 5688 5689 return (NXGE_OK); 5690 } 5691 5692 /* 5693 * This function monitors link status using interrupt or polling. 5694 * It calls nxgep->xcvr.check_link, a member function of 5695 * nxge_xcvr_table_t. But nxgep->xcvr.check_link calls this 5696 * function back, that is why the check_link routine is 5697 * executed periodically. 5698 */ 5699 nxge_status_t 5700 nxge_link_monitor(p_nxge_t nxgep, link_mon_enable_t enable) 5701 { 5702 nxge_status_t status = NXGE_OK; 5703 5704 /* If we are a guest domain driver, don't bother. */ 5705 if (isLDOMguest(nxgep)) 5706 return (status); 5707 5708 /* 5709 * Return immediately if this is an imaginary XMAC port. 5710 * (At least, we don't have 4-port XMAC cards yet.) 5711 */ 5712 if ((nxgep->mac.portmode == PORT_10G_FIBER || 5713 nxgep->mac.portmode == PORT_10G_SERDES) && 5714 (nxgep->mac.portnum > 1)) 5715 return (NXGE_OK); 5716 5717 if (nxgep->statsp == NULL) { 5718 /* stats has not been allocated. */ 5719 return (NXGE_OK); 5720 } 5721 /* Don't check link if we're in internal loopback mode */ 5722 if (nxgep->statsp->port_stats.lb_mode >= nxge_lb_serdes10g) 5723 return (NXGE_OK); 5724 5725 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5726 "==> nxge_link_monitor port<%d> enable=%d", 5727 nxgep->mac.portnum, enable)); 5728 if (enable == LINK_MONITOR_START) { 5729 if (nxgep->mac.linkchkmode == LINKCHK_INTR) { 5730 if ((status = nxge_link_intr(nxgep, LINK_INTR_START)) 5731 != NXGE_OK) 5732 goto fail; 5733 } else { 5734 timeout_id_t timerid; 5735 /* 5736 * check_link_stop means "Stop the link check", so 5737 * we return without starting the timer. 5738 */ 5739 if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 5740 return (NXGE_OK); 5741 5742 /* 5743 * Otherwise fire the timer for the nxge to check 5744 * the link using the check_link function 5745 * of the nxge_xcvr_table and pass "nxgep" as the 5746 * argument to the check_link function. 5747 */ 5748 if (nxgep->xcvr.check_link) { 5749 timerid = timeout( 5750 (fptrv_t)(nxgep->xcvr.check_link), 5751 nxgep, 5752 drv_usectohz(LINK_MONITOR_PERIOD)); 5753 MUTEX_ENTER(&nxgep->poll_lock); 5754 nxgep->nxge_link_poll_timerid = timerid; 5755 MUTEX_EXIT(&nxgep->poll_lock); 5756 nxgep->link_check_count ++; 5757 } else { 5758 return (NXGE_ERROR); 5759 } 5760 } 5761 } else { 5762 if (nxgep->mac.linkchkmode == LINKCHK_INTR) { 5763 if ((status = nxge_link_intr(nxgep, LINK_INTR_STOP)) 5764 != NXGE_OK) 5765 goto fail; 5766 } else { 5767 clock_t rv; 5768 5769 MUTEX_ENTER(&nxgep->poll_lock); 5770 5771 /* If <timerid> == 0, the link monitor has */ 5772 /* never been started, or just now stopped. */ 5773 if (nxgep->nxge_link_poll_timerid == 0) { 5774 MUTEX_EXIT(&nxgep->poll_lock); 5775 return (NXGE_OK); 5776 } 5777 5778 nxgep->poll_state = LINK_MONITOR_STOPPING; 5779 rv = cv_reltimedwait(&nxgep->poll_cv, &nxgep->poll_lock, 5780 drv_usectohz(LM_WAIT_MULTIPLIER * 5781 LINK_MONITOR_PERIOD), TR_CLOCK_TICK); 5782 if (rv == -1) { 5783 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5784 "==> stopping port %d: " 5785 "cv_timedwait(%d) timed out", 5786 nxgep->mac.portnum, nxgep->poll_state)); 5787 nxgep->poll_state = LINK_MONITOR_STOP; 5788 nxgep->nxge_link_poll_timerid = 0; 5789 } 5790 5791 MUTEX_EXIT(&nxgep->poll_lock); 5792 } 5793 } 5794 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 5795 "<== nxge_link_monitor port<%d> enable=%d", 5796 nxgep->mac.portnum, enable)); 5797 5798 return (NXGE_OK); 5799 fail: 5800 return (status); 5801 5802 } 5803 5804 nxge_status_t 5805 nxge_check_tn1010_link(p_nxge_t nxgep) 5806 { 5807 nxge_status_t status = NXGE_OK; 5808 nxge_link_state_t link_up; 5809 5810 if (nxgep->nxge_magic != NXGE_MAGIC) { 5811 /* magic is 0 if driver is not attached */ 5812 return (NXGE_ERROR); 5813 } 5814 5815 /* Link has been stopped, no need to continue */ 5816 if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) { 5817 return (NXGE_OK); 5818 } 5819 5820 if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10) 5821 goto nxge_check_tn1010_link_exit; 5822 5823 if ((status = nxge_tn1010_check(nxgep, &link_up)) != NXGE_OK) 5824 goto fail; 5825 5826 nxge_check_tn1010_link_exit: 5827 if (link_up == LINK_IS_UP) 5828 nxge_link_is_up(nxgep); 5829 else if (link_up == LINK_IS_DOWN) 5830 nxge_link_is_down(nxgep); 5831 5832 /* 5833 * nxge_link_monitor will call (nxgep->xcvr.check_link) 5834 * which could be THIS function. 5835 */ 5836 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 5837 5838 return (NXGE_OK); 5839 5840 fail: 5841 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 5842 5843 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5844 "nxge_check_tn1010_link: Failed to check link")); 5845 return (status); 5846 } 5847 5848 5849 /* 5850 * Fill variable "link_up" with either LINK_IS_UP or LINK_IS_DOWN. 5851 */ 5852 static nxge_status_t 5853 nxge_tn1010_check(p_nxge_t nxgep, nxge_link_state_t *link_up) 5854 { 5855 nxge_status_t status = NXGE_OK; 5856 p_nxge_stats_t statsp; 5857 uint8_t phy_port_addr, portn; 5858 uint16_t val; 5859 5860 *link_up = LINK_NO_CHANGE; 5861 5862 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 5863 phy_port_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 5864 statsp = nxgep->statsp; 5865 5866 /* Check if link is up */ 5867 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 5868 TN1010_AUTONEG_DEV_ADDR, TN1010_AUTONEG_STATUS_REG, &val)) 5869 != NXGE_OK) { 5870 goto fail; 5871 } 5872 /* 5873 * nxge_link_is_up has called nxge_set_tn1010_param and set 5874 * portmode and link_speed 5875 */ 5876 if (val & TN1010_AN_LINK_STAT_BIT) { 5877 if ((nxgep->link_notify && 5878 nxgep->nxge_mac_state == NXGE_MAC_STARTED) || 5879 nxgep->statsp->mac_stats.link_up == 0) { 5880 statsp->mac_stats.link_up = 1; 5881 statsp->mac_stats.link_duplex = 2; 5882 *link_up = LINK_IS_UP; 5883 nxgep->link_notify = B_FALSE; 5884 } 5885 } else { 5886 if ((nxgep->link_notify && nxgep->link_check_count > 3 && 5887 nxgep->nxge_mac_state == NXGE_MAC_STARTED) || 5888 nxgep->statsp->mac_stats.link_up == 1) { 5889 statsp->mac_stats.link_up = 0; 5890 statsp->mac_stats.link_speed = 0; 5891 statsp->mac_stats.link_duplex = 0; 5892 *link_up = LINK_IS_DOWN; 5893 nxgep->link_notify = B_FALSE; 5894 } 5895 } 5896 return (NXGE_OK); 5897 5898 fail: 5899 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 5900 "nxge_tn1010_check: Unable to check TN1010")); 5901 return (status); 5902 } 5903 5904 5905 /* Set promiscous mode */ 5906 5907 nxge_status_t 5908 nxge_set_promisc(p_nxge_t nxgep, boolean_t on) 5909 { 5910 nxge_status_t status = NXGE_OK; 5911 5912 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_promisc: on %d", on)); 5913 5914 nxgep->filter.all_phys_cnt = ((on) ? 1 : 0); 5915 5916 RW_ENTER_WRITER(&nxgep->filter_lock); 5917 5918 if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) { 5919 goto fail; 5920 } 5921 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) { 5922 goto fail; 5923 } 5924 5925 RW_EXIT(&nxgep->filter_lock); 5926 5927 if (on) 5928 nxgep->statsp->mac_stats.promisc = B_TRUE; 5929 else 5930 nxgep->statsp->mac_stats.promisc = B_FALSE; 5931 5932 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_promisc")); 5933 5934 return (NXGE_OK); 5935 fail: 5936 RW_EXIT(&nxgep->filter_lock); 5937 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_promisc: " 5938 "Unable to set promisc (%d)", on)); 5939 5940 return (status); 5941 } 5942 5943 /*ARGSUSED*/ 5944 uint_t 5945 nxge_mif_intr(void *arg1, void *arg2) 5946 { 5947 #ifdef NXGE_DEBUG 5948 p_nxge_t nxgep = (p_nxge_t)arg2; 5949 #endif 5950 #if NXGE_MIF 5951 p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1; 5952 uint32_t status; 5953 npi_handle_t handle; 5954 uint8_t portn; 5955 p_nxge_stats_t statsp; 5956 #endif 5957 5958 #ifdef NXGE_MIF 5959 if (arg2 == NULL || (void *)ldvp->nxgep != arg2) { 5960 nxgep = ldvp->nxgep; 5961 } 5962 nxgep = ldvp->nxgep; 5963 #endif 5964 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mif_intr")); 5965 5966 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr")); 5967 return (DDI_INTR_CLAIMED); 5968 5969 mif_intr_fail: 5970 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr")); 5971 return (DDI_INTR_UNCLAIMED); 5972 } 5973 5974 /*ARGSUSED*/ 5975 uint_t 5976 nxge_mac_intr(void *arg1, void *arg2) 5977 { 5978 p_nxge_t nxgep = (p_nxge_t)arg2; 5979 p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1; 5980 p_nxge_ldg_t ldgp; 5981 uint32_t status; 5982 npi_handle_t handle; 5983 uint8_t portn; 5984 p_nxge_stats_t statsp; 5985 npi_status_t rs = NPI_SUCCESS; 5986 5987 if (arg2 == NULL || (void *)ldvp->nxgep != arg2) { 5988 nxgep = ldvp->nxgep; 5989 } 5990 5991 ldgp = ldvp->ldgp; 5992 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mac_intr: " 5993 "group %d", ldgp->ldg)); 5994 5995 handle = NXGE_DEV_NPI_HANDLE(nxgep); 5996 /* 5997 * This interrupt handler is for a specific 5998 * mac port. 5999 */ 6000 statsp = (p_nxge_stats_t)nxgep->statsp; 6001 portn = nxgep->mac.portnum; 6002 6003 NXGE_DEBUG_MSG((nxgep, INT_CTL, 6004 "==> nxge_mac_intr: reading mac stats: port<%d>", portn)); 6005 6006 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 6007 rs = npi_xmac_tx_get_istatus(handle, portn, 6008 (xmac_tx_iconfig_t *)&status); 6009 if (rs != NPI_SUCCESS) 6010 goto npi_fail; 6011 if (status & ICFG_XMAC_TX_ALL) { 6012 if (status & ICFG_XMAC_TX_UNDERRUN) { 6013 statsp->xmac_stats.tx_underflow_err++; 6014 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 6015 NXGE_FM_EREPORT_TXMAC_UNDERFLOW); 6016 } 6017 if (status & ICFG_XMAC_TX_MAX_PACKET_ERR) { 6018 statsp->xmac_stats.tx_maxpktsize_err++; 6019 /* 6020 * Do not send FMA ereport because this 6021 * error does not indicate HW failure. 6022 */ 6023 } 6024 if (status & ICFG_XMAC_TX_OVERFLOW) { 6025 statsp->xmac_stats.tx_overflow_err++; 6026 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 6027 NXGE_FM_EREPORT_TXMAC_OVERFLOW); 6028 } 6029 if (status & ICFG_XMAC_TX_FIFO_XFR_ERR) { 6030 statsp->xmac_stats.tx_fifo_xfr_err++; 6031 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 6032 NXGE_FM_EREPORT_TXMAC_TXFIFO_XFR_ERR); 6033 } 6034 if (status & ICFG_XMAC_TX_BYTE_CNT_EXP) { 6035 statsp->xmac_stats.tx_byte_cnt += 6036 XTXMAC_BYTE_CNT_MASK; 6037 } 6038 if (status & ICFG_XMAC_TX_FRAME_CNT_EXP) { 6039 statsp->xmac_stats.tx_frame_cnt += 6040 XTXMAC_FRM_CNT_MASK; 6041 } 6042 } 6043 6044 rs = npi_xmac_rx_get_istatus(handle, portn, 6045 (xmac_rx_iconfig_t *)&status); 6046 if (rs != NPI_SUCCESS) 6047 goto npi_fail; 6048 if (status & ICFG_XMAC_RX_ALL) { 6049 if (status & ICFG_XMAC_RX_OVERFLOW) 6050 statsp->xmac_stats.rx_overflow_err++; 6051 if (status & ICFG_XMAC_RX_UNDERFLOW) { 6052 statsp->xmac_stats.rx_underflow_err++; 6053 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 6054 NXGE_FM_EREPORT_RXMAC_UNDERFLOW); 6055 } 6056 /* 6057 * Do not send FMA ereport for the following 3 errors 6058 * because they do not indicate HW failures. 6059 */ 6060 if (status & ICFG_XMAC_RX_CRC_ERR_CNT_EXP) { 6061 statsp->xmac_stats.rx_crc_err_cnt += 6062 XRXMAC_CRC_ER_CNT_MASK; 6063 } 6064 if (status & ICFG_XMAC_RX_LEN_ERR_CNT_EXP) { 6065 statsp->xmac_stats.rx_len_err_cnt += 6066 MAC_LEN_ER_CNT_MASK; 6067 } 6068 if (status & ICFG_XMAC_RX_VIOL_ERR_CNT_EXP) { 6069 statsp->xmac_stats.rx_viol_err_cnt += 6070 XRXMAC_CD_VIO_CNT_MASK; 6071 } 6072 if (status & ICFG_XMAC_RX_OCT_CNT_EXP) { 6073 statsp->xmac_stats.rx_byte_cnt += 6074 XRXMAC_BT_CNT_MASK; 6075 } 6076 if (status & ICFG_XMAC_RX_HST_CNT1_EXP) { 6077 statsp->xmac_stats.rx_hist1_cnt += 6078 XRXMAC_HIST_CNT1_MASK; 6079 } 6080 if (status & ICFG_XMAC_RX_HST_CNT2_EXP) { 6081 statsp->xmac_stats.rx_hist2_cnt += 6082 XRXMAC_HIST_CNT2_MASK; 6083 } 6084 if (status & ICFG_XMAC_RX_HST_CNT3_EXP) { 6085 statsp->xmac_stats.rx_hist3_cnt += 6086 XRXMAC_HIST_CNT3_MASK; 6087 } 6088 if (status & ICFG_XMAC_RX_HST_CNT4_EXP) { 6089 statsp->xmac_stats.rx_hist4_cnt += 6090 XRXMAC_HIST_CNT4_MASK; 6091 } 6092 if (status & ICFG_XMAC_RX_HST_CNT5_EXP) { 6093 statsp->xmac_stats.rx_hist5_cnt += 6094 XRXMAC_HIST_CNT5_MASK; 6095 } 6096 if (status & ICFG_XMAC_RX_HST_CNT6_EXP) { 6097 statsp->xmac_stats.rx_hist6_cnt += 6098 XRXMAC_HIST_CNT6_MASK; 6099 } 6100 if (status & ICFG_XMAC_RX_BCAST_CNT_EXP) { 6101 statsp->xmac_stats.rx_broadcast_cnt += 6102 XRXMAC_BC_FRM_CNT_MASK; 6103 } 6104 if (status & ICFG_XMAC_RX_MCAST_CNT_EXP) { 6105 statsp->xmac_stats.rx_mult_cnt += 6106 XRXMAC_MC_FRM_CNT_MASK; 6107 } 6108 /* 6109 * Do not send FMA ereport for the following 3 errors 6110 * because they do not indicate HW failures. 6111 */ 6112 if (status & ICFG_XMAC_RX_FRAG_CNT_EXP) { 6113 statsp->xmac_stats.rx_frag_cnt += 6114 XRXMAC_FRAG_CNT_MASK; 6115 } 6116 if (status & ICFG_XMAC_RX_ALIGNERR_CNT_EXP) { 6117 statsp->xmac_stats.rx_frame_align_err_cnt += 6118 XRXMAC_AL_ER_CNT_MASK; 6119 } 6120 if (status & ICFG_XMAC_RX_LINK_FLT_CNT_EXP) { 6121 statsp->xmac_stats.rx_linkfault_err_cnt += 6122 XMAC_LINK_FLT_CNT_MASK; 6123 } 6124 if (status & ICFG_XMAC_RX_REMOTE_FLT_DET) { 6125 statsp->xmac_stats.rx_remotefault_err++; 6126 } 6127 if (status & ICFG_XMAC_RX_LOCAL_FLT_DET) { 6128 statsp->xmac_stats.rx_localfault_err++; 6129 } 6130 } 6131 6132 rs = npi_xmac_ctl_get_istatus(handle, portn, 6133 (xmac_ctl_iconfig_t *)&status); 6134 if (rs != NPI_SUCCESS) 6135 goto npi_fail; 6136 if (status & ICFG_XMAC_CTRL_ALL) { 6137 if (status & ICFG_XMAC_CTRL_PAUSE_RCVD) 6138 statsp->xmac_stats.rx_pause_cnt++; 6139 if (status & ICFG_XMAC_CTRL_PAUSE_STATE) 6140 statsp->xmac_stats.tx_pause_state++; 6141 if (status & ICFG_XMAC_CTRL_NOPAUSE_STATE) 6142 statsp->xmac_stats.tx_nopause_state++; 6143 } 6144 } else if (nxgep->mac.porttype == PORT_TYPE_BMAC) { 6145 rs = npi_bmac_tx_get_istatus(handle, portn, 6146 (bmac_tx_iconfig_t *)&status); 6147 if (rs != NPI_SUCCESS) 6148 goto npi_fail; 6149 if (status & ICFG_BMAC_TX_ALL) { 6150 if (status & ICFG_BMAC_TX_UNDERFLOW) { 6151 statsp->bmac_stats.tx_underrun_err++; 6152 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 6153 NXGE_FM_EREPORT_TXMAC_UNDERFLOW); 6154 } 6155 if (status & ICFG_BMAC_TX_MAXPKTSZ_ERR) { 6156 statsp->bmac_stats.tx_max_pkt_err++; 6157 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 6158 NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR); 6159 } 6160 if (status & ICFG_BMAC_TX_BYTE_CNT_EXP) { 6161 statsp->bmac_stats.tx_byte_cnt += 6162 BTXMAC_BYTE_CNT_MASK; 6163 } 6164 if (status & ICFG_BMAC_TX_FRAME_CNT_EXP) { 6165 statsp->bmac_stats.tx_frame_cnt += 6166 BTXMAC_FRM_CNT_MASK; 6167 } 6168 } 6169 6170 rs = npi_bmac_rx_get_istatus(handle, portn, 6171 (bmac_rx_iconfig_t *)&status); 6172 if (rs != NPI_SUCCESS) 6173 goto npi_fail; 6174 if (status & ICFG_BMAC_RX_ALL) { 6175 if (status & ICFG_BMAC_RX_OVERFLOW) { 6176 statsp->bmac_stats.rx_overflow_err++; 6177 } 6178 if (status & ICFG_BMAC_RX_FRAME_CNT_EXP) { 6179 statsp->bmac_stats.rx_frame_cnt += 6180 RXMAC_FRM_CNT_MASK; 6181 } 6182 if (status & ICFG_BMAC_RX_CRC_ERR_CNT_EXP) { 6183 statsp->bmac_stats.rx_crc_err_cnt += 6184 BMAC_CRC_ER_CNT_MASK; 6185 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 6186 NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP); 6187 } 6188 if (status & ICFG_BMAC_RX_LEN_ERR_CNT_EXP) { 6189 statsp->bmac_stats.rx_len_err_cnt += 6190 MAC_LEN_ER_CNT_MASK; 6191 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 6192 NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP); 6193 } 6194 if (status & ICFG_BMAC_RX_VIOL_ERR_CNT_EXP) 6195 statsp->bmac_stats.rx_viol_err_cnt += 6196 BMAC_CD_VIO_CNT_MASK; 6197 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 6198 NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP); 6199 } 6200 if (status & ICFG_BMAC_RX_BYTE_CNT_EXP) { 6201 statsp->bmac_stats.rx_byte_cnt += 6202 BRXMAC_BYTE_CNT_MASK; 6203 } 6204 if (status & ICFG_BMAC_RX_ALIGNERR_CNT_EXP) { 6205 statsp->bmac_stats.rx_align_err_cnt += 6206 BMAC_AL_ER_CNT_MASK; 6207 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 6208 NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP); 6209 } 6210 6211 rs = npi_bmac_ctl_get_istatus(handle, portn, 6212 (bmac_ctl_iconfig_t *)&status); 6213 if (rs != NPI_SUCCESS) 6214 goto npi_fail; 6215 6216 if (status & ICFG_BMAC_CTL_ALL) { 6217 if (status & ICFG_BMAC_CTL_RCVPAUSE) 6218 statsp->bmac_stats.rx_pause_cnt++; 6219 if (status & ICFG_BMAC_CTL_INPAUSE_ST) 6220 statsp->bmac_stats.tx_pause_state++; 6221 if (status & ICFG_BMAC_CTL_INNOTPAUSE_ST) 6222 statsp->bmac_stats.tx_nopause_state++; 6223 } 6224 } 6225 6226 if (ldgp->nldvs == 1) { 6227 (void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg, 6228 B_TRUE, ldgp->ldg_timer); 6229 } 6230 6231 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mac_intr")); 6232 return (DDI_INTR_CLAIMED); 6233 6234 npi_fail: 6235 NXGE_ERROR_MSG((nxgep, INT_CTL, "<== nxge_mac_intr")); 6236 return (DDI_INTR_UNCLAIMED); 6237 } 6238 6239 nxge_status_t 6240 nxge_check_bcm8704_link(p_nxge_t nxgep, boolean_t *link_up) 6241 { 6242 uint8_t phy_port_addr; 6243 nxge_status_t status = NXGE_OK; 6244 boolean_t rx_sig_ok; 6245 boolean_t pcs_blk_lock; 6246 boolean_t link_align; 6247 uint16_t val1, val2, val3; 6248 #ifdef NXGE_DEBUG_SYMBOL_ERR 6249 uint16_t val_debug; 6250 uint32_t val; 6251 #endif 6252 6253 phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn; 6254 6255 #ifdef NXGE_DEBUG_SYMBOL_ERR 6256 /* Check Device 3 Register Device 3 0xC809 */ 6257 (void) nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0xC809, &val_debug); 6258 if ((val_debug & ~0x200) != 0) { 6259 cmn_err(CE_NOTE, "!Port%d BCM8704 Dev3 Reg 0xc809 = 0x%x\n", 6260 nxgep->mac.portnum, val_debug); 6261 (void) nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, 6262 &val_debug); 6263 cmn_err(CE_NOTE, "!Port%d BCM8704 Dev4 Reg 0x18 = 0x%x\n", 6264 nxgep->mac.portnum, val_debug); 6265 } 6266 6267 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 6268 XPCS_REG_DESCWERR_COUNTER, &val); 6269 if (val != 0) 6270 cmn_err(CE_NOTE, "!XPCS DESCWERR = 0x%x\n", val); 6271 6272 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 6273 XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val); 6274 if (val != 0) 6275 cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L0_1 = 0x%x\n", val); 6276 6277 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 6278 XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val); 6279 if (val != 0) 6280 cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L2_3 = 0x%x\n", val); 6281 #endif 6282 6283 /* Check from BCM8704 if 10G link is up or down */ 6284 6285 /* Check Device 1 Register 0xA bit0 */ 6286 status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PMA_PMD_DEV_ADDR, 6287 BCM8704_PMD_RECEIVE_SIG_DETECT, &val1); 6288 if (status != NXGE_OK) 6289 goto fail; 6290 rx_sig_ok = ((val1 & GLOB_PMD_RX_SIG_OK) ? B_TRUE : B_FALSE); 6291 6292 /* Check Device 3 Register 0x20 bit0 */ 6293 if ((status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PCS_DEV_ADDR, 6294 BCM8704_10GBASE_R_PCS_STATUS_REG, &val2)) != NPI_SUCCESS) 6295 goto fail; 6296 pcs_blk_lock = ((val2 & PCS_10GBASE_R_PCS_BLK_LOCK) ? B_TRUE : B_FALSE); 6297 6298 /* Check Device 4 Register 0x18 bit12 */ 6299 status = nxge_mdio_read(nxgep, phy_port_addr, BCM8704_PHYXS_ADDR, 6300 BCM8704_PHYXS_XGXS_LANE_STATUS_REG, &val3); 6301 if (status != NXGE_OK) 6302 goto fail; 6303 6304 switch (nxgep->chip_id) { 6305 case BCM8704_CHIP_ID: 6306 link_align = (val3 == (XGXS_LANE_ALIGN_STATUS | 6307 XGXS_LANE3_SYNC | XGXS_LANE2_SYNC | XGXS_LANE1_SYNC | 6308 XGXS_LANE0_SYNC | 0x400)) ? B_TRUE : B_FALSE; 6309 break; 6310 case BCM8706_CHIP_ID: 6311 link_align = ((val3 & XGXS_LANE_ALIGN_STATUS) && 6312 (val3 & XGXS_LANE3_SYNC) && (val3 & XGXS_LANE2_SYNC) && 6313 (val3 & XGXS_LANE1_SYNC) && (val3 & XGXS_LANE0_SYNC)) ? 6314 B_TRUE : B_FALSE; 6315 break; 6316 default: 6317 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_check_bcm8704_link:" 6318 "Unknown chip ID [0x%x]", nxgep->chip_id)); 6319 goto fail; 6320 } 6321 6322 #ifdef NXGE_DEBUG_ALIGN_ERR 6323 /* Temp workaround for link down issue */ 6324 if (pcs_blk_lock == B_FALSE) { 6325 if (val2 != 0x4) { 6326 pcs_blk_lock = B_TRUE; 6327 cmn_err(CE_NOTE, "!LINK DEBUG: port%d PHY Dev3 " 6328 "Reg 0x20 = 0x%x\n", nxgep->mac.portnum, val2); 6329 } 6330 } 6331 6332 if (link_align == B_FALSE) { 6333 if (val3 != 0x140f) { 6334 link_align = B_TRUE; 6335 cmn_err(CE_NOTE, "!LINK DEBUG: port%d PHY Dev4 " 6336 "Reg 0x18 = 0x%x\n", nxgep->mac.portnum, val3); 6337 } 6338 } 6339 6340 if (rx_sig_ok == B_FALSE) { 6341 if ((val2 == 0) || (val3 == 0)) { 6342 rx_sig_ok = B_TRUE; 6343 cmn_err(CE_NOTE, 6344 "!LINK DEBUG: port %d Dev3 or Dev4 read zero\n", 6345 nxgep->mac.portnum); 6346 } 6347 } 6348 #endif 6349 6350 *link_up = ((rx_sig_ok == B_TRUE) && (pcs_blk_lock == B_TRUE) && 6351 (link_align == B_TRUE)) ? B_TRUE : B_FALSE; 6352 6353 return (NXGE_OK); 6354 fail: 6355 return (status); 6356 } 6357 6358 static nxge_status_t 6359 nxge_check_mrvl88x2011_link(p_nxge_t nxgep, boolean_t *link_up) 6360 { 6361 uint8_t phy; 6362 nxge_status_t status = NXGE_OK; 6363 boolean_t pma_status; 6364 boolean_t pcs_status; 6365 boolean_t xgxs_status; 6366 uint16_t val; 6367 6368 phy = nxgep->statsp->mac_stats.xcvr_portn; 6369 6370 MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR, 6371 MRVL_88X2011_10G_PMD_STAT_2, &val); 6372 6373 *link_up = B_FALSE; 6374 6375 /* Check from Marvell 88X2011 if 10G link is up or down */ 6376 6377 /* Check PMA/PMD Register: 1.0001.2 == 1 */ 6378 MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV1_ADDR, 6379 MRVL_88X2011_PMA_PMD_STAT_1, &val); 6380 6381 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6382 "nxge_check_mrvl88x2011_link: pmd=0x%x", val)); 6383 6384 pma_status = ((val & MRVL_88X2011_LNK_STATUS_OK) ? B_TRUE : B_FALSE); 6385 6386 /* Check PMC Register : 3.0001.2 == 1: read twice */ 6387 MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR, 6388 MRVL_88X2011_PMA_PMD_STAT_1, &val); 6389 MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV3_ADDR, 6390 MRVL_88X2011_PMA_PMD_STAT_1, &val); 6391 6392 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6393 "nxge_check_mrvl88x2011_link: pcs=0x%x", val)); 6394 6395 pcs_status = ((val & MRVL_88X2011_LNK_STATUS_OK) ? B_TRUE : B_FALSE); 6396 6397 /* Check XGXS Register : 4.0018.[0-3,12] */ 6398 MRVL88X2011_RD(nxgep, phy, MRVL_88X2011_USER_DEV4_ADDR, 6399 MRVL_88X2011_10G_XGXS_LANE_STAT, &val); 6400 6401 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6402 "nxge_check_mrvl88x2011_link: xgxs=0x%x", val)); 6403 6404 xgxs_status = (val == (XGXS_LANE_ALIGN_STATUS | XGXS_LANE3_SYNC | 6405 XGXS_LANE2_SYNC | XGXS_LANE1_SYNC | 6406 XGXS_LANE0_SYNC | XGXS_PATTERN_TEST_ABILITY | 6407 XGXS_LANE_STAT_MAGIC)) ? B_TRUE : B_FALSE; 6408 6409 *link_up = (pma_status && pcs_status && xgxs_status) ? 6410 B_TRUE : B_FALSE; 6411 6412 fail: 6413 6414 if (*link_up == B_FALSE) { 6415 /* PCS OFF */ 6416 nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_CTL_OFF); 6417 } else { 6418 /* PCS Activity */ 6419 nxge_mrvl88x2011_led(nxgep, MRVL_88X2011_LED_CTL_PCS_ACT); 6420 } 6421 6422 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6423 " <== nxge_check_mrvl88x2011_link: up=%d", *link_up)); 6424 6425 return (status); 6426 } 6427 6428 nxge_status_t 6429 nxge_10g_link_led_on(p_nxge_t nxgep) 6430 { 6431 if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_TRUE) 6432 != NPI_SUCCESS) 6433 return (NXGE_ERROR); 6434 else 6435 return (NXGE_OK); 6436 } 6437 6438 nxge_status_t 6439 nxge_10g_link_led_off(p_nxge_t nxgep) 6440 { 6441 if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_FALSE) 6442 != NPI_SUCCESS) 6443 return (NXGE_ERROR); 6444 else 6445 return (NXGE_OK); 6446 } 6447 6448 static boolean_t 6449 nxge_is_phy_present(p_nxge_t nxgep, int addr, uint32_t id, uint32_t mask) 6450 { 6451 uint32_t pma_pmd_id = 0; 6452 uint32_t pcs_id = 0; 6453 uint32_t phy_id = 0; 6454 6455 pma_pmd_id = nxge_get_cl45_pma_pmd_id(nxgep, addr); 6456 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6457 "nxge_is_phy_present: pma_pmd_id[0x%x]", pma_pmd_id)); 6458 if ((pma_pmd_id & mask) == (id & mask)) 6459 goto found_phy; 6460 pcs_id = nxge_get_cl45_pcs_id(nxgep, addr); 6461 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6462 "nxge_is_phy_present: pcs_id[0x%x]", pcs_id)); 6463 if ((pcs_id & mask) == (id & mask)) 6464 goto found_phy; 6465 phy_id = nxge_get_cl22_phy_id(nxgep, addr); 6466 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6467 "nxge_is_phy_present: phy_id[0x%x]", phy_id)); 6468 if ((phy_id & mask) == (id & mask)) 6469 goto found_phy; 6470 6471 return (B_FALSE); 6472 6473 found_phy: 6474 return (B_TRUE); 6475 } 6476 6477 /* Check if the given id read using the given MDIO Clause is supported */ 6478 6479 static boolean_t 6480 nxge_is_supported_phy(uint32_t id, uint8_t type) 6481 { 6482 int i; 6483 boolean_t found = B_FALSE; 6484 6485 switch (type) { 6486 case CLAUSE_45_TYPE: 6487 for (i = 0; i < NUM_CLAUSE_45_IDS; i++) { 6488 if (((nxge_supported_cl45_ids[i] & BCM_PHY_ID_MASK) == 6489 (id & BCM_PHY_ID_MASK)) || 6490 (TN1010_DEV_ID == (id & TN1010_DEV_ID_MASK))) { 6491 found = B_TRUE; 6492 break; 6493 } 6494 } 6495 break; 6496 case CLAUSE_22_TYPE: 6497 for (i = 0; i < NUM_CLAUSE_22_IDS; i++) { 6498 if ((nxge_supported_cl22_ids[i] & BCM_PHY_ID_MASK) == 6499 (id & BCM_PHY_ID_MASK)) { 6500 found = B_TRUE; 6501 break; 6502 } 6503 } 6504 break; 6505 default: 6506 break; 6507 } 6508 6509 return (found); 6510 } 6511 6512 static uint32_t 6513 nxge_get_cl45_pma_pmd_id(p_nxge_t nxgep, int phy_port) 6514 { 6515 uint16_t val1 = 0; 6516 uint16_t val2 = 0; 6517 uint32_t pma_pmd_dev_id = 0; 6518 npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep); 6519 6520 MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 6521 (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR, 6522 NXGE_DEV_ID_REG_1, &val1); 6523 (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PMA_PMD_DEV_ADDR, 6524 NXGE_DEV_ID_REG_2, &val2); 6525 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 6526 6527 /* Concatenate the Device ID stored in two registers. */ 6528 pma_pmd_dev_id = val1; 6529 pma_pmd_dev_id = (pma_pmd_dev_id << 16); 6530 pma_pmd_dev_id |= val2; 6531 6532 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PMA/PMD " 6533 "devid[0x%llx]", phy_port, pma_pmd_dev_id)); 6534 6535 return (pma_pmd_dev_id); 6536 } 6537 6538 static uint32_t 6539 nxge_get_cl45_pcs_id(p_nxge_t nxgep, int phy_port) 6540 { 6541 uint16_t val1 = 0; 6542 uint16_t val2 = 0; 6543 uint32_t pcs_dev_id = 0; 6544 npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep); 6545 6546 MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 6547 (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR, 6548 NXGE_DEV_ID_REG_1, &val1); 6549 (void) npi_mac_mif_mdio_read(handle, phy_port, NXGE_PCS_DEV_ADDR, 6550 NXGE_DEV_ID_REG_2, &val2); 6551 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 6552 6553 pcs_dev_id = val1; 6554 pcs_dev_id = (pcs_dev_id << 16); 6555 pcs_dev_id |= val2; 6556 6557 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS " 6558 "devid[0x%llx]", phy_port, pcs_dev_id)); 6559 6560 return (pcs_dev_id); 6561 } 6562 6563 static uint32_t 6564 nxge_get_cl22_phy_id(p_nxge_t nxgep, int phy_port) 6565 { 6566 uint16_t val1 = 0; 6567 uint16_t val2 = 0; 6568 uint32_t phy_id = 0; 6569 npi_handle_t handle = NXGE_DEV_NPI_HANDLE(nxgep); 6570 npi_status_t npi_status = NPI_SUCCESS; 6571 6572 MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 6573 npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_1, 6574 &val1); 6575 if (npi_status != NPI_SUCCESS) { 6576 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] " 6577 "clause 22 read to reg 2 failed!!!")); 6578 goto exit; 6579 } 6580 npi_status = npi_mac_mif_mii_read(handle, phy_port, NXGE_PHY_ID_REG_2, 6581 &val2); 6582 if (npi_status != 0) { 6583 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] " 6584 "clause 22 read to reg 3 failed!!!")); 6585 goto exit; 6586 } 6587 phy_id = val1; 6588 phy_id = (phy_id << 16); 6589 phy_id |= val2; 6590 6591 exit: 6592 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 6593 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID [0x%llx]", 6594 phy_port, phy_id)); 6595 6596 return (phy_id); 6597 } 6598 6599 /* 6600 * Scan the PHY ports 0 through 31 to get the PHY ID using Clause 22 MDIO 6601 * read and the PMA/PMD device ID and the PCS device ID using Clause 45 MDIO 6602 * read. Then use the values obtained to determine the phy type of each port 6603 * and the Neptune type. 6604 * 6605 * This function sets hw_p->xcvr_addr[i] for future MDIO access and set 6606 * hw_p->niu_type for each nxge instance to figure out nxgep->mac.portmode 6607 * in case the portmode information is not available via OBP, nxge.conf, 6608 * VPD or SEEPROM. 6609 */ 6610 nxge_status_t 6611 nxge_scan_ports_phy(p_nxge_t nxgep, p_nxge_hw_list_t hw_p) 6612 { 6613 int i, j, l; 6614 uint32_t pma_pmd_dev_id = 0; 6615 uint32_t pcs_dev_id = 0; 6616 uint32_t phy_id = 0; 6617 uint32_t port_pma_pmd_dev_id[NXGE_PORTS_NEPTUNE]; 6618 uint32_t port_pcs_dev_id[NXGE_PORTS_NEPTUNE]; 6619 uint32_t port_phy_id[NXGE_PORTS_NEPTUNE]; 6620 uint8_t pma_pmd_dev_fd[NXGE_MAX_PHY_PORTS]; 6621 uint8_t pcs_dev_fd[NXGE_MAX_PHY_PORTS]; 6622 uint8_t phy_fd_arr[NXGE_MAX_PHY_PORTS]; 6623 uint8_t port_fd_arr[NXGE_MAX_PHY_PORTS]; 6624 uint8_t total_port_fd, total_phy_fd; 6625 uint8_t num_xaui; 6626 nxge_status_t status = NXGE_OK; 6627 6628 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_scan_ports_phy: ")); 6629 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6630 "==> nxge_scan_ports_phy: nxge niu_type[0x%x]", 6631 nxgep->niu_type)); 6632 6633 if (isLDOMguest(nxgep)) { 6634 hw_p->niu_type = NIU_TYPE_NONE; 6635 hw_p->platform_type = P_NEPTUNE_NONE; 6636 return (NXGE_OK); 6637 } 6638 6639 j = l = 0; 6640 total_port_fd = total_phy_fd = 0; 6641 /* 6642 * Clause 45 and Clause 22 port/phy addresses 0 through 5 are reserved 6643 * for on chip serdes usages. "i" in the following for loop starts at 6. 6644 */ 6645 for (i = NXGE_EXT_PHY_PORT_ST; i < NXGE_MAX_PHY_PORTS; i++) { 6646 6647 pma_pmd_dev_id = nxge_get_cl45_pma_pmd_id(nxgep, i); 6648 6649 if (nxge_is_supported_phy(pma_pmd_dev_id, CLAUSE_45_TYPE)) { 6650 pma_pmd_dev_fd[i] = 1; 6651 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] " 6652 "PMA/PMD dev %x found", i, pma_pmd_dev_id)); 6653 if (j < NXGE_PORTS_NEPTUNE) { 6654 if ((pma_pmd_dev_id & TN1010_DEV_ID_MASK) 6655 == TN1010_DEV_ID) { 6656 port_pma_pmd_dev_id[j] = TN1010_DEV_ID; 6657 } else { 6658 port_pma_pmd_dev_id[j] = 6659 pma_pmd_dev_id & BCM_PHY_ID_MASK; 6660 } 6661 port_fd_arr[j] = (uint8_t)i; 6662 j++; 6663 } 6664 } else { 6665 pma_pmd_dev_fd[i] = 0; 6666 } 6667 6668 pcs_dev_id = nxge_get_cl45_pcs_id(nxgep, i); 6669 6670 if (nxge_is_supported_phy(pcs_dev_id, CLAUSE_45_TYPE)) { 6671 pcs_dev_fd[i] = 1; 6672 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PCS " 6673 "dev %x found", i, pcs_dev_id)); 6674 if (pma_pmd_dev_fd[i] == 1) { 6675 if ((pcs_dev_id & TN1010_DEV_ID_MASK) 6676 == TN1010_DEV_ID) { 6677 port_pcs_dev_id[j - 1] = 6678 TN1010_DEV_ID; 6679 } else { 6680 port_pcs_dev_id[j - 1] = 6681 pcs_dev_id & 6682 BCM_PHY_ID_MASK; 6683 } 6684 } else { 6685 if (j < NXGE_PORTS_NEPTUNE) { 6686 if ((pcs_dev_id & TN1010_DEV_ID_MASK) 6687 == TN1010_DEV_ID) { 6688 port_pcs_dev_id[j] = 6689 TN1010_DEV_ID; 6690 } else { 6691 port_pcs_dev_id[j] = 6692 pcs_dev_id & 6693 BCM_PHY_ID_MASK; 6694 } 6695 port_fd_arr[j] = (uint8_t)i; 6696 j++; 6697 } 6698 } 6699 } else { 6700 pcs_dev_fd[i] = 0; 6701 } 6702 6703 if (pcs_dev_fd[i] || pma_pmd_dev_fd[i]) { 6704 total_port_fd ++; 6705 } 6706 6707 phy_id = nxge_get_cl22_phy_id(nxgep, i); 6708 if (nxge_is_supported_phy(phy_id, CLAUSE_22_TYPE)) { 6709 total_phy_fd ++; 6710 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "port[%d] PHY ID" 6711 "%x found", i, phy_id)); 6712 if (l < NXGE_PORTS_NEPTUNE) { 6713 if ((phy_id & TN1010_DEV_ID_MASK) 6714 == TN1010_DEV_ID) { 6715 port_phy_id[l] = TN1010_DEV_ID; 6716 } else { 6717 port_phy_id[l] 6718 = phy_id & BCM_PHY_ID_MASK; 6719 } 6720 phy_fd_arr[l] = (uint8_t)i; 6721 l++; 6722 } 6723 } 6724 } 6725 6726 switch (total_port_fd) { 6727 case 2: 6728 switch (total_phy_fd) { 6729 case 2: 6730 /* 2 10G, 2 1G RGMII Fiber / copper */ 6731 if ((((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) && 6732 (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) || 6733 ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) && 6734 (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY))) && 6735 ((port_phy_id[0] == PHY_BCM5482_FAMILY) && 6736 (port_phy_id[1] == PHY_BCM5482_FAMILY))) { 6737 6738 switch (hw_p->platform_type) { 6739 case P_NEPTUNE_ROCK: 6740 hw_p->niu_type = NEPTUNE_2_10GF_2_1GC; 6741 /* 6742 * ROCK platform has assigned a lower 6743 * addr to port 1. (port 0 = 0x9 and 6744 * port 1 = 0x8). 6745 */ 6746 hw_p->xcvr_addr[1] = port_fd_arr[0]; 6747 hw_p->xcvr_addr[0] = port_fd_arr[1]; 6748 6749 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6750 "Rock with 2 10G, 2 1GC")); 6751 break; 6752 6753 case P_NEPTUNE_NONE: 6754 default: 6755 hw_p->platform_type = 6756 P_NEPTUNE_GENERIC; 6757 hw_p->niu_type = NEPTUNE_2_10GF_2_1GRF; 6758 6759 hw_p->xcvr_addr[0] = port_fd_arr[0]; 6760 hw_p->xcvr_addr[1] = port_fd_arr[1]; 6761 6762 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6763 "ARTM card with 2 10G, 2 1GF")); 6764 break; 6765 } 6766 6767 hw_p->xcvr_addr[2] = phy_fd_arr[0]; 6768 hw_p->xcvr_addr[3] = phy_fd_arr[1]; 6769 6770 } else { 6771 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6772 "Unsupported neptune type 1")); 6773 goto error_exit; 6774 } 6775 break; 6776 6777 case 1: 6778 /* TODO - 2 10G, 1 1G */ 6779 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6780 "Unsupported neptune type 2 10G, 1 1G")); 6781 goto error_exit; 6782 case 0: 6783 /* 6784 * 2 10G: 2XGF NIC, Marvell, Goa, Huron with 2 XAUI 6785 * cards, etc. 6786 */ 6787 if (((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) && 6788 (port_pcs_dev_id[1] == PHY_BCM8704_FAMILY)) || 6789 ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) && 6790 (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY)) || 6791 ((port_pcs_dev_id[0] == MARVELL_88X201X_PHY_ID) && 6792 (port_pcs_dev_id[1] == MARVELL_88X201X_PHY_ID)) || 6793 ((port_pma_pmd_dev_id[0] == 6794 MARVELL_88X201X_PHY_ID) && 6795 (port_pma_pmd_dev_id[1] == 6796 MARVELL_88X201X_PHY_ID))) { 6797 6798 /* 6799 * Check the first phy port address against 6800 * the known phy start addresses to determine 6801 * the platform type. 6802 */ 6803 6804 switch (port_fd_arr[0]) { 6805 case NEPTUNE_CLAUSE45_PORT_ADDR_BASE: 6806 /* 6807 * The Marvell case also falls into 6808 * this case as 6809 * MRVL88X2011_NEPTUNE_PORT_ADDR_BASE 6810 * == NEPTUNE_CLAUSE45_PORT_ADDR_BASE. 6811 * This is OK for the 2 10G case. 6812 */ 6813 hw_p->niu_type = NEPTUNE_2_10GF; 6814 hw_p->platform_type = 6815 P_NEPTUNE_ATLAS_2PORT; 6816 break; 6817 case GOA_CLAUSE45_PORT_ADDR_BASE: 6818 if (hw_p->platform_type != 6819 P_NEPTUNE_NIU) { 6820 hw_p->platform_type = 6821 P_NEPTUNE_GENERIC; 6822 hw_p->niu_type = 6823 NEPTUNE_2_10GF; 6824 } 6825 break; 6826 default: 6827 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6828 "Unsupported neptune type 2 - 1")); 6829 goto error_exit; 6830 } 6831 6832 for (i = 0; i < 2; i++) { 6833 hw_p->xcvr_addr[i] = port_fd_arr[i]; 6834 } 6835 6836 /* Both XAUI slots have copper XAUI cards */ 6837 } else if ((((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 6838 == TN1010_DEV_ID) && 6839 ((port_pcs_dev_id[1] & TN1010_DEV_ID_MASK) 6840 == TN1010_DEV_ID)) || 6841 (((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK) 6842 == TN1010_DEV_ID) && 6843 ((port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK) 6844 == TN1010_DEV_ID))) { 6845 hw_p->niu_type = NEPTUNE_2_TN1010; 6846 hw_p->xcvr_addr[0] = port_fd_arr[0]; 6847 hw_p->xcvr_addr[1] = port_fd_arr[1]; 6848 6849 /* Slot0 has fiber XAUI, slot1 has copper XAUI */ 6850 } else if ((port_pcs_dev_id[0] == PHY_BCM8704_FAMILY && 6851 (port_pcs_dev_id[1] & TN1010_DEV_ID_MASK) 6852 == TN1010_DEV_ID) || 6853 (port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY && 6854 (port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK) == 6855 TN1010_DEV_ID)) { 6856 hw_p->niu_type = NEPTUNE_1_10GF_1_TN1010; 6857 hw_p->xcvr_addr[0] = port_fd_arr[0]; 6858 hw_p->xcvr_addr[1] = port_fd_arr[1]; 6859 6860 /* Slot0 has copper XAUI, slot1 has fiber XAUI */ 6861 } else if ((port_pcs_dev_id[1] == PHY_BCM8704_FAMILY && 6862 (port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 6863 == TN1010_DEV_ID) || 6864 (port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY && 6865 (port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK) 6866 == TN1010_DEV_ID)) { 6867 hw_p->niu_type = NEPTUNE_1_TN1010_1_10GF; 6868 hw_p->xcvr_addr[0] = port_fd_arr[0]; 6869 hw_p->xcvr_addr[1] = port_fd_arr[1]; 6870 6871 } else { 6872 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6873 "Unsupported neptune type 2")); 6874 goto error_exit; 6875 } 6876 break; 6877 6878 case 4: 6879 if (nxge_get_num_of_xaui( 6880 port_pma_pmd_dev_id, port_pcs_dev_id, 6881 port_phy_id, &num_xaui) == NXGE_ERROR) { 6882 goto error_exit; 6883 } 6884 if (num_xaui != 2) 6885 goto error_exit; 6886 6887 /* 6888 * Maramba with 2 XAUIs (either fiber or copper) 6889 * 6890 * Check the first phy port address against 6891 * the known phy start addresses to determine 6892 * the platform type. 6893 */ 6894 switch (phy_fd_arr[0]) { 6895 case MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE: 6896 hw_p->platform_type = 6897 P_NEPTUNE_MARAMBA_P0; 6898 break; 6899 case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE: 6900 hw_p->platform_type = 6901 P_NEPTUNE_MARAMBA_P1; 6902 break; 6903 default: 6904 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 6905 "Unknown port %d...Cannot " 6906 "determine platform type", i)); 6907 goto error_exit; 6908 } 6909 6910 hw_p->xcvr_addr[0] = port_fd_arr[0]; 6911 hw_p->xcvr_addr[1] = port_fd_arr[1]; 6912 hw_p->xcvr_addr[2] = phy_fd_arr[2]; 6913 hw_p->xcvr_addr[3] = phy_fd_arr[3]; 6914 6915 /* slot0 has fiber XAUI, slot1 has Cu XAUI */ 6916 if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY && 6917 (port_pcs_dev_id[1] & TN1010_DEV_ID_MASK) 6918 == TN1010_DEV_ID) { 6919 hw_p->niu_type = NEPTUNE_1_10GF_1_TN1010_2_1GC; 6920 6921 /* slot0 has Cu XAUI, slot1 has fiber XAUI */ 6922 } else if (((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 6923 == TN1010_DEV_ID) && 6924 port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) { 6925 hw_p->niu_type = NEPTUNE_1_TN1010_1_10GF_2_1GC; 6926 6927 /* Both slots have fiber XAUI */ 6928 } else if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY && 6929 port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) { 6930 hw_p->niu_type = NEPTUNE_2_10GF_2_1GC; 6931 6932 /* Both slots have copper XAUI */ 6933 } else if (((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 6934 == TN1010_DEV_ID) && 6935 (port_pcs_dev_id[1] & TN1010_DEV_ID_MASK) 6936 == TN1010_DEV_ID) { 6937 hw_p->niu_type = NEPTUNE_2_TN1010_2_1GC; 6938 6939 } else { 6940 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6941 "Unsupported neptune type 3")); 6942 goto error_exit; 6943 } 6944 break; 6945 default: 6946 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6947 "Unsupported neptune type 5")); 6948 goto error_exit; 6949 } 6950 break; 6951 case 1: /* Only one clause45 port */ 6952 switch (total_phy_fd) { /* Number of clause22 ports */ 6953 case 3: 6954 /* 6955 * TODO 3 1G, 1 10G mode. 6956 * Differentiate between 1_1G_1_10G_2_1G and 6957 * 1_10G_3_1G 6958 */ 6959 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6960 "Unsupported neptune type 7")); 6961 goto error_exit; 6962 case 2: 6963 /* 6964 * TODO 2 1G, 1 10G mode. 6965 * Differentiate between 1_1G_1_10G_1_1G and 6966 * 1_10G_2_1G 6967 */ 6968 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6969 "Unsupported neptune type 8")); 6970 goto error_exit; 6971 case 1: 6972 /* 6973 * TODO 1 1G, 1 10G mode. 6974 * Differentiate between 1_1G_1_10G and 6975 * 1_10G_1_1G 6976 */ 6977 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 6978 "Unsupported neptune type 9")); 6979 goto error_exit; 6980 case 0: /* N2 with 1 XAUI (fiber or copper) */ 6981 /* Fiber XAUI */ 6982 if (port_pcs_dev_id[0] == PHY_BCM8704_FAMILY || 6983 port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY) { 6984 6985 /* 6986 * Check the first phy port address against 6987 * the known phy start addresses to determine 6988 * the platform type. 6989 */ 6990 6991 switch (port_fd_arr[0]) { 6992 case N2_CLAUSE45_PORT_ADDR_BASE: 6993 case (N2_CLAUSE45_PORT_ADDR_BASE + 1): 6994 case ALT_GOA_CLAUSE45_PORT1_ADDR: 6995 /* 6996 * If hw_p->platform_type == 6997 * P_NEPTUNE_NIU, then portmode 6998 * is already known, so there is 6999 * no need to figure out hw_p-> 7000 * platform_type because 7001 * platform_type is only for 7002 * figuring out portmode. 7003 */ 7004 if (hw_p->platform_type != 7005 P_NEPTUNE_NIU) { 7006 hw_p->platform_type = 7007 P_NEPTUNE_GENERIC; 7008 hw_p->niu_type = 7009 NEPTUNE_2_10GF; 7010 } 7011 break; 7012 default: 7013 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7014 "Unsupported neptune type 10")); 7015 goto error_exit; 7016 } 7017 /* 7018 * For GOA, which is a hot swappable PHY, the 7019 * phy address to function number mapping 7020 * should be preserved, i.e., addr 16 is 7021 * assigned to function 0 and 20 to function 1 7022 * But for Huron XAUI, the assignment should 7023 * be by function number, i.e., whichever 7024 * function number attaches should be 7025 * assigned the available PHY (this is required 7026 * primarily to support pre-production Huron 7027 * boards where function 0 is mapped to addr 17 7028 */ 7029 if (port_fd_arr[0] == 7030 ALT_GOA_CLAUSE45_PORT1_ADDR) { 7031 hw_p->xcvr_addr[1] = port_fd_arr[0]; 7032 } else { 7033 hw_p->xcvr_addr[nxgep->function_num] = 7034 port_fd_arr[0]; 7035 } 7036 7037 /* A 10G copper XAUI in either slot0 or slot1 */ 7038 } else if ((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 7039 == TN1010_DEV_ID || 7040 (port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK) 7041 == TN1010_DEV_ID) { 7042 switch (port_fd_arr[0]) { 7043 /* The XAUI is in slot0 */ 7044 case N2_CLAUSE45_PORT_ADDR_BASE: 7045 hw_p->niu_type = NEPTUNE_1_TN1010; 7046 break; 7047 7048 /* The XAUI is in slot1 */ 7049 case (N2_CLAUSE45_PORT_ADDR_BASE + 1): 7050 hw_p->niu_type 7051 = NEPTUNE_1_NONE_1_TN1010; 7052 break; 7053 default: 7054 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7055 "Unsupported XAUI port address")); 7056 goto error_exit; 7057 } 7058 hw_p->xcvr_addr[nxgep->function_num] 7059 = port_fd_arr[0]; 7060 7061 } else { 7062 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7063 "Unsupported PHY type")); 7064 goto error_exit; 7065 } 7066 break; 7067 case 4: /* Maramba always have 4 clause 45 ports */ 7068 7069 /* Maramba with 1 XAUI */ 7070 if ((port_pcs_dev_id[0] != PHY_BCM8704_FAMILY) && 7071 (port_pma_pmd_dev_id[0] != PHY_BCM8704_FAMILY) && 7072 ((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 7073 != TN1010_DEV_ID) && 7074 ((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK) 7075 != TN1010_DEV_ID)) { 7076 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7077 "Unsupported neptune type 12")); 7078 goto error_exit; 7079 } 7080 7081 /* 7082 * Check the first phy port address against 7083 * the known phy start addresses to determine 7084 * the platform type. 7085 */ 7086 switch (phy_fd_arr[0]) { 7087 case MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE: 7088 hw_p->platform_type = 7089 P_NEPTUNE_MARAMBA_P0; 7090 break; 7091 case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE: 7092 hw_p->platform_type = 7093 P_NEPTUNE_MARAMBA_P1; 7094 break; 7095 default: 7096 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7097 "Unknown port %d...Cannot " 7098 "determine platform type 10 - 2", 7099 i)); 7100 goto error_exit; 7101 } 7102 7103 /* 7104 * Check the clause45 address to determine 7105 * if XAUI is in port 0 or port 1. 7106 */ 7107 switch (port_fd_arr[0]) { 7108 case MARAMBA_CLAUSE45_PORT_ADDR_BASE: 7109 if (port_pcs_dev_id[0] 7110 == PHY_BCM8704_FAMILY || 7111 port_pma_pmd_dev_id[0] 7112 == PHY_BCM8704_FAMILY) { 7113 hw_p->niu_type 7114 = NEPTUNE_1_10GF_3_1GC; 7115 } else { 7116 hw_p->niu_type 7117 = NEPTUNE_1_TN1010_3_1GC; 7118 } 7119 hw_p->xcvr_addr[0] = port_fd_arr[0]; 7120 for (i = 1; i < NXGE_MAX_PORTS; i++) { 7121 hw_p->xcvr_addr[i] = 7122 phy_fd_arr[i]; 7123 } 7124 break; 7125 case (MARAMBA_CLAUSE45_PORT_ADDR_BASE + 1): 7126 if (port_pcs_dev_id[0] 7127 == PHY_BCM8704_FAMILY || 7128 port_pma_pmd_dev_id[0] 7129 == PHY_BCM8704_FAMILY) { 7130 hw_p->niu_type = 7131 NEPTUNE_1_1GC_1_10GF_2_1GC; 7132 } else { 7133 hw_p->niu_type = 7134 NEPTUNE_1_1GC_1_TN1010_2_1GC; 7135 } 7136 hw_p->xcvr_addr[0] = phy_fd_arr[0]; 7137 hw_p->xcvr_addr[1] = port_fd_arr[0]; 7138 hw_p->xcvr_addr[2] = phy_fd_arr[2]; 7139 hw_p->xcvr_addr[3] = phy_fd_arr[3]; 7140 break; 7141 default: 7142 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7143 "Unsupported neptune type 11")); 7144 goto error_exit; 7145 } 7146 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7147 "Maramba with 1 XAUI (fiber or copper)")); 7148 break; 7149 default: 7150 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7151 "Unsupported neptune type 13")); 7152 goto error_exit; 7153 } 7154 break; 7155 case 0: /* 4 ports Neptune based NIC */ 7156 switch (total_phy_fd) { 7157 case 4: 7158 if ((port_phy_id[0] == PHY_BCM5464R_FAMILY) && 7159 (port_phy_id[1] == PHY_BCM5464R_FAMILY) && 7160 (port_phy_id[2] == PHY_BCM5464R_FAMILY) && 7161 (port_phy_id[3] == PHY_BCM5464R_FAMILY)) { 7162 7163 /* 7164 * Check the first phy port address against 7165 * the known phy start addresses to determine 7166 * the platform type. 7167 */ 7168 switch (phy_fd_arr[0]) { 7169 case MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE: 7170 hw_p->platform_type = 7171 P_NEPTUNE_MARAMBA_P1; 7172 break; 7173 case NEPTUNE_CLAUSE22_PORT_ADDR_BASE: 7174 hw_p->platform_type = 7175 P_NEPTUNE_ATLAS_4PORT; 7176 break; 7177 default: 7178 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7179 "Unknown port %d...Cannot " 7180 "determine platform type", i)); 7181 goto error_exit; 7182 } 7183 hw_p->niu_type = NEPTUNE_4_1GC; 7184 for (i = 0; i < NXGE_MAX_PORTS; i++) { 7185 hw_p->xcvr_addr[i] = phy_fd_arr[i]; 7186 } 7187 } else { 7188 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7189 "Unsupported neptune type 14")); 7190 goto error_exit; 7191 } 7192 break; 7193 case 3: 7194 /* TODO 3 1G mode */ 7195 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7196 "Unsupported neptune type 15")); 7197 goto error_exit; 7198 case 2: 7199 /* TODO 2 1G mode */ 7200 if ((port_phy_id[0] == PHY_BCM5482_FAMILY) && 7201 (port_phy_id[1] == PHY_BCM5482_FAMILY)) { 7202 hw_p->platform_type = P_NEPTUNE_GENERIC; 7203 hw_p->niu_type = NEPTUNE_2_1GRF; 7204 hw_p->xcvr_addr[2] = phy_fd_arr[0]; 7205 hw_p->xcvr_addr[3] = phy_fd_arr[1]; 7206 } else { 7207 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7208 "Unsupported neptune type 16")); 7209 goto error_exit; 7210 } 7211 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7212 "2 RGMII Fiber ports - RTM")); 7213 break; 7214 7215 case 1: 7216 /* TODO 1 1G mode */ 7217 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7218 "Unsupported neptune type 17")); 7219 goto error_exit; 7220 default: 7221 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7222 "Unsupported neptune type 18, total phy fd %d", 7223 total_phy_fd)); 7224 goto error_exit; 7225 } 7226 break; 7227 default: 7228 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7229 "Unsupported neptune type 19")); 7230 goto error_exit; 7231 } 7232 7233 scan_exit: 7234 7235 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_scan_ports_phy, " 7236 "niu type [0x%x]\n", hw_p->niu_type)); 7237 return (status); 7238 7239 error_exit: 7240 return (NXGE_ERROR); 7241 } 7242 7243 boolean_t 7244 nxge_is_valid_local_mac(ether_addr_st mac_addr) 7245 { 7246 if ((mac_addr.ether_addr_octet[0] & 0x01) || 7247 (ether_cmp(&mac_addr, ðerbroadcastaddr) == 0) || 7248 (ether_cmp(&mac_addr, ðerzeroaddr) == 0)) 7249 return (B_FALSE); 7250 else 7251 return (B_TRUE); 7252 } 7253 7254 static void 7255 nxge_bcm5464_link_led_off(p_nxge_t nxgep) { 7256 7257 npi_status_t rs = NPI_SUCCESS; 7258 uint8_t xcvr_portn; 7259 uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 7260 7261 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_bcm5464_link_led_off")); 7262 7263 if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P1) { 7264 xcvr_portn = MARAMBA_P1_CLAUSE22_PORT_ADDR_BASE; 7265 } else if (nxgep->nxge_hw_p->platform_type == P_NEPTUNE_MARAMBA_P0) { 7266 xcvr_portn = MARAMBA_P0_CLAUSE22_PORT_ADDR_BASE; 7267 } 7268 /* 7269 * For Altas 4-1G copper, Xcvr port numbers are 7270 * swapped with ethernet port number. This is 7271 * designed for better signal integrity in routing. 7272 */ 7273 switch (portn) { 7274 case 0: 7275 xcvr_portn += 3; 7276 break; 7277 case 1: 7278 xcvr_portn += 2; 7279 break; 7280 case 2: 7281 xcvr_portn += 1; 7282 break; 7283 case 3: 7284 default: 7285 break; 7286 } 7287 7288 MUTEX_ENTER(&nxgep->nxge_hw_p->nxge_mdio_lock); 7289 rs = npi_mac_mif_mii_write(nxgep->npi_handle, 7290 xcvr_portn, BCM5464R_MISC, 0xb4ee); 7291 if (rs != NPI_SUCCESS) { 7292 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7293 "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write " 7294 "returned error 0x[%x]", rs)); 7295 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 7296 return; 7297 } 7298 7299 rs = npi_mac_mif_mii_write(nxgep->npi_handle, 7300 xcvr_portn, BCM5464R_MISC, 0xb8ee); 7301 if (rs != NPI_SUCCESS) { 7302 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7303 "<== nxge_bcm5464_link_led_off: npi_mac_mif_mii_write " 7304 "returned error 0x[%x]", rs)); 7305 } 7306 7307 MUTEX_EXIT(&nxgep->nxge_hw_p->nxge_mdio_lock); 7308 } 7309 7310 static nxge_status_t 7311 nxge_mii_get_link_mode(p_nxge_t nxgep) 7312 { 7313 p_nxge_stats_t statsp; 7314 uint8_t xcvr_portn; 7315 p_mii_regs_t mii_regs; 7316 mii_mode_control_stat_t mode; 7317 int status = NXGE_OK; 7318 7319 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_get_link_mode")); 7320 7321 statsp = nxgep->statsp; 7322 xcvr_portn = statsp->mac_stats.xcvr_portn; 7323 mii_regs = NULL; 7324 mode.value = 0; 7325 mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG; 7326 #if defined(__i386) 7327 if ((status = nxge_mii_write(nxgep, xcvr_portn, 7328 (uint8_t)(uint32_t)(&mii_regs->shadow), 7329 mode.value)) != NXGE_OK) { 7330 goto fail; 7331 #else 7332 if ((status = nxge_mii_write(nxgep, xcvr_portn, 7333 (uint8_t)(uint64_t)(&mii_regs->shadow), 7334 mode.value)) != NXGE_OK) { 7335 goto fail; 7336 #endif 7337 } 7338 #if defined(__i386) 7339 if ((status = nxge_mii_read(nxgep, xcvr_portn, 7340 (uint8_t)(uint32_t)(&mii_regs->shadow), 7341 &mode.value)) != NXGE_OK) { 7342 goto fail; 7343 } 7344 #else 7345 if ((status = nxge_mii_read(nxgep, xcvr_portn, 7346 (uint8_t)(uint64_t)(&mii_regs->shadow), 7347 &mode.value)) != NXGE_OK) { 7348 goto fail; 7349 } 7350 #endif 7351 7352 if (mode.bits.mode == NXGE_MODE_SELECT_FIBER) { 7353 nxgep->mac.portmode = PORT_1G_RGMII_FIBER; 7354 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7355 "nxge_mii_get_link_mode: fiber mode")); 7356 } 7357 7358 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7359 "nxge_mii_get_link_mode: " 7360 "(address 0x%x) port 0x%x mode value 0x%x link mode 0x%x", 7361 NXGE_MII_MODE_CONTROL_REG, xcvr_portn, 7362 mode.value, nxgep->mac.portmode)); 7363 7364 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7365 "<== nxge_mii_get_link_mode")); 7366 return (status); 7367 fail: 7368 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7369 "<== nxge_mii_get_link_mode (failed)")); 7370 return (NXGE_ERROR); 7371 } 7372 7373 nxge_status_t 7374 nxge_mac_set_framesize(p_nxge_t nxgep) 7375 { 7376 npi_attr_t ap; 7377 uint8_t portn; 7378 npi_handle_t handle; 7379 npi_status_t rs = NPI_SUCCESS; 7380 7381 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_set_framesize")); 7382 7383 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 7384 handle = nxgep->npi_handle; 7385 7386 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7387 "==> nxge_mac_sec_framesize: port<%d> " 7388 "min framesize %d max framesize %d ", 7389 portn, 7390 nxgep->mac.minframesize, 7391 nxgep->mac.maxframesize)); 7392 7393 SET_MAC_ATTR2(handle, ap, portn, 7394 MAC_PORT_FRAME_SIZE, 7395 nxgep->mac.minframesize, 7396 nxgep->mac.maxframesize, 7397 rs); 7398 if (rs != NPI_SUCCESS) { 7399 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7400 "<== nxge_mac_set_framesize: failed to configure " 7401 "max/min frame size port %d", portn)); 7402 7403 return (NXGE_ERROR | rs); 7404 } 7405 7406 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7407 "<== nxge_mac_set_framesize: port<%d>", portn)); 7408 7409 return (NXGE_OK); 7410 } 7411 7412 static nxge_status_t 7413 nxge_get_num_of_xaui(uint32_t *port_pma_pmd_dev_id, 7414 uint32_t *port_pcs_dev_id, uint32_t *port_phy_id, uint8_t *num_xaui) 7415 { 7416 uint8_t i; 7417 7418 for (i = 0; i < 4; i++) { 7419 if (port_phy_id[i] != PHY_BCM5464R_FAMILY) 7420 return (NXGE_ERROR); 7421 } 7422 7423 *num_xaui = 0; 7424 if ((port_pma_pmd_dev_id[0] == PHY_BCM8704_FAMILY && 7425 port_pcs_dev_id[0] == PHY_BCM8704_FAMILY) || 7426 (((port_pma_pmd_dev_id[0] & TN1010_DEV_ID_MASK) 7427 == TN1010_DEV_ID) && 7428 ((port_pcs_dev_id[0] & TN1010_DEV_ID_MASK) 7429 == TN1010_DEV_ID))) { 7430 (*num_xaui) ++; 7431 } 7432 if ((port_pma_pmd_dev_id[1] == PHY_BCM8704_FAMILY && 7433 port_pcs_dev_id[1] == PHY_BCM8704_FAMILY) || 7434 (((port_pma_pmd_dev_id[1] & TN1010_DEV_ID_MASK) 7435 == TN1010_DEV_ID) && 7436 ((port_pcs_dev_id[1] & TN1010_DEV_ID_MASK) 7437 == TN1010_DEV_ID))) { 7438 (*num_xaui) ++; 7439 } 7440 return (NXGE_OK); 7441 } 7442 7443 /* 7444 * Instruction from Teranetics: Once you detect link is up, go 7445 * read Reg 30.1.4 for link speed: '1' for 1G and '0' for 10G. You 7446 * may want to qualify it by first checking Register 30.1.7:6 and 7447 * making sure it reads "01" (Auto-Neg Complete). 7448 * 7449 * If this function is called when the link is down or before auto- 7450 * negotiation has completed, then the speed of the PHY is not certain. 7451 * In such cases, this function returns 1G as the default speed with 7452 * NXGE_OK status instead of NXGE_ERROR. It is OK to initialize the 7453 * driver based on a default speed because this function will be called 7454 * again when the link comes up. Returning NXGE_ERROR, which may 7455 * cause brutal chain reaction in caller functions, is not necessary. 7456 */ 7457 static nxge_status_t 7458 nxge_get_tn1010_speed(p_nxge_t nxgep, uint16_t *speed) 7459 { 7460 uint8_t phy_port_addr, autoneg_stat, link_up; 7461 nxge_status_t status = NXGE_OK; 7462 uint16_t val; 7463 uint8_t portn = NXGE_GET_PORT_NUM(nxgep->function_num); 7464 7465 /* Set default speed to 10G */ 7466 *speed = TN1010_SPEED_10G; 7467 7468 /* Set Clause 45 */ 7469 npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE); 7470 7471 phy_port_addr = nxgep->nxge_hw_p->xcvr_addr[portn]; 7472 7473 /* Check Device 1 Register 0xA bit0 for link up status */ 7474 status = nxge_mdio_read(nxgep, phy_port_addr, 7475 TN1010_AUTONEG_DEV_ADDR, TN1010_AUTONEG_STATUS_REG, &val); 7476 if (status != NXGE_OK) 7477 goto fail; 7478 7479 link_up = ((val & TN1010_AN_LINK_STAT_BIT) 7480 ? B_TRUE : B_FALSE); 7481 if (link_up == B_FALSE) { 7482 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7483 "nxge_get_tn1010_speed: link is down")); 7484 goto nxge_get_tn1010_speed_exit; 7485 } 7486 7487 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 7488 TN1010_VENDOR_MMD1_DEV_ADDR, TN1010_VENDOR_MMD1_STATUS_REG, 7489 &val)) != NXGE_OK) { 7490 goto fail; 7491 } 7492 autoneg_stat = (val & TN1010_VENDOR_MMD1_AN_STAT_BITS) >> 7493 TN1010_VENDOR_MMD1_AN_STAT_SHIFT; 7494 7495 /* 7496 * Return NXGE_OK even when we can not get a settled speed. In 7497 * such case, the speed reported should not be trusted but that 7498 * is OK, we will call this function periodically and will get 7499 * the correct speed after the link is up. 7500 */ 7501 switch (autoneg_stat) { 7502 case TN1010_AN_IN_PROG: 7503 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7504 "nxge_get_tn1010_speed: Auto-negotiation in progress")); 7505 break; 7506 case TN1010_AN_COMPLETE: 7507 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 7508 TN1010_VENDOR_MMD1_DEV_ADDR, 7509 TN1010_VENDOR_MMD1_STATUS_REG, 7510 &val)) != NXGE_OK) { 7511 goto fail; 7512 } 7513 *speed = (val & TN1010_VENDOR_MMD1_AN_SPEED_BIT) >> 7514 TN1010_VENDOR_MMD1_AN_SPEED_SHIFT; 7515 break; 7516 case TN1010_AN_RSVD: 7517 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7518 "nxge_get_tn1010_speed: Autoneg status undefined")); 7519 break; 7520 case TN1010_AN_FAILED: 7521 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 7522 "nxge_get_tn1010_speed: Auto-negotiation failed")); 7523 break; 7524 default: 7525 break; 7526 } 7527 nxge_get_tn1010_speed_exit: 7528 return (NXGE_OK); 7529 fail: 7530 return (status); 7531 } 7532 7533 7534 /* 7535 * Teranetics TN1010 PHY chip supports both 1G and 10G modes, this function 7536 * figures out the speed of the PHY determined by the autonegotiation 7537 * process and sets the following 3 parameters, 7538 * nxgep->mac.portmode 7539 * nxgep->statsp->mac_stats.link_speed 7540 * nxgep->statsp->mac_stats.xcvr_inuse 7541 */ 7542 static nxge_status_t 7543 nxge_set_tn1010_param(p_nxge_t nxgep) 7544 { 7545 uint16_t speed; 7546 7547 if (nxge_get_tn1010_speed(nxgep, &speed) != NXGE_OK) { 7548 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7549 "nxge_set_tn1010_param: " 7550 "Failed to get TN1010 speed")); 7551 return (NXGE_ERROR); 7552 } 7553 if (speed == TN1010_SPEED_1G) { 7554 nxgep->mac.portmode = PORT_1G_TN1010; 7555 nxgep->statsp->mac_stats.link_speed = 1000; 7556 nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 7557 } else { 7558 nxgep->mac.portmode = PORT_10G_TN1010; 7559 nxgep->statsp->mac_stats.link_speed = 10000; 7560 nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 7561 } 7562 return (NXGE_OK); 7563 } 7564 7565 #ifdef NXGE_DEBUG 7566 static void 7567 nxge_mii_dump(p_nxge_t nxgep) 7568 { 7569 p_nxge_stats_t statsp; 7570 uint8_t xcvr_portn; 7571 p_mii_regs_t mii_regs; 7572 mii_bmcr_t bmcr; 7573 mii_bmsr_t bmsr; 7574 mii_idr1_t idr1; 7575 mii_idr2_t idr2; 7576 mii_mode_control_stat_t mode; 7577 p_nxge_param_t param_arr; 7578 7579 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "==> nxge_mii_dump")); 7580 7581 statsp = nxgep->statsp; 7582 xcvr_portn = statsp->mac_stats.xcvr_portn; 7583 7584 mii_regs = NULL; 7585 7586 #if defined(__i386) 7587 (void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn, 7588 (uint8_t)(uint32_t)(&mii_regs->bmcr), &bmcr.value); 7589 #else 7590 (void) nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn, 7591 (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value); 7592 #endif 7593 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7594 "nxge_mii_dump: bmcr (0) xcvr 0x%x value 0x%x", 7595 xcvr_portn, bmcr.value)); 7596 7597 #if defined(__i386) 7598 (void) nxge_mii_read(nxgep, 7599 nxgep->statsp->mac_stats.xcvr_portn, 7600 (uint8_t)(uint32_t)(&mii_regs->bmsr), &bmsr.value); 7601 #else 7602 (void) nxge_mii_read(nxgep, 7603 nxgep->statsp->mac_stats.xcvr_portn, 7604 (uint8_t)(uint64_t)(&mii_regs->bmsr), &bmsr.value); 7605 #endif 7606 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7607 "nxge_mii_dump: bmsr (1) xcvr 0x%x value 0x%x", 7608 xcvr_portn, bmsr.value)); 7609 7610 #if defined(__i386) 7611 (void) nxge_mii_read(nxgep, 7612 nxgep->statsp->mac_stats.xcvr_portn, 7613 (uint8_t)(uint32_t)(&mii_regs->idr1), &idr1.value); 7614 #else 7615 (void) nxge_mii_read(nxgep, 7616 nxgep->statsp->mac_stats.xcvr_portn, 7617 (uint8_t)(uint64_t)(&mii_regs->idr1), &idr1.value); 7618 #endif 7619 7620 7621 #if defined(__i386) 7622 (void) nxge_mii_read(nxgep, 7623 nxgep->statsp->mac_stats.xcvr_portn, 7624 (uint8_t)(uint32_t)(&mii_regs->idr2), &idr2.value); 7625 #else 7626 (void) nxge_mii_read(nxgep, 7627 nxgep->statsp->mac_stats.xcvr_portn, 7628 (uint8_t)(uint64_t)(&mii_regs->idr2), &idr2.value); 7629 #endif 7630 7631 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7632 "nxge_mii_dump: idr1 (2) xcvr 0x%x value 0x%x", 7633 xcvr_portn, idr1.value)); 7634 7635 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7636 "nxge_mii_dump: idr2 (3) xcvr 0x%x value 0x%x", 7637 xcvr_portn, idr2.value)); 7638 7639 mode.value = 0; 7640 mode.bits.shadow = NXGE_MII_MODE_CONTROL_REG; 7641 7642 #if defined(__i386) 7643 (void) nxge_mii_write(nxgep, xcvr_portn, 7644 (uint8_t)(uint32_t)(&mii_regs->shadow), mode.value); 7645 7646 (void) nxge_mii_read(nxgep, xcvr_portn, 7647 (uint8_t)(uint32_t)(&mii_regs->shadow), &mode.value); 7648 #else 7649 (void) nxge_mii_write(nxgep, xcvr_portn, 7650 (uint8_t)(uint64_t)(&mii_regs->shadow), mode.value); 7651 7652 (void) nxge_mii_read(nxgep, xcvr_portn, 7653 (uint8_t)(uint64_t)(&mii_regs->shadow), &mode.value); 7654 #endif 7655 7656 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 7657 "nxge_mii_dump: mode control xcvr 0x%x value 0x%x", 7658 xcvr_portn, mode.value)); 7659 } 7660 #endif 7661