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 "dmfe_impl.h" 29 30 /* 31 * The bit-twiddling required by the MII interface makes the functions 32 * in this file relatively slow, so they should probably only be called 33 * from base/low-pri code. However, there's nothing here that really 34 * won't work at hi-pri, AFAIK; and 'relatively slow' only means that 35 * they have microsecond busy-waits all over the place. 36 * 37 * dmfe_recheck_link(), on the other hand, uses delay() and loops for 38 * up to dmfe_restart_time_us microseconds (currently 12 seconds), so 39 * it should only be called from user (ioctl) or factotum context. 40 * 41 * Time parameters: 42 * 43 * RESTART_TIME is the time in microseconds to allow for the link 44 * to go down and recover after changing the PHY parameters. 45 * 46 * RESTART_POLL is the interval between checks on the link state 47 * while waiting for up to RESTART_TIME in total. 48 * 49 * SETTLE_TIME is the time to allow for the PHY to stabilise 50 * after a change from LINK DOWN to LINK UP; multiple changes 51 * within this time are coalesced into one (in case the link 52 * goes UP-DOWN-UP as negotiation tries different speeds, etc). 53 * 54 * Patchable globals: 55 * dmfe_restart_time_us: RESTART_TIME 56 * dmfe_restart_poll_us: RESTART_POLL 57 * dmfe_mii_settle_time: SETTLE_TIME 58 */ 59 60 #define RESTART_POLL 600000 /* microseconds */ 61 #define RESTART_TIME 12000000 /* microseconds */ 62 #define SETTLE_TIME 3000000 /* microseconds */ 63 64 #define MII_AN_SELECTOR_8023 1 65 #define MII_STATUS_INVAL 0xffffU 66 67 static clock_t dmfe_restart_poll_us = RESTART_POLL; 68 static clock_t dmfe_restart_time_us = RESTART_TIME; 69 static clock_t dmfe_mii_settle_time = SETTLE_TIME; 70 static const int mii_reg_size = 16; /* bits */ 71 72 #define DMFE_DBG DMFE_DBG_MII /* debug flag for this code */ 73 74 /* 75 * Type of transceiver currently in use. The IEEE 802.3 std aPhyType 76 * enumerates the following set 77 */ 78 enum xcvr_type { 79 XCVR_TYPE_UNDEFINED = 0, /* undefined, or not yet known */ 80 XCVR_TYPE_10BASE_T = 7, /* 10 Mbps copper */ 81 XCVR_TYPE_100BASE_X = 24 /* 100 Mbps copper */ 82 }; 83 84 /* 85 * ======== Low-level SROM access ======== 86 */ 87 88 /* 89 * EEPROM access is here because it shares register functionality with MII. 90 * NB: <romaddr> is a byte address but must be 16-bit aligned. 91 * <cnt> is a byte count, and must be a multiple of 2. 92 */ 93 void 94 dmfe_read_eeprom(dmfe_t *dmfep, uint16_t raddr, uint8_t *ptr, int cnt) 95 { 96 uint16_t value; 97 uint16_t bit; 98 99 /* only a whole number of words for now */ 100 ASSERT((cnt % 2) == 0); 101 ASSERT((raddr % 2) == 0); 102 ASSERT(cnt > 0); 103 ASSERT(((raddr + cnt) / 2) < (HIGH_ADDRESS_BIT << 1)); 104 105 raddr /= 2; /* make it a word address */ 106 107 /* loop over multiple words... rom access in 16-bit increments */ 108 while (cnt > 0) { 109 110 /* select the eeprom */ 111 dmfe_chip_put32(dmfep, ETHER_ROM_REG, READ_EEPROM); 112 drv_usecwait(1); 113 dmfe_chip_put32(dmfep, ETHER_ROM_REG, READ_EEPROM_CS); 114 drv_usecwait(1); 115 dmfe_chip_put32(dmfep, ETHER_ROM_REG, READ_EEPROM_CS | SEL_CLK); 116 drv_usecwait(1); 117 dmfe_chip_put32(dmfep, ETHER_ROM_REG, READ_EEPROM_CS); 118 drv_usecwait(1); 119 120 /* send 3 bit read command */ 121 for (bit = HIGH_CMD_BIT; bit != 0; bit >>= 1) { 122 123 value = (bit & EEPROM_READ_CMD) ? DATA_IN : 0; 124 125 /* strobe the bit in */ 126 dmfe_chip_put32(dmfep, ETHER_ROM_REG, 127 READ_EEPROM_CS | value); 128 drv_usecwait(1); 129 dmfe_chip_put32(dmfep, ETHER_ROM_REG, 130 READ_EEPROM_CS | SEL_CLK | value); 131 drv_usecwait(1); 132 dmfe_chip_put32(dmfep, ETHER_ROM_REG, 133 READ_EEPROM_CS | value); 134 drv_usecwait(1); 135 } 136 137 /* send 6 bit address */ 138 for (bit = HIGH_ADDRESS_BIT; bit != 0; bit >>= 1) { 139 value = (bit & raddr) ? DATA_IN : 0; 140 141 /* strobe the bit in */ 142 dmfe_chip_put32(dmfep, ETHER_ROM_REG, 143 READ_EEPROM_CS | value); 144 drv_usecwait(1); 145 dmfe_chip_put32(dmfep, ETHER_ROM_REG, 146 READ_EEPROM_CS | SEL_CLK | value); 147 drv_usecwait(1); 148 dmfe_chip_put32(dmfep, ETHER_ROM_REG, 149 READ_EEPROM_CS | value); 150 drv_usecwait(1); 151 } 152 153 /* shift out data */ 154 value = 0; 155 for (bit = HIGH_DATA_BIT; bit != 0; bit >>= 1) { 156 157 dmfe_chip_put32(dmfep, ETHER_ROM_REG, 158 READ_EEPROM_CS | SEL_CLK); 159 drv_usecwait(1); 160 161 if (dmfe_chip_get32(dmfep, ETHER_ROM_REG) & DATA_OUT) 162 value |= bit; 163 drv_usecwait(1); 164 165 dmfe_chip_put32(dmfep, ETHER_ROM_REG, READ_EEPROM_CS); 166 drv_usecwait(1); 167 } 168 169 /* turn off EEPROM access */ 170 dmfe_chip_put32(dmfep, ETHER_ROM_REG, READ_EEPROM); 171 drv_usecwait(1); 172 173 /* this makes it endian neutral */ 174 *ptr++ = value & 0xff; 175 *ptr++ = (value >> 8); 176 177 cnt -= 2; 178 raddr++; 179 } 180 } 181 182 /* 183 * ======== Lowest-level bit-twiddling to drive MII interface ======== 184 */ 185 186 /* 187 * Poke <nbits> (up to 32) bits from <mii_data> along the MII control lines. 188 * Note: the data is taken starting with the MSB of <mii_data> and working 189 * down through progressively less significant bits. 190 */ 191 static void 192 dmfe_poke_mii(dmfe_t *dmfep, uint32_t mii_data, uint_t nbits) 193 { 194 uint32_t dbit; 195 196 ASSERT(mutex_owned(dmfep->milock)); 197 198 for (; nbits > 0; mii_data <<= 1, --nbits) { 199 /* 200 * Extract the MSB of <mii_data> and shift it to the 201 * proper bit position in the MII-poking register 202 */ 203 dbit = mii_data >> 31; 204 dbit <<= MII_DATA_OUT_SHIFT; 205 ASSERT((dbit & ~MII_DATA_OUT) == 0); 206 207 /* 208 * Drive the bit across the wire ... 209 */ 210 dmfe_chip_put32(dmfep, ETHER_ROM_REG, 211 MII_WRITE | dbit); /* Clock Low */ 212 drv_usecwait(MII_DELAY); 213 dmfe_chip_put32(dmfep, ETHER_ROM_REG, 214 MII_WRITE | MII_CLOCK | dbit); /* Clock High */ 215 drv_usecwait(MII_DELAY); 216 } 217 218 dmfe_chip_put32(dmfep, ETHER_ROM_REG, 219 MII_WRITE | dbit); /* Clock Low */ 220 drv_usecwait(MII_DELAY); 221 } 222 223 /* 224 * Put the MDIO port in tri-state for the turn around bits 225 * in MII read and at end of MII management sequence. 226 */ 227 static void 228 dmfe_tristate_mii(dmfe_t *dmfep) 229 { 230 ASSERT(mutex_owned(dmfep->milock)); 231 232 dmfe_chip_put32(dmfep, ETHER_ROM_REG, MII_TRISTATE); 233 drv_usecwait(MII_DELAY); 234 dmfe_chip_put32(dmfep, ETHER_ROM_REG, MII_TRISTATE | MII_CLOCK); 235 drv_usecwait(MII_DELAY); 236 } 237 238 239 /* 240 * ======== Next level: issue an MII access command/get a response ======== 241 */ 242 243 static void 244 dmfe_mii_command(dmfe_t *dmfep, uint32_t command_word, int nbits) 245 { 246 ASSERT(mutex_owned(dmfep->milock)); 247 248 /* Write Preamble & Command & return to tristate */ 249 dmfe_poke_mii(dmfep, MII_PREAMBLE, 2*mii_reg_size); 250 dmfe_poke_mii(dmfep, command_word, nbits); 251 dmfe_tristate_mii(dmfep); 252 } 253 254 static uint16_t 255 dmfe_mii_response(dmfe_t *dmfep) 256 { 257 boolean_t ack; 258 uint32_t data; 259 uint32_t tmp; 260 int i; 261 262 /* Check that the PHY generated a zero bit on the 2nd clock */ 263 tmp = dmfe_chip_get32(dmfep, ETHER_ROM_REG); 264 ack = (tmp & MII_DATA_IN) == 0; 265 266 /* read data WORD */ 267 for (data = 0, i = 0; i < mii_reg_size; ++i) { 268 dmfe_chip_put32(dmfep, ETHER_ROM_REG, MII_READ); 269 drv_usecwait(MII_DELAY); 270 dmfe_chip_put32(dmfep, ETHER_ROM_REG, MII_READ | MII_CLOCK); 271 drv_usecwait(MII_DELAY); 272 tmp = dmfe_chip_get32(dmfep, ETHER_ROM_REG); 273 data <<= 1; 274 data |= (tmp >> MII_DATA_IN_SHIFT) & 1; 275 } 276 277 /* leave the interface tristated */ 278 dmfe_tristate_mii(dmfep); 279 280 return (ack ? data : ~0); 281 } 282 283 /* 284 * ======== Next level: 16-bit PHY register access routines ======== 285 */ 286 287 static void 288 dmfe_phy_write(dmfe_t *dmfep, uint_t reg_num, uint_t reg_dat) 289 { 290 uint32_t command_word; 291 292 /* Issue MII command */ 293 command_word = MII_WRITE_FRAME; 294 command_word |= dmfep->phy_addr << MII_PHY_ADDR_SHIFT; 295 command_word |= reg_num << MII_REG_ADDR_SHIFT; 296 command_word |= reg_dat; 297 dmfe_mii_command(dmfep, command_word, 2*mii_reg_size); 298 } 299 300 static uint16_t 301 dmfe_phy_read(dmfe_t *dmfep, uint_t reg_num) 302 { 303 uint32_t command_word; 304 305 /* Issue MII command */ 306 command_word = MII_READ_FRAME; 307 command_word |= dmfep->phy_addr << MII_PHY_ADDR_SHIFT; 308 command_word |= reg_num << MII_REG_ADDR_SHIFT; 309 dmfe_mii_command(dmfep, command_word, mii_reg_size-2); 310 311 return (dmfe_mii_response(dmfep)); 312 } 313 314 /* 315 * ======== Next level: PHY control operations ======== 316 */ 317 318 /* 319 * Reset the PHYceiver, using a wierd sequence of accesses to CR12 320 * 321 * This could be done using MII accesses; but this should be quicker .... 322 */ 323 static void 324 dmfe_phy_reset(dmfe_t *dmfep) 325 { 326 DMFE_TRACE(("dmfe_phy_reset($%p)", (void *)dmfep)); 327 328 ASSERT(mutex_owned(dmfep->milock)); 329 330 dmfe_chip_put32(dmfep, PHY_STATUS_REG, GPS_WRITE_ENABLE|GPS_PHY_RESET); 331 drv_usecwait(10); 332 dmfe_chip_put32(dmfep, PHY_STATUS_REG, GPS_PHY_RESET); 333 drv_usecwait(10); 334 dmfe_chip_put32(dmfep, PHY_STATUS_REG, 0); 335 drv_usecwait(10); 336 } 337 338 /* 339 * Read the MII_STATUS register (BMSR) 340 */ 341 static uint16_t 342 dmfe_mii_status(dmfe_t *dmfep) 343 { 344 uint16_t bmsr; 345 346 bmsr = dmfe_phy_read(dmfep, MII_STATUS); 347 348 DMFE_DEBUG(("dmfe_mii_status: bmsr 0x%x", bmsr)); 349 350 return (bmsr); 351 } 352 353 /* 354 * Returns true if PHY at address <phy_addr> is present and accessible. 355 * We determine whether the PHY is there by looking for at least one 356 * set bit, and at least one clear bit, in the value returned from its 357 * status register (i.e. BMSR is not all zeroes or all ones). 358 */ 359 static boolean_t 360 dmfe_probe_phy(dmfe_t *dmfep) 361 { 362 uint16_t bmsr; 363 364 ASSERT(mutex_owned(dmfep->milock)); 365 366 /* Clear any latched bits by reading twice */ 367 bmsr = dmfe_mii_status(dmfep); 368 bmsr = dmfe_mii_status(dmfep); 369 370 DMFE_DEBUG(("dmfe_probe_phy($%p, %d) BMSR 0x%x", 371 (void *)dmfep, dmfep->phy_addr, bmsr)); 372 373 /* 374 * At least one bit in BMSR should be set (for the device 375 * capabilities) and at least one clear (one of the error 376 * bits). Unconnected devices tend to show 0xffff, but 377 * 0x0000 has also been seen. 378 */ 379 return (bmsr != 0 && bmsr != MII_STATUS_INVAL); 380 } 381 382 static boolean_t 383 dmfe_find_phy(dmfe_t *dmfep) 384 { 385 int mii_addr; 386 387 ASSERT(mutex_owned(dmfep->milock)); 388 389 /* 390 * Verify that the PHY responds to MII accesses. It *should* 391 * be at MII address 1, but the Davicom internal PHY can be 392 * reprogrammed to appear at a different address, so we'll 393 * check all 32 possible addresses if necessary (in the order 394 * 1, 2, 3..31, 0) 395 */ 396 for (mii_addr = 1; ; ) { 397 dmfep->phy_addr = mii_addr % 32; 398 if (dmfe_probe_phy(dmfep)) 399 break; 400 if (++mii_addr > 32) { 401 DMFE_DEBUG(("No PHY found")); 402 return (B_FALSE); 403 } 404 } 405 406 dmfep->phy_id = dmfe_phy_read(dmfep, MII_PHYIDH) << 16; 407 dmfep->phy_id |= dmfe_phy_read(dmfep, MII_PHYIDL); 408 409 DMFE_DEBUG(("PHY at address %d, id 0x%x", mii_addr, dmfep->phy_id)); 410 411 switch (PHY_MANUFACTURER(dmfep->phy_id)) { 412 case OUI_DAVICOM: 413 return (B_TRUE); 414 415 default: 416 dmfe_warning(dmfep, "unsupported (non-Davicom) PHY found!"); 417 return (B_FALSE); 418 } 419 } 420 421 #undef DMFE_DBG 422 423 #define DMFE_DBG DMFE_DBG_LINK /* debug flag for this code */ 424 425 /* 426 * ======== Top-level PHY management routines ======== 427 */ 428 429 /* 430 * (Re)initalise the PHY's speed/duplex/autonegotiation registers, basing 431 * the required settings on the various param_* variables that can be poked 432 * via the NDD interface. 433 * 434 * NOTE: the Tx/Rx processes should be STOPPED when this routine is called 435 */ 436 void 437 dmfe_update_phy(dmfe_t *dmfep) 438 { 439 uint16_t control; 440 uint16_t anar; 441 442 DMFE_DEBUG(("dmfe_update_phy: autoneg %d 100fdx %d 100hdx %d " 443 "10fdx %d 10hdx %d", dmfep->param_autoneg, 444 dmfep->param_anar_100fdx, dmfep->param_anar_100hdx, 445 dmfep->param_anar_10fdx, dmfep->param_anar_10hdx)); 446 447 ASSERT(mutex_owned(dmfep->milock)); 448 449 /* 450 * NDD initialisation will have already set up the param_* 451 * variables based on the values of the various properties. 452 * Here we have to transform these into the proper settings 453 * of the PHY registers ... 454 */ 455 anar = control = 0; 456 457 if (dmfep->param_anar_100fdx) 458 control |= MII_CONTROL_100MB|MII_CONTROL_FDUPLEX; 459 else if (dmfep->param_anar_100hdx) 460 control |= MII_CONTROL_100MB; 461 else if (dmfep->param_anar_10fdx) 462 control |= MII_CONTROL_FDUPLEX; 463 464 if (dmfep->param_anar_100fdx) 465 anar |= MII_ABILITY_100BASE_TX_FD; 466 if (dmfep->param_anar_100hdx) 467 anar |= MII_ABILITY_100BASE_TX; 468 if (dmfep->param_anar_10fdx) 469 anar |= MII_ABILITY_10BASE_T_FD; 470 if (dmfep->param_anar_10hdx) 471 anar |= MII_ABILITY_10BASE_T; 472 473 if (anar == 0) { 474 /* 475 * A stupid combination of settings has left us with no 476 * options - so select the default (100Mb/s half-duplex) 477 * for now and re-enable ALL autonegotiation options. 478 */ 479 control |= MII_CONTROL_100MB; 480 anar |= MII_ABILITY_100BASE_TX_FD; 481 anar |= MII_ABILITY_100BASE_TX; 482 anar |= MII_ABILITY_10BASE_T_FD; 483 anar |= MII_ABILITY_10BASE_T; 484 } 485 486 if ((dmfep->opmode & LOOPBACK_MODE_MASK) != LOOPBACK_OFF) { 487 /* 488 * If loopback is selected at the MAC level, we have 489 * to make sure that the settings are consistent at 490 * the PHY, and also keep autonegotiation switched OFF, 491 * otherwise we can get all sorts of strange effects 492 * including continuous link change interrupts :-( 493 */ 494 control |= MII_CONTROL_LOOPBACK; 495 } else if (dmfep->param_autoneg) { 496 /* 497 * Autonegotiation is only possible if loopback is OFF 498 */ 499 control |= MII_CONTROL_ANE; 500 } 501 502 DMFE_DEBUG(("dmfe_update_phy: anar 0x%x control 0x%x", anar, control)); 503 504 anar |= MII_AN_SELECTOR_8023; 505 if ((anar != dmfep->phy_anar_w) || (control != dmfep->phy_control) || 506 (dmfep->update_phy)) { 507 /* 508 * Something's changed; reset the PHY and write the new 509 * values to the PHY CONTROL and ANAR registers. This 510 * will probably cause the link to go down, and then back 511 * up again once the link is stable and autonegotiation 512 * (if enabled) is complete. We should get a link state 513 * change at the end; but in any case the ticker will keep 514 * an eye on what's going on ... 515 */ 516 dmfe_phy_reset(dmfep); 517 dmfe_phy_write(dmfep, MII_CONTROL, control); 518 dmfe_phy_write(dmfep, MII_AN_ADVERT, anar); 519 } 520 521 /* 522 * If autonegotiation is (now) enabled, we want to trigger 523 * a new autonegotiation cycle now that the PHY has been 524 * programmed with the capabilities to be advertised. 525 */ 526 if (control & MII_CONTROL_ANE) 527 dmfe_phy_write(dmfep, MII_CONTROL, control | MII_CONTROL_RSAN); 528 529 /* 530 * Save the values written in the shadow copies of the CONTROL 531 * and ANAR registers, and clear the shadow BMSR 'cos it's no 532 * longer valid. 533 */ 534 dmfep->phy_control = control; 535 dmfep->phy_anar_w = anar; 536 dmfep->phy_bmsr = 0; 537 } 538 539 540 /* 541 * PHY initialisation, called only once 542 * 543 * Discover the MII address of the PHY (should be 1). 544 * Initialise according to preset NDD parameters. 545 * Return status 546 */ 547 boolean_t 548 dmfe_init_phy(dmfe_t *dmfep) 549 { 550 boolean_t ok; 551 552 mutex_enter(dmfep->milock); 553 ok = dmfe_find_phy(dmfep); 554 if (ok) 555 dmfe_update_phy(dmfep); 556 mutex_exit(dmfep->milock); 557 558 return (ok); 559 } 560 561 /* 562 * ========== Active Media Determination Routines ========== 563 */ 564 565 566 /* 567 * Check whether the BMSR has changed. If it hasn't, this routine 568 * just returns B_FALSE (no further action required). Otherwise, 569 * it records the time when the change was seen and returns B_TRUE. 570 * 571 * This routine needs only the <milock>, although <oplock> may 572 * also be held. This is why full processing of the link change 573 * is left to dmfe_recheck_link() below. 574 */ 575 static boolean_t 576 dmfe_check_bmsr(dmfe_t *dmfep) 577 { 578 uint16_t new_bmsr; 579 580 DMFE_TRACE(("dmfe_check_bmsr($%p)", (void *)dmfep)); 581 582 ASSERT(mutex_owned(dmfep->milock)); 583 584 /* 585 * Read the BMSR and check it against the previous value 586 */ 587 new_bmsr = dmfe_mii_status(dmfep); 588 DMFE_DEBUG(("dmfe_check_bmsr: bmsr 0x%x -> 0x%x", 589 dmfep->phy_bmsr, new_bmsr)); 590 591 /* 592 * Record new value and timestamp if it's changed 593 */ 594 if (new_bmsr != dmfep->phy_bmsr) { 595 dmfep->phy_bmsr = new_bmsr; 596 dmfep->phy_bmsr_lbolt = ddi_get_lbolt(); 597 return (B_TRUE); 598 } 599 600 return (B_FALSE); 601 } 602 603 /* 604 * 'Quick' link check routine 605 * 606 * Call whenever the link state may have changed, or periodically to 607 * poll for link up/down events. Returns B_FALSE if nothing interesting 608 * has happened. Otherwise, it returns B_TRUE, telling the caller to 609 * call dmfe_recheck_link() (below). If the link state is UNKNOWN, we 610 * return B_TRUE anyway, even if the BMSR hasn't changed - but only after 611 * going through the motions, 'cos the read of the BMSR has side-effects - 612 * some of the BMSR bits are latching-until-read, and dmfe_check_bmsr() 613 * also records the time of any change to the BMSR! 614 */ 615 boolean_t 616 dmfe_check_link(dmfe_t *dmfep) 617 { 618 if (dmfe_check_bmsr(dmfep)) 619 return (B_TRUE); 620 return (dmfep->link_state == LINK_STATE_UNKNOWN); 621 } 622 623 624 /* 625 * Update all parameters and statistics after a link state change. 626 */ 627 static void 628 dmfe_media_update(dmfe_t *dmfep, link_state_t newstate, int speed, int duplex) 629 { 630 int ks_id; 631 632 ASSERT(mutex_owned(dmfep->milock)); 633 ASSERT(mutex_owned(dmfep->oplock)); 634 ASSERT(newstate != dmfep->link_state); 635 636 switch (newstate) { 637 case LINK_STATE_UP: 638 dmfep->param_linkup = 1; 639 break; 640 641 default: 642 dmfep->param_linkup = 0; 643 break; 644 } 645 646 switch (speed) { 647 case 100: 648 dmfep->op_stats_speed = 100000000; 649 dmfep->param_speed = speed; 650 dmfep->phy_inuse = XCVR_100X; 651 break; 652 653 case 10: 654 dmfep->op_stats_speed = 10000000; 655 dmfep->param_speed = speed; 656 dmfep->phy_inuse = XCVR_10; 657 break; 658 659 default: 660 dmfep->op_stats_speed = 0; 661 dmfep->phy_inuse = XCVR_UNDEFINED; 662 break; 663 } 664 665 dmfep->op_stats_duplex = dmfep->param_duplex = duplex; 666 667 if (newstate == LINK_STATE_UP) 668 ks_id = KS_LINK_UP_CNT; 669 else 670 ks_id = KS_LINK_DROP_CNT; 671 DRV_KS_INC(dmfep, ks_id); 672 } 673 674 /* 675 * Verify and report a change in the state of the link ... 676 */ 677 static void 678 dmfe_link_change(dmfe_t *dmfep, link_state_t newstate) 679 { 680 boolean_t report; 681 uint32_t gpsr; 682 int speed; 683 int duplex; 684 685 ASSERT(mutex_owned(dmfep->milock)); 686 ASSERT(mutex_owned(dmfep->oplock)); 687 ASSERT(newstate != dmfep->link_state); 688 689 switch (newstate) { 690 case LINK_STATE_UP: 691 gpsr = dmfe_chip_get32(dmfep, PHY_STATUS_REG); 692 speed = gpsr & GPS_LINK_100 ? 100 : 10; 693 duplex = (gpsr & GPS_FULL_DUPLEX) ? 694 LINK_DUPLEX_FULL: LINK_DUPLEX_HALF; 695 report = B_TRUE; 696 break; 697 698 default: 699 speed = 0; 700 duplex = LINK_DUPLEX_UNKNOWN; 701 switch (dmfep->link_state) { 702 case LINK_STATE_DOWN: /* DOWN->UNKNOWN */ 703 case LINK_STATE_UNKNOWN: /* UNKNOWN->DOWN */ 704 report = B_FALSE; 705 break; 706 707 case LINK_STATE_UP: /* UP->DOWN/UNKNOWN */ 708 report = B_TRUE; 709 break; 710 } 711 break; 712 } 713 714 /* 715 * Update status & report new link state if required ... 716 */ 717 if (report) 718 dmfe_media_update(dmfep, newstate, speed, duplex); 719 } 720 721 /* 722 * Examine the value most recently read from the BMSR and derive 723 * the (new) link state. 724 * 725 * This routine also incorporates heuristics determining when to 726 * accept a new state as valid and report it, based on the new 727 * (apparent) state, the old state, and the time elapsed since 728 * the last time we saw a (potential) state change. For example, 729 * we want to accept UP->DOWN immediately, but UNKNOWN->UP only 730 * once autonegotiation is completed and the results are stable. 731 */ 732 static link_state_t 733 dmfe_process_bmsr(dmfe_t *dmfep, clock_t time) 734 { 735 link_state_t newstate; 736 uint32_t gpsr; 737 uint16_t bmsr; 738 uint16_t anlpar; 739 uint16_t anar; 740 741 ASSERT(mutex_owned(dmfep->milock)); 742 ASSERT(mutex_owned(dmfep->oplock)); 743 744 /* 745 * Read PHY registers & publish through driver-specific kstats 746 * Decode abilities & publish through ndd & standard MII kstats 747 */ 748 dmfep->phy_anar_r = dmfe_phy_read(dmfep, MII_AN_ADVERT); 749 dmfep->phy_aner = dmfe_phy_read(dmfep, MII_AN_EXPANSION); 750 dmfep->phy_anlpar = dmfe_phy_read(dmfep, MII_AN_LPABLE); 751 dmfep->phy_dscsr = dmfe_phy_read(dmfep, DM_SCSR); 752 753 DRV_KS_SET(dmfep, KS_MIIREG_BMSR, dmfep->phy_bmsr); 754 DRV_KS_SET(dmfep, KS_MIIREG_ANAR, dmfep->phy_anar_r); 755 DRV_KS_SET(dmfep, KS_MIIREG_ANER, dmfep->phy_aner); 756 DRV_KS_SET(dmfep, KS_MIIREG_ANLPAR, dmfep->phy_anlpar); 757 DRV_KS_SET(dmfep, KS_MIIREG_DSCSR, dmfep->phy_dscsr); 758 759 DMFE_DEBUG(("dmfe_process_bmsr: ANAR 0x%x->0x%x ANLPAR 0x%x SCSR 0x%x", 760 dmfep->phy_anar_w, dmfep->phy_anar_r, 761 dmfep->phy_anlpar, dmfep->phy_dscsr)); 762 763 /* 764 * Capabilities of DM9102A 765 */ 766 bmsr = dmfep->phy_bmsr; 767 768 dmfep->param_bmsr_100T4 = BIS(bmsr, MII_STATUS_100_BASE_T4); 769 dmfep->param_bmsr_100fdx = BIS(bmsr, MII_STATUS_100_BASEX_FD); 770 dmfep->param_bmsr_100hdx = BIS(bmsr, MII_STATUS_100_BASEX); 771 dmfep->param_bmsr_10fdx = BIS(bmsr, MII_STATUS_10_FD); 772 dmfep->param_bmsr_10hdx = BIS(bmsr, MII_STATUS_10); 773 dmfep->param_bmsr_remfault = 1; 774 dmfep->param_bmsr_autoneg = BIS(bmsr, MII_STATUS_CANAUTONEG); 775 776 /* 777 * Advertised abilities of DM9102A 778 */ 779 anar = dmfep->phy_anar_r; 780 dmfep->param_anar_remfault = BIS(anar, MII_AN_ADVERT_REMFAULT); 781 782 /* 783 * Link Partners advertised abilities 784 */ 785 if ((dmfep->phy_aner & MII_AN_EXP_LPCANAN) == 0) { 786 anlpar = 0; 787 dmfep->param_lp_autoneg = 0; 788 } else { 789 anlpar = dmfep->phy_anlpar; 790 dmfep->param_lp_autoneg = 1; 791 } 792 793 dmfep->param_lp_100T4 = BIS(anlpar, MII_ABILITY_100BASE_T4); 794 dmfep->param_lp_100fdx = BIS(anlpar, MII_ABILITY_100BASE_TX_FD); 795 dmfep->param_lp_100hdx = BIS(anlpar, MII_ABILITY_100BASE_TX); 796 dmfep->param_lp_10fdx = BIS(anlpar, MII_ABILITY_10BASE_T_FD); 797 dmfep->param_lp_10hdx = BIS(anlpar, MII_ABILITY_10BASE_T); 798 dmfep->param_lp_remfault = BIS(anlpar, MII_AN_ADVERT_REMFAULT); 799 800 /* 801 * Derive new state & time since last change 802 */ 803 newstate = (dmfep->phy_bmsr & MII_STATUS_LINKUP) ? 804 LINK_STATE_UP : LINK_STATE_DOWN; 805 time -= dmfep->phy_bmsr_lbolt; 806 807 /* 808 * Hah! That would be just too easy ... we have to check 809 * for all sorts of special cases before we decide :( 810 */ 811 if (dmfep->phy_bmsr == MII_STATUS_INVAL) 812 newstate = LINK_STATE_DOWN; 813 else if ((dmfep->link_state == LINK_STATE_UP) && 814 (newstate == LINK_STATE_DOWN)) 815 /*EMPTY*/; 816 else if (time < drv_usectohz(dmfe_mii_settle_time)) 817 newstate = LINK_STATE_UNKNOWN; 818 else if (dmfep->phy_bmsr & MII_STATUS_ANDONE) 819 /*EMPTY*/; 820 else if (dmfep->phy_control & MII_CONTROL_ANE) 821 newstate = LINK_STATE_DOWN; 822 823 if (newstate == LINK_STATE_UP) { 824 /* 825 * Link apparently UP - but get the PHY status register 826 * (GPSR) and make sure it also shows a consistent value. 827 * In particular, both the link status bits should be 1, 828 * and the speed bits should show one set and one clear. 829 * Any other combination indicates that we haven't really 830 * got a stable link yet ... 831 */ 832 gpsr = dmfe_chip_get32(dmfep, PHY_STATUS_REG); 833 DMFE_DEBUG(("dmfe_process_bmsr: GPSR 0x%x", gpsr)); 834 835 switch (gpsr & (GPS_LINK_STATUS|GPS_UTP_SIG)) { 836 case GPS_LINK_STATUS|GPS_UTP_SIG: 837 break; 838 default: 839 newstate = LINK_STATE_UNKNOWN; 840 break; 841 } 842 843 switch (gpsr & (GPS_LINK_10|GPS_LINK_100)) { 844 case GPS_LINK_100: 845 case GPS_LINK_10: 846 break; 847 default: 848 newstate = LINK_STATE_UNKNOWN; 849 break; 850 } 851 } 852 853 DMFE_DEBUG(("dmfe_process_bmsr: BMSR 0x%x state %d -> %d @ %d", 854 dmfep->phy_bmsr, dmfep->link_state, newstate, time)); 855 856 return (newstate); 857 } 858 859 /* 860 * 'Full' link check routine 861 * 862 * Call whenever dmfe_check_link() above indicates that the link 863 * state may have changed. Handles all changes to the link state 864 * (up/down, speed/duplex changes), including multiple changes 865 * occuring within the <timeout>. <timeout> will be zero if called 866 * from the factotum (for an unexpected change) or the number of 867 * ticks for which to wait for stability after an ioctl that changes 868 * the link parameters. Even when <timeout> is zero, we loop while 869 * the BMSR keeps changing ... 870 * 871 * Needs both <milock> and <oplock>, and the Tx/Rx processes 872 * should already be stopped so we're not liable to confuse them 873 * by changing the PHY/MAC parameters under them ... 874 * 875 */ 876 void 877 dmfe_recheck_link(dmfe_t *dmfep, boolean_t ioctl) 878 { 879 link_state_t newstate; 880 boolean_t again; 881 clock_t deadline; 882 clock_t now; 883 884 DMFE_TRACE(("dmfe_recheck_link($%p, %d)", (void *)dmfep, ioctl)); 885 886 ASSERT(mutex_owned(dmfep->milock)); 887 ASSERT(mutex_owned(dmfep->oplock)); 888 889 now = deadline = ddi_get_lbolt(); 890 if (ioctl) 891 deadline += drv_usectohz(dmfe_restart_time_us); 892 893 for (; ; now = ddi_get_lbolt()) { 894 newstate = dmfe_process_bmsr(dmfep, now); 895 again = dmfe_check_bmsr(dmfep); 896 if (newstate != dmfep->link_state) { 897 dmfe_link_change(dmfep, newstate); 898 dmfep->link_state = newstate; 899 again = B_TRUE; 900 } 901 ASSERT(dmfep->link_state == newstate); 902 if (again) 903 continue; 904 if (newstate == LINK_STATE_UP) { 905 dmfep->update_phy = B_TRUE; 906 break; 907 } 908 if (now >= deadline) 909 break; 910 delay(drv_usectohz(dmfe_restart_poll_us)); 911 } 912 } 913 914 #undef DMFE_DBG 915