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