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 2007 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 31 #define LINK_MONITOR_PERIOD (1000 * 1000) 32 #define LM_WAIT_MULTIPLIER 8 33 34 extern uint32_t nxge_no_link_notify; 35 extern uint32_t nxge_lb_dbg; 36 extern nxge_os_mutex_t nxge_mdio_lock; 37 extern nxge_os_mutex_t nxge_mii_lock; 38 extern boolean_t nxge_jumbo_enable; 39 40 typedef enum { 41 CHECK_LINK_RESCHEDULE, 42 CHECK_LINK_STOP 43 } check_link_state_t; 44 45 static check_link_state_t nxge_check_link_stop(nxge_t *); 46 47 /* 48 * Ethernet broadcast address definition. 49 */ 50 static ether_addr_st etherbroadcastaddr = 51 {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}}; 52 static ether_addr_st etherzeroaddr = 53 {{0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}; 54 55 nxge_status_t nxge_mac_init(p_nxge_t); 56 57 /* Initialize the entire MAC and physical layer */ 58 59 nxge_status_t 60 nxge_mac_init(p_nxge_t nxgep) 61 { 62 uint8_t portn; 63 nxge_status_t status = NXGE_OK; 64 65 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 66 67 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mac_init: port<%d>", portn)); 68 69 nxgep->mac.portnum = portn; 70 nxgep->mac.porttype = PORT_TYPE_XMAC; 71 72 if ((portn == BMAC_PORT_0) || (portn == BMAC_PORT_1)) 73 nxgep->mac.porttype = PORT_TYPE_BMAC; 74 75 /* Initialize XIF to configure a network mode */ 76 if ((status = nxge_xif_init(nxgep)) != NXGE_OK) { 77 goto fail; 78 } 79 80 if ((status = nxge_pcs_init(nxgep)) != NXGE_OK) { 81 goto fail; 82 } 83 84 /* Initialize TX and RX MACs */ 85 /* 86 * Always perform XIF init first, before TX and RX MAC init 87 */ 88 if ((status = nxge_tx_mac_reset(nxgep)) != NXGE_OK) 89 goto fail; 90 91 if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK) 92 goto fail; 93 94 if ((status = nxge_rx_mac_reset(nxgep)) != NXGE_OK) 95 goto fail; 96 97 if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK) 98 goto fail; 99 100 if ((status = nxge_tx_mac_enable(nxgep)) != NXGE_OK) 101 goto fail; 102 103 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 104 goto fail; 105 106 nxgep->statsp->mac_stats.mac_mtu = nxgep->mac.maxframesize; 107 108 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mac_init: port<%d>", portn)); 109 110 return (NXGE_OK); 111 fail: 112 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 113 "nxge_mac_init: failed to initialize MAC port<%d>", 114 portn)); 115 return (status); 116 } 117 118 /* Initialize the Ethernet Link */ 119 120 nxge_status_t 121 nxge_link_init(p_nxge_t nxgep) 122 { 123 nxge_status_t status = NXGE_OK; 124 #ifdef NXGE_DEBUG 125 uint8_t portn; 126 127 portn = nxgep->mac.portnum; 128 129 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_init: port<%d>", portn)); 130 #endif 131 132 if (nxgep->niu_type == N2_NIU) { 133 /* Workaround to get link up in both NIU ports */ 134 if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK) 135 goto fail; 136 } 137 NXGE_DELAY(200000); 138 /* Initialize internal serdes */ 139 if ((status = nxge_serdes_init(nxgep)) != NXGE_OK) 140 goto fail; 141 NXGE_DELAY(200000); 142 if ((status = nxge_xcvr_init(nxgep)) != NXGE_OK) 143 goto fail; 144 145 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_init: port<%d>", portn)); 146 147 return (NXGE_OK); 148 149 fail: 150 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 151 "nxge_link_init: ", 152 "failed to initialize Ethernet link on port<%d>", 153 portn)); 154 155 return (status); 156 } 157 158 159 /* Initialize the XIF sub-block within the MAC */ 160 161 nxge_status_t 162 nxge_xif_init(p_nxge_t nxgep) 163 { 164 uint32_t xif_cfg = 0; 165 npi_attr_t ap; 166 uint8_t portn; 167 nxge_port_t portt; 168 nxge_port_mode_t portmode; 169 p_nxge_stats_t statsp; 170 npi_status_t rs = NPI_SUCCESS; 171 npi_handle_t handle; 172 173 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 174 175 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xif_init: port<%d>", portn)); 176 177 handle = nxgep->npi_handle; 178 portmode = nxgep->mac.portmode; 179 portt = nxgep->mac.porttype; 180 statsp = nxgep->statsp; 181 182 if (portt == PORT_TYPE_XMAC) { 183 184 /* Setup XIF Configuration for XMAC */ 185 186 if ((portmode == PORT_10G_FIBER) || 187 (portmode == PORT_10G_COPPER)) 188 xif_cfg |= CFG_XMAC_XIF_LFS; 189 190 if (portmode == PORT_1G_COPPER) { 191 xif_cfg |= CFG_XMAC_XIF_1G_PCS_BYPASS; 192 } 193 194 /* Set MAC Internal Loopback if necessary */ 195 if (statsp->port_stats.lb_mode == nxge_lb_mac1000) 196 xif_cfg |= CFG_XMAC_XIF_LOOPBACK; 197 198 if (statsp->mac_stats.link_speed == 100) 199 xif_cfg |= CFG_XMAC_XIF_SEL_CLK_25MHZ; 200 201 xif_cfg |= CFG_XMAC_XIF_TX_OUTPUT; 202 203 if (portmode == PORT_10G_FIBER) { 204 if (statsp->mac_stats.link_up) { 205 xif_cfg |= CFG_XMAC_XIF_LED_POLARITY; 206 } else { 207 xif_cfg |= CFG_XMAC_XIF_LED_FORCE; 208 } 209 } 210 211 rs = npi_xmac_xif_config(handle, INIT, portn, xif_cfg); 212 if (rs != NPI_SUCCESS) 213 goto fail; 214 215 nxgep->mac.xif_config = xif_cfg; 216 217 /* Set Port Mode */ 218 if ((portmode == PORT_10G_FIBER) || 219 (portmode == PORT_10G_COPPER)) { 220 SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE, 221 MAC_XGMII_MODE, rs); 222 if (rs != NPI_SUCCESS) 223 goto fail; 224 if (statsp->mac_stats.link_up) { 225 if (nxge_10g_link_led_on(nxgep) != NXGE_OK) 226 goto fail; 227 } else { 228 if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 229 goto fail; 230 } 231 } else if ((portmode == PORT_1G_FIBER) || 232 (portmode == PORT_1G_COPPER)) { 233 if (statsp->mac_stats.link_speed == 1000) { 234 SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE, 235 MAC_GMII_MODE, rs); 236 } else { 237 SET_MAC_ATTR1(handle, ap, portn, MAC_PORT_MODE, 238 MAC_MII_MODE, rs); 239 } 240 if (rs != NPI_SUCCESS) 241 goto fail; 242 } else { 243 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 244 "nxge_xif_init: Unknown port mode (%d)" 245 " for port<%d>", portmode, portn)); 246 goto fail; 247 } 248 249 } else if (portt == PORT_TYPE_BMAC) { 250 251 /* Setup XIF Configuration for BMAC */ 252 253 if (portmode == PORT_1G_COPPER) { 254 if (statsp->mac_stats.link_speed == 100) 255 xif_cfg |= CFG_BMAC_XIF_SEL_CLK_25MHZ; 256 } 257 258 if (statsp->port_stats.lb_mode == nxge_lb_mac1000) 259 xif_cfg |= CFG_BMAC_XIF_LOOPBACK; 260 261 if (statsp->mac_stats.link_speed == 1000) 262 xif_cfg |= CFG_BMAC_XIF_GMII_MODE; 263 264 xif_cfg |= CFG_BMAC_XIF_TX_OUTPUT; 265 266 rs = npi_bmac_xif_config(handle, INIT, portn, xif_cfg); 267 if (rs != NPI_SUCCESS) 268 goto fail; 269 nxgep->mac.xif_config = xif_cfg; 270 } 271 272 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xif_init: port<%d>", portn)); 273 return (NXGE_OK); 274 fail: 275 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 276 "nxge_xif_init: Failed to initialize XIF port<%d>", 277 portn)); 278 return (NXGE_ERROR | rs); 279 } 280 281 /* Initialize the PCS sub-block in the MAC */ 282 283 nxge_status_t 284 nxge_pcs_init(p_nxge_t nxgep) 285 { 286 pcs_cfg_t pcs_cfg; 287 uint32_t val; 288 uint8_t portn; 289 nxge_port_mode_t portmode; 290 npi_handle_t handle; 291 p_nxge_stats_t statsp; 292 npi_status_t rs = NPI_SUCCESS; 293 294 handle = nxgep->npi_handle; 295 portmode = nxgep->mac.portmode; 296 portn = nxgep->mac.portnum; 297 statsp = nxgep->statsp; 298 299 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_pcs_init: port<%d>", portn)); 300 301 if (portmode == PORT_1G_FIBER) { 302 /* Initialize port's PCS */ 303 pcs_cfg.value = 0; 304 pcs_cfg.bits.w0.enable = 1; 305 pcs_cfg.bits.w0.mask = 1; 306 PCS_REG_WR(handle, portn, PCS_CONFIG_REG, pcs_cfg.value); 307 PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG, 0); 308 if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS) 309 goto fail; 310 311 } else if ((portmode == PORT_10G_FIBER) || 312 (portmode == PORT_10G_COPPER)) { 313 /* Use internal XPCS, bypass 1G PCS */ 314 XMAC_REG_RD(handle, portn, XMAC_CONFIG_REG, &val); 315 val &= ~XMAC_XIF_XPCS_BYPASS; 316 XMAC_REG_WR(handle, portn, XMAC_CONFIG_REG, val); 317 318 if ((rs = npi_xmac_xpcs_reset(handle, portn)) != NPI_SUCCESS) 319 goto fail; 320 321 /* Set XPCS Internal Loopback if necessary */ 322 if ((rs = npi_xmac_xpcs_read(handle, portn, 323 XPCS_REG_CONTROL1, &val)) 324 != NPI_SUCCESS) 325 goto fail; 326 if ((statsp->port_stats.lb_mode == nxge_lb_mac10g) || 327 (statsp->port_stats.lb_mode == nxge_lb_mac1000)) 328 val |= XPCS_CTRL1_LOOPBK; 329 else 330 val &= ~XPCS_CTRL1_LOOPBK; 331 if ((rs = npi_xmac_xpcs_write(handle, portn, 332 XPCS_REG_CONTROL1, val)) 333 != NPI_SUCCESS) 334 goto fail; 335 336 /* Clear descw errors */ 337 if ((rs = npi_xmac_xpcs_write(handle, portn, 338 XPCS_REG_DESCWERR_COUNTER, 0)) 339 != NPI_SUCCESS) 340 goto fail; 341 /* Clear symbol errors */ 342 if ((rs = npi_xmac_xpcs_read(handle, portn, 343 XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val)) 344 != NPI_SUCCESS) 345 goto fail; 346 if ((rs = npi_xmac_xpcs_read(handle, portn, 347 XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val)) 348 != NPI_SUCCESS) 349 goto fail; 350 351 } else if (portmode == PORT_1G_COPPER) { 352 if (portn < 4) { 353 PCS_REG_WR(handle, portn, PCS_DATAPATH_MODE_REG, 354 PCS_DATAPATH_MODE_MII); 355 } 356 if ((rs = npi_mac_pcs_reset(handle, portn)) != NPI_SUCCESS) 357 goto fail; 358 359 } else { 360 goto fail; 361 } 362 pass: 363 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_pcs_init: port<%d>", portn)); 364 return (NXGE_OK); 365 fail: 366 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 367 "nxge_pcs_init: Failed to initialize PCS port<%d>", 368 portn)); 369 return (NXGE_ERROR | rs); 370 } 371 372 /* Initialize the Internal Serdes */ 373 374 nxge_status_t 375 nxge_serdes_init(p_nxge_t nxgep) 376 { 377 p_nxge_stats_t statsp; 378 #ifdef NXGE_DEBUG 379 uint8_t portn; 380 #endif 381 nxge_status_t status = NXGE_OK; 382 383 #ifdef NXGE_DEBUG 384 portn = nxgep->mac.portnum; 385 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 386 "==> nxge_serdes_init port<%d>", portn)); 387 #endif 388 389 statsp = nxgep->statsp; 390 391 if (nxgep->niu_type == N2_NIU) { 392 if (nxge_n2_serdes_init(nxgep) != NXGE_OK) 393 goto fail; 394 } else if ((nxgep->niu_type == NEPTUNE) || 395 (nxgep->niu_type == NEPTUNE_2)) { 396 if ((status = nxge_neptune_serdes_init(nxgep)) 397 != NXGE_OK) 398 goto fail; 399 } else { 400 goto fail; 401 } 402 403 statsp->mac_stats.serdes_inits++; 404 405 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_serdes_init port<%d>", 406 portn)); 407 408 return (NXGE_OK); 409 410 fail: 411 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 412 "nxge_serdes_init: Failed to initialize serdes for port<%d>", 413 portn)); 414 415 return (status); 416 } 417 418 /* Initialize the TI Hedwig Internal Serdes (N2-NIU only) */ 419 420 nxge_status_t 421 nxge_n2_serdes_init(p_nxge_t nxgep) 422 { 423 uint8_t portn; 424 int chan; 425 esr_ti_cfgpll_l_t pll_cfg_l; 426 esr_ti_cfgrx_l_t rx_cfg_l; 427 esr_ti_cfgrx_h_t rx_cfg_h; 428 esr_ti_cfgtx_l_t tx_cfg_l; 429 esr_ti_cfgtx_h_t tx_cfg_h; 430 esr_ti_testcfg_t test_cfg; 431 nxge_status_t status = NXGE_OK; 432 433 portn = nxgep->mac.portnum; 434 435 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_n2_serdes_init port<%d>", 436 portn)); 437 438 tx_cfg_l.value = 0; 439 tx_cfg_h.value = 0; 440 rx_cfg_l.value = 0; 441 rx_cfg_h.value = 0; 442 pll_cfg_l.value = 0; 443 test_cfg.value = 0; 444 445 if (nxgep->mac.portmode == PORT_10G_FIBER) { 446 /* 0x0E01 */ 447 tx_cfg_l.bits.entx = 1; 448 tx_cfg_l.bits.swing = CFGTX_SWING_1375MV; 449 450 /* 0x9101 */ 451 rx_cfg_l.bits.enrx = 1; 452 rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT; 453 rx_cfg_l.bits.align = CFGRX_ALIGN_EN; 454 rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES; 455 456 /* 0x0008 */ 457 rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF; 458 459 /* Set loopback mode if necessary */ 460 if (nxgep->statsp->port_stats.lb_mode == nxge_lb_serdes10g) { 461 tx_cfg_l.bits.entest = 1; 462 rx_cfg_l.bits.entest = 1; 463 test_cfg.bits.loopback = TESTCFG_INNER_CML_DIS_LOOPBACK; 464 if ((status = nxge_mdio_write(nxgep, portn, 465 ESR_N2_DEV_ADDR, 466 ESR_N2_TEST_CFG_REG, test_cfg.value)) 467 != NXGE_OK) 468 goto fail; 469 } 470 471 /* Use default PLL value */ 472 473 } else if (nxgep->mac.portmode == PORT_1G_FIBER) { 474 475 /* 0x0E21 */ 476 tx_cfg_l.bits.entx = 1; 477 tx_cfg_l.bits.rate = CFGTX_RATE_HALF; 478 tx_cfg_l.bits.swing = CFGTX_SWING_1375MV; 479 480 /* 0x9121 */ 481 rx_cfg_l.bits.enrx = 1; 482 rx_cfg_l.bits.rate = CFGRX_RATE_HALF; 483 rx_cfg_l.bits.term = CFGRX_TERM_0P8VDDT; 484 rx_cfg_l.bits.align = CFGRX_ALIGN_EN; 485 rx_cfg_l.bits.los = CFGRX_LOS_LOTHRES; 486 487 /* 0x8 */ 488 rx_cfg_h.bits.eq = CFGRX_EQ_ADAPTIVE_LP_ADAPTIVE_ZF; 489 490 /* MPY = 0x100 */ 491 pll_cfg_l.bits.mpy = CFGPLL_MPY_8X; 492 493 /* Set PLL */ 494 pll_cfg_l.bits.enpll = 1; 495 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 496 ESR_N2_PLL_CFG_L_REG, pll_cfg_l.value)) 497 != NXGE_OK) 498 goto fail; 499 } else { 500 goto fail; 501 } 502 503 /* MIF_REG_WR(handle, MIF_MASK_REG, ~mask); */ 504 505 NXGE_DELAY(20); 506 507 /* init TX channels */ 508 for (chan = 0; chan < 4; chan++) { 509 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 510 ESR_N2_TX_CFG_L_REG_ADDR(chan), tx_cfg_l.value)) 511 != NXGE_OK) 512 goto fail; 513 514 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 515 ESR_N2_TX_CFG_H_REG_ADDR(chan), tx_cfg_h.value)) 516 != NXGE_OK) 517 goto fail; 518 } 519 520 /* init RX channels */ 521 for (chan = 0; chan < 4; chan++) { 522 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 523 ESR_N2_RX_CFG_L_REG_ADDR(chan), rx_cfg_l.value)) 524 != NXGE_OK) 525 goto fail; 526 527 if ((status = nxge_mdio_write(nxgep, portn, ESR_N2_DEV_ADDR, 528 ESR_N2_RX_CFG_H_REG_ADDR(chan), rx_cfg_h.value)) 529 != NXGE_OK) 530 goto fail; 531 } 532 533 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_n2_serdes_init port<%d>", 534 portn)); 535 536 return (NXGE_OK); 537 fail: 538 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 539 "nxge_n2_serdes_init: Failed to initialize N2 serdes for port<%d>", 540 portn)); 541 542 return (status); 543 } 544 545 /* Initialize Neptune Internal Serdes (Neptune only) */ 546 547 nxge_status_t 548 nxge_neptune_serdes_init(p_nxge_t nxgep) 549 { 550 npi_handle_t handle; 551 uint8_t portn; 552 nxge_port_mode_t portmode; 553 int chan; 554 sr_rx_tx_ctrl_l_t rx_tx_ctrl_l; 555 sr_rx_tx_ctrl_h_t rx_tx_ctrl_h; 556 sr_glue_ctrl0_l_t glue_ctrl0_l; 557 sr_glue_ctrl0_h_t glue_ctrl0_h; 558 uint64_t val; 559 uint16_t val16l; 560 uint16_t val16h; 561 nxge_status_t status = NXGE_OK; 562 563 portn = nxgep->mac.portnum; 564 565 if ((portn != 0) && (portn != 1)) 566 return (NXGE_OK); 567 568 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_neptune_serdes_init port<%d>", 569 portn)); 570 571 handle = nxgep->npi_handle; 572 portmode = nxgep->mac.portmode; 573 574 if ((portmode == PORT_10G_FIBER) || (portmode == PORT_10G_COPPER)) { 575 576 switch (portn) { 577 case 0: 578 ESR_REG_WR(handle, ESR_0_CONTROL_REG, 579 ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 | 580 ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 | 581 (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) | 582 (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) | 583 (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) | 584 (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 585 (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 586 (0x1 << ESR_CTL_LOSADJ_0_SHIFT) | 587 (0x1 << ESR_CTL_LOSADJ_1_SHIFT) | 588 (0x1 << ESR_CTL_LOSADJ_2_SHIFT) | 589 (0x1 << ESR_CTL_LOSADJ_3_SHIFT)); 590 591 /* Set Serdes0 Internal Loopback if necessary */ 592 if (nxgep->statsp->port_stats.lb_mode == 593 nxge_lb_serdes10g) { 594 ESR_REG_WR(handle, 595 ESR_0_TEST_CONFIG_REG, 596 ESR_PAD_LOOPBACK_CH3 | 597 ESR_PAD_LOOPBACK_CH2 | 598 ESR_PAD_LOOPBACK_CH1 | 599 ESR_PAD_LOOPBACK_CH0); 600 } else { 601 ESR_REG_WR(handle, 602 ESR_0_TEST_CONFIG_REG, 0); 603 } 604 break; 605 case 1: 606 ESR_REG_WR(handle, ESR_1_CONTROL_REG, 607 ESR_CTL_EN_SYNCDET_0 | ESR_CTL_EN_SYNCDET_1 | 608 ESR_CTL_EN_SYNCDET_2 | ESR_CTL_EN_SYNCDET_3 | 609 (0x5 << ESR_CTL_OUT_EMPH_0_SHIFT) | 610 (0x5 << ESR_CTL_OUT_EMPH_1_SHIFT) | 611 (0x5 << ESR_CTL_OUT_EMPH_2_SHIFT) | 612 (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 613 (0x5 << ESR_CTL_OUT_EMPH_3_SHIFT) | 614 (0x1 << ESR_CTL_LOSADJ_0_SHIFT) | 615 (0x1 << ESR_CTL_LOSADJ_1_SHIFT) | 616 (0x1 << ESR_CTL_LOSADJ_2_SHIFT) | 617 (0x1 << ESR_CTL_LOSADJ_3_SHIFT)); 618 619 /* Set Serdes1 Internal Loopback if necessary */ 620 if (nxgep->statsp->port_stats.lb_mode == 621 nxge_lb_serdes10g) { 622 ESR_REG_WR(handle, 623 ESR_1_TEST_CONFIG_REG, 624 ESR_PAD_LOOPBACK_CH3 | 625 ESR_PAD_LOOPBACK_CH2 | 626 ESR_PAD_LOOPBACK_CH1 | 627 ESR_PAD_LOOPBACK_CH0); 628 } else { 629 ESR_REG_WR(handle, 630 ESR_1_TEST_CONFIG_REG, 0); 631 } 632 break; 633 default: 634 /* Nothing to do here */ 635 goto done; 636 } 637 638 /* init TX RX channels */ 639 for (chan = 0; chan < 4; chan++) { 640 if ((status = nxge_mdio_read(nxgep, portn, 641 ESR_NEPTUNE_DEV_ADDR, 642 ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 643 &rx_tx_ctrl_l.value)) != NXGE_OK) 644 goto fail; 645 if ((status = nxge_mdio_read(nxgep, portn, 646 ESR_NEPTUNE_DEV_ADDR, 647 ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 648 &rx_tx_ctrl_h.value)) != NXGE_OK) 649 goto fail; 650 if ((status = nxge_mdio_read(nxgep, portn, 651 ESR_NEPTUNE_DEV_ADDR, 652 ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 653 &glue_ctrl0_l.value)) != NXGE_OK) 654 goto fail; 655 if ((status = nxge_mdio_read(nxgep, portn, 656 ESR_NEPTUNE_DEV_ADDR, 657 ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 658 &glue_ctrl0_h.value)) != NXGE_OK) 659 goto fail; 660 rx_tx_ctrl_l.bits.enstretch = 1; 661 rx_tx_ctrl_h.bits.vmuxlo = 2; 662 rx_tx_ctrl_h.bits.vpulselo = 2; 663 glue_ctrl0_l.bits.rxlosenable = 1; 664 glue_ctrl0_l.bits.samplerate = 0xF; 665 glue_ctrl0_l.bits.thresholdcount = 0xFF; 666 glue_ctrl0_h.bits.bitlocktime = BITLOCKTIME_300_CYCLES; 667 if ((status = nxge_mdio_write(nxgep, portn, 668 ESR_NEPTUNE_DEV_ADDR, 669 ESR_NEP_RX_TX_CONTROL_L_ADDR(chan), 670 rx_tx_ctrl_l.value)) != NXGE_OK) 671 goto fail; 672 if ((status = nxge_mdio_write(nxgep, portn, 673 ESR_NEPTUNE_DEV_ADDR, 674 ESR_NEP_RX_TX_CONTROL_H_ADDR(chan), 675 rx_tx_ctrl_h.value)) != NXGE_OK) 676 goto fail; 677 if ((status = nxge_mdio_write(nxgep, portn, 678 ESR_NEPTUNE_DEV_ADDR, 679 ESR_NEP_GLUE_CONTROL0_L_ADDR(chan), 680 glue_ctrl0_l.value)) != NXGE_OK) 681 goto fail; 682 if ((status = nxge_mdio_write(nxgep, portn, 683 ESR_NEPTUNE_DEV_ADDR, 684 ESR_NEP_GLUE_CONTROL0_H_ADDR(chan), 685 glue_ctrl0_h.value)) != NXGE_OK) 686 goto fail; 687 } 688 689 /* Apply Tx core reset */ 690 if ((status = nxge_mdio_write(nxgep, portn, 691 ESR_NEPTUNE_DEV_ADDR, 692 ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), 693 (uint16_t)0)) != NXGE_OK) 694 goto fail; 695 696 if ((status = nxge_mdio_write(nxgep, portn, 697 ESR_NEPTUNE_DEV_ADDR, 698 ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), 699 (uint16_t)0xffff)) != NXGE_OK) 700 goto fail; 701 702 NXGE_DELAY(200); 703 704 /* Apply Rx core reset */ 705 if ((status = nxge_mdio_write(nxgep, portn, 706 ESR_NEPTUNE_DEV_ADDR, 707 ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), 708 (uint16_t)0xffff)) != NXGE_OK) 709 goto fail; 710 711 NXGE_DELAY(200); 712 if ((status = nxge_mdio_write(nxgep, portn, 713 ESR_NEPTUNE_DEV_ADDR, 714 ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), 715 (uint16_t)0)) != NXGE_OK) 716 goto fail; 717 718 NXGE_DELAY(200); 719 if ((status = nxge_mdio_read(nxgep, portn, 720 ESR_NEPTUNE_DEV_ADDR, 721 ESR_NEP_RX_TX_RESET_CONTROL_L_ADDR(), 722 &val16l)) != NXGE_OK) 723 goto fail; 724 if ((status = nxge_mdio_read(nxgep, portn, 725 ESR_NEPTUNE_DEV_ADDR, 726 ESR_NEP_RX_TX_RESET_CONTROL_H_ADDR(), 727 &val16h)) != NXGE_OK) 728 goto fail; 729 if ((val16l != 0) || (val16h != 0)) { 730 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 731 "Failed to reset port<%d> XAUI Serdes", 732 portn)); 733 } 734 735 ESR_REG_RD(handle, ESR_INTERNAL_SIGNALS_REG, &val); 736 737 if (portn == 0) { 738 if ((val & ESR_SIG_P0_BITS_MASK) != 739 (ESR_SIG_SERDES_RDY0_P0 | ESR_SIG_DETECT0_P0 | 740 ESR_SIG_XSERDES_RDY_P0 | 741 ESR_SIG_XDETECT_P0_CH3 | 742 ESR_SIG_XDETECT_P0_CH2 | 743 ESR_SIG_XDETECT_P0_CH1 | 744 ESR_SIG_XDETECT_P0_CH0)) { 745 goto fail; 746 } 747 } else if (portn == 1) { 748 if ((val & ESR_SIG_P1_BITS_MASK) != 749 (ESR_SIG_SERDES_RDY0_P1 | ESR_SIG_DETECT0_P1 | 750 ESR_SIG_XSERDES_RDY_P1 | 751 ESR_SIG_XDETECT_P1_CH3 | 752 ESR_SIG_XDETECT_P1_CH2 | 753 ESR_SIG_XDETECT_P1_CH1 | 754 ESR_SIG_XDETECT_P1_CH0)) { 755 goto fail; 756 } 757 } 758 759 } else if (portmode == PORT_1G_FIBER) { 760 ESR_REG_RD(handle, ESR_1_PLL_CONFIG_REG, &val) 761 val &= ~ESR_PLL_CFG_FBDIV_2; 762 switch (portn) { 763 case 0: 764 val |= ESR_PLL_CFG_HALF_RATE_0; 765 break; 766 case 1: 767 val |= ESR_PLL_CFG_HALF_RATE_1; 768 break; 769 case 2: 770 val |= ESR_PLL_CFG_HALF_RATE_2; 771 break; 772 case 3: 773 val |= ESR_PLL_CFG_HALF_RATE_3; 774 break; 775 default: 776 goto fail; 777 } 778 779 ESR_REG_WR(handle, ESR_1_PLL_CONFIG_REG, val); 780 } 781 782 done: 783 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_neptune_serdes_init port<%d>", 784 portn)); 785 return (NXGE_OK); 786 fail: 787 NXGE_DEBUG_MSG((nxgep, TX_CTL, 788 "nxge_neptune_serdes_init: " 789 "Failed to initialize Neptune serdes for port<%d>", 790 portn)); 791 792 return (status); 793 } 794 795 /* Look for transceiver type */ 796 797 nxge_status_t 798 nxge_xcvr_find(p_nxge_t nxgep) 799 { 800 uint8_t portn; 801 802 portn = nxgep->mac.portnum; 803 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_find: port<%d>", portn)); 804 805 if (nxge_get_xcvr_type(nxgep) != NXGE_OK) 806 return (NXGE_ERROR); 807 808 nxgep->mac.linkchkmode = LINKCHK_TIMER; 809 if (nxgep->mac.portmode == PORT_10G_FIBER) { 810 nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 811 if ((nxgep->niu_type == NEPTUNE) || 812 (nxgep->niu_type == NEPTUNE_2)) { 813 nxgep->statsp->mac_stats.xcvr_portn = 814 BCM8704_NEPTUNE_PORT_ADDR_BASE + portn; 815 } else if (nxgep->niu_type == N2_NIU) { 816 nxgep->statsp->mac_stats.xcvr_portn = 817 BCM8704_N2_PORT_ADDR_BASE + portn; 818 } else 819 return (NXGE_ERROR); 820 } else if (nxgep->mac.portmode == PORT_1G_COPPER) { 821 nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR; 822 /* 823 * For Altas, Xcvr port numbers are swapped with ethernet 824 * port number. This is designed for better signal 825 * integrity in routing. 826 */ 827 828 switch (portn) { 829 case 0: 830 nxgep->statsp->mac_stats.xcvr_portn = 831 BCM5464_NEPTUNE_PORT_ADDR_BASE + 3; 832 break; 833 case 1: 834 nxgep->statsp->mac_stats.xcvr_portn = 835 BCM5464_NEPTUNE_PORT_ADDR_BASE + 2; 836 break; 837 case 2: 838 nxgep->statsp->mac_stats.xcvr_portn = 839 BCM5464_NEPTUNE_PORT_ADDR_BASE + 1; 840 break; 841 case 3: 842 nxgep->statsp->mac_stats.xcvr_portn = 843 BCM5464_NEPTUNE_PORT_ADDR_BASE; 844 break; 845 default: 846 return (NXGE_ERROR); 847 } 848 } else if (nxgep->mac.portmode == PORT_1G_FIBER) { 849 nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 850 nxgep->statsp->mac_stats.xcvr_portn = portn; 851 } else { 852 return (NXGE_ERROR); 853 } 854 855 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_xcvr_find: xcvr_inuse = %d", 856 nxgep->statsp->mac_stats.xcvr_inuse)); 857 return (NXGE_OK); 858 } 859 860 /* Initialize transceiver */ 861 862 nxge_status_t 863 nxge_xcvr_init(p_nxge_t nxgep) 864 { 865 p_nxge_param_t param_arr; 866 p_nxge_stats_t statsp; 867 uint16_t val; 868 #ifdef NXGE_DEBUG 869 uint8_t portn; 870 uint16_t val1; 871 #endif 872 uint8_t phy_port_addr; 873 pmd_tx_control_t tx_ctl; 874 control_t ctl; 875 phyxs_control_t phyxs_ctl; 876 pcs_control_t pcs_ctl; 877 uint32_t delay = 0; 878 optics_dcntr_t op_ctr; 879 nxge_status_t status = NXGE_OK; 880 #ifdef NXGE_DEBUG 881 portn = nxgep->mac.portnum; 882 #endif 883 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", portn)); 884 885 param_arr = nxgep->param_arr; 886 statsp = nxgep->statsp; 887 888 /* 889 * Initialize the xcvr statistics. 890 */ 891 statsp->mac_stats.cap_autoneg = 0; 892 statsp->mac_stats.cap_100T4 = 0; 893 statsp->mac_stats.cap_100fdx = 0; 894 statsp->mac_stats.cap_100hdx = 0; 895 statsp->mac_stats.cap_10fdx = 0; 896 statsp->mac_stats.cap_10hdx = 0; 897 statsp->mac_stats.cap_asmpause = 0; 898 statsp->mac_stats.cap_pause = 0; 899 statsp->mac_stats.cap_1000fdx = 0; 900 statsp->mac_stats.cap_1000hdx = 0; 901 statsp->mac_stats.cap_10gfdx = 0; 902 statsp->mac_stats.cap_10ghdx = 0; 903 904 /* 905 * Initialize the link statistics. 906 */ 907 statsp->mac_stats.link_T4 = 0; 908 statsp->mac_stats.link_asmpause = 0; 909 statsp->mac_stats.link_pause = 0; 910 911 phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn; 912 913 switch (nxgep->mac.portmode) { 914 case PORT_10G_FIBER: 915 /* Disable Link LEDs */ 916 if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 917 goto fail; 918 919 /* Set Clause 45 */ 920 npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_TRUE); 921 922 /* Reset the transceiver */ 923 if ((status = nxge_mdio_read(nxgep, 924 phy_port_addr, 925 BCM8704_PHYXS_ADDR, 926 BCM8704_PHYXS_CONTROL_REG, 927 &phyxs_ctl.value)) != NXGE_OK) 928 goto fail; 929 930 phyxs_ctl.bits.reset = 1; 931 if ((status = nxge_mdio_write(nxgep, 932 phy_port_addr, 933 BCM8704_PHYXS_ADDR, 934 BCM8704_PHYXS_CONTROL_REG, 935 phyxs_ctl.value)) != NXGE_OK) 936 goto fail; 937 938 do { 939 drv_usecwait(500); 940 if ((status = nxge_mdio_read(nxgep, 941 phy_port_addr, 942 BCM8704_PHYXS_ADDR, 943 BCM8704_PHYXS_CONTROL_REG, 944 &phyxs_ctl.value)) != NXGE_OK) 945 goto fail; 946 delay++; 947 } while ((phyxs_ctl.bits.reset) && (delay < 100)); 948 if (delay == 100) { 949 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 950 "nxge_xcvr_init: " 951 "failed to reset Transceiver on port<%d>", 952 portn)); 953 status = NXGE_ERROR; 954 goto fail; 955 } 956 957 /* Set to 0x7FBF */ 958 ctl.value = 0; 959 ctl.bits.res1 = 0x3F; 960 ctl.bits.optxon_lvl = 1; 961 ctl.bits.oprxflt_lvl = 1; 962 ctl.bits.optrxlos_lvl = 1; 963 ctl.bits.optxflt_lvl = 1; 964 ctl.bits.opprflt_lvl = 1; 965 ctl.bits.obtmpflt_lvl = 1; 966 ctl.bits.opbiasflt_lvl = 1; 967 ctl.bits.optxrst_lvl = 1; 968 if ((status = nxge_mdio_write(nxgep, 969 phy_port_addr, 970 BCM8704_USER_DEV3_ADDR, 971 BCM8704_USER_CONTROL_REG, ctl.value)) 972 != NXGE_OK) 973 goto fail; 974 975 /* Set to 0x164 */ 976 tx_ctl.value = 0; 977 tx_ctl.bits.tsck_lpwren = 1; 978 tx_ctl.bits.tx_dac_txck = 0x2; 979 tx_ctl.bits.tx_dac_txd = 0x1; 980 tx_ctl.bits.xfp_clken = 1; 981 if ((status = nxge_mdio_write(nxgep, 982 phy_port_addr, 983 BCM8704_USER_DEV3_ADDR, 984 BCM8704_USER_PMD_TX_CONTROL_REG, tx_ctl.value)) 985 != NXGE_OK) 986 goto fail; 987 /* 988 * According to Broadcom's instruction, SW needs to read 989 * back these registers twice after written. 990 */ 991 if ((status = nxge_mdio_read(nxgep, 992 phy_port_addr, 993 BCM8704_USER_DEV3_ADDR, 994 BCM8704_USER_CONTROL_REG, &val)) 995 != NXGE_OK) 996 goto fail; 997 998 if ((status = nxge_mdio_read(nxgep, 999 phy_port_addr, 1000 BCM8704_USER_DEV3_ADDR, 1001 BCM8704_USER_CONTROL_REG, &val)) 1002 != NXGE_OK) 1003 goto fail; 1004 1005 if ((status = nxge_mdio_read(nxgep, 1006 phy_port_addr, 1007 BCM8704_USER_DEV3_ADDR, 1008 BCM8704_USER_PMD_TX_CONTROL_REG, &val)) 1009 != NXGE_OK) 1010 goto fail; 1011 1012 if ((status = nxge_mdio_read(nxgep, 1013 phy_port_addr, 1014 BCM8704_USER_DEV3_ADDR, 1015 BCM8704_USER_PMD_TX_CONTROL_REG, &val)) 1016 != NXGE_OK) 1017 goto fail; 1018 1019 1020 /* Enable Tx and Rx LEDs to be driven by traffic */ 1021 if ((status = nxge_mdio_read(nxgep, 1022 phy_port_addr, 1023 BCM8704_USER_DEV3_ADDR, 1024 BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 1025 &op_ctr.value)) != NXGE_OK) 1026 goto fail; 1027 op_ctr.bits.gpio_sel = 0x3; 1028 if ((status = nxge_mdio_write(nxgep, 1029 phy_port_addr, 1030 BCM8704_USER_DEV3_ADDR, 1031 BCM8704_USER_OPTICS_DIGITAL_CTRL_REG, 1032 op_ctr.value)) != NXGE_OK) 1033 goto fail; 1034 1035 NXGE_DELAY(1000000); 1036 1037 /* Set BCM8704 Internal Loopback mode if necessary */ 1038 if ((status = nxge_mdio_read(nxgep, 1039 phy_port_addr, 1040 BCM8704_PCS_DEV_ADDR, 1041 BCM8704_PCS_CONTROL_REG, 1042 &pcs_ctl.value)) != NXGE_OK) 1043 goto fail; 1044 if (nxgep->statsp->port_stats.lb_mode == nxge_lb_phy10g) 1045 pcs_ctl.bits.loopback = 1; 1046 else 1047 pcs_ctl.bits.loopback = 0; 1048 if ((status = nxge_mdio_write(nxgep, 1049 phy_port_addr, 1050 BCM8704_PCS_DEV_ADDR, 1051 BCM8704_PCS_CONTROL_REG, 1052 pcs_ctl.value)) != NXGE_OK) 1053 goto fail; 1054 1055 status = nxge_mdio_read(nxgep, phy_port_addr, 1056 0x1, 0xA, &val); 1057 if (status != NXGE_OK) 1058 goto fail; 1059 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1060 "BCM8704 port<%d> Dev 1 Reg 0xA = 0x%x\n", 1061 portn, val)); 1062 status = nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0x20, &val); 1063 if (status != NXGE_OK) 1064 goto fail; 1065 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1066 "BCM8704 port<%d> Dev 3 Reg 0x20 = 0x%x\n", 1067 portn, val)); 1068 status = nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, &val); 1069 if (status != NXGE_OK) 1070 goto fail; 1071 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1072 "BCM8704 port<%d> Dev 4 Reg 0x18 = 0x%x\n", 1073 portn, val)); 1074 1075 #ifdef NXGE_DEBUG 1076 /* Diagnose link issue if link is not up */ 1077 status = nxge_mdio_read(nxgep, phy_port_addr, 1078 BCM8704_USER_DEV3_ADDR, 1079 BCM8704_USER_ANALOG_STATUS0_REG, 1080 &val); 1081 if (status != NXGE_OK) 1082 goto fail; 1083 1084 status = nxge_mdio_read(nxgep, phy_port_addr, 1085 BCM8704_USER_DEV3_ADDR, 1086 BCM8704_USER_ANALOG_STATUS0_REG, 1087 &val); 1088 if (status != NXGE_OK) 1089 goto fail; 1090 1091 status = nxge_mdio_read(nxgep, phy_port_addr, 1092 BCM8704_USER_DEV3_ADDR, 1093 BCM8704_USER_TX_ALARM_STATUS_REG, 1094 &val1); 1095 if (status != NXGE_OK) 1096 goto fail; 1097 1098 status = nxge_mdio_read(nxgep, phy_port_addr, 1099 BCM8704_USER_DEV3_ADDR, 1100 BCM8704_USER_TX_ALARM_STATUS_REG, 1101 &val1); 1102 if (status != NXGE_OK) 1103 goto fail; 1104 1105 if (val != 0x3FC) { 1106 if ((val == 0x43BC) && (val1 != 0)) { 1107 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1108 "Cable not connected to peer or bad" 1109 " cable on port<%d>\n", portn)); 1110 } else if (val == 0x639C) { 1111 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1112 "Optical module (XFP) is bad or absence" 1113 " on port<%d>\n", portn)); 1114 } 1115 } 1116 #endif 1117 1118 statsp->mac_stats.cap_10gfdx = 1; 1119 statsp->mac_stats.lp_cap_10gfdx = 1; 1120 break; 1121 case PORT_10G_COPPER: 1122 break; 1123 case PORT_1G_FIBER: 1124 case PORT_1G_COPPER: 1125 /* Set Clause 22 */ 1126 npi_mac_mif_set_indirect_mode(nxgep->npi_handle, B_FALSE); 1127 1128 /* Set capability flags */ 1129 statsp->mac_stats.cap_1000fdx = 1130 param_arr[param_anar_1000fdx].value; 1131 statsp->mac_stats.cap_100fdx = 1132 param_arr[param_anar_100fdx].value; 1133 statsp->mac_stats.cap_10fdx = param_arr[param_anar_10fdx].value; 1134 1135 if ((status = nxge_mii_xcvr_init(nxgep)) != NXGE_OK) 1136 goto fail; 1137 break; 1138 default: 1139 goto fail; 1140 } 1141 1142 statsp->mac_stats.xcvr_inits++; 1143 1144 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_xcvr_init: port<%d>", portn)); 1145 return (NXGE_OK); 1146 1147 fail: 1148 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1149 "nxge_xcvr_init: failed to initialize transceiver for port<%d>", 1150 portn)); 1151 return (status); 1152 } 1153 1154 1155 /* Initialize the TxMAC sub-block */ 1156 1157 nxge_status_t 1158 nxge_tx_mac_init(p_nxge_t nxgep) 1159 { 1160 npi_attr_t ap; 1161 uint8_t portn; 1162 nxge_port_mode_t portmode; 1163 nxge_port_t portt; 1164 npi_handle_t handle; 1165 npi_status_t rs = NPI_SUCCESS; 1166 1167 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 1168 portt = nxgep->mac.porttype; 1169 handle = nxgep->npi_handle; 1170 portmode = nxgep->mac.portmode; 1171 1172 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_init: port<%d>", 1173 portn)); 1174 1175 /* Set Max and Min Frame Size */ 1176 if (nxgep->param_arr[param_accept_jumbo].value || nxge_jumbo_enable) { 1177 SET_MAC_ATTR2(handle, ap, portn, 1178 MAC_PORT_FRAME_SIZE, 64, 0x2400, rs); 1179 } else { 1180 SET_MAC_ATTR2(handle, ap, portn, 1181 MAC_PORT_FRAME_SIZE, 64, 0x5EE + 4, rs); 1182 } 1183 1184 if (rs != NPI_SUCCESS) 1185 goto fail; 1186 if (nxgep->param_arr[param_accept_jumbo].value || 1187 nxgep->mac.is_jumbo == B_TRUE) 1188 nxgep->mac.maxframesize = 0x2400; 1189 else 1190 nxgep->mac.maxframesize = 0x5EE + 4; 1191 nxgep->mac.minframesize = 64; 1192 1193 if (portt == PORT_TYPE_XMAC) { 1194 if ((rs = npi_xmac_tx_iconfig(handle, INIT, portn, 1195 0)) != NPI_SUCCESS) 1196 goto fail; 1197 nxgep->mac.tx_iconfig = NXGE_XMAC_TX_INTRS; 1198 if ((portmode == PORT_10G_FIBER) || 1199 (portmode == PORT_10G_COPPER)) { 1200 SET_MAC_ATTR1(handle, ap, portn, XMAC_10G_PORT_IPG, 1201 XGMII_IPG_12_15, rs); 1202 if (rs != NPI_SUCCESS) 1203 goto fail; 1204 nxgep->mac.ipg[0] = XGMII_IPG_12_15; 1205 } else { 1206 SET_MAC_ATTR1(handle, ap, portn, XMAC_PORT_IPG, 1207 MII_GMII_IPG_12, rs); 1208 if (rs != NPI_SUCCESS) 1209 goto fail; 1210 nxgep->mac.ipg[0] = MII_GMII_IPG_12; 1211 } 1212 if ((rs = npi_xmac_tx_config(handle, INIT, portn, 1213 CFG_XMAC_TX_CRC | CFG_XMAC_TX)) != NPI_SUCCESS) 1214 goto fail; 1215 nxgep->mac.tx_config = CFG_XMAC_TX_CRC | CFG_XMAC_TX; 1216 nxgep->mac.maxburstsize = 0; /* not programmable */ 1217 nxgep->mac.ctrltype = 0; /* not programmable */ 1218 nxgep->mac.pa_size = 0; /* not programmable */ 1219 1220 if ((rs = npi_xmac_zap_tx_counters(handle, portn)) 1221 != NPI_SUCCESS) 1222 goto fail; 1223 1224 } else { 1225 if ((rs = npi_bmac_tx_iconfig(handle, INIT, portn, 1226 0)) != NPI_SUCCESS) 1227 goto fail; 1228 nxgep->mac.tx_iconfig = NXGE_BMAC_TX_INTRS; 1229 1230 SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_CTRL_TYPE, 0x8808, 1231 rs); 1232 if (rs != NPI_SUCCESS) 1233 goto fail; 1234 nxgep->mac.ctrltype = 0x8808; 1235 1236 SET_MAC_ATTR1(handle, ap, portn, BMAC_PORT_PA_SIZE, 0x7, rs); 1237 if (rs != NPI_SUCCESS) 1238 goto fail; 1239 nxgep->mac.pa_size = 0x7; 1240 1241 if ((rs = npi_bmac_tx_config(handle, INIT, portn, 1242 CFG_BMAC_TX_CRC | CFG_BMAC_TX)) != NPI_SUCCESS) 1243 goto fail; 1244 nxgep->mac.tx_config = CFG_BMAC_TX_CRC | CFG_BMAC_TX; 1245 } 1246 1247 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_init: port<%d>", 1248 portn)); 1249 1250 return (NXGE_OK); 1251 fail: 1252 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1253 "nxge_tx_mac_init: failed to initialize port<%d> TXMAC", 1254 portn)); 1255 1256 return (NXGE_ERROR | rs); 1257 } 1258 1259 /* Initialize the RxMAC sub-block */ 1260 1261 nxge_status_t 1262 nxge_rx_mac_init(p_nxge_t nxgep) 1263 { 1264 npi_attr_t ap; 1265 uint32_t i; 1266 uint16_t hashtab_e; 1267 p_hash_filter_t hash_filter; 1268 nxge_port_t portt; 1269 uint8_t portn; 1270 npi_handle_t handle; 1271 npi_status_t rs = NPI_SUCCESS; 1272 uint16_t *addr16p; 1273 uint16_t addr0, addr1, addr2; 1274 xmac_rx_config_t xconfig; 1275 bmac_rx_config_t bconfig; 1276 1277 portn = NXGE_GET_PORT_NUM(nxgep->function_num); 1278 1279 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_init: port<%d>\n", 1280 portn)); 1281 handle = nxgep->npi_handle; 1282 portt = nxgep->mac.porttype; 1283 1284 addr16p = (uint16_t *)nxgep->ouraddr.ether_addr_octet; 1285 addr0 = ntohs(addr16p[2]); 1286 addr1 = ntohs(addr16p[1]); 1287 addr2 = ntohs(addr16p[0]); 1288 SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR, addr0, addr1, addr2, 1289 rs); 1290 1291 if (rs != NPI_SUCCESS) 1292 goto fail; 1293 SET_MAC_ATTR3(handle, ap, portn, MAC_PORT_ADDR_FILTER, 0, 0, 0, rs); 1294 if (rs != NPI_SUCCESS) 1295 goto fail; 1296 SET_MAC_ATTR2(handle, ap, portn, MAC_PORT_ADDR_FILTER_MASK, 0, 0, rs); 1297 if (rs != NPI_SUCCESS) 1298 goto fail; 1299 1300 /* 1301 * Load the multicast hash filter bits. 1302 */ 1303 hash_filter = nxgep->hash_filter; 1304 for (i = 0; i < MAC_MAX_HASH_ENTRY; i++) { 1305 if (hash_filter != NULL) { 1306 hashtab_e = (uint16_t)hash_filter->hash_filter_regs[ 1307 (NMCFILTER_REGS - 1) - i]; 1308 } else { 1309 hashtab_e = 0; 1310 } 1311 1312 if ((rs = npi_mac_hashtab_entry(handle, OP_SET, portn, i, 1313 (uint16_t *)&hashtab_e)) != NPI_SUCCESS) 1314 goto fail; 1315 } 1316 1317 if (portt == PORT_TYPE_XMAC) { 1318 if ((rs = npi_xmac_rx_iconfig(handle, INIT, portn, 1319 0)) != NPI_SUCCESS) 1320 goto fail; 1321 nxgep->mac.rx_iconfig = NXGE_XMAC_RX_INTRS; 1322 1323 (void) nxge_fflp_init_hostinfo(nxgep); 1324 1325 xconfig = CFG_XMAC_RX_ERRCHK | CFG_XMAC_RX_CRC_CHK | 1326 CFG_XMAC_RX | CFG_XMAC_RX_CODE_VIO_CHK & 1327 ~CFG_XMAC_RX_STRIP_CRC; 1328 1329 if (nxgep->filter.all_phys_cnt != 0) 1330 xconfig |= CFG_XMAC_RX_PROMISCUOUS; 1331 1332 if (nxgep->filter.all_multicast_cnt != 0) 1333 xconfig |= CFG_XMAC_RX_PROMISCUOUSGROUP; 1334 1335 xconfig |= CFG_XMAC_RX_HASH_FILTER; 1336 1337 if ((rs = npi_xmac_rx_config(handle, INIT, portn, 1338 xconfig)) != NPI_SUCCESS) 1339 goto fail; 1340 nxgep->mac.rx_config = xconfig; 1341 1342 /* Comparison of mac unique address is always enabled on XMAC */ 1343 1344 if ((rs = npi_xmac_zap_rx_counters(handle, portn)) 1345 != NPI_SUCCESS) 1346 goto fail; 1347 } else { 1348 (void) nxge_fflp_init_hostinfo(nxgep); 1349 1350 if (npi_bmac_rx_iconfig(nxgep->npi_handle, INIT, portn, 1351 0) != NPI_SUCCESS) 1352 goto fail; 1353 nxgep->mac.rx_iconfig = NXGE_BMAC_RX_INTRS; 1354 1355 bconfig = CFG_BMAC_RX_DISCARD_ON_ERR | CFG_BMAC_RX & 1356 ~CFG_BMAC_RX_STRIP_CRC; 1357 1358 if (nxgep->filter.all_phys_cnt != 0) 1359 bconfig |= CFG_BMAC_RX_PROMISCUOUS; 1360 1361 if (nxgep->filter.all_multicast_cnt != 0) 1362 bconfig |= CFG_BMAC_RX_PROMISCUOUSGROUP; 1363 1364 bconfig |= CFG_BMAC_RX_HASH_FILTER; 1365 if ((rs = npi_bmac_rx_config(handle, INIT, portn, 1366 bconfig)) != NPI_SUCCESS) 1367 goto fail; 1368 nxgep->mac.rx_config = bconfig; 1369 1370 /* Always enable comparison of mac unique address */ 1371 if ((rs = npi_mac_altaddr_enable(handle, portn, 0)) 1372 != NPI_SUCCESS) 1373 goto fail; 1374 } 1375 1376 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_init: port<%d>\n", 1377 portn)); 1378 1379 return (NXGE_OK); 1380 1381 fail: 1382 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1383 "nxge_rx_mac_init: Failed to Initialize port<%d> RxMAC", 1384 portn)); 1385 1386 return (NXGE_ERROR | rs); 1387 } 1388 1389 /* Enable TXMAC */ 1390 1391 nxge_status_t 1392 nxge_tx_mac_enable(p_nxge_t nxgep) 1393 { 1394 npi_handle_t handle; 1395 npi_status_t rs = NPI_SUCCESS; 1396 nxge_status_t status = NXGE_OK; 1397 1398 handle = nxgep->npi_handle; 1399 1400 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_enable: port<%d>", 1401 nxgep->mac.portnum)); 1402 1403 if ((status = nxge_tx_mac_init(nxgep)) != NXGE_OK) 1404 goto fail; 1405 1406 /* based on speed */ 1407 nxgep->msg_min = ETHERMIN; 1408 1409 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 1410 if ((rs = npi_xmac_tx_config(handle, ENABLE, nxgep->mac.portnum, 1411 CFG_XMAC_TX)) != NPI_SUCCESS) 1412 goto fail; 1413 } else { 1414 if ((rs = npi_bmac_tx_config(handle, ENABLE, nxgep->mac.portnum, 1415 CFG_BMAC_TX)) != NPI_SUCCESS) 1416 goto fail; 1417 } 1418 1419 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_enable: port<%d>", 1420 nxgep->mac.portnum)); 1421 1422 return (NXGE_OK); 1423 fail: 1424 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1425 "nxgep_tx_mac_enable: Failed to enable port<%d> TxMAC", 1426 nxgep->mac.portnum)); 1427 if (rs != NPI_SUCCESS) 1428 return (NXGE_ERROR | rs); 1429 else 1430 return (status); 1431 } 1432 1433 /* Disable TXMAC */ 1434 1435 nxge_status_t 1436 nxge_tx_mac_disable(p_nxge_t nxgep) 1437 { 1438 npi_handle_t handle; 1439 npi_status_t rs = NPI_SUCCESS; 1440 1441 handle = nxgep->npi_handle; 1442 1443 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_disable: port<%d>", 1444 nxgep->mac.portnum)); 1445 1446 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 1447 if ((rs = npi_xmac_tx_config(handle, DISABLE, 1448 nxgep->mac.portnum, CFG_XMAC_TX)) != NPI_SUCCESS) 1449 goto fail; 1450 } else { 1451 if ((rs = npi_bmac_tx_config(handle, DISABLE, 1452 nxgep->mac.portnum, CFG_BMAC_TX)) != NPI_SUCCESS) 1453 goto fail; 1454 } 1455 1456 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_disable: port<%d>", 1457 nxgep->mac.portnum)); 1458 return (NXGE_OK); 1459 fail: 1460 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1461 "nxge_tx_mac_disable: Failed to disable port<%d> TxMAC", 1462 nxgep->mac.portnum)); 1463 return (NXGE_ERROR | rs); 1464 } 1465 1466 /* Enable RXMAC */ 1467 1468 nxge_status_t 1469 nxge_rx_mac_enable(p_nxge_t nxgep) 1470 { 1471 npi_handle_t handle; 1472 uint8_t portn; 1473 npi_status_t rs = NPI_SUCCESS; 1474 nxge_status_t status = NXGE_OK; 1475 1476 handle = nxgep->npi_handle; 1477 portn = nxgep->mac.portnum; 1478 1479 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_enable: port<%d>", 1480 portn)); 1481 1482 if ((status = nxge_rx_mac_init(nxgep)) != NXGE_OK) 1483 goto fail; 1484 1485 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 1486 if ((rs = npi_xmac_rx_config(handle, ENABLE, portn, 1487 CFG_XMAC_RX)) != NPI_SUCCESS) 1488 goto fail; 1489 } else { 1490 if ((rs = npi_bmac_rx_config(handle, ENABLE, portn, 1491 CFG_BMAC_RX)) != NPI_SUCCESS) 1492 goto fail; 1493 } 1494 1495 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_enable: port<%d>", 1496 portn)); 1497 1498 return (NXGE_OK); 1499 fail: 1500 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1501 "nxgep_rx_mac_enable: Failed to enable port<%d> RxMAC", 1502 portn)); 1503 1504 if (rs != NPI_SUCCESS) 1505 return (NXGE_ERROR | rs); 1506 else 1507 return (status); 1508 } 1509 1510 /* Disable RXMAC */ 1511 1512 nxge_status_t 1513 nxge_rx_mac_disable(p_nxge_t nxgep) 1514 { 1515 npi_handle_t handle; 1516 uint8_t portn; 1517 npi_status_t rs = NPI_SUCCESS; 1518 1519 handle = nxgep->npi_handle; 1520 portn = nxgep->mac.portnum; 1521 1522 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_disable: port<%d>", 1523 portn)); 1524 1525 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 1526 if ((rs = npi_xmac_rx_config(handle, DISABLE, portn, 1527 CFG_XMAC_RX)) != NPI_SUCCESS) 1528 goto fail; 1529 } else { 1530 if ((rs = npi_bmac_rx_config(handle, DISABLE, portn, 1531 CFG_BMAC_RX)) != NPI_SUCCESS) 1532 goto fail; 1533 } 1534 1535 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_disable: port<%d>", 1536 portn)); 1537 return (NXGE_OK); 1538 fail: 1539 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1540 "nxgep_rx_mac_disable: ", 1541 "Failed to disable port<%d> RxMAC", 1542 portn)); 1543 1544 return (NXGE_ERROR | rs); 1545 } 1546 1547 /* Reset TXMAC */ 1548 1549 nxge_status_t 1550 nxge_tx_mac_reset(p_nxge_t nxgep) 1551 { 1552 npi_handle_t handle; 1553 uint8_t portn; 1554 npi_status_t rs = NPI_SUCCESS; 1555 1556 handle = nxgep->npi_handle; 1557 portn = nxgep->mac.portnum; 1558 1559 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_tx_mac_reset: port<%d>", 1560 portn)); 1561 1562 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 1563 if ((rs = npi_xmac_reset(handle, portn, XTX_MAC_RESET_ALL)) 1564 != NPI_SUCCESS) 1565 goto fail; 1566 } else { 1567 if ((rs = npi_bmac_reset(handle, portn, TX_MAC_RESET)) 1568 != NPI_SUCCESS) 1569 goto fail; 1570 } 1571 1572 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_tx_mac_reset: port<%d>", 1573 portn)); 1574 1575 return (NXGE_OK); 1576 fail: 1577 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1578 "nxge_tx_mac_reset: Failed to Reset TxMAC port<%d>", 1579 portn)); 1580 1581 return (NXGE_ERROR | rs); 1582 } 1583 1584 /* Reset RXMAC */ 1585 1586 nxge_status_t 1587 nxge_rx_mac_reset(p_nxge_t nxgep) 1588 { 1589 npi_handle_t handle; 1590 uint8_t portn; 1591 npi_status_t rs = NPI_SUCCESS; 1592 1593 handle = nxgep->npi_handle; 1594 portn = nxgep->mac.portnum; 1595 1596 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_rx_mac_reset: port<%d>", 1597 portn)); 1598 1599 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 1600 if ((rs = npi_xmac_reset(handle, portn, XRX_MAC_RESET_ALL)) 1601 != NPI_SUCCESS) 1602 goto fail; 1603 } else { 1604 if ((rs = npi_bmac_reset(handle, portn, RX_MAC_RESET)) 1605 != NPI_SUCCESS) 1606 goto fail; 1607 } 1608 1609 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_rx_mac_reset: port<%d>", 1610 portn)); 1611 1612 return (NXGE_OK); 1613 fail: 1614 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1615 "nxge_rx_mac_reset: Failed to Reset RxMAC port<%d>", 1616 portn)); 1617 return (NXGE_ERROR | rs); 1618 } 1619 1620 1621 /* Enable/Disable MII Link Status change interrupt */ 1622 1623 nxge_status_t 1624 nxge_link_intr(p_nxge_t nxgep, link_intr_enable_t enable) 1625 { 1626 uint8_t portn; 1627 nxge_port_mode_t portmode; 1628 npi_status_t rs = NPI_SUCCESS; 1629 1630 portn = nxgep->mac.portnum; 1631 portmode = nxgep->mac.portmode; 1632 1633 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_intr: port<%d>", portn)); 1634 1635 if (enable == LINK_INTR_START) { 1636 if (portmode == PORT_10G_FIBER) { 1637 if ((rs = npi_xmac_xpcs_link_intr_enable( 1638 nxgep->npi_handle, 1639 portn)) != NPI_SUCCESS) 1640 goto fail; 1641 } else if (portmode == PORT_1G_FIBER) { 1642 if ((rs = npi_mac_pcs_link_intr_enable( 1643 nxgep->npi_handle, 1644 portn)) != NPI_SUCCESS) 1645 goto fail; 1646 } else if (portmode == PORT_1G_COPPER) { 1647 if ((rs = npi_mac_mif_link_intr_enable( 1648 nxgep->npi_handle, 1649 portn, MII_BMSR, BMSR_LSTATUS)) != NPI_SUCCESS) 1650 goto fail; 1651 } else 1652 goto fail; 1653 } else if (enable == LINK_INTR_STOP) { 1654 if (portmode == PORT_10G_FIBER) { 1655 if ((rs = npi_xmac_xpcs_link_intr_disable( 1656 nxgep->npi_handle, 1657 portn)) != NPI_SUCCESS) 1658 goto fail; 1659 } else if (portmode == PORT_1G_FIBER) { 1660 if ((rs = npi_mac_pcs_link_intr_disable( 1661 nxgep->npi_handle, 1662 portn)) != NPI_SUCCESS) 1663 goto fail; 1664 } else if (portmode == PORT_1G_COPPER) { 1665 if ((rs = npi_mac_mif_link_intr_disable( 1666 nxgep->npi_handle, 1667 portn)) != NPI_SUCCESS) 1668 goto fail; 1669 } else 1670 goto fail; 1671 } 1672 1673 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_intr: port<%d>", portn)); 1674 1675 return (NXGE_OK); 1676 fail: 1677 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 1678 "nxge_link_intr: Failed to set port<%d> mif intr mode", 1679 portn)); 1680 1681 return (NXGE_ERROR | rs); 1682 } 1683 1684 /* Initialize 1G Fiber / Copper transceiver using Clause 22 */ 1685 1686 nxge_status_t 1687 nxge_mii_xcvr_init(p_nxge_t nxgep) 1688 { 1689 p_nxge_param_t param_arr; 1690 p_nxge_stats_t statsp; 1691 uint8_t xcvr_portn; 1692 p_mii_regs_t mii_regs; 1693 mii_bmcr_t bmcr; 1694 mii_bmsr_t bmsr; 1695 mii_anar_t anar; 1696 mii_gcr_t gcr; 1697 mii_esr_t esr; 1698 mii_aux_ctl_t bcm5464r_aux; 1699 int status = NXGE_OK; 1700 1701 uint_t delay; 1702 1703 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_xcvr_init")); 1704 1705 param_arr = nxgep->param_arr; 1706 statsp = nxgep->statsp; 1707 xcvr_portn = statsp->mac_stats.xcvr_portn; 1708 1709 mii_regs = NULL; 1710 1711 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1712 "nxge_param_autoneg = 0x%02x", param_arr[param_autoneg].value)); 1713 1714 /* 1715 * Reset the transceiver. 1716 */ 1717 delay = 0; 1718 bmcr.value = 0; 1719 bmcr.bits.reset = 1; 1720 if ((status = nxge_mii_write(nxgep, xcvr_portn, 1721 (uint8_t)(uint64_t)&mii_regs->bmcr, bmcr.value)) != NXGE_OK) 1722 goto fail; 1723 do { 1724 drv_usecwait(500); 1725 if ((status = nxge_mii_read(nxgep, xcvr_portn, 1726 (uint8_t)(uint64_t)&mii_regs->bmcr, &bmcr.value)) 1727 != NXGE_OK) 1728 goto fail; 1729 delay++; 1730 } while ((bmcr.bits.reset) && (delay < 1000)); 1731 if (delay == 1000) { 1732 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Xcvr reset failed.")); 1733 goto fail; 1734 } 1735 1736 if ((status = nxge_mii_read(nxgep, xcvr_portn, 1737 (uint8_t)(uint64_t)(&mii_regs->bmsr), 1738 &bmsr.value)) != NXGE_OK) 1739 goto fail; 1740 1741 param_arr[param_autoneg].value &= bmsr.bits.auto_neg_able; 1742 param_arr[param_anar_100T4].value &= bmsr.bits.link_100T4; 1743 param_arr[param_anar_100fdx].value &= bmsr.bits.link_100fdx; 1744 param_arr[param_anar_100hdx].value = 0; 1745 param_arr[param_anar_10fdx].value &= bmsr.bits.link_10fdx; 1746 param_arr[param_anar_10hdx].value = 0; 1747 1748 /* 1749 * Initialize the xcvr statistics. 1750 */ 1751 statsp->mac_stats.cap_autoneg = bmsr.bits.auto_neg_able; 1752 statsp->mac_stats.cap_100T4 = bmsr.bits.link_100T4; 1753 statsp->mac_stats.cap_100fdx = bmsr.bits.link_100fdx; 1754 statsp->mac_stats.cap_100hdx = 0; 1755 statsp->mac_stats.cap_10fdx = bmsr.bits.link_10fdx; 1756 statsp->mac_stats.cap_10hdx = 0; 1757 statsp->mac_stats.cap_asmpause = param_arr[param_anar_asmpause].value; 1758 statsp->mac_stats.cap_pause = param_arr[param_anar_pause].value; 1759 1760 /* 1761 * Initialise the xcvr advertised capability statistics. 1762 */ 1763 statsp->mac_stats.adv_cap_autoneg = param_arr[param_autoneg].value; 1764 statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 1765 statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 1766 statsp->mac_stats.adv_cap_100T4 = param_arr[param_anar_100T4].value; 1767 statsp->mac_stats.adv_cap_100fdx = param_arr[param_anar_100fdx].value; 1768 statsp->mac_stats.adv_cap_100hdx = param_arr[param_anar_100hdx].value; 1769 statsp->mac_stats.adv_cap_10fdx = param_arr[param_anar_10fdx].value; 1770 statsp->mac_stats.adv_cap_10hdx = param_arr[param_anar_10hdx].value; 1771 statsp->mac_stats.adv_cap_asmpause = 1772 param_arr[param_anar_asmpause].value; 1773 statsp->mac_stats.adv_cap_pause = param_arr[param_anar_pause].value; 1774 1775 1776 /* 1777 * Check for extended status just in case we're 1778 * running a Gigibit phy. 1779 */ 1780 if (bmsr.bits.extend_status) { 1781 if ((status = nxge_mii_read(nxgep, xcvr_portn, 1782 (uint8_t)(uint64_t)(&mii_regs->esr), &esr.value)) 1783 != NXGE_OK) 1784 goto fail; 1785 param_arr[param_anar_1000fdx].value &= 1786 esr.bits.link_1000fdx; 1787 param_arr[param_anar_1000hdx].value = 0; 1788 1789 statsp->mac_stats.cap_1000fdx = 1790 (esr.bits.link_1000Xfdx || 1791 esr.bits.link_1000fdx); 1792 statsp->mac_stats.cap_1000hdx = 0; 1793 } else { 1794 param_arr[param_anar_1000fdx].value = 0; 1795 param_arr[param_anar_1000hdx].value = 0; 1796 } 1797 1798 /* 1799 * Initialize 1G Statistics once the capability is established. 1800 */ 1801 statsp->mac_stats.adv_cap_1000fdx = param_arr[param_anar_1000fdx].value; 1802 statsp->mac_stats.adv_cap_1000hdx = param_arr[param_anar_1000hdx].value; 1803 1804 /* 1805 * Initialise the link statistics. 1806 */ 1807 statsp->mac_stats.link_T4 = 0; 1808 statsp->mac_stats.link_asmpause = 0; 1809 statsp->mac_stats.link_pause = 0; 1810 statsp->mac_stats.link_speed = 0; 1811 statsp->mac_stats.link_duplex = 0; 1812 statsp->mac_stats.link_up = 0; 1813 1814 /* 1815 * Switch off Auto-negotiation, 100M and full duplex. 1816 */ 1817 bmcr.value = 0; 1818 if ((status = nxge_mii_write(nxgep, xcvr_portn, 1819 (uint8_t)(uint64_t)(&mii_regs->bmcr), bmcr.value)) != NXGE_OK) 1820 goto fail; 1821 1822 if ((statsp->port_stats.lb_mode == nxge_lb_phy) || 1823 (statsp->port_stats.lb_mode == nxge_lb_phy1000)) { 1824 bmcr.bits.loopback = 1; 1825 bmcr.bits.enable_autoneg = 0; 1826 if (statsp->port_stats.lb_mode == nxge_lb_phy1000) 1827 bmcr.bits.speed_1000_sel = 1; 1828 bmcr.bits.duplex_mode = 1; 1829 param_arr[param_autoneg].value = 0; 1830 } else { 1831 bmcr.bits.loopback = 0; 1832 } 1833 1834 if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) || 1835 (statsp->port_stats.lb_mode == nxge_lb_ext100) || 1836 (statsp->port_stats.lb_mode == nxge_lb_ext10)) { 1837 param_arr[param_autoneg].value = 0; 1838 bcm5464r_aux.value = 0; 1839 bcm5464r_aux.bits.ext_lb = 1; 1840 bcm5464r_aux.bits.write_1 = 1; 1841 if ((status = nxge_mii_write(nxgep, xcvr_portn, 1842 BCM5464R_AUX_CTL, bcm5464r_aux.value)) 1843 != NXGE_OK) 1844 goto fail; 1845 } 1846 1847 if (param_arr[param_autoneg].value) { 1848 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1849 "Restarting Auto-negotiation.")); 1850 /* 1851 * Setup our Auto-negotiation advertisement register. 1852 */ 1853 anar.value = 0; 1854 anar.bits.selector = 1; 1855 anar.bits.cap_100T4 = param_arr[param_anar_100T4].value; 1856 anar.bits.cap_100fdx = param_arr[param_anar_100fdx].value; 1857 anar.bits.cap_100hdx = param_arr[param_anar_100hdx].value; 1858 anar.bits.cap_10fdx = param_arr[param_anar_10fdx].value; 1859 anar.bits.cap_10hdx = param_arr[param_anar_10hdx].value; 1860 anar.bits.cap_asmpause = 0; 1861 anar.bits.cap_pause = 0; 1862 if (param_arr[param_anar_1000fdx].value || 1863 param_arr[param_anar_100fdx].value || 1864 param_arr[param_anar_10fdx].value) { 1865 anar.bits.cap_asmpause = statsp->mac_stats.cap_asmpause; 1866 anar.bits.cap_pause = statsp->mac_stats.cap_pause; 1867 } 1868 1869 if ((status = nxge_mii_write(nxgep, xcvr_portn, 1870 (uint8_t)(uint64_t)(&mii_regs->anar), anar.value)) 1871 != NXGE_OK) 1872 goto fail; 1873 if (bmsr.bits.extend_status) { 1874 gcr.value = 0; 1875 gcr.bits.ms_mode_en = 1876 param_arr[param_master_cfg_enable].value; 1877 gcr.bits.master = 1878 param_arr[param_master_cfg_value].value; 1879 gcr.bits.link_1000fdx = 1880 param_arr[param_anar_1000fdx].value; 1881 gcr.bits.link_1000hdx = 1882 param_arr[param_anar_1000hdx].value; 1883 if ((status = nxge_mii_write(nxgep, xcvr_portn, 1884 (uint8_t)(uint64_t)(&mii_regs->gcr), gcr.value)) 1885 != NXGE_OK) 1886 goto fail; 1887 } 1888 1889 bmcr.bits.enable_autoneg = 1; 1890 bmcr.bits.restart_autoneg = 1; 1891 1892 } else { 1893 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "Going into forced mode.")); 1894 bmcr.bits.speed_1000_sel = 1895 param_arr[param_anar_1000fdx].value | 1896 param_arr[param_anar_1000hdx].value; 1897 bmcr.bits.speed_sel = (~bmcr.bits.speed_1000_sel) & 1898 (param_arr[param_anar_100fdx].value | 1899 param_arr[param_anar_100hdx].value); 1900 if (bmcr.bits.speed_1000_sel) { 1901 statsp->mac_stats.link_speed = 1000; 1902 gcr.value = 0; 1903 gcr.bits.ms_mode_en = 1904 param_arr[param_master_cfg_enable].value; 1905 gcr.bits.master = 1906 param_arr[param_master_cfg_value].value; 1907 if ((status = nxge_mii_write(nxgep, xcvr_portn, 1908 (uint8_t)(uint64_t)(&mii_regs->gcr), 1909 gcr.value)) 1910 != NXGE_OK) 1911 goto fail; 1912 if (param_arr[param_anar_1000fdx].value) { 1913 bmcr.bits.duplex_mode = 1; 1914 statsp->mac_stats.link_duplex = 2; 1915 } else 1916 statsp->mac_stats.link_duplex = 1; 1917 } else if (bmcr.bits.speed_sel) { 1918 statsp->mac_stats.link_speed = 100; 1919 if (param_arr[param_anar_100fdx].value) { 1920 bmcr.bits.duplex_mode = 1; 1921 statsp->mac_stats.link_duplex = 2; 1922 } else 1923 statsp->mac_stats.link_duplex = 1; 1924 } else { 1925 statsp->mac_stats.link_speed = 10; 1926 if (param_arr[param_anar_10fdx].value) { 1927 bmcr.bits.duplex_mode = 1; 1928 statsp->mac_stats.link_duplex = 2; 1929 } else 1930 statsp->mac_stats.link_duplex = 1; 1931 } 1932 if (statsp->mac_stats.link_duplex != 1) { 1933 statsp->mac_stats.link_asmpause = 1934 statsp->mac_stats.cap_asmpause; 1935 statsp->mac_stats.link_pause = 1936 statsp->mac_stats.cap_pause; 1937 } 1938 1939 if ((statsp->port_stats.lb_mode == nxge_lb_ext1000) || 1940 (statsp->port_stats.lb_mode == nxge_lb_ext100) || 1941 (statsp->port_stats.lb_mode == nxge_lb_ext10)) { 1942 if (statsp->port_stats.lb_mode == nxge_lb_ext1000) { 1943 /* BCM5464R 1000mbps external loopback mode */ 1944 gcr.value = 0; 1945 gcr.bits.ms_mode_en = 1; 1946 gcr.bits.master = 1; 1947 if ((status = nxge_mii_write(nxgep, xcvr_portn, 1948 (uint8_t)(uint64_t)(&mii_regs->gcr), 1949 gcr.value)) 1950 != NXGE_OK) 1951 goto fail; 1952 bmcr.value = 0; 1953 bmcr.bits.speed_1000_sel = 1; 1954 statsp->mac_stats.link_speed = 1000; 1955 } else if (statsp->port_stats.lb_mode 1956 == nxge_lb_ext100) { 1957 /* BCM5464R 100mbps external loopback mode */ 1958 bmcr.value = 0; 1959 bmcr.bits.speed_sel = 1; 1960 bmcr.bits.duplex_mode = 1; 1961 statsp->mac_stats.link_speed = 100; 1962 } else if (statsp->port_stats.lb_mode 1963 == nxge_lb_ext10) { 1964 /* BCM5464R 10mbps external loopback mode */ 1965 bmcr.value = 0; 1966 bmcr.bits.duplex_mode = 1; 1967 statsp->mac_stats.link_speed = 10; 1968 } 1969 } 1970 } 1971 1972 if ((status = nxge_mii_write(nxgep, xcvr_portn, 1973 (uint8_t)(uint64_t)(&mii_regs->bmcr), 1974 bmcr.value)) != NXGE_OK) 1975 goto fail; 1976 1977 if ((status = nxge_mii_read(nxgep, xcvr_portn, 1978 (uint8_t)(uint64_t)(&mii_regs->bmcr), &bmcr.value)) != NXGE_OK) 1979 goto fail; 1980 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "bmcr = 0x%04X", bmcr.value)); 1981 1982 /* 1983 * Initialize the xcvr status kept in the context structure. 1984 */ 1985 nxgep->soft_bmsr.value = 0; 1986 1987 if ((status = nxge_mii_read(nxgep, xcvr_portn, 1988 (uint8_t)(uint64_t)(&mii_regs->bmsr), 1989 &nxgep->bmsr.value)) != NXGE_OK) 1990 goto fail; 1991 1992 statsp->mac_stats.xcvr_inits++; 1993 nxgep->bmsr.value = 0; 1994 1995 fail: 1996 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 1997 "<== nxge_mii_xcvr_init status 0x%x", status)); 1998 return (status); 1999 } 2000 2001 /* Read from a MII compliant register */ 2002 2003 nxge_status_t 2004 nxge_mii_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg, 2005 uint16_t *value) 2006 { 2007 npi_status_t rs = NPI_SUCCESS; 2008 2009 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_read: xcvr_port<%d>" 2010 "xcvr_reg<%d>", xcvr_portn, xcvr_reg)); 2011 2012 MUTEX_ENTER(&nxge_mii_lock); 2013 2014 if (nxgep->mac.portmode == PORT_1G_COPPER) { 2015 if ((rs = npi_mac_mif_mii_read(nxgep->npi_handle, 2016 xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 2017 goto fail; 2018 } else if (nxgep->mac.portmode == PORT_1G_FIBER) { 2019 if ((rs = npi_mac_pcs_mii_read(nxgep->npi_handle, 2020 xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 2021 goto fail; 2022 } else 2023 goto fail; 2024 2025 MUTEX_EXIT(&nxge_mii_lock); 2026 2027 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_read: xcvr_port<%d>" 2028 "xcvr_reg<%d> value=0x%x", 2029 xcvr_portn, xcvr_reg, *value)); 2030 return (NXGE_OK); 2031 fail: 2032 MUTEX_EXIT(&nxge_mii_lock); 2033 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2034 "nxge_mii_read: Failed to read mii on xcvr %d", 2035 xcvr_portn)); 2036 2037 return (NXGE_ERROR | rs); 2038 } 2039 2040 /* Write to a MII compliant Register */ 2041 2042 nxge_status_t 2043 nxge_mii_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t xcvr_reg, 2044 uint16_t value) 2045 { 2046 npi_status_t rs = NPI_SUCCESS; 2047 2048 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mii_write: xcvr_port<%d>" 2049 "xcvr_reg<%d> value=0x%x", xcvr_portn, xcvr_reg, 2050 value)); 2051 2052 MUTEX_ENTER(&nxge_mii_lock); 2053 2054 if (nxgep->mac.portmode == PORT_1G_COPPER) { 2055 if ((rs = npi_mac_mif_mii_write(nxgep->npi_handle, 2056 xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 2057 goto fail; 2058 } else if (nxgep->mac.portmode == PORT_1G_FIBER) { 2059 if ((rs = npi_mac_pcs_mii_write(nxgep->npi_handle, 2060 xcvr_portn, xcvr_reg, value)) != NPI_SUCCESS) 2061 goto fail; 2062 } else 2063 goto fail; 2064 2065 MUTEX_EXIT(&nxge_mii_lock); 2066 2067 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mii_write: xcvr_port<%d>" 2068 "xcvr_reg<%d>", xcvr_portn, xcvr_reg)); 2069 return (NXGE_OK); 2070 fail: 2071 MUTEX_EXIT(&nxge_mii_lock); 2072 2073 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2074 "nxge_mii_write: Failed to write mii on xcvr %d", 2075 xcvr_portn)); 2076 2077 return (NXGE_ERROR | rs); 2078 } 2079 2080 /* Perform read from Clause45 serdes / transceiver device */ 2081 2082 nxge_status_t 2083 nxge_mdio_read(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device, 2084 uint16_t xcvr_reg, uint16_t *value) 2085 { 2086 npi_status_t rs = NPI_SUCCESS; 2087 2088 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_read: xcvr_port<%d>", 2089 xcvr_portn)); 2090 2091 MUTEX_ENTER(&nxge_mdio_lock); 2092 2093 if ((rs = npi_mac_mif_mdio_read(nxgep->npi_handle, 2094 xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS) 2095 goto fail; 2096 2097 MUTEX_EXIT(&nxge_mdio_lock); 2098 2099 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_read: xcvr_port<%d>", 2100 xcvr_portn)); 2101 return (NXGE_OK); 2102 fail: 2103 MUTEX_EXIT(&nxge_mdio_lock); 2104 2105 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2106 "nxge_mdio_read: Failed to read mdio on xcvr %d", 2107 xcvr_portn)); 2108 2109 return (NXGE_ERROR | rs); 2110 } 2111 2112 /* Perform write to Clause45 serdes / transceiver device */ 2113 2114 nxge_status_t 2115 nxge_mdio_write(p_nxge_t nxgep, uint8_t xcvr_portn, uint8_t device, 2116 uint16_t xcvr_reg, uint16_t value) 2117 { 2118 npi_status_t rs = NPI_SUCCESS; 2119 2120 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "==> nxge_mdio_write: xcvr_port<%d>", 2121 xcvr_portn)); 2122 2123 MUTEX_ENTER(&nxge_mdio_lock); 2124 2125 if ((rs = npi_mac_mif_mdio_write(nxgep->npi_handle, 2126 xcvr_portn, device, xcvr_reg, value)) != NPI_SUCCESS) 2127 goto fail; 2128 2129 MUTEX_EXIT(&nxge_mdio_lock); 2130 2131 NXGE_DEBUG_MSG((nxgep, MIF_CTL, "<== nxge_mdio_write: xcvr_port<%d>", 2132 xcvr_portn)); 2133 return (NXGE_OK); 2134 fail: 2135 MUTEX_EXIT(&nxge_mdio_lock); 2136 2137 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2138 "nxge_mdio_write: Failed to write mdio on xcvr %d", 2139 xcvr_portn)); 2140 2141 return (NXGE_ERROR | rs); 2142 } 2143 2144 2145 /* Check MII to see if there is any link status change */ 2146 2147 nxge_status_t 2148 nxge_mii_check(p_nxge_t nxgep, mii_bmsr_t bmsr, mii_bmsr_t bmsr_ints, 2149 nxge_link_state_t *link_up) 2150 { 2151 p_nxge_param_t param_arr; 2152 p_nxge_stats_t statsp; 2153 p_mii_regs_t mii_regs; 2154 p_mii_bmsr_t soft_bmsr; 2155 mii_anar_t anar; 2156 mii_anlpar_t anlpar; 2157 mii_anar_t an_common; 2158 mii_aner_t aner; 2159 mii_gsr_t gsr; 2160 nxge_status_t status = NXGE_OK; 2161 2162 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_mii_check")); 2163 2164 mii_regs = NULL; 2165 param_arr = nxgep->param_arr; 2166 statsp = nxgep->statsp; 2167 soft_bmsr = &nxgep->soft_bmsr; 2168 *link_up = LINK_NO_CHANGE; 2169 2170 if (bmsr_ints.bits.link_status) { 2171 if (bmsr.bits.link_status) { 2172 soft_bmsr->bits.link_status = 1; 2173 } else { 2174 statsp->mac_stats.link_up = 0; 2175 soft_bmsr->bits.link_status = 0; 2176 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2177 "Link down cable problem")); 2178 *link_up = LINK_IS_DOWN; 2179 } 2180 } 2181 2182 if (param_arr[param_autoneg].value) { 2183 if (bmsr_ints.bits.auto_neg_complete) { 2184 if (bmsr.bits.auto_neg_complete) 2185 soft_bmsr->bits.auto_neg_complete = 1; 2186 else 2187 soft_bmsr->bits.auto_neg_complete = 0; 2188 } 2189 if (soft_bmsr->bits.link_status == 0) { 2190 statsp->mac_stats.link_T4 = 0; 2191 statsp->mac_stats.link_speed = 0; 2192 statsp->mac_stats.link_duplex = 0; 2193 statsp->mac_stats.link_asmpause = 0; 2194 statsp->mac_stats.link_pause = 0; 2195 statsp->mac_stats.lp_cap_autoneg = 0; 2196 statsp->mac_stats.lp_cap_100T4 = 0; 2197 statsp->mac_stats.lp_cap_1000fdx = 0; 2198 statsp->mac_stats.lp_cap_1000hdx = 0; 2199 statsp->mac_stats.lp_cap_100fdx = 0; 2200 statsp->mac_stats.lp_cap_100hdx = 0; 2201 statsp->mac_stats.lp_cap_10fdx = 0; 2202 statsp->mac_stats.lp_cap_10hdx = 0; 2203 statsp->mac_stats.lp_cap_10gfdx = 0; 2204 statsp->mac_stats.lp_cap_10ghdx = 0; 2205 statsp->mac_stats.lp_cap_asmpause = 0; 2206 statsp->mac_stats.lp_cap_pause = 0; 2207 } 2208 } else 2209 soft_bmsr->bits.auto_neg_complete = 1; 2210 2211 if ((bmsr_ints.bits.link_status || 2212 bmsr_ints.bits.auto_neg_complete) && 2213 soft_bmsr->bits.link_status && 2214 soft_bmsr->bits.auto_neg_complete) { 2215 statsp->mac_stats.link_up = 1; 2216 if (param_arr[param_autoneg].value) { 2217 if ((status = nxge_mii_read(nxgep, 2218 statsp->mac_stats.xcvr_portn, 2219 (uint8_t)(uint64_t)(&mii_regs->anar), 2220 &anar.value)) != NXGE_OK) 2221 goto fail; 2222 if ((status = nxge_mii_read(nxgep, 2223 statsp->mac_stats.xcvr_portn, 2224 (uint8_t)(uint64_t)(&mii_regs->anlpar), 2225 &anlpar.value)) != NXGE_OK) 2226 goto fail; 2227 if ((status = nxge_mii_read(nxgep, 2228 statsp->mac_stats.xcvr_portn, 2229 (uint8_t)(uint64_t)(&mii_regs->aner), 2230 &aner.value)) != NXGE_OK) 2231 goto fail; 2232 statsp->mac_stats.lp_cap_autoneg = aner.bits.lp_an_able; 2233 statsp->mac_stats.lp_cap_100T4 = anlpar.bits.cap_100T4; 2234 statsp->mac_stats.lp_cap_100fdx = 2235 anlpar.bits.cap_100fdx; 2236 statsp->mac_stats.lp_cap_100hdx = 2237 anlpar.bits.cap_100hdx; 2238 statsp->mac_stats.lp_cap_10fdx = anlpar.bits.cap_10fdx; 2239 statsp->mac_stats.lp_cap_10hdx = anlpar.bits.cap_10hdx; 2240 statsp->mac_stats.lp_cap_asmpause = 2241 anlpar.bits.cap_asmpause; 2242 statsp->mac_stats.lp_cap_pause = anlpar.bits.cap_pause; 2243 an_common.value = anar.value & anlpar.value; 2244 if (param_arr[param_anar_1000fdx].value || 2245 param_arr[param_anar_1000hdx].value) { 2246 if ((status = nxge_mii_read(nxgep, 2247 statsp->mac_stats.xcvr_portn, 2248 (uint8_t)(uint64_t)(&mii_regs->gsr), 2249 &gsr.value)) 2250 != NXGE_OK) 2251 goto fail; 2252 statsp->mac_stats.lp_cap_1000fdx = 2253 gsr.bits.link_1000fdx; 2254 statsp->mac_stats.lp_cap_1000hdx = 2255 gsr.bits.link_1000hdx; 2256 if (param_arr[param_anar_1000fdx].value && 2257 gsr.bits.link_1000fdx) { 2258 statsp->mac_stats.link_speed = 1000; 2259 statsp->mac_stats.link_duplex = 2; 2260 } else if ( 2261 param_arr[param_anar_1000hdx].value && 2262 gsr.bits.link_1000hdx) { 2263 statsp->mac_stats.link_speed = 1000; 2264 statsp->mac_stats.link_duplex = 1; 2265 } 2266 } 2267 if ((an_common.value != 0) && 2268 !(statsp->mac_stats.link_speed)) { 2269 if (an_common.bits.cap_100T4) { 2270 statsp->mac_stats.link_T4 = 1; 2271 statsp->mac_stats.link_speed = 100; 2272 statsp->mac_stats.link_duplex = 1; 2273 } else if (an_common.bits.cap_100fdx) { 2274 statsp->mac_stats.link_speed = 100; 2275 statsp->mac_stats.link_duplex = 2; 2276 } else if (an_common.bits.cap_100hdx) { 2277 statsp->mac_stats.link_speed = 100; 2278 statsp->mac_stats.link_duplex = 1; 2279 } else if (an_common.bits.cap_10fdx) { 2280 statsp->mac_stats.link_speed = 10; 2281 statsp->mac_stats.link_duplex = 2; 2282 } else if (an_common.bits.cap_10hdx) { 2283 statsp->mac_stats.link_speed = 10; 2284 statsp->mac_stats.link_duplex = 1; 2285 } else { 2286 goto fail; 2287 } 2288 } 2289 if (statsp->mac_stats.link_duplex != 1) { 2290 statsp->mac_stats.link_asmpause = 2291 an_common.bits.cap_asmpause; 2292 if (statsp->mac_stats.link_asmpause) 2293 if ((statsp->mac_stats.cap_pause == 0) && 2294 (statsp->mac_stats.lp_cap_pause 2295 == 1)) 2296 statsp->mac_stats.link_pause 2297 = 0; 2298 else 2299 statsp->mac_stats.link_pause 2300 = 1; 2301 else 2302 statsp->mac_stats.link_pause = 2303 an_common.bits.cap_pause; 2304 } 2305 } 2306 *link_up = LINK_IS_UP; 2307 } 2308 2309 if (nxgep->link_notify) { 2310 *link_up = ((statsp->mac_stats.link_up) ? LINK_IS_UP : 2311 LINK_IS_DOWN); 2312 nxgep->link_notify = B_FALSE; 2313 } 2314 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_mii_check")); 2315 return (NXGE_OK); 2316 fail: 2317 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2318 "nxge_mii_check: Unable to check MII")); 2319 return (status); 2320 } 2321 2322 /* Add a multicast address entry into the HW hash table */ 2323 2324 nxge_status_t 2325 nxge_add_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp) 2326 { 2327 uint32_t mchash; 2328 p_hash_filter_t hash_filter; 2329 uint16_t hash_bit; 2330 boolean_t rx_init = B_FALSE; 2331 uint_t j; 2332 nxge_status_t status = NXGE_OK; 2333 2334 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_add_mcast_addr")); 2335 2336 RW_ENTER_WRITER(&nxgep->filter_lock); 2337 mchash = crc32_mchash(addrp); 2338 if (nxgep->hash_filter == NULL) { 2339 NXGE_DEBUG_MSG((NULL, STR_CTL, 2340 "Allocating hash filter storage.")); 2341 nxgep->hash_filter = KMEM_ZALLOC(sizeof (hash_filter_t), 2342 KM_SLEEP); 2343 } 2344 hash_filter = nxgep->hash_filter; 2345 j = mchash / HASH_REG_WIDTH; 2346 hash_bit = (1 << (mchash % HASH_REG_WIDTH)); 2347 hash_filter->hash_filter_regs[j] |= hash_bit; 2348 hash_filter->hash_bit_ref_cnt[mchash]++; 2349 if (hash_filter->hash_bit_ref_cnt[mchash] == 1) { 2350 hash_filter->hash_ref_cnt++; 2351 rx_init = B_TRUE; 2352 } 2353 if (rx_init) { 2354 if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 2355 goto fail; 2356 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 2357 goto fail; 2358 } 2359 2360 RW_EXIT(&nxgep->filter_lock); 2361 2362 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_add_mcast_addr")); 2363 2364 return (NXGE_OK); 2365 fail: 2366 RW_EXIT(&nxgep->filter_lock); 2367 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_add_mcast_addr: " 2368 "Unable to add multicast address")); 2369 return (status); 2370 } 2371 2372 /* Remove a multicast address entry from the HW hash table */ 2373 2374 nxge_status_t 2375 nxge_del_mcast_addr(p_nxge_t nxgep, struct ether_addr *addrp) 2376 { 2377 uint32_t mchash; 2378 p_hash_filter_t hash_filter; 2379 uint16_t hash_bit; 2380 boolean_t rx_init = B_FALSE; 2381 uint_t j; 2382 nxge_status_t status = NXGE_OK; 2383 2384 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_del_mcast_addr")); 2385 RW_ENTER_WRITER(&nxgep->filter_lock); 2386 mchash = crc32_mchash(addrp); 2387 if (nxgep->hash_filter == NULL) { 2388 NXGE_DEBUG_MSG((NULL, STR_CTL, 2389 "Hash filter already de_allocated.")); 2390 RW_EXIT(&nxgep->filter_lock); 2391 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr")); 2392 return (NXGE_OK); 2393 } 2394 hash_filter = nxgep->hash_filter; 2395 hash_filter->hash_bit_ref_cnt[mchash]--; 2396 if (hash_filter->hash_bit_ref_cnt[mchash] == 0) { 2397 j = mchash / HASH_REG_WIDTH; 2398 hash_bit = (1 << (mchash % HASH_REG_WIDTH)); 2399 hash_filter->hash_filter_regs[j] &= ~hash_bit; 2400 hash_filter->hash_ref_cnt--; 2401 rx_init = B_TRUE; 2402 } 2403 if (hash_filter->hash_ref_cnt == 0) { 2404 NXGE_DEBUG_MSG((NULL, STR_CTL, 2405 "De-allocating hash filter storage.")); 2406 KMEM_FREE(hash_filter, sizeof (hash_filter_t)); 2407 nxgep->hash_filter = NULL; 2408 } 2409 2410 if (rx_init) { 2411 if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 2412 goto fail; 2413 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 2414 goto fail; 2415 } 2416 RW_EXIT(&nxgep->filter_lock); 2417 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_del_mcast_addr")); 2418 2419 return (NXGE_OK); 2420 fail: 2421 RW_EXIT(&nxgep->filter_lock); 2422 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_del_mcast_addr: " 2423 "Unable to remove multicast address")); 2424 2425 return (status); 2426 } 2427 2428 /* Set MAC address into MAC address HW registers */ 2429 2430 nxge_status_t 2431 nxge_set_mac_addr(p_nxge_t nxgep, struct ether_addr *addrp) 2432 { 2433 nxge_status_t status = NXGE_OK; 2434 2435 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_set_mac_addr")); 2436 2437 MUTEX_ENTER(&nxgep->ouraddr_lock); 2438 /* 2439 * Exit if the address is same as ouraddr or multicast or broadcast 2440 */ 2441 if (((addrp->ether_addr_octet[0] & 01) == 1) || 2442 (ether_cmp(addrp, ðerbroadcastaddr) == 0) || 2443 (ether_cmp(addrp, &nxgep->ouraddr) == 0)) { 2444 goto nxge_set_mac_addr_exit; 2445 } 2446 nxgep->ouraddr = *addrp; 2447 /* 2448 * Set new interface local address and re-init device. 2449 * This is destructive to any other streams attached 2450 * to this device. 2451 */ 2452 RW_ENTER_WRITER(&nxgep->filter_lock); 2453 if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) 2454 goto fail; 2455 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) 2456 goto fail; 2457 2458 RW_EXIT(&nxgep->filter_lock); 2459 MUTEX_EXIT(&nxgep->ouraddr_lock); 2460 goto nxge_set_mac_addr_end; 2461 nxge_set_mac_addr_exit: 2462 MUTEX_EXIT(&nxgep->ouraddr_lock); 2463 nxge_set_mac_addr_end: 2464 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_mac_addr")); 2465 2466 return (NXGE_OK); 2467 fail: 2468 MUTEX_EXIT(&nxgep->ouraddr_lock); 2469 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_mac_addr: " 2470 "Unable to set mac address")); 2471 return (status); 2472 } 2473 2474 static 2475 check_link_state_t 2476 nxge_check_link_stop( 2477 nxge_t *nxge) 2478 { 2479 /* If the poll has been cancelled, return STOP. */ 2480 MUTEX_ENTER(&nxge->poll_lock); 2481 if (nxge->suspended || nxge->poll_state == LINK_MONITOR_STOPPING) { 2482 nxge->poll_state = LINK_MONITOR_STOP; 2483 nxge->nxge_link_poll_timerid = 0; 2484 cv_broadcast(&nxge->poll_cv); 2485 MUTEX_EXIT(&nxge->poll_lock); 2486 2487 NXGE_DEBUG_MSG((nxge, MAC_CTL, 2488 "nxge_check_%s_link(port<%d>) stopped.", 2489 nxge->mac.portmode == PORT_10G_FIBER ? "10g" : "mii", 2490 nxge->mac.portnum)); 2491 return (CHECK_LINK_STOP); 2492 } 2493 MUTEX_EXIT(&nxge->poll_lock); 2494 2495 return (CHECK_LINK_RESCHEDULE); 2496 } 2497 2498 /* Check status of MII (MIF or PCS) link */ 2499 2500 nxge_status_t 2501 nxge_check_mii_link(p_nxge_t nxgep) 2502 { 2503 mii_bmsr_t bmsr_ints, bmsr_data; 2504 mii_anlpar_t anlpar; 2505 mii_gsr_t gsr; 2506 p_mii_regs_t mii_regs; 2507 nxge_status_t status = NXGE_OK; 2508 uint8_t portn; 2509 nxge_link_state_t link_up; 2510 2511 if (nxgep->nxge_magic != NXGE_MAGIC) 2512 return (NXGE_ERROR); 2513 2514 if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 2515 return (NXGE_OK); 2516 2517 portn = nxgep->mac.portnum; 2518 2519 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_mii_link port<%d>", 2520 portn)); 2521 2522 mii_regs = NULL; 2523 2524 RW_ENTER_WRITER(&nxgep->filter_lock); 2525 2526 if (nxgep->statsp->port_stats.lb_mode > nxge_lb_ext10) 2527 goto nxge_check_mii_link_exit; 2528 2529 if ((status = nxge_mii_read(nxgep, nxgep->statsp->mac_stats.xcvr_portn, 2530 (uint8_t)(uint64_t)(&mii_regs->bmsr), 2531 &bmsr_data.value)) != NXGE_OK) 2532 goto fail; 2533 2534 if (nxgep->param_arr[param_autoneg].value) { 2535 if ((status = nxge_mii_read(nxgep, 2536 nxgep->statsp->mac_stats.xcvr_portn, 2537 (uint8_t)(uint64_t)(&mii_regs->gsr), 2538 &gsr.value)) != NXGE_OK) 2539 goto fail; 2540 if ((status = nxge_mii_read(nxgep, 2541 nxgep->statsp->mac_stats.xcvr_portn, 2542 (uint8_t)(uint64_t)(&mii_regs->anlpar), 2543 &anlpar.value)) != NXGE_OK) 2544 goto fail; 2545 if (nxgep->statsp->mac_stats.link_up && 2546 ((nxgep->statsp->mac_stats.lp_cap_1000fdx ^ 2547 gsr.bits.link_1000fdx) || 2548 (nxgep->statsp->mac_stats.lp_cap_1000hdx ^ 2549 gsr.bits.link_1000hdx) || 2550 (nxgep->statsp->mac_stats.lp_cap_100T4 ^ 2551 anlpar.bits.cap_100T4) || 2552 (nxgep->statsp->mac_stats.lp_cap_100fdx ^ 2553 anlpar.bits.cap_100fdx) || 2554 (nxgep->statsp->mac_stats.lp_cap_100hdx ^ 2555 anlpar.bits.cap_100hdx) || 2556 (nxgep->statsp->mac_stats.lp_cap_10fdx ^ 2557 anlpar.bits.cap_10fdx) || 2558 (nxgep->statsp->mac_stats.lp_cap_10hdx ^ 2559 anlpar.bits.cap_10hdx))) { 2560 bmsr_data.bits.link_status = 0; 2561 } 2562 } 2563 2564 /* Workaround for link down issue */ 2565 if (bmsr_data.value == 0) { 2566 cmn_err(CE_NOTE, "!LINK DEBUG: Read zero bmsr\n"); 2567 goto nxge_check_mii_link_exit; 2568 } 2569 2570 bmsr_ints.value = nxgep->bmsr.value ^ bmsr_data.value; 2571 nxgep->bmsr.value = bmsr_data.value; 2572 if ((status = nxge_mii_check(nxgep, bmsr_data, bmsr_ints, &link_up)) 2573 != NXGE_OK) 2574 goto fail; 2575 2576 nxge_check_mii_link_exit: 2577 RW_EXIT(&nxgep->filter_lock); 2578 if (link_up == LINK_IS_UP) { 2579 nxge_link_is_up(nxgep); 2580 } else if (link_up == LINK_IS_DOWN) { 2581 nxge_link_is_down(nxgep); 2582 } 2583 2584 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 2585 2586 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_mii_link port<%d>", 2587 portn)); 2588 return (NXGE_OK); 2589 2590 fail: 2591 RW_EXIT(&nxgep->filter_lock); 2592 2593 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 2594 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2595 "nxge_check_mii_link: Failed to check link port<%d>", 2596 portn)); 2597 return (status); 2598 } 2599 2600 2601 /*ARGSUSED*/ 2602 nxge_status_t 2603 nxge_check_10g_link(p_nxge_t nxgep) 2604 { 2605 uint8_t portn; 2606 2607 nxge_status_t status = NXGE_OK; 2608 boolean_t link_up; 2609 2610 if (nxgep->nxge_magic != NXGE_MAGIC) 2611 return (NXGE_ERROR); 2612 2613 if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 2614 return (NXGE_OK); 2615 2616 portn = nxgep->mac.portnum; 2617 2618 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_check_10g_link port<%d>", 2619 portn)); 2620 2621 status = nxge_check_bcm8704_link(nxgep, &link_up); 2622 2623 if (status != NXGE_OK) 2624 goto fail; 2625 2626 if (link_up) { 2627 if (nxgep->link_notify || 2628 nxgep->statsp->mac_stats.link_up == 0) { 2629 if (nxge_10g_link_led_on(nxgep) != NXGE_OK) 2630 goto fail; 2631 nxgep->statsp->mac_stats.link_up = 1; 2632 nxgep->statsp->mac_stats.link_speed = 10000; 2633 nxgep->statsp->mac_stats.link_duplex = 2; 2634 2635 nxge_link_is_up(nxgep); 2636 nxgep->link_notify = B_FALSE; 2637 } 2638 } else { 2639 if (nxgep->link_notify || 2640 nxgep->statsp->mac_stats.link_up == 1) { 2641 if (nxge_10g_link_led_off(nxgep) != NXGE_OK) 2642 goto fail; 2643 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2644 "Link down cable problem")); 2645 nxgep->statsp->mac_stats.link_up = 0; 2646 nxgep->statsp->mac_stats.link_speed = 0; 2647 nxgep->statsp->mac_stats.link_duplex = 0; 2648 2649 nxge_link_is_down(nxgep); 2650 nxgep->link_notify = B_FALSE; 2651 } 2652 } 2653 2654 (void) nxge_link_monitor(nxgep, LINK_MONITOR_START); 2655 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_check_10g_link port<%d>", 2656 portn)); 2657 return (NXGE_OK); 2658 2659 fail: 2660 (void) nxge_check_link_stop(nxgep); 2661 2662 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 2663 "nxge_check_10g_link: Failed to check link port<%d>", 2664 portn)); 2665 return (status); 2666 } 2667 2668 2669 /* Declare link down */ 2670 2671 void 2672 nxge_link_is_down(p_nxge_t nxgep) 2673 { 2674 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_down")); 2675 2676 mac_link_update(nxgep->mach, LINK_STATE_DOWN); 2677 2678 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_down")); 2679 } 2680 2681 /* Declare link up */ 2682 2683 void 2684 nxge_link_is_up(p_nxge_t nxgep) 2685 { 2686 uint32_t val; 2687 2688 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "==> nxge_link_is_up")); 2689 2690 (void) nxge_xif_init(nxgep); 2691 2692 /* Clean up symbol errors incurred during link transition */ 2693 if (nxgep->mac.portmode == PORT_10G_FIBER) { 2694 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 2695 XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val); 2696 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 2697 XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val); 2698 } 2699 2700 mac_link_update(nxgep->mach, LINK_STATE_UP); 2701 2702 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_link_is_up")); 2703 } 2704 2705 /* 2706 * Calculate the bit in the multicast address filter 2707 * that selects the given * address. 2708 * Note: For GEM, the last 8-bits are used. 2709 */ 2710 uint32_t 2711 crc32_mchash(p_ether_addr_t addr) 2712 { 2713 uint8_t *cp; 2714 uint32_t crc; 2715 uint32_t c; 2716 int byte; 2717 int bit; 2718 2719 cp = (uint8_t *)addr; 2720 crc = (uint32_t)0xffffffff; 2721 for (byte = 0; byte < 6; byte++) { 2722 c = (uint32_t)cp[byte]; 2723 for (bit = 0; bit < 8; bit++) { 2724 if ((c & 0x1) ^ (crc & 0x1)) 2725 crc = (crc >> 1)^0xedb88320; 2726 else 2727 crc = (crc >> 1); 2728 c >>= 1; 2729 } 2730 } 2731 return ((~crc) >> (32 - HASH_BITS)); 2732 } 2733 2734 /* Reset serdes */ 2735 2736 nxge_status_t 2737 nxge_serdes_reset(p_nxge_t nxgep) 2738 { 2739 npi_handle_t handle; 2740 2741 handle = nxgep->npi_handle; 2742 2743 ESR_REG_WR(handle, ESR_RESET_REG, ESR_RESET_0 | ESR_RESET_1); 2744 drv_usecwait(500); 2745 ESR_REG_WR(handle, ESR_CONFIG_REG, 0); 2746 2747 return (NXGE_OK); 2748 } 2749 2750 /* Monitor link status using interrupt or polling */ 2751 2752 nxge_status_t 2753 nxge_link_monitor(p_nxge_t nxgep, link_mon_enable_t enable) 2754 { 2755 nxge_status_t status = NXGE_OK; 2756 2757 /* 2758 * Return immediately if this is an imaginary XMAC port. 2759 * (At least, we don't have 4-port XMAC cards yet.) 2760 */ 2761 if ((nxgep->mac.portmode == PORT_10G_FIBER) && (nxgep->mac.portnum > 1)) 2762 return (NXGE_OK); 2763 2764 if (nxgep->statsp == NULL) { 2765 /* stats has not been allocated. */ 2766 return (NXGE_OK); 2767 } 2768 /* Don't check link if we're not in internal loopback mode */ 2769 if (nxgep->statsp->port_stats.lb_mode != nxge_lb_normal) 2770 return (NXGE_OK); 2771 2772 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2773 "==> nxge_link_monitor port<%d> enable=%d", 2774 nxgep->mac.portnum, enable)); 2775 if (enable == LINK_MONITOR_START) { 2776 if (nxgep->mac.linkchkmode == LINKCHK_INTR) { 2777 if ((status = nxge_link_intr(nxgep, LINK_INTR_START)) 2778 != NXGE_OK) 2779 goto fail; 2780 } else { 2781 timeout_id_t timerid; 2782 2783 if (nxge_check_link_stop(nxgep) == CHECK_LINK_STOP) 2784 return (NXGE_OK); 2785 2786 switch (nxgep->mac.portmode) { 2787 case PORT_10G_FIBER: 2788 timerid = timeout((fptrv_t)nxge_check_10g_link, 2789 nxgep, 2790 drv_usectohz(LINK_MONITOR_PERIOD)); 2791 break; 2792 2793 case PORT_1G_COPPER: 2794 case PORT_1G_FIBER: 2795 timerid = timeout((fptrv_t)nxge_check_mii_link, 2796 nxgep, 2797 drv_usectohz(LINK_MONITOR_PERIOD)); 2798 break; 2799 default: 2800 return (NXGE_ERROR); 2801 } 2802 MUTEX_ENTER(&nxgep->poll_lock); 2803 nxgep->nxge_link_poll_timerid = timerid; 2804 MUTEX_EXIT(&nxgep->poll_lock); 2805 } 2806 } else { 2807 if (nxgep->mac.linkchkmode == LINKCHK_INTR) { 2808 if ((status = nxge_link_intr(nxgep, LINK_INTR_STOP)) 2809 != NXGE_OK) 2810 goto fail; 2811 } else { 2812 clock_t rv; 2813 2814 MUTEX_ENTER(&nxgep->poll_lock); 2815 2816 /* If <timerid> == 0, the link monitor has */ 2817 /* never been started, or just now stopped. */ 2818 if (nxgep->nxge_link_poll_timerid == 0) { 2819 MUTEX_EXIT(&nxgep->poll_lock); 2820 return (NXGE_OK); 2821 } 2822 2823 nxgep->poll_state = LINK_MONITOR_STOPPING; 2824 rv = cv_timedwait(&nxgep->poll_cv, 2825 &nxgep->poll_lock, 2826 ddi_get_lbolt() + 2827 drv_usectohz(LM_WAIT_MULTIPLIER * 2828 LINK_MONITOR_PERIOD)); 2829 if (rv == -1) { 2830 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2831 "==> stopping port %d: " 2832 "cv_timedwait(%d) timed out", 2833 nxgep->mac.portnum, nxgep->poll_state)); 2834 nxgep->poll_state = LINK_MONITOR_STOP; 2835 nxgep->nxge_link_poll_timerid = 0; 2836 } 2837 2838 MUTEX_EXIT(&nxgep->poll_lock); 2839 } 2840 } 2841 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2842 "<== nxge_link_monitor port<%d> enable=%d", 2843 nxgep->mac.portnum, enable)); 2844 return (NXGE_OK); 2845 fail: 2846 return (status); 2847 } 2848 2849 /* Set promiscous mode */ 2850 2851 nxge_status_t 2852 nxge_set_promisc(p_nxge_t nxgep, boolean_t on) 2853 { 2854 nxge_status_t status = NXGE_OK; 2855 2856 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 2857 "==> nxge_set_promisc: on %d", on)); 2858 2859 nxgep->filter.all_phys_cnt = ((on) ? 1 : 0); 2860 2861 RW_ENTER_WRITER(&nxgep->filter_lock); 2862 2863 if ((status = nxge_rx_mac_disable(nxgep)) != NXGE_OK) { 2864 goto fail; 2865 } 2866 if ((status = nxge_rx_mac_enable(nxgep)) != NXGE_OK) { 2867 goto fail; 2868 } 2869 2870 RW_EXIT(&nxgep->filter_lock); 2871 2872 if (on) 2873 nxgep->statsp->mac_stats.promisc = B_TRUE; 2874 else 2875 nxgep->statsp->mac_stats.promisc = B_FALSE; 2876 2877 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_set_promisc")); 2878 2879 return (NXGE_OK); 2880 fail: 2881 RW_EXIT(&nxgep->filter_lock); 2882 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "nxge_set_promisc: " 2883 "Unable to set promisc (%d)", on)); 2884 2885 return (status); 2886 } 2887 2888 /*ARGSUSED*/ 2889 uint_t 2890 nxge_mif_intr(void *arg1, void *arg2) 2891 { 2892 #ifdef NXGE_DEBUG 2893 p_nxge_t nxgep = (p_nxge_t)arg2; 2894 #endif 2895 #if NXGE_MIF 2896 p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1; 2897 uint32_t status; 2898 npi_handle_t handle; 2899 uint8_t portn; 2900 p_nxge_stats_t statsp; 2901 #endif 2902 2903 #ifdef NXGE_MIF 2904 if (arg2 == NULL || (void *)ldvp->nxgep != arg2) { 2905 nxgep = ldvp->nxgep; 2906 } 2907 nxgep = ldvp->nxgep; 2908 #endif 2909 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mif_intr")); 2910 2911 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr")); 2912 return (DDI_INTR_CLAIMED); 2913 2914 mif_intr_fail: 2915 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mif_intr")); 2916 return (DDI_INTR_UNCLAIMED); 2917 } 2918 2919 /*ARGSUSED*/ 2920 uint_t 2921 nxge_mac_intr(void *arg1, void *arg2) 2922 { 2923 p_nxge_t nxgep = (p_nxge_t)arg2; 2924 p_nxge_ldv_t ldvp = (p_nxge_ldv_t)arg1; 2925 p_nxge_ldg_t ldgp; 2926 uint32_t status; 2927 npi_handle_t handle; 2928 uint8_t portn; 2929 p_nxge_stats_t statsp; 2930 npi_status_t rs = NPI_SUCCESS; 2931 2932 if (arg2 == NULL || (void *)ldvp->nxgep != arg2) { 2933 nxgep = ldvp->nxgep; 2934 } 2935 2936 ldgp = ldvp->ldgp; 2937 NXGE_DEBUG_MSG((nxgep, INT_CTL, "==> nxge_mac_intr: " 2938 "group %d", ldgp->ldg)); 2939 2940 handle = NXGE_DEV_NPI_HANDLE(nxgep); 2941 /* 2942 * This interrupt handler is for a specific 2943 * mac port. 2944 */ 2945 statsp = (p_nxge_stats_t)nxgep->statsp; 2946 portn = nxgep->mac.portnum; 2947 2948 NXGE_DEBUG_MSG((nxgep, INT_CTL, 2949 "==> nxge_mac_intr: reading mac stats: port<%d>", portn)); 2950 2951 if (nxgep->mac.porttype == PORT_TYPE_XMAC) { 2952 rs = npi_xmac_tx_get_istatus(handle, portn, 2953 (xmac_tx_iconfig_t *)&status); 2954 if (rs != NPI_SUCCESS) 2955 goto npi_fail; 2956 if (status & ICFG_XMAC_TX_ALL) { 2957 if (status & ICFG_XMAC_TX_UNDERRUN) { 2958 statsp->xmac_stats.tx_underflow_err++; 2959 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 2960 NXGE_FM_EREPORT_TXMAC_UNDERFLOW); 2961 } 2962 if (status & ICFG_XMAC_TX_MAX_PACKET_ERR) { 2963 statsp->xmac_stats.tx_maxpktsize_err++; 2964 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 2965 NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR); 2966 } 2967 if (status & ICFG_XMAC_TX_OVERFLOW) { 2968 statsp->xmac_stats.tx_overflow_err++; 2969 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 2970 NXGE_FM_EREPORT_TXMAC_OVERFLOW); 2971 } 2972 if (status & ICFG_XMAC_TX_FIFO_XFR_ERR) { 2973 statsp->xmac_stats.tx_fifo_xfr_err++; 2974 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 2975 NXGE_FM_EREPORT_TXMAC_TXFIFO_XFR_ERR); 2976 } 2977 if (status & ICFG_XMAC_TX_BYTE_CNT_EXP) { 2978 statsp->xmac_stats.tx_byte_cnt += 2979 XTXMAC_BYTE_CNT_MASK; 2980 } 2981 if (status & ICFG_XMAC_TX_FRAME_CNT_EXP) { 2982 statsp->xmac_stats.tx_frame_cnt += 2983 XTXMAC_FRM_CNT_MASK; 2984 } 2985 } 2986 2987 rs = npi_xmac_rx_get_istatus(handle, portn, 2988 (xmac_rx_iconfig_t *)&status); 2989 if (rs != NPI_SUCCESS) 2990 goto npi_fail; 2991 if (status & ICFG_XMAC_RX_ALL) { 2992 if (status & ICFG_XMAC_RX_OVERFLOW) 2993 statsp->xmac_stats.rx_overflow_err++; 2994 if (status & ICFG_XMAC_RX_UNDERFLOW) { 2995 statsp->xmac_stats.rx_underflow_err++; 2996 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 2997 NXGE_FM_EREPORT_RXMAC_UNDERFLOW); 2998 } 2999 if (status & ICFG_XMAC_RX_CRC_ERR_CNT_EXP) { 3000 statsp->xmac_stats.rx_crc_err_cnt += 3001 XRXMAC_CRC_ER_CNT_MASK; 3002 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 3003 NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP); 3004 } 3005 if (status & ICFG_XMAC_RX_LEN_ERR_CNT_EXP) { 3006 statsp->xmac_stats.rx_len_err_cnt += 3007 MAC_LEN_ER_CNT_MASK; 3008 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 3009 NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP); 3010 } 3011 if (status & ICFG_XMAC_RX_VIOL_ERR_CNT_EXP) { 3012 statsp->xmac_stats.rx_viol_err_cnt += 3013 XRXMAC_CD_VIO_CNT_MASK; 3014 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 3015 NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP); 3016 } 3017 if (status & ICFG_XMAC_RX_OCT_CNT_EXP) { 3018 statsp->xmac_stats.rx_byte_cnt += 3019 XRXMAC_BT_CNT_MASK; 3020 } 3021 if (status & ICFG_XMAC_RX_HST_CNT1_EXP) { 3022 statsp->xmac_stats.rx_hist1_cnt += 3023 XRXMAC_HIST_CNT1_MASK; 3024 } 3025 if (status & ICFG_XMAC_RX_HST_CNT2_EXP) { 3026 statsp->xmac_stats.rx_hist2_cnt += 3027 XRXMAC_HIST_CNT2_MASK; 3028 } 3029 if (status & ICFG_XMAC_RX_HST_CNT3_EXP) { 3030 statsp->xmac_stats.rx_hist3_cnt += 3031 XRXMAC_HIST_CNT3_MASK; 3032 } 3033 if (status & ICFG_XMAC_RX_HST_CNT4_EXP) { 3034 statsp->xmac_stats.rx_hist4_cnt += 3035 XRXMAC_HIST_CNT4_MASK; 3036 } 3037 if (status & ICFG_XMAC_RX_HST_CNT5_EXP) { 3038 statsp->xmac_stats.rx_hist5_cnt += 3039 XRXMAC_HIST_CNT5_MASK; 3040 } 3041 if (status & ICFG_XMAC_RX_HST_CNT6_EXP) { 3042 statsp->xmac_stats.rx_hist6_cnt += 3043 XRXMAC_HIST_CNT6_MASK; 3044 } 3045 if (status & ICFG_XMAC_RX_BCAST_CNT_EXP) { 3046 statsp->xmac_stats.rx_broadcast_cnt += 3047 XRXMAC_BC_FRM_CNT_MASK; 3048 } 3049 if (status & ICFG_XMAC_RX_MCAST_CNT_EXP) { 3050 statsp->xmac_stats.rx_mult_cnt += 3051 XRXMAC_MC_FRM_CNT_MASK; 3052 } 3053 if (status & ICFG_XMAC_RX_FRAG_CNT_EXP) { 3054 statsp->xmac_stats.rx_frag_cnt += 3055 XRXMAC_FRAG_CNT_MASK; 3056 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 3057 NXGE_FM_EREPORT_RXMAC_RXFRAG_CNT_EXP); 3058 } 3059 if (status & ICFG_XMAC_RX_ALIGNERR_CNT_EXP) { 3060 statsp->xmac_stats.rx_frame_align_err_cnt += 3061 XRXMAC_AL_ER_CNT_MASK; 3062 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 3063 NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP); 3064 } 3065 if (status & ICFG_XMAC_RX_LINK_FLT_CNT_EXP) { 3066 statsp->xmac_stats.rx_linkfault_err_cnt += 3067 XMAC_LINK_FLT_CNT_MASK; 3068 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 3069 NXGE_FM_EREPORT_RXMAC_LINKFAULT_CNT_EXP); 3070 } 3071 if (status & ICFG_XMAC_RX_REMOTE_FLT_DET) { 3072 statsp->xmac_stats.rx_remotefault_err++; 3073 } 3074 if (status & ICFG_XMAC_RX_LOCAL_FLT_DET) { 3075 statsp->xmac_stats.rx_localfault_err++; 3076 } 3077 } 3078 3079 rs = npi_xmac_ctl_get_istatus(handle, portn, 3080 (xmac_ctl_iconfig_t *)&status); 3081 if (rs != NPI_SUCCESS) 3082 goto npi_fail; 3083 if (status & ICFG_XMAC_CTRL_ALL) { 3084 if (status & ICFG_XMAC_CTRL_PAUSE_RCVD) 3085 statsp->xmac_stats.rx_pause_cnt++; 3086 if (status & ICFG_XMAC_CTRL_PAUSE_STATE) 3087 statsp->xmac_stats.tx_pause_state++; 3088 if (status & ICFG_XMAC_CTRL_NOPAUSE_STATE) 3089 statsp->xmac_stats.tx_nopause_state++; 3090 } 3091 } else if (nxgep->mac.porttype == PORT_TYPE_BMAC) { 3092 rs = npi_bmac_tx_get_istatus(handle, portn, 3093 (bmac_tx_iconfig_t *)&status); 3094 if (rs != NPI_SUCCESS) 3095 goto npi_fail; 3096 if (status & ICFG_BMAC_TX_ALL) { 3097 if (status & ICFG_BMAC_TX_UNDERFLOW) { 3098 statsp->bmac_stats.tx_underrun_err++; 3099 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 3100 NXGE_FM_EREPORT_TXMAC_UNDERFLOW); 3101 } 3102 if (status & ICFG_BMAC_TX_MAXPKTSZ_ERR) { 3103 statsp->bmac_stats.tx_max_pkt_err++; 3104 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 3105 NXGE_FM_EREPORT_TXMAC_MAX_PKT_ERR); 3106 } 3107 if (status & ICFG_BMAC_TX_BYTE_CNT_EXP) { 3108 statsp->bmac_stats.tx_byte_cnt += 3109 BTXMAC_BYTE_CNT_MASK; 3110 } 3111 if (status & ICFG_BMAC_TX_FRAME_CNT_EXP) { 3112 statsp->bmac_stats.tx_frame_cnt += 3113 BTXMAC_FRM_CNT_MASK; 3114 } 3115 } 3116 3117 rs = npi_bmac_rx_get_istatus(handle, portn, 3118 (bmac_rx_iconfig_t *)&status); 3119 if (rs != NPI_SUCCESS) 3120 goto npi_fail; 3121 if (status & ICFG_BMAC_RX_ALL) { 3122 if (status & ICFG_BMAC_RX_OVERFLOW) { 3123 statsp->bmac_stats.rx_overflow_err++; 3124 } 3125 if (status & ICFG_BMAC_RX_FRAME_CNT_EXP) { 3126 statsp->bmac_stats.rx_frame_cnt += 3127 RXMAC_FRM_CNT_MASK; 3128 } 3129 if (status & ICFG_BMAC_RX_CRC_ERR_CNT_EXP) { 3130 statsp->bmac_stats.rx_crc_err_cnt += 3131 BMAC_CRC_ER_CNT_MASK; 3132 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 3133 NXGE_FM_EREPORT_RXMAC_CRC_ERRCNT_EXP); 3134 } 3135 if (status & ICFG_BMAC_RX_LEN_ERR_CNT_EXP) { 3136 statsp->bmac_stats.rx_len_err_cnt += 3137 MAC_LEN_ER_CNT_MASK; 3138 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 3139 NXGE_FM_EREPORT_RXMAC_LENGTH_ERRCNT_EXP); 3140 } 3141 if (status & ICFG_BMAC_RX_VIOL_ERR_CNT_EXP) 3142 statsp->bmac_stats.rx_viol_err_cnt += 3143 BMAC_CD_VIO_CNT_MASK; 3144 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 3145 NXGE_FM_EREPORT_RXMAC_VIOL_ERRCNT_EXP); 3146 } 3147 if (status & ICFG_BMAC_RX_BYTE_CNT_EXP) { 3148 statsp->bmac_stats.rx_byte_cnt += 3149 BRXMAC_BYTE_CNT_MASK; 3150 } 3151 if (status & ICFG_BMAC_RX_ALIGNERR_CNT_EXP) { 3152 statsp->bmac_stats.rx_align_err_cnt += 3153 BMAC_AL_ER_CNT_MASK; 3154 NXGE_FM_REPORT_ERROR(nxgep, portn, NULL, 3155 NXGE_FM_EREPORT_RXMAC_ALIGN_ECNT_EXP); 3156 } 3157 3158 rs = npi_bmac_ctl_get_istatus(handle, portn, 3159 (bmac_ctl_iconfig_t *)&status); 3160 if (rs != NPI_SUCCESS) 3161 goto npi_fail; 3162 3163 if (status & ICFG_BMAC_CTL_ALL) { 3164 if (status & ICFG_BMAC_CTL_RCVPAUSE) 3165 statsp->bmac_stats.rx_pause_cnt++; 3166 if (status & ICFG_BMAC_CTL_INPAUSE_ST) 3167 statsp->bmac_stats.tx_pause_state++; 3168 if (status & ICFG_BMAC_CTL_INNOTPAUSE_ST) 3169 statsp->bmac_stats.tx_nopause_state++; 3170 } 3171 } 3172 3173 if (ldgp->nldvs == 1) { 3174 (void) npi_intr_ldg_mgmt_set(handle, ldgp->ldg, 3175 B_TRUE, ldgp->ldg_timer); 3176 } 3177 3178 NXGE_DEBUG_MSG((nxgep, INT_CTL, "<== nxge_mac_intr")); 3179 return (DDI_INTR_CLAIMED); 3180 3181 npi_fail: 3182 NXGE_ERROR_MSG((nxgep, INT_CTL, "<== nxge_mac_intr")); 3183 return (DDI_INTR_UNCLAIMED); 3184 } 3185 3186 nxge_status_t 3187 nxge_check_bcm8704_link(p_nxge_t nxgep, boolean_t *link_up) 3188 { 3189 uint8_t phy_port_addr; 3190 nxge_status_t status = NXGE_OK; 3191 boolean_t rx_sig_ok; 3192 boolean_t pcs_blk_lock; 3193 boolean_t link_align; 3194 uint16_t val1, val2, val3; 3195 #ifdef NXGE_DEBUG_SYMBOL_ERR 3196 uint16_t val_debug; 3197 uint16_t val; 3198 #endif 3199 3200 phy_port_addr = nxgep->statsp->mac_stats.xcvr_portn; 3201 3202 #ifdef NXGE_DEBUG_SYMBOL_ERR 3203 /* Check Device 3 Register Device 3 0xC809 */ 3204 (void) nxge_mdio_read(nxgep, phy_port_addr, 0x3, 0xC809, &val_debug); 3205 if ((val_debug & ~0x200) != 0) { 3206 cmn_err(CE_NOTE, "!Port%d BCM8704 Dev3 Reg 0xc809 = 0x%x\n", 3207 nxgep->mac.portnum, val_debug); 3208 (void) nxge_mdio_read(nxgep, phy_port_addr, 0x4, 0x18, 3209 &val_debug); 3210 cmn_err(CE_NOTE, "!Port%d BCM8704 Dev4 Reg 0x18 = 0x%x\n", 3211 nxgep->mac.portnum, val_debug); 3212 } 3213 3214 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 3215 XPCS_REG_DESCWERR_COUNTER, &val); 3216 if (val != 0) 3217 cmn_err(CE_NOTE, "!XPCS DESCWERR = 0x%x\n", val); 3218 3219 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 3220 XPCS_REG_SYMBOL_ERR_L0_1_COUNTER, &val); 3221 if (val != 0) 3222 cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L0_1 = 0x%x\n", val); 3223 3224 (void) npi_xmac_xpcs_read(nxgep->npi_handle, nxgep->mac.portnum, 3225 XPCS_REG_SYMBOL_ERR_L2_3_COUNTER, &val); 3226 if (val != 0) 3227 cmn_err(CE_NOTE, "!XPCS SYMBOL_ERR_L2_3 = 0x%x\n", val); 3228 #endif 3229 3230 /* Check from BCM8704 if 10G link is up or down */ 3231 3232 /* Check Device 1 Register 0xA bit0 */ 3233 status = nxge_mdio_read(nxgep, phy_port_addr, 3234 BCM8704_PMA_PMD_DEV_ADDR, 3235 BCM8704_PMD_RECEIVE_SIG_DETECT, 3236 &val1); 3237 if (status != NXGE_OK) 3238 goto fail; 3239 rx_sig_ok = ((val1 & GLOB_PMD_RX_SIG_OK) ? B_TRUE : B_FALSE); 3240 3241 /* Check Device 3 Register 0x20 bit0 */ 3242 if ((status = nxge_mdio_read(nxgep, phy_port_addr, 3243 BCM8704_PCS_DEV_ADDR, 3244 BCM8704_10GBASE_R_PCS_STATUS_REG, 3245 &val2)) != NPI_SUCCESS) 3246 goto fail; 3247 pcs_blk_lock = ((val2 & PCS_10GBASE_R_PCS_BLK_LOCK) ? B_TRUE : B_FALSE); 3248 3249 /* Check Device 4 Register 0x18 bit12 */ 3250 status = nxge_mdio_read(nxgep, phy_port_addr, 3251 BCM8704_PHYXS_ADDR, 3252 BCM8704_PHYXS_XGXS_LANE_STATUS_REG, 3253 &val3); 3254 if (status != NXGE_OK) 3255 goto fail; 3256 link_align = (val3 == (XGXS_LANE_ALIGN_STATUS | XGXS_LANE3_SYNC | 3257 XGXS_LANE2_SYNC | XGXS_LANE1_SYNC | 3258 XGXS_LANE0_SYNC | 0x400)) ? B_TRUE : B_FALSE; 3259 3260 #ifdef NXGE_DEBUG_ALIGN_ERR 3261 /* Temp workaround for link down issue */ 3262 if (pcs_blk_lock == B_FALSE) { 3263 if (val2 != 0x4) { 3264 pcs_blk_lock = B_TRUE; 3265 cmn_err(CE_NOTE, 3266 "!LINK DEBUG: port%d PHY Dev3 " 3267 "Reg 0x20 = 0x%x\n", 3268 nxgep->mac.portnum, val2); 3269 } 3270 } 3271 3272 if (link_align == B_FALSE) { 3273 if (val3 != 0x140f) { 3274 link_align = B_TRUE; 3275 cmn_err(CE_NOTE, 3276 "!LINK DEBUG: port%d PHY Dev4 " 3277 "Reg 0x18 = 0x%x\n", 3278 nxgep->mac.portnum, val3); 3279 } 3280 } 3281 3282 if (rx_sig_ok == B_FALSE) { 3283 if ((val2 == 0) || (val3 == 0)) { 3284 rx_sig_ok = B_TRUE; 3285 cmn_err(CE_NOTE, 3286 "!LINK DEBUG: port %d Dev3 or Dev4 read zero\n", 3287 nxgep->mac.portnum); 3288 } 3289 } 3290 #endif 3291 3292 *link_up = ((rx_sig_ok == B_TRUE) && (pcs_blk_lock == B_TRUE) && 3293 (link_align == B_TRUE)) ? B_TRUE : B_FALSE; 3294 3295 return (NXGE_OK); 3296 fail: 3297 return (status); 3298 } 3299 3300 3301 nxge_status_t 3302 nxge_get_xcvr_type(p_nxge_t nxgep) 3303 { 3304 nxge_status_t status = NXGE_OK; 3305 char *phy_type; 3306 char *prop_val; 3307 3308 if (nxgep->niu_type == N2_NIU) { 3309 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, nxgep->dip, 0, 3310 "phy-type", &prop_val) == DDI_PROP_SUCCESS) { 3311 if (strcmp("xgf", prop_val) == 0) { 3312 nxgep->statsp->mac_stats.xcvr_inuse = 3313 XPCS_XCVR; 3314 nxgep->mac.portmode = PORT_10G_FIBER; 3315 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3316 "10G Fiber Xcvr")); 3317 } else if (strcmp("mif", prop_val) == 0) { 3318 nxgep->statsp->mac_stats.xcvr_inuse = 3319 INT_MII_XCVR; 3320 nxgep->mac.portmode = PORT_1G_COPPER; 3321 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3322 "1G Copper Xcvr")); 3323 } else if (strcmp("pcs", prop_val) == 0) { 3324 nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 3325 nxgep->mac.portmode = PORT_1G_FIBER; 3326 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3327 "1G Fiber Xcvr")); 3328 } else if (strcmp("xgc", prop_val) == 0) { 3329 nxgep->statsp->mac_stats.xcvr_inuse = 3330 XPCS_XCVR; 3331 nxgep->mac.portmode = PORT_10G_COPPER; 3332 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3333 "10G Copper Xcvr")); 3334 } else { 3335 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3336 "Unknown phy-type: %s", prop_val)); 3337 ddi_prop_free(prop_val); 3338 return (NXGE_ERROR); 3339 } 3340 status = NXGE_OK; 3341 (void) ddi_prop_update_string(DDI_DEV_T_NONE, 3342 nxgep->dip, "phy-type", prop_val); 3343 ddi_prop_free(prop_val); 3344 return (status); 3345 } else { 3346 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, 3347 "Exiting...phy-type property not found")); 3348 return (NXGE_ERROR); 3349 } 3350 } 3351 3352 if (!nxgep->vpd_info.ver_valid) { 3353 /* 3354 * read the phy type from the SEEPROM - NCR registers 3355 */ 3356 status = nxge_espc_phy_type_get(nxgep); 3357 if (status != NXGE_OK) 3358 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "EEPROM version " 3359 "[%s] invalid...please update", 3360 nxgep->vpd_info.ver)); 3361 return (status); 3362 } 3363 3364 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3365 "Reading phy type from expansion ROM")); 3366 /* 3367 * Try to read the phy type from the vpd data read off the 3368 * expansion ROM. 3369 */ 3370 phy_type = nxgep->vpd_info.phy_type; 3371 if (phy_type[0] == 'm' && phy_type[1] == 'i' && phy_type[2] == 'f') { 3372 nxgep->mac.portmode = PORT_1G_COPPER; 3373 nxgep->statsp->mac_stats.xcvr_inuse = INT_MII_XCVR; 3374 } else if (phy_type[0] == 'x' && phy_type[1] == 'g' && 3375 phy_type[2] == 'f') { 3376 nxgep->mac.portmode = PORT_10G_FIBER; 3377 nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 3378 } else if (phy_type[0] == 'p' && phy_type[1] == 'c' && 3379 phy_type[2] == 's') { 3380 nxgep->mac.portmode = PORT_1G_FIBER; 3381 nxgep->statsp->mac_stats.xcvr_inuse = PCS_XCVR; 3382 } else if (phy_type[0] == 'x' && phy_type[1] == 'g' && 3383 phy_type[2] == 'c') { 3384 nxgep->mac.portmode = PORT_10G_COPPER; 3385 nxgep->statsp->mac_stats.xcvr_inuse = XPCS_XCVR; 3386 } else { 3387 NXGE_DEBUG_MSG((nxgep, MAC_CTL, 3388 "nxge_get_xcvr_type: Unknown phy type [%c%c%c] in EEPROM", 3389 phy_type[0], phy_type[1], phy_type[2])); 3390 /* 3391 * read the phy type from the SEEPROM - NCR registers 3392 */ 3393 status = nxge_espc_phy_type_get(nxgep); 3394 if (status != NXGE_OK) 3395 NXGE_ERROR_MSG((nxgep, NXGE_ERR_CTL, "EEPROM version " 3396 "[%s] invalid...please update", 3397 nxgep->vpd_info.ver)); 3398 } 3399 3400 NXGE_DEBUG_MSG((nxgep, MAC_CTL, "<== nxge_get_xcvr_type")); 3401 return (status); 3402 } 3403 3404 nxge_status_t 3405 nxge_10g_link_led_on(p_nxge_t nxgep) 3406 { 3407 if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_TRUE) 3408 != NPI_SUCCESS) 3409 return (NXGE_ERROR); 3410 else 3411 return (NXGE_OK); 3412 } 3413 3414 nxge_status_t 3415 nxge_10g_link_led_off(p_nxge_t nxgep) 3416 { 3417 if (npi_xmac_xif_led(nxgep->npi_handle, nxgep->mac.portnum, B_FALSE) 3418 != NPI_SUCCESS) 3419 return (NXGE_ERROR); 3420 else 3421 return (NXGE_OK); 3422 } 3423 3424 boolean_t 3425 nxge_is_valid_local_mac(ether_addr_st mac_addr) 3426 { 3427 if ((mac_addr.ether_addr_octet[0] & 0x01) || 3428 (ether_cmp(&mac_addr, ðerbroadcastaddr) == 0) || 3429 (ether_cmp(&mac_addr, ðerzeroaddr) == 0)) 3430 return (B_FALSE); 3431 else 3432 return (B_TRUE); 3433 } 3434