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