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