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