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