1/****************************************************************************** 2 * 3 * Name: skxmac2.c 4 * Project: Gigabit Ethernet Adapters, Common Modules 5 * Version: $Revision: 1.1.1.1 $ 6 * Date: $Date: 2007-08-03 18:52:48 $ 7 * Purpose: Contains functions to initialize the MACs and PHYs 8 * 9 ******************************************************************************/ 10 11/****************************************************************************** 12 * 13 * (C)Copyright 1998-2002 SysKonnect. 14 * (C)Copyright 2002-2003 Marvell. 15 * 16 * This program is free software; you can redistribute it and/or modify 17 * it under the terms of the GNU General Public License as published by 18 * the Free Software Foundation; either version 2 of the License, or 19 * (at your option) any later version. 20 * 21 * The information in this file is provided "AS IS" without warranty. 22 * 23 ******************************************************************************/ 24 25#include "h/skdrv1st.h" 26#include "h/skdrv2nd.h" 27 28/* typedefs *******************************************************************/ 29 30/* BCOM PHY magic pattern list */ 31typedef struct s_PhyHack { 32 int PhyReg; /* Phy register */ 33 SK_U16 PhyVal; /* Value to write */ 34} BCOM_HACK; 35 36/* local variables ************************************************************/ 37 38#if (defined(DEBUG) || (!defined(LINT) && !defined(SK_SLIM))) 39static const char SysKonnectFileId[] = 40 "@(#) $Id: skxmac2.c,v 1.1.1.1 2007-08-03 18:52:48 $ (C) Marvell."; 41#endif 42 43#ifdef GENESIS 44static BCOM_HACK BcomRegA1Hack[] = { 45 { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1104 }, { 0x17, 0x0013 }, 46 { 0x15, 0x0404 }, { 0x17, 0x8006 }, { 0x15, 0x0132 }, { 0x17, 0x8006 }, 47 { 0x15, 0x0232 }, { 0x17, 0x800D }, { 0x15, 0x000F }, { 0x18, 0x0420 }, 48 { 0, 0 } 49}; 50static BCOM_HACK BcomRegC0Hack[] = { 51 { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1204 }, { 0x17, 0x0013 }, 52 { 0x15, 0x0A04 }, { 0x18, 0x0420 }, 53 { 0, 0 } 54}; 55#endif 56 57/* function prototypes ********************************************************/ 58#ifdef GENESIS 59static void SkXmInitPhyXmac(SK_AC*, SK_IOC, int, SK_BOOL); 60static void SkXmInitPhyBcom(SK_AC*, SK_IOC, int, SK_BOOL); 61static int SkXmAutoNegDoneXmac(SK_AC*, SK_IOC, int); 62static int SkXmAutoNegDoneBcom(SK_AC*, SK_IOC, int); 63#endif /* GENESIS */ 64#ifdef YUKON 65static void SkGmInitPhyMarv(SK_AC*, SK_IOC, int, SK_BOOL); 66static int SkGmAutoNegDoneMarv(SK_AC*, SK_IOC, int); 67#endif /* YUKON */ 68#ifdef OTHER_PHY 69static void SkXmInitPhyLone(SK_AC*, SK_IOC, int, SK_BOOL); 70static void SkXmInitPhyNat (SK_AC*, SK_IOC, int, SK_BOOL); 71static int SkXmAutoNegDoneLone(SK_AC*, SK_IOC, int); 72static int SkXmAutoNegDoneNat (SK_AC*, SK_IOC, int); 73#endif /* OTHER_PHY */ 74 75 76#ifdef GENESIS 77/****************************************************************************** 78 * 79 * SkXmPhyRead() - Read from XMAC PHY register 80 * 81 * Description: reads a 16-bit word from XMAC PHY or ext. PHY 82 * 83 * Returns: 84 * nothing 85 */ 86void SkXmPhyRead( 87SK_AC *pAC, /* Adapter Context */ 88SK_IOC IoC, /* I/O Context */ 89int Port, /* Port Index (MAC_1 + n) */ 90int PhyReg, /* Register Address (Offset) */ 91SK_U16 SK_FAR *pVal) /* Pointer to Value */ 92{ 93 SK_U16 Mmu; 94 SK_GEPORT *pPrt; 95 96 pPrt = &pAC->GIni.GP[Port]; 97 98 /* write the PHY register's address */ 99 XM_OUT16(IoC, Port, XM_PHY_ADDR, PhyReg | pPrt->PhyAddr); 100 101 /* get the PHY register's value */ 102 XM_IN16(IoC, Port, XM_PHY_DATA, pVal); 103 104 if (pPrt->PhyType != SK_PHY_XMAC) { 105 do { 106 XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu); 107 /* wait until 'Ready' is set */ 108 } while ((Mmu & XM_MMU_PHY_RDY) == 0); 109 110 /* get the PHY register's value */ 111 XM_IN16(IoC, Port, XM_PHY_DATA, pVal); 112 } 113} /* SkXmPhyRead */ 114 115 116/****************************************************************************** 117 * 118 * SkXmPhyWrite() - Write to XMAC PHY register 119 * 120 * Description: writes a 16-bit word to XMAC PHY or ext. PHY 121 * 122 * Returns: 123 * nothing 124 */ 125void SkXmPhyWrite( 126SK_AC *pAC, /* Adapter Context */ 127SK_IOC IoC, /* I/O Context */ 128int Port, /* Port Index (MAC_1 + n) */ 129int PhyReg, /* Register Address (Offset) */ 130SK_U16 Val) /* Value */ 131{ 132 SK_U16 Mmu; 133 SK_GEPORT *pPrt; 134 135 pPrt = &pAC->GIni.GP[Port]; 136 137 if (pPrt->PhyType != SK_PHY_XMAC) { 138 do { 139 XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu); 140 /* wait until 'Busy' is cleared */ 141 } while ((Mmu & XM_MMU_PHY_BUSY) != 0); 142 } 143 144 /* write the PHY register's address */ 145 XM_OUT16(IoC, Port, XM_PHY_ADDR, PhyReg | pPrt->PhyAddr); 146 147 /* write the PHY register's value */ 148 XM_OUT16(IoC, Port, XM_PHY_DATA, Val); 149 150 if (pPrt->PhyType != SK_PHY_XMAC) { 151 do { 152 XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu); 153 /* wait until 'Busy' is cleared */ 154 } while ((Mmu & XM_MMU_PHY_BUSY) != 0); 155 } 156} /* SkXmPhyWrite */ 157#endif /* GENESIS */ 158 159 160#ifdef YUKON 161/****************************************************************************** 162 * 163 * SkGmPhyRead() - Read from GPHY register 164 * 165 * Description: reads a 16-bit word from GPHY through MDIO 166 * 167 * Returns: 168 * nothing 169 */ 170void SkGmPhyRead( 171SK_AC *pAC, /* Adapter Context */ 172SK_IOC IoC, /* I/O Context */ 173int Port, /* Port Index (MAC_1 + n) */ 174int PhyReg, /* Register Address (Offset) */ 175SK_U16 SK_FAR *pVal) /* Pointer to Value */ 176{ 177 SK_U16 Ctrl; 178 SK_GEPORT *pPrt; 179#ifdef VCPU 180 u_long SimCyle; 181 u_long SimLowTime; 182 183 VCPUgetTime(&SimCyle, &SimLowTime); 184 VCPUprintf(0, "SkGmPhyRead(%u), SimCyle=%u, SimLowTime=%u\n", 185 PhyReg, SimCyle, SimLowTime); 186#endif /* VCPU */ 187 188 pPrt = &pAC->GIni.GP[Port]; 189 190 /* set PHY-Register offset and 'Read' OpCode (= 1) */ 191 *pVal = (SK_U16)(GM_SMI_CT_PHY_AD(pPrt->PhyAddr) | 192 GM_SMI_CT_REG_AD(PhyReg) | GM_SMI_CT_OP_RD); 193 194 GM_OUT16(IoC, Port, GM_SMI_CTRL, *pVal); 195 196 GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl); 197 198 /* additional check for MDC/MDIO activity */ 199 if ((Ctrl & GM_SMI_CT_BUSY) == 0) { 200 *pVal = 0; 201 return; 202 } 203 204 *pVal |= GM_SMI_CT_BUSY; 205 206 do { 207#ifdef VCPU 208 VCPUwaitTime(1000); 209#endif /* VCPU */ 210 211 GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl); 212 213 /* wait until 'ReadValid' is set */ 214 } while (Ctrl == *pVal); 215 216 /* get the PHY register's value */ 217 GM_IN16(IoC, Port, GM_SMI_DATA, pVal); 218 219#ifdef VCPU 220 VCPUgetTime(&SimCyle, &SimLowTime); 221 VCPUprintf(0, "VCPUgetTime(), SimCyle=%u, SimLowTime=%u\n", 222 SimCyle, SimLowTime); 223#endif /* VCPU */ 224 225} /* SkGmPhyRead */ 226 227 228/****************************************************************************** 229 * 230 * SkGmPhyWrite() - Write to GPHY register 231 * 232 * Description: writes a 16-bit word to GPHY through MDIO 233 * 234 * Returns: 235 * nothing 236 */ 237void SkGmPhyWrite( 238SK_AC *pAC, /* Adapter Context */ 239SK_IOC IoC, /* I/O Context */ 240int Port, /* Port Index (MAC_1 + n) */ 241int PhyReg, /* Register Address (Offset) */ 242SK_U16 Val) /* Value */ 243{ 244 SK_U16 Ctrl; 245 SK_GEPORT *pPrt; 246#ifdef VCPU 247 SK_U32 DWord; 248 u_long SimCyle; 249 u_long SimLowTime; 250 251 VCPUgetTime(&SimCyle, &SimLowTime); 252 VCPUprintf(0, "SkGmPhyWrite(Reg=%u, Val=0x%04x), SimCyle=%u, SimLowTime=%u\n", 253 PhyReg, Val, SimCyle, SimLowTime); 254#endif /* VCPU */ 255 256 pPrt = &pAC->GIni.GP[Port]; 257 258 /* write the PHY register's value */ 259 GM_OUT16(IoC, Port, GM_SMI_DATA, Val); 260 261 /* set PHY-Register offset and 'Write' OpCode (= 0) */ 262 Val = GM_SMI_CT_PHY_AD(pPrt->PhyAddr) | GM_SMI_CT_REG_AD(PhyReg); 263 264 GM_OUT16(IoC, Port, GM_SMI_CTRL, Val); 265 266 GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl); 267 268 /* additional check for MDC/MDIO activity */ 269 if ((Ctrl & GM_SMI_CT_BUSY) == 0) { 270 return; 271 } 272 273 Val |= GM_SMI_CT_BUSY; 274 275 do { 276#ifdef VCPU 277 /* read Timer value */ 278 SK_IN32(IoC, B2_TI_VAL, &DWord); 279 280 VCPUwaitTime(1000); 281#endif /* VCPU */ 282 283 GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl); 284 285 /* wait until 'Busy' is cleared */ 286 } while (Ctrl == Val); 287 288#ifdef VCPU 289 VCPUgetTime(&SimCyle, &SimLowTime); 290 VCPUprintf(0, "VCPUgetTime(), SimCyle=%u, SimLowTime=%u\n", 291 SimCyle, SimLowTime); 292#endif /* VCPU */ 293 294} /* SkGmPhyWrite */ 295#endif /* YUKON */ 296 297 298#ifdef SK_DIAG 299/****************************************************************************** 300 * 301 * SkGePhyRead() - Read from PHY register 302 * 303 * Description: calls a read PHY routine dep. on board type 304 * 305 * Returns: 306 * nothing 307 */ 308void SkGePhyRead( 309SK_AC *pAC, /* Adapter Context */ 310SK_IOC IoC, /* I/O Context */ 311int Port, /* Port Index (MAC_1 + n) */ 312int PhyReg, /* Register Address (Offset) */ 313SK_U16 *pVal) /* Pointer to Value */ 314{ 315 void (*r_func)(SK_AC *pAC, SK_IOC IoC, int Port, int Reg, SK_U16 *pVal); 316 317 if (pAC->GIni.GIGenesis) { 318 r_func = SkXmPhyRead; 319 } 320 else { 321 r_func = SkGmPhyRead; 322 } 323 324 r_func(pAC, IoC, Port, PhyReg, pVal); 325} /* SkGePhyRead */ 326 327 328/****************************************************************************** 329 * 330 * SkGePhyWrite() - Write to PHY register 331 * 332 * Description: calls a write PHY routine dep. on board type 333 * 334 * Returns: 335 * nothing 336 */ 337void SkGePhyWrite( 338SK_AC *pAC, /* Adapter Context */ 339SK_IOC IoC, /* I/O Context */ 340int Port, /* Port Index (MAC_1 + n) */ 341int PhyReg, /* Register Address (Offset) */ 342SK_U16 Val) /* Value */ 343{ 344 void (*w_func)(SK_AC *pAC, SK_IOC IoC, int Port, int Reg, SK_U16 Val); 345 346 if (pAC->GIni.GIGenesis) { 347 w_func = SkXmPhyWrite; 348 } 349 else { 350 w_func = SkGmPhyWrite; 351 } 352 353 w_func(pAC, IoC, Port, PhyReg, Val); 354} /* SkGePhyWrite */ 355#endif /* SK_DIAG */ 356 357 358/****************************************************************************** 359 * 360 * SkMacPromiscMode() - Enable / Disable Promiscuous Mode 361 * 362 * Description: 363 * enables / disables promiscuous mode by setting Mode Register (XMAC) or 364 * Receive Control Register (GMAC) dep. on board type 365 * 366 * Returns: 367 * nothing 368 */ 369void SkMacPromiscMode( 370SK_AC *pAC, /* adapter context */ 371SK_IOC IoC, /* IO context */ 372int Port, /* Port Index (MAC_1 + n) */ 373SK_BOOL Enable) /* Enable / Disable */ 374{ 375#ifdef YUKON 376 SK_U16 RcReg; 377#endif 378#ifdef GENESIS 379 SK_U32 MdReg; 380#endif 381 382#ifdef GENESIS 383 if (pAC->GIni.GIGenesis) { 384 385 XM_IN32(IoC, Port, XM_MODE, &MdReg); 386 /* enable or disable promiscuous mode */ 387 if (Enable) { 388 MdReg |= XM_MD_ENA_PROM; 389 } 390 else { 391 MdReg &= ~XM_MD_ENA_PROM; 392 } 393 /* setup Mode Register */ 394 XM_OUT32(IoC, Port, XM_MODE, MdReg); 395 } 396#endif /* GENESIS */ 397 398#ifdef YUKON 399 if (pAC->GIni.GIYukon) { 400 401 GM_IN16(IoC, Port, GM_RX_CTRL, &RcReg); 402 403 /* enable or disable unicast and multicast filtering */ 404 if (Enable) { 405 RcReg &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA); 406 } 407 else { 408 RcReg |= (GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA); 409 } 410 /* setup Receive Control Register */ 411 GM_OUT16(IoC, Port, GM_RX_CTRL, RcReg); 412 } 413#endif /* YUKON */ 414 415} /* SkMacPromiscMode*/ 416 417 418/****************************************************************************** 419 * 420 * SkMacHashing() - Enable / Disable Hashing 421 * 422 * Description: 423 * enables / disables hashing by setting Mode Register (XMAC) or 424 * Receive Control Register (GMAC) dep. on board type 425 * 426 * Returns: 427 * nothing 428 */ 429void SkMacHashing( 430SK_AC *pAC, /* adapter context */ 431SK_IOC IoC, /* IO context */ 432int Port, /* Port Index (MAC_1 + n) */ 433SK_BOOL Enable) /* Enable / Disable */ 434{ 435#ifdef YUKON 436 SK_U16 RcReg; 437#endif 438#ifdef GENESIS 439 SK_U32 MdReg; 440#endif 441 442#ifdef GENESIS 443 if (pAC->GIni.GIGenesis) { 444 445 XM_IN32(IoC, Port, XM_MODE, &MdReg); 446 /* enable or disable hashing */ 447 if (Enable) { 448 MdReg |= XM_MD_ENA_HASH; 449 } 450 else { 451 MdReg &= ~XM_MD_ENA_HASH; 452 } 453 /* setup Mode Register */ 454 XM_OUT32(IoC, Port, XM_MODE, MdReg); 455 } 456#endif /* GENESIS */ 457 458#ifdef YUKON 459 if (pAC->GIni.GIYukon) { 460 461 GM_IN16(IoC, Port, GM_RX_CTRL, &RcReg); 462 463 /* enable or disable multicast filtering */ 464 if (Enable) { 465 RcReg |= GM_RXCR_MCF_ENA; 466 } 467 else { 468 RcReg &= ~GM_RXCR_MCF_ENA; 469 } 470 /* setup Receive Control Register */ 471 GM_OUT16(IoC, Port, GM_RX_CTRL, RcReg); 472 } 473#endif /* YUKON */ 474 475} /* SkMacHashing*/ 476 477 478#ifdef SK_DIAG 479/****************************************************************************** 480 * 481 * SkXmSetRxCmd() - Modify the value of the XMAC's Rx Command Register 482 * 483 * Description: 484 * The features 485 * - FCS stripping, SK_STRIP_FCS_ON/OFF 486 * - pad byte stripping, SK_STRIP_PAD_ON/OFF 487 * - don't set XMR_FS_ERR in status SK_LENERR_OK_ON/OFF 488 * for inrange length error frames 489 * - don't set XMR_FS_ERR in status SK_BIG_PK_OK_ON/OFF 490 * for frames > 1514 bytes 491 * - enable Rx of own packets SK_SELF_RX_ON/OFF 492 * 493 * for incoming packets may be enabled/disabled by this function. 494 * Additional modes may be added later. 495 * Multiple modes can be enabled/disabled at the same time. 496 * The new configuration is written to the Rx Command register immediately. 497 * 498 * Returns: 499 * nothing 500 */ 501static void SkXmSetRxCmd( 502SK_AC *pAC, /* adapter context */ 503SK_IOC IoC, /* IO context */ 504int Port, /* Port Index (MAC_1 + n) */ 505int Mode) /* Mode is SK_STRIP_FCS_ON/OFF, SK_STRIP_PAD_ON/OFF, 506 SK_LENERR_OK_ON/OFF, or SK_BIG_PK_OK_ON/OFF */ 507{ 508 SK_U16 OldRxCmd; 509 SK_U16 RxCmd; 510 511 XM_IN16(IoC, Port, XM_RX_CMD, &OldRxCmd); 512 513 RxCmd = OldRxCmd; 514 515 switch (Mode & (SK_STRIP_FCS_ON | SK_STRIP_FCS_OFF)) { 516 case SK_STRIP_FCS_ON: 517 RxCmd |= XM_RX_STRIP_FCS; 518 break; 519 case SK_STRIP_FCS_OFF: 520 RxCmd &= ~XM_RX_STRIP_FCS; 521 break; 522 } 523 524 switch (Mode & (SK_STRIP_PAD_ON | SK_STRIP_PAD_OFF)) { 525 case SK_STRIP_PAD_ON: 526 RxCmd |= XM_RX_STRIP_PAD; 527 break; 528 case SK_STRIP_PAD_OFF: 529 RxCmd &= ~XM_RX_STRIP_PAD; 530 break; 531 } 532 533 switch (Mode & (SK_LENERR_OK_ON | SK_LENERR_OK_OFF)) { 534 case SK_LENERR_OK_ON: 535 RxCmd |= XM_RX_LENERR_OK; 536 break; 537 case SK_LENERR_OK_OFF: 538 RxCmd &= ~XM_RX_LENERR_OK; 539 break; 540 } 541 542 switch (Mode & (SK_BIG_PK_OK_ON | SK_BIG_PK_OK_OFF)) { 543 case SK_BIG_PK_OK_ON: 544 RxCmd |= XM_RX_BIG_PK_OK; 545 break; 546 case SK_BIG_PK_OK_OFF: 547 RxCmd &= ~XM_RX_BIG_PK_OK; 548 break; 549 } 550 551 switch (Mode & (SK_SELF_RX_ON | SK_SELF_RX_OFF)) { 552 case SK_SELF_RX_ON: 553 RxCmd |= XM_RX_SELF_RX; 554 break; 555 case SK_SELF_RX_OFF: 556 RxCmd &= ~XM_RX_SELF_RX; 557 break; 558 } 559 560 /* Write the new mode to the Rx command register if required */ 561 if (OldRxCmd != RxCmd) { 562 XM_OUT16(IoC, Port, XM_RX_CMD, RxCmd); 563 } 564} /* SkXmSetRxCmd */ 565 566 567/****************************************************************************** 568 * 569 * SkGmSetRxCmd() - Modify the value of the GMAC's Rx Control Register 570 * 571 * Description: 572 * The features 573 * - FCS (CRC) stripping, SK_STRIP_FCS_ON/OFF 574 * - don't set GMR_FS_LONG_ERR SK_BIG_PK_OK_ON/OFF 575 * for frames > 1514 bytes 576 * - enable Rx of own packets SK_SELF_RX_ON/OFF 577 * 578 * for incoming packets may be enabled/disabled by this function. 579 * Additional modes may be added later. 580 * Multiple modes can be enabled/disabled at the same time. 581 * The new configuration is written to the Rx Command register immediately. 582 * 583 * Returns: 584 * nothing 585 */ 586static void SkGmSetRxCmd( 587SK_AC *pAC, /* adapter context */ 588SK_IOC IoC, /* IO context */ 589int Port, /* Port Index (MAC_1 + n) */ 590int Mode) /* Mode is SK_STRIP_FCS_ON/OFF, SK_STRIP_PAD_ON/OFF, 591 SK_LENERR_OK_ON/OFF, or SK_BIG_PK_OK_ON/OFF */ 592{ 593 SK_U16 OldRxCmd; 594 SK_U16 RxCmd; 595 596 if ((Mode & (SK_STRIP_FCS_ON | SK_STRIP_FCS_OFF)) != 0) { 597 598 GM_IN16(IoC, Port, GM_RX_CTRL, &OldRxCmd); 599 600 RxCmd = OldRxCmd; 601 602 if ((Mode & SK_STRIP_FCS_ON) != 0) { 603 RxCmd |= GM_RXCR_CRC_DIS; 604 } 605 else { 606 RxCmd &= ~GM_RXCR_CRC_DIS; 607 } 608 /* Write the new mode to the Rx control register if required */ 609 if (OldRxCmd != RxCmd) { 610 GM_OUT16(IoC, Port, GM_RX_CTRL, RxCmd); 611 } 612 } 613 614 if ((Mode & (SK_BIG_PK_OK_ON | SK_BIG_PK_OK_OFF)) != 0) { 615 616 GM_IN16(IoC, Port, GM_SERIAL_MODE, &OldRxCmd); 617 618 RxCmd = OldRxCmd; 619 620 if ((Mode & SK_BIG_PK_OK_ON) != 0) { 621 RxCmd |= GM_SMOD_JUMBO_ENA; 622 } 623 else { 624 RxCmd &= ~GM_SMOD_JUMBO_ENA; 625 } 626 /* Write the new mode to the Rx control register if required */ 627 if (OldRxCmd != RxCmd) { 628 GM_OUT16(IoC, Port, GM_SERIAL_MODE, RxCmd); 629 } 630 } 631} /* SkGmSetRxCmd */ 632 633 634/****************************************************************************** 635 * 636 * SkMacSetRxCmd() - Modify the value of the MAC's Rx Control Register 637 * 638 * Description: modifies the MAC's Rx Control reg. dep. on board type 639 * 640 * Returns: 641 * nothing 642 */ 643void SkMacSetRxCmd( 644SK_AC *pAC, /* adapter context */ 645SK_IOC IoC, /* IO context */ 646int Port, /* Port Index (MAC_1 + n) */ 647int Mode) /* Rx Mode */ 648{ 649 if (pAC->GIni.GIGenesis) { 650 651 SkXmSetRxCmd(pAC, IoC, Port, Mode); 652 } 653 else { 654 655 SkGmSetRxCmd(pAC, IoC, Port, Mode); 656 } 657 658} /* SkMacSetRxCmd */ 659 660 661/****************************************************************************** 662 * 663 * SkMacCrcGener() - Enable / Disable CRC Generation 664 * 665 * Description: enables / disables CRC generation dep. on board type 666 * 667 * Returns: 668 * nothing 669 */ 670void SkMacCrcGener( 671SK_AC *pAC, /* adapter context */ 672SK_IOC IoC, /* IO context */ 673int Port, /* Port Index (MAC_1 + n) */ 674SK_BOOL Enable) /* Enable / Disable */ 675{ 676 SK_U16 Word; 677 678 if (pAC->GIni.GIGenesis) { 679 680 XM_IN16(IoC, Port, XM_TX_CMD, &Word); 681 682 if (Enable) { 683 Word &= ~XM_TX_NO_CRC; 684 } 685 else { 686 Word |= XM_TX_NO_CRC; 687 } 688 /* setup Tx Command Register */ 689 XM_OUT16(IoC, Port, XM_TX_CMD, Word); 690 } 691 else { 692 693 GM_IN16(IoC, Port, GM_TX_CTRL, &Word); 694 695 if (Enable) { 696 Word &= ~GM_TXCR_CRC_DIS; 697 } 698 else { 699 Word |= GM_TXCR_CRC_DIS; 700 } 701 /* setup Tx Control Register */ 702 GM_OUT16(IoC, Port, GM_TX_CTRL, Word); 703 } 704 705} /* SkMacCrcGener*/ 706 707#endif /* SK_DIAG */ 708 709 710#ifdef GENESIS 711/****************************************************************************** 712 * 713 * SkXmClrExactAddr() - Clear Exact Match Address Registers 714 * 715 * Description: 716 * All Exact Match Address registers of the XMAC 'Port' will be 717 * cleared starting with 'StartNum' up to (and including) the 718 * Exact Match address number of 'StopNum'. 719 * 720 * Returns: 721 * nothing 722 */ 723void SkXmClrExactAddr( 724SK_AC *pAC, /* adapter context */ 725SK_IOC IoC, /* IO context */ 726int Port, /* Port Index (MAC_1 + n) */ 727int StartNum, /* Begin with this Address Register Index (0..15) */ 728int StopNum) /* Stop after finished with this Register Idx (0..15) */ 729{ 730 int i; 731 SK_U16 ZeroAddr[3] = {0x0000, 0x0000, 0x0000}; 732 733 if ((unsigned)StartNum > 15 || (unsigned)StopNum > 15 || 734 StartNum > StopNum) { 735 736 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E001, SKERR_HWI_E001MSG); 737 return; 738 } 739 740 for (i = StartNum; i <= StopNum; i++) { 741 XM_OUTADDR(IoC, Port, XM_EXM(i), &ZeroAddr[0]); 742 } 743} /* SkXmClrExactAddr */ 744#endif /* GENESIS */ 745 746 747/****************************************************************************** 748 * 749 * SkMacFlushTxFifo() - Flush the MAC's transmit FIFO 750 * 751 * Description: 752 * Flush the transmit FIFO of the MAC specified by the index 'Port' 753 * 754 * Returns: 755 * nothing 756 */ 757void SkMacFlushTxFifo( 758SK_AC *pAC, /* adapter context */ 759SK_IOC IoC, /* IO context */ 760int Port) /* Port Index (MAC_1 + n) */ 761{ 762#ifdef GENESIS 763 SK_U32 MdReg; 764 765 if (pAC->GIni.GIGenesis) { 766 767 XM_IN32(IoC, Port, XM_MODE, &MdReg); 768 769 XM_OUT32(IoC, Port, XM_MODE, MdReg | XM_MD_FTF); 770 } 771#endif /* GENESIS */ 772 773#ifdef YUKON 774 if (pAC->GIni.GIYukon) { 775 /* no way to flush the FIFO we have to issue a reset */ 776 /* TBD */ 777 } 778#endif /* YUKON */ 779 780} /* SkMacFlushTxFifo */ 781 782 783/****************************************************************************** 784 * 785 * SkMacFlushRxFifo() - Flush the MAC's receive FIFO 786 * 787 * Description: 788 * Flush the receive FIFO of the MAC specified by the index 'Port' 789 * 790 * Returns: 791 * nothing 792 */ 793static void SkMacFlushRxFifo( 794SK_AC *pAC, /* adapter context */ 795SK_IOC IoC, /* IO context */ 796int Port) /* Port Index (MAC_1 + n) */ 797{ 798#ifdef GENESIS 799 SK_U32 MdReg; 800 801 if (pAC->GIni.GIGenesis) { 802 803 XM_IN32(IoC, Port, XM_MODE, &MdReg); 804 805 XM_OUT32(IoC, Port, XM_MODE, MdReg | XM_MD_FRF); 806 } 807#endif /* GENESIS */ 808 809#ifdef YUKON 810 if (pAC->GIni.GIYukon) { 811 /* no way to flush the FIFO we have to issue a reset */ 812 /* TBD */ 813 } 814#endif /* YUKON */ 815 816} /* SkMacFlushRxFifo */ 817 818 819#ifdef GENESIS 820/****************************************************************************** 821 * 822 * SkXmSoftRst() - Do a XMAC software reset 823 * 824 * Description: 825 * The PHY registers should not be destroyed during this 826 * kind of software reset. Therefore the XMAC Software Reset 827 * (XM_GP_RES_MAC bit in XM_GP_PORT) must not be used! 828 * 829 * The software reset is done by 830 * - disabling the Rx and Tx state machine, 831 * - resetting the statistics module, 832 * - clear all other significant XMAC Mode, 833 * Command, and Control Registers 834 * - clearing the Hash Register and the 835 * Exact Match Address registers, and 836 * - flushing the XMAC's Rx and Tx FIFOs. 837 * 838 * Note: 839 * Another requirement when stopping the XMAC is to 840 * avoid sending corrupted frames on the network. 841 * Disabling the Tx state machine will NOT interrupt 842 * the currently transmitted frame. But we must take care 843 * that the Tx FIFO is cleared AFTER the current frame 844 * is complete sent to the network. 845 * 846 * It takes about 12ns to send a frame with 1538 bytes. 847 * One PCI clock goes at least 15ns (66MHz). Therefore 848 * after reading XM_GP_PORT back, we are sure that the 849 * transmitter is disabled AND idle. And this means 850 * we may flush the transmit FIFO now. 851 * 852 * Returns: 853 * nothing 854 */ 855static void SkXmSoftRst( 856SK_AC *pAC, /* adapter context */ 857SK_IOC IoC, /* IO context */ 858int Port) /* Port Index (MAC_1 + n) */ 859{ 860 SK_U16 ZeroAddr[4] = {0x0000, 0x0000, 0x0000, 0x0000}; 861 862 /* reset the statistics module */ 863 XM_OUT32(IoC, Port, XM_GP_PORT, XM_GP_RES_STAT); 864 865 /* disable all XMAC IRQs */ 866 XM_OUT16(IoC, Port, XM_IMSK, 0xffff); 867 868 XM_OUT32(IoC, Port, XM_MODE, 0); /* clear Mode Reg */ 869 870 XM_OUT16(IoC, Port, XM_TX_CMD, 0); /* reset TX CMD Reg */ 871 XM_OUT16(IoC, Port, XM_RX_CMD, 0); /* reset RX CMD Reg */ 872 873 /* disable all PHY IRQs */ 874 switch (pAC->GIni.GP[Port].PhyType) { 875 case SK_PHY_BCOM: 876 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, 0xffff); 877 break; 878#ifdef OTHER_PHY 879 case SK_PHY_LONE: 880 SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, 0); 881 break; 882 case SK_PHY_NAT: 883 /* todo: National 884 SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, 0xffff); */ 885 break; 886#endif /* OTHER_PHY */ 887 } 888 889 /* clear the Hash Register */ 890 XM_OUTHASH(IoC, Port, XM_HSM, &ZeroAddr); 891 892 /* clear the Exact Match Address registers */ 893 SkXmClrExactAddr(pAC, IoC, Port, 0, 15); 894 895 /* clear the Source Check Address registers */ 896 XM_OUTHASH(IoC, Port, XM_SRC_CHK, &ZeroAddr); 897 898} /* SkXmSoftRst */ 899 900 901/****************************************************************************** 902 * 903 * SkXmHardRst() - Do a XMAC hardware reset 904 * 905 * Description: 906 * The XMAC of the specified 'Port' and all connected devices 907 * (PHY and SERDES) will receive a reset signal on its *Reset pins. 908 * External PHYs must be reset by clearing a bit in the GPIO register 909 * (Timing requirements: Broadcom: 400ns, Level One: none, National: 80ns). 910 * 911 * ATTENTION: 912 * It is absolutely necessary to reset the SW_RST Bit first 913 * before calling this function. 914 * 915 * Returns: 916 * nothing 917 */ 918static void SkXmHardRst( 919SK_AC *pAC, /* adapter context */ 920SK_IOC IoC, /* IO context */ 921int Port) /* Port Index (MAC_1 + n) */ 922{ 923 SK_U32 Reg; 924 int i; 925 int TOut; 926 SK_U16 Word; 927 928 for (i = 0; i < 4; i++) { 929 /* TX_MFF_CTRL1 has 32 bits, but only the lowest 16 bits are used */ 930 SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_MAC_RST); 931 932 TOut = 0; 933 do { 934 if (TOut++ > 10000) { 935 /* 936 * Adapter seems to be in RESET state. 937 * Registers cannot be written. 938 */ 939 return; 940 } 941 942 SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_SET_MAC_RST); 943 944 SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &Word); 945 946 } while ((Word & MFF_SET_MAC_RST) == 0); 947 } 948 949 /* For external PHYs there must be special handling */ 950 if (pAC->GIni.GP[Port].PhyType != SK_PHY_XMAC) { 951 952 SK_IN32(IoC, B2_GP_IO, &Reg); 953 954 if (Port == 0) { 955 Reg |= GP_DIR_0; /* set to output */ 956 Reg &= ~GP_IO_0; /* set PHY reset (active low) */ 957 } 958 else { 959 Reg |= GP_DIR_2; /* set to output */ 960 Reg &= ~GP_IO_2; /* set PHY reset (active low) */ 961 } 962 /* reset external PHY */ 963 SK_OUT32(IoC, B2_GP_IO, Reg); 964 965 /* short delay */ 966 SK_IN32(IoC, B2_GP_IO, &Reg); 967 } 968} /* SkXmHardRst */ 969 970 971/****************************************************************************** 972 * 973 * SkXmClearRst() - Release the PHY & XMAC reset 974 * 975 * Description: 976 * 977 * Returns: 978 * nothing 979 */ 980static void SkXmClearRst( 981SK_AC *pAC, /* adapter context */ 982SK_IOC IoC, /* IO context */ 983int Port) /* Port Index (MAC_1 + n) */ 984{ 985 SK_U32 DWord; 986 987 /* clear HW reset */ 988 SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_MAC_RST); 989 990 if (pAC->GIni.GP[Port].PhyType != SK_PHY_XMAC) { 991 992 SK_IN32(IoC, B2_GP_IO, &DWord); 993 994 if (Port == 0) { 995 DWord |= (GP_DIR_0 | GP_IO_0); /* set to output */ 996 } 997 else { 998 DWord |= (GP_DIR_2 | GP_IO_2); /* set to output */ 999 } 1000 /* Clear PHY reset */ 1001 SK_OUT32(IoC, B2_GP_IO, DWord); 1002 1003 /* Enable GMII interface */ 1004 XM_OUT16(IoC, Port, XM_HW_CFG, XM_HW_GMII_MD); 1005 } 1006} /* SkXmClearRst */ 1007#endif /* GENESIS */ 1008 1009 1010#ifdef YUKON 1011/****************************************************************************** 1012 * 1013 * SkGmSoftRst() - Do a GMAC software reset 1014 * 1015 * Description: 1016 * The GPHY registers should not be destroyed during this 1017 * kind of software reset. 1018 * 1019 * Returns: 1020 * nothing 1021 */ 1022static void SkGmSoftRst( 1023SK_AC *pAC, /* adapter context */ 1024SK_IOC IoC, /* IO context */ 1025int Port) /* Port Index (MAC_1 + n) */ 1026{ 1027 SK_U16 EmptyHash[4] = {0x0000, 0x0000, 0x0000, 0x0000}; 1028 SK_U16 RxCtrl; 1029 1030 /* reset the statistics module */ 1031 1032 /* disable all GMAC IRQs */ 1033 SK_OUT8(IoC, GMAC_IRQ_MSK, 0); 1034 1035 /* disable all PHY IRQs */ 1036 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, 0); 1037 1038 /* clear the Hash Register */ 1039 GM_OUTHASH(IoC, Port, GM_MC_ADDR_H1, EmptyHash); 1040 1041 /* Enable Unicast and Multicast filtering */ 1042 GM_IN16(IoC, Port, GM_RX_CTRL, &RxCtrl); 1043 1044 GM_OUT16(IoC, Port, GM_RX_CTRL, 1045 (SK_U16)(RxCtrl | GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA)); 1046 1047} /* SkGmSoftRst */ 1048 1049 1050/****************************************************************************** 1051 * 1052 * SkGmHardRst() - Do a GMAC hardware reset 1053 * 1054 * Description: 1055 * 1056 * Returns: 1057 * nothing 1058 */ 1059static void SkGmHardRst( 1060SK_AC *pAC, /* adapter context */ 1061SK_IOC IoC, /* IO context */ 1062int Port) /* Port Index (MAC_1 + n) */ 1063{ 1064 SK_U32 DWord; 1065 1066 /* WA code for COMA mode */ 1067 if (pAC->GIni.GIYukonLite && 1068 pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) { 1069 1070 SK_IN32(IoC, B2_GP_IO, &DWord); 1071 1072 DWord |= (GP_DIR_9 | GP_IO_9); 1073 1074 /* set PHY reset */ 1075 SK_OUT32(IoC, B2_GP_IO, DWord); 1076 } 1077 1078 /* set GPHY Control reset */ 1079 SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), GPC_RST_SET); 1080 1081 /* set GMAC Control reset */ 1082 SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET); 1083 1084} /* SkGmHardRst */ 1085 1086 1087/****************************************************************************** 1088 * 1089 * SkGmClearRst() - Release the GPHY & GMAC reset 1090 * 1091 * Description: 1092 * 1093 * Returns: 1094 * nothing 1095 */ 1096static void SkGmClearRst( 1097SK_AC *pAC, /* adapter context */ 1098SK_IOC IoC, /* IO context */ 1099int Port) /* Port Index (MAC_1 + n) */ 1100{ 1101 SK_U32 DWord; 1102 1103#ifdef XXX 1104 /* clear GMAC Control reset */ 1105 SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_CLR); 1106 1107 /* set GMAC Control reset */ 1108 SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET); 1109#endif 1110 1111 /* WA code for COMA mode */ 1112 if (pAC->GIni.GIYukonLite && 1113 pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) { 1114 1115 SK_IN32(IoC, B2_GP_IO, &DWord); 1116 1117 DWord |= GP_DIR_9; /* set to output */ 1118 DWord &= ~GP_IO_9; /* clear PHY reset (active high) */ 1119 1120 /* clear PHY reset */ 1121 SK_OUT32(IoC, B2_GP_IO, DWord); 1122 } 1123 1124 /* set HWCFG_MODE */ 1125 DWord = GPC_INT_POL_HI | GPC_DIS_FC | GPC_DIS_SLEEP | 1126 GPC_ENA_XC | GPC_ANEG_ADV_ALL_M | GPC_ENA_PAUSE | 1127 (pAC->GIni.GICopperType ? GPC_HWCFG_GMII_COP : 1128 GPC_HWCFG_GMII_FIB); 1129 1130 /* set GPHY Control reset */ 1131 SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_SET); 1132 1133 /* release GPHY Control reset */ 1134 SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_CLR); 1135 1136#ifdef VCPU 1137 VCpuWait(9000); 1138#endif /* VCPU */ 1139 1140 /* clear GMAC Control reset */ 1141 SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_PAUSE_ON | GMC_RST_CLR); 1142 1143#ifdef VCPU 1144 VCpuWait(2000); 1145 1146 SK_IN32(IoC, MR_ADDR(Port, GPHY_CTRL), &DWord); 1147 1148 SK_IN32(IoC, B0_ISRC, &DWord); 1149#endif /* VCPU */ 1150 1151} /* SkGmClearRst */ 1152#endif /* YUKON */ 1153 1154 1155/****************************************************************************** 1156 * 1157 * SkMacSoftRst() - Do a MAC software reset 1158 * 1159 * Description: calls a MAC software reset routine dep. on board type 1160 * 1161 * Returns: 1162 * nothing 1163 */ 1164void SkMacSoftRst( 1165SK_AC *pAC, /* adapter context */ 1166SK_IOC IoC, /* IO context */ 1167int Port) /* Port Index (MAC_1 + n) */ 1168{ 1169 SK_GEPORT *pPrt; 1170 1171 pPrt = &pAC->GIni.GP[Port]; 1172 1173 /* disable receiver and transmitter */ 1174 SkMacRxTxDisable(pAC, IoC, Port); 1175 1176#ifdef GENESIS 1177 if (pAC->GIni.GIGenesis) { 1178 1179 SkXmSoftRst(pAC, IoC, Port); 1180 } 1181#endif /* GENESIS */ 1182 1183#ifdef YUKON 1184 if (pAC->GIni.GIYukon) { 1185 1186 SkGmSoftRst(pAC, IoC, Port); 1187 } 1188#endif /* YUKON */ 1189 1190 /* flush the MAC's Rx and Tx FIFOs */ 1191 SkMacFlushTxFifo(pAC, IoC, Port); 1192 1193 SkMacFlushRxFifo(pAC, IoC, Port); 1194 1195 pPrt->PState = SK_PRT_STOP; 1196 1197} /* SkMacSoftRst */ 1198 1199 1200/****************************************************************************** 1201 * 1202 * SkMacHardRst() - Do a MAC hardware reset 1203 * 1204 * Description: calls a MAC hardware reset routine dep. on board type 1205 * 1206 * Returns: 1207 * nothing 1208 */ 1209void SkMacHardRst( 1210SK_AC *pAC, /* adapter context */ 1211SK_IOC IoC, /* IO context */ 1212int Port) /* Port Index (MAC_1 + n) */ 1213{ 1214 1215#ifdef GENESIS 1216 if (pAC->GIni.GIGenesis) { 1217 1218 SkXmHardRst(pAC, IoC, Port); 1219 } 1220#endif /* GENESIS */ 1221 1222#ifdef YUKON 1223 if (pAC->GIni.GIYukon) { 1224 1225 SkGmHardRst(pAC, IoC, Port); 1226 } 1227#endif /* YUKON */ 1228 1229 pAC->GIni.GP[Port].PState = SK_PRT_RESET; 1230 1231} /* SkMacHardRst */ 1232 1233 1234#ifdef GENESIS 1235/****************************************************************************** 1236 * 1237 * SkXmInitMac() - Initialize the XMAC II 1238 * 1239 * Description: 1240 * Initialize the XMAC of the specified port. 1241 * The XMAC must be reset or stopped before calling this function. 1242 * 1243 * Note: 1244 * The XMAC's Rx and Tx state machine is still disabled when returning. 1245 * 1246 * Returns: 1247 * nothing 1248 */ 1249void SkXmInitMac( 1250SK_AC *pAC, /* adapter context */ 1251SK_IOC IoC, /* IO context */ 1252int Port) /* Port Index (MAC_1 + n) */ 1253{ 1254 SK_GEPORT *pPrt; 1255 int i; 1256 SK_U16 SWord; 1257 1258 pPrt = &pAC->GIni.GP[Port]; 1259 1260 if (pPrt->PState == SK_PRT_STOP) { 1261 /* Port State: SK_PRT_STOP */ 1262 /* Verify that the reset bit is cleared */ 1263 SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &SWord); 1264 1265 if ((SWord & MFF_SET_MAC_RST) != 0) { 1266 /* PState does not match HW state */ 1267 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E006, SKERR_HWI_E006MSG); 1268 /* Correct it */ 1269 pPrt->PState = SK_PRT_RESET; 1270 } 1271 } 1272 1273 if (pPrt->PState == SK_PRT_RESET) { 1274 1275 SkXmClearRst(pAC, IoC, Port); 1276 1277 if (pPrt->PhyType != SK_PHY_XMAC) { 1278 /* read Id from external PHY (all have the same address) */ 1279 SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_ID1, &pPrt->PhyId1); 1280 1281 /* 1282 * Optimize MDIO transfer by suppressing preamble. 1283 * Must be done AFTER first access to BCOM chip. 1284 */ 1285 XM_IN16(IoC, Port, XM_MMU_CMD, &SWord); 1286 1287 XM_OUT16(IoC, Port, XM_MMU_CMD, SWord | XM_MMU_NO_PRE); 1288 1289 if (pPrt->PhyId1 == PHY_BCOM_ID1_C0) { 1290 i = 0; 1291 while (BcomRegC0Hack[i].PhyReg != 0) { 1292 SkXmPhyWrite(pAC, IoC, Port, BcomRegC0Hack[i].PhyReg, 1293 BcomRegC0Hack[i].PhyVal); 1294 i++; 1295 } 1296 } 1297 else if (pPrt->PhyId1 == PHY_BCOM_ID1_A1) { 1298 i = 0; 1299 while (BcomRegA1Hack[i].PhyReg != 0) { 1300 SkXmPhyWrite(pAC, IoC, Port, BcomRegA1Hack[i].PhyReg, 1301 BcomRegA1Hack[i].PhyVal); 1302 i++; 1303 } 1304 } 1305 1306 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &SWord); 1307 1308 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, 1309 (SK_U16)(SWord | PHY_B_AC_DIS_PM)); 1310 1311 /* PHY LED initialization is done in SkGeXmitLED() */ 1312 } 1313 1314 /* Dummy read the Interrupt source register */ 1315 XM_IN16(IoC, Port, XM_ISRC, &SWord); 1316 1317 /* 1318 * The auto-negotiation process starts immediately after 1319 * clearing the reset. The auto-negotiation process should be 1320 * started by the SIRQ, therefore stop it here immediately. 1321 */ 1322 SkMacInitPhy(pAC, IoC, Port, SK_FALSE); 1323 1324#ifdef TEST_ONLY 1325 /* temp. code: enable signal detect */ 1326 /* WARNING: do not override GMII setting above */ 1327 XM_OUT16(IoC, Port, XM_HW_CFG, XM_HW_COM4SIG); 1328#endif 1329 } 1330 1331 /* 1332 * configure the XMACs Station Address 1333 * B2_MAC_2 = xx xx xx xx xx x1 is programmed to XMAC A 1334 * B2_MAC_3 = xx xx xx xx xx x2 is programmed to XMAC B 1335 */ 1336 for (i = 0; i < 3; i++) { 1337 /* 1338 * The following 2 statements are together endianess 1339 * independent. Remember this when changing. 1340 */ 1341 SK_IN16(IoC, (B2_MAC_2 + Port * 8 + i * 2), &SWord); 1342 1343 XM_OUT16(IoC, Port, (XM_SA + i * 2), SWord); 1344 } 1345 1346 /* Tx Inter Packet Gap (XM_TX_IPG): use default */ 1347 /* Tx High Water Mark (XM_TX_HI_WM): use default */ 1348 /* Tx Low Water Mark (XM_TX_LO_WM): use default */ 1349 /* Host Request Threshold (XM_HT_THR): use default */ 1350 /* Rx Request Threshold (XM_RX_THR): use default */ 1351 /* Rx Low Water Mark (XM_RX_LO_WM): use default */ 1352 1353 /* configure Rx High Water Mark (XM_RX_HI_WM) */ 1354 XM_OUT16(IoC, Port, XM_RX_HI_WM, SK_XM_RX_HI_WM); 1355 1356 /* Configure Tx Request Threshold */ 1357 SWord = SK_XM_THR_SL; /* for single port */ 1358 1359 if (pAC->GIni.GIMacsFound > 1) { 1360 switch (pAC->GIni.GIPortUsage) { 1361 case SK_RED_LINK: 1362 SWord = SK_XM_THR_REDL; /* redundant link */ 1363 break; 1364 case SK_MUL_LINK: 1365 SWord = SK_XM_THR_MULL; /* load balancing */ 1366 break; 1367 case SK_JUMBO_LINK: 1368 SWord = SK_XM_THR_JUMBO; /* jumbo frames */ 1369 break; 1370 default: 1371 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E014, SKERR_HWI_E014MSG); 1372 break; 1373 } 1374 } 1375 XM_OUT16(IoC, Port, XM_TX_THR, SWord); 1376 1377 /* setup register defaults for the Tx Command Register */ 1378 XM_OUT16(IoC, Port, XM_TX_CMD, XM_TX_AUTO_PAD); 1379 1380 /* setup register defaults for the Rx Command Register */ 1381 SWord = XM_RX_STRIP_FCS | XM_RX_LENERR_OK; 1382 1383 if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) { 1384 SWord |= XM_RX_BIG_PK_OK; 1385 } 1386 1387 if (pPrt->PLinkMode == SK_LMODE_HALF) { 1388 /* 1389 * If in manual half duplex mode the other side might be in 1390 * full duplex mode, so ignore if a carrier extension is not seen 1391 * on frames received 1392 */ 1393 SWord |= XM_RX_DIS_CEXT; 1394 } 1395 1396 XM_OUT16(IoC, Port, XM_RX_CMD, SWord); 1397 1398 /* 1399 * setup register defaults for the Mode Register 1400 * - Don't strip error frames to avoid Store & Forward 1401 * on the Rx side. 1402 * - Enable 'Check Station Address' bit 1403 * - Enable 'Check Address Array' bit 1404 */ 1405 XM_OUT32(IoC, Port, XM_MODE, XM_DEF_MODE); 1406 1407 /* 1408 * Initialize the Receive Counter Event Mask (XM_RX_EV_MSK) 1409 * - Enable all bits excepting 'Octets Rx OK Low CntOv' 1410 * and 'Octets Rx OK Hi Cnt Ov'. 1411 */ 1412 XM_OUT32(IoC, Port, XM_RX_EV_MSK, XMR_DEF_MSK); 1413 1414 /* 1415 * Initialize the Transmit Counter Event Mask (XM_TX_EV_MSK) 1416 * - Enable all bits excepting 'Octets Tx OK Low CntOv' 1417 * and 'Octets Tx OK Hi Cnt Ov'. 1418 */ 1419 XM_OUT32(IoC, Port, XM_TX_EV_MSK, XMT_DEF_MSK); 1420 1421 /* 1422 * Do NOT init XMAC interrupt mask here. 1423 * All interrupts remain disable until link comes up! 1424 */ 1425 1426 /* 1427 * Any additional configuration changes may be done now. 1428 * The last action is to enable the Rx and Tx state machine. 1429 * This should be done after the auto-negotiation process 1430 * has been completed successfully. 1431 */ 1432} /* SkXmInitMac */ 1433#endif /* GENESIS */ 1434 1435 1436#ifdef YUKON 1437/****************************************************************************** 1438 * 1439 * SkGmInitMac() - Initialize the GMAC 1440 * 1441 * Description: 1442 * Initialize the GMAC of the specified port. 1443 * The GMAC must be reset or stopped before calling this function. 1444 * 1445 * Note: 1446 * The GMAC's Rx and Tx state machine is still disabled when returning. 1447 * 1448 * Returns: 1449 * nothing 1450 */ 1451void SkGmInitMac( 1452SK_AC *pAC, /* adapter context */ 1453SK_IOC IoC, /* IO context */ 1454int Port) /* Port Index (MAC_1 + n) */ 1455{ 1456 SK_GEPORT *pPrt; 1457 int i; 1458 SK_U16 SWord; 1459 SK_U32 DWord; 1460 1461 pPrt = &pAC->GIni.GP[Port]; 1462 1463 if (pPrt->PState == SK_PRT_STOP) { 1464 /* Port State: SK_PRT_STOP */ 1465 /* Verify that the reset bit is cleared */ 1466 SK_IN32(IoC, MR_ADDR(Port, GMAC_CTRL), &DWord); 1467 1468 if ((DWord & GMC_RST_SET) != 0) { 1469 /* PState does not match HW state */ 1470 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E006, SKERR_HWI_E006MSG); 1471 /* Correct it */ 1472 pPrt->PState = SK_PRT_RESET; 1473 } 1474 } 1475 1476 if (pPrt->PState == SK_PRT_RESET) { 1477 1478 SkGmHardRst(pAC, IoC, Port); 1479 1480 SkGmClearRst(pAC, IoC, Port); 1481 1482 /* Auto-negotiation ? */ 1483 if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) { 1484 /* Auto-negotiation disabled */ 1485 1486 /* get General Purpose Control */ 1487 GM_IN16(IoC, Port, GM_GP_CTRL, &SWord); 1488 1489 /* disable auto-update for speed, duplex and flow-control */ 1490 SWord |= GM_GPCR_AU_ALL_DIS; 1491 1492 /* setup General Purpose Control Register */ 1493 GM_OUT16(IoC, Port, GM_GP_CTRL, SWord); 1494 1495 SWord = GM_GPCR_AU_ALL_DIS; 1496 } 1497 else { 1498 SWord = 0; 1499 } 1500 1501 /* speed settings */ 1502 switch (pPrt->PLinkSpeed) { 1503 case SK_LSPEED_AUTO: 1504 case SK_LSPEED_1000MBPS: 1505 SWord |= GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100; 1506 break; 1507 case SK_LSPEED_100MBPS: 1508 SWord |= GM_GPCR_SPEED_100; 1509 break; 1510 case SK_LSPEED_10MBPS: 1511 break; 1512 } 1513 1514 /* duplex settings */ 1515 if (pPrt->PLinkMode != SK_LMODE_HALF) { 1516 /* set full duplex */ 1517 SWord |= GM_GPCR_DUP_FULL; 1518 } 1519 1520 /* flow-control settings */ 1521 switch (pPrt->PFlowCtrlMode) { 1522 case SK_FLOW_MODE_NONE: 1523 /* set Pause Off */ 1524 SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_PAUSE_OFF); 1525 /* disable Tx & Rx flow-control */ 1526 SWord |= GM_GPCR_FC_TX_DIS | GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS; 1527 break; 1528 case SK_FLOW_MODE_LOC_SEND: 1529 /* disable Rx flow-control */ 1530 SWord |= GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS; 1531 break; 1532 case SK_FLOW_MODE_SYMMETRIC: 1533 case SK_FLOW_MODE_SYM_OR_REM: 1534 /* enable Tx & Rx flow-control */ 1535 break; 1536 } 1537 1538 /* setup General Purpose Control Register */ 1539 GM_OUT16(IoC, Port, GM_GP_CTRL, SWord); 1540 1541 /* dummy read the Interrupt Source Register */ 1542 SK_IN16(IoC, GMAC_IRQ_SRC, &SWord); 1543 1544#ifndef VCPU 1545 /* read Id from PHY */ 1546 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_ID1, &pPrt->PhyId1); 1547 1548 SkGmInitPhyMarv(pAC, IoC, Port, SK_FALSE); 1549#endif /* VCPU */ 1550 } 1551 1552 (void)SkGmResetCounter(pAC, IoC, Port); 1553 1554 /* setup Transmit Control Register */ 1555 GM_OUT16(IoC, Port, GM_TX_CTRL, TX_COL_THR(pPrt->PMacColThres)); 1556 1557 /* setup Receive Control Register */ 1558 GM_OUT16(IoC, Port, GM_RX_CTRL, GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA | 1559 GM_RXCR_CRC_DIS); 1560 1561 /* setup Transmit Flow Control Register */ 1562 GM_OUT16(IoC, Port, GM_TX_FLOW_CTRL, 0xffff); 1563 1564 /* setup Transmit Parameter Register */ 1565#ifdef VCPU 1566 GM_IN16(IoC, Port, GM_TX_PARAM, &SWord); 1567#endif /* VCPU */ 1568 1569 SWord = TX_JAM_LEN_VAL(pPrt->PMacJamLen) | 1570 TX_JAM_IPG_VAL(pPrt->PMacJamIpgVal) | 1571 TX_IPG_JAM_DATA(pPrt->PMacJamIpgData); 1572 1573 GM_OUT16(IoC, Port, GM_TX_PARAM, SWord); 1574 1575 /* configure the Serial Mode Register */ 1576#ifdef VCPU 1577 GM_IN16(IoC, Port, GM_SERIAL_MODE, &SWord); 1578#endif /* VCPU */ 1579 1580 SWord = GM_SMOD_VLAN_ENA | IPG_DATA_VAL(pPrt->PMacIpgData); 1581 1582 if (pPrt->PMacLimit4) { 1583 /* reset of collision counter after 4 consecutive collisions */ 1584 SWord |= GM_SMOD_LIMIT_4; 1585 } 1586 1587 if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) { 1588 /* enable jumbo mode (Max. Frame Length = 9018) */ 1589 SWord |= GM_SMOD_JUMBO_ENA; 1590 } 1591 1592 GM_OUT16(IoC, Port, GM_SERIAL_MODE, SWord); 1593 1594 /* 1595 * configure the GMACs Station Addresses 1596 * in PROM you can find our addresses at: 1597 * B2_MAC_1 = xx xx xx xx xx x0 virtual address 1598 * B2_MAC_2 = xx xx xx xx xx x1 is programmed to GMAC A 1599 * B2_MAC_3 = xx xx xx xx xx x2 is reserved for DualPort 1600 */ 1601 1602 for (i = 0; i < 3; i++) { 1603 /* 1604 * The following 2 statements are together endianess 1605 * independent. Remember this when changing. 1606 */ 1607 /* physical address: will be used for pause frames */ 1608 SK_IN16(IoC, (B2_MAC_2 + Port * 8 + i * 2), &SWord); 1609 1610#ifdef WA_DEV_16 1611 /* WA for deviation #16 */ 1612 if (pAC->GIni.GIChipId == CHIP_ID_YUKON && pAC->GIni.GIChipRev == 0) { 1613 /* swap the address bytes */ 1614 SWord = ((SWord & 0xff00) >> 8) | ((SWord & 0x00ff) << 8); 1615 1616 /* write to register in reversed order */ 1617 GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + (2 - i) * 4), SWord); 1618 } 1619 else { 1620 GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + i * 4), SWord); 1621 } 1622#else 1623 GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + i * 4), SWord); 1624#endif /* WA_DEV_16 */ 1625 1626 /* virtual address: will be used for data */ 1627 SK_IN16(IoC, (B2_MAC_1 + Port * 8 + i * 2), &SWord); 1628 1629 GM_OUT16(IoC, Port, (GM_SRC_ADDR_2L + i * 4), SWord); 1630 1631 /* reset Multicast filtering Hash registers 1-3 */ 1632 GM_OUT16(IoC, Port, GM_MC_ADDR_H1 + 4*i, 0); 1633 } 1634 1635 /* reset Multicast filtering Hash register 4 */ 1636 GM_OUT16(IoC, Port, GM_MC_ADDR_H4, 0); 1637 1638 /* enable interrupt mask for counter overflows */ 1639 GM_OUT16(IoC, Port, GM_TX_IRQ_MSK, 0); 1640 GM_OUT16(IoC, Port, GM_RX_IRQ_MSK, 0); 1641 GM_OUT16(IoC, Port, GM_TR_IRQ_MSK, 0); 1642 1643#if defined(SK_DIAG) || defined(DEBUG) 1644 /* read General Purpose Status */ 1645 GM_IN16(IoC, Port, GM_GP_STAT, &SWord); 1646 1647 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 1648 ("MAC Stat Reg.=0x%04X\n", SWord)); 1649#endif /* SK_DIAG || DEBUG */ 1650 1651#ifdef SK_DIAG 1652 c_print("MAC Stat Reg=0x%04X\n", SWord); 1653#endif /* SK_DIAG */ 1654 1655} /* SkGmInitMac */ 1656#endif /* YUKON */ 1657 1658 1659#ifdef GENESIS 1660/****************************************************************************** 1661 * 1662 * SkXmInitDupMd() - Initialize the XMACs Duplex Mode 1663 * 1664 * Description: 1665 * This function initializes the XMACs Duplex Mode. 1666 * It should be called after successfully finishing 1667 * the Auto-negotiation Process 1668 * 1669 * Returns: 1670 * nothing 1671 */ 1672static void SkXmInitDupMd( 1673SK_AC *pAC, /* adapter context */ 1674SK_IOC IoC, /* IO context */ 1675int Port) /* Port Index (MAC_1 + n) */ 1676{ 1677 switch (pAC->GIni.GP[Port].PLinkModeStatus) { 1678 case SK_LMODE_STAT_AUTOHALF: 1679 case SK_LMODE_STAT_HALF: 1680 /* Configuration Actions for Half Duplex Mode */ 1681 /* 1682 * XM_BURST = default value. We are probable not quick 1683 * enough at the 'XMAC' bus to burst 8kB. 1684 * The XMAC stops bursting if no transmit frames 1685 * are available or the burst limit is exceeded. 1686 */ 1687 /* XM_TX_RT_LIM = default value (15) */ 1688 /* XM_TX_STIME = default value (0xff = 4096 bit times) */ 1689 break; 1690 case SK_LMODE_STAT_AUTOFULL: 1691 case SK_LMODE_STAT_FULL: 1692 /* Configuration Actions for Full Duplex Mode */ 1693 /* 1694 * The duplex mode is configured by the PHY, 1695 * therefore it seems to be that there is nothing 1696 * to do here. 1697 */ 1698 break; 1699 case SK_LMODE_STAT_UNKNOWN: 1700 default: 1701 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E007, SKERR_HWI_E007MSG); 1702 break; 1703 } 1704} /* SkXmInitDupMd */ 1705 1706 1707/****************************************************************************** 1708 * 1709 * SkXmInitPauseMd() - initialize the Pause Mode to be used for this port 1710 * 1711 * Description: 1712 * This function initializes the Pause Mode which should 1713 * be used for this port. 1714 * It should be called after successfully finishing 1715 * the Auto-negotiation Process 1716 * 1717 * Returns: 1718 * nothing 1719 */ 1720static void SkXmInitPauseMd( 1721SK_AC *pAC, /* adapter context */ 1722SK_IOC IoC, /* IO context */ 1723int Port) /* Port Index (MAC_1 + n) */ 1724{ 1725 SK_GEPORT *pPrt; 1726 SK_U32 DWord; 1727 SK_U16 Word; 1728 1729 pPrt = &pAC->GIni.GP[Port]; 1730 1731 XM_IN16(IoC, Port, XM_MMU_CMD, &Word); 1732 1733 if (pPrt->PFlowCtrlStatus == SK_FLOW_STAT_NONE || 1734 pPrt->PFlowCtrlStatus == SK_FLOW_STAT_LOC_SEND) { 1735 1736 /* Disable Pause Frame Reception */ 1737 Word |= XM_MMU_IGN_PF; 1738 } 1739 else { 1740 /* 1741 * enabling pause frame reception is required for 1000BT 1742 * because the XMAC is not reset if the link is going down 1743 */ 1744 /* Enable Pause Frame Reception */ 1745 Word &= ~XM_MMU_IGN_PF; 1746 } 1747 1748 XM_OUT16(IoC, Port, XM_MMU_CMD, Word); 1749 1750 XM_IN32(IoC, Port, XM_MODE, &DWord); 1751 1752 if (pPrt->PFlowCtrlStatus == SK_FLOW_STAT_SYMMETRIC || 1753 pPrt->PFlowCtrlStatus == SK_FLOW_STAT_LOC_SEND) { 1754 1755 /* 1756 * Configure Pause Frame Generation 1757 * Use internal and external Pause Frame Generation. 1758 * Sending pause frames is edge triggered. 1759 * Send a Pause frame with the maximum pause time if 1760 * internal oder external FIFO full condition occurs. 1761 * Send a zero pause time frame to re-start transmission. 1762 */ 1763 1764 /* XM_PAUSE_DA = '010000C28001' (default) */ 1765 1766 /* XM_MAC_PTIME = 0xffff (maximum) */ 1767 /* remember this value is defined in big endian (!) */ 1768 XM_OUT16(IoC, Port, XM_MAC_PTIME, 0xffff); 1769 1770 /* Set Pause Mode in Mode Register */ 1771 DWord |= XM_PAUSE_MODE; 1772 1773 /* Set Pause Mode in MAC Rx FIFO */ 1774 SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_ENA_PAUSE); 1775 } 1776 else { 1777 /* 1778 * disable pause frame generation is required for 1000BT 1779 * because the XMAC is not reset if the link is going down 1780 */ 1781 /* Disable Pause Mode in Mode Register */ 1782 DWord &= ~XM_PAUSE_MODE; 1783 1784 /* Disable Pause Mode in MAC Rx FIFO */ 1785 SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_DIS_PAUSE); 1786 } 1787 1788 XM_OUT32(IoC, Port, XM_MODE, DWord); 1789} /* SkXmInitPauseMd*/ 1790 1791 1792/****************************************************************************** 1793 * 1794 * SkXmInitPhyXmac() - Initialize the XMAC Phy registers 1795 * 1796 * Description: initializes all the XMACs Phy registers 1797 * 1798 * Note: 1799 * 1800 * Returns: 1801 * nothing 1802 */ 1803static void SkXmInitPhyXmac( 1804SK_AC *pAC, /* adapter context */ 1805SK_IOC IoC, /* IO context */ 1806int Port, /* Port Index (MAC_1 + n) */ 1807SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ 1808{ 1809 SK_GEPORT *pPrt; 1810 SK_U16 Ctrl; 1811 1812 pPrt = &pAC->GIni.GP[Port]; 1813 Ctrl = 0; 1814 1815 /* Auto-negotiation ? */ 1816 if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) { 1817 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 1818 ("InitPhyXmac: no auto-negotiation Port %d\n", Port)); 1819 /* Set DuplexMode in Config register */ 1820 if (pPrt->PLinkMode == SK_LMODE_FULL) { 1821 Ctrl |= PHY_CT_DUP_MD; 1822 } 1823 1824 /* 1825 * Do NOT enable Auto-negotiation here. This would hold 1826 * the link down because no IDLEs are transmitted 1827 */ 1828 } 1829 else { 1830 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 1831 ("InitPhyXmac: with auto-negotiation Port %d\n", Port)); 1832 /* Set Auto-negotiation advertisement */ 1833 1834 /* Set Full/half duplex capabilities */ 1835 switch (pPrt->PLinkMode) { 1836 case SK_LMODE_AUTOHALF: 1837 Ctrl |= PHY_X_AN_HD; 1838 break; 1839 case SK_LMODE_AUTOFULL: 1840 Ctrl |= PHY_X_AN_FD; 1841 break; 1842 case SK_LMODE_AUTOBOTH: 1843 Ctrl |= PHY_X_AN_FD | PHY_X_AN_HD; 1844 break; 1845 default: 1846 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015, 1847 SKERR_HWI_E015MSG); 1848 } 1849 1850 /* Set Flow-control capabilities */ 1851 switch (pPrt->PFlowCtrlMode) { 1852 case SK_FLOW_MODE_NONE: 1853 Ctrl |= PHY_X_P_NO_PAUSE; 1854 break; 1855 case SK_FLOW_MODE_LOC_SEND: 1856 Ctrl |= PHY_X_P_ASYM_MD; 1857 break; 1858 case SK_FLOW_MODE_SYMMETRIC: 1859 Ctrl |= PHY_X_P_SYM_MD; 1860 break; 1861 case SK_FLOW_MODE_SYM_OR_REM: 1862 Ctrl |= PHY_X_P_BOTH_MD; 1863 break; 1864 default: 1865 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016, 1866 SKERR_HWI_E016MSG); 1867 } 1868 1869 /* Write AutoNeg Advertisement Register */ 1870 SkXmPhyWrite(pAC, IoC, Port, PHY_XMAC_AUNE_ADV, Ctrl); 1871 1872 /* Restart Auto-negotiation */ 1873 Ctrl = PHY_CT_ANE | PHY_CT_RE_CFG; 1874 } 1875 1876 if (DoLoop) { 1877 /* Set the Phy Loopback bit, too */ 1878 Ctrl |= PHY_CT_LOOP; 1879 } 1880 1881 /* Write to the Phy control register */ 1882 SkXmPhyWrite(pAC, IoC, Port, PHY_XMAC_CTRL, Ctrl); 1883} /* SkXmInitPhyXmac */ 1884 1885 1886/****************************************************************************** 1887 * 1888 * SkXmInitPhyBcom() - Initialize the Broadcom Phy registers 1889 * 1890 * Description: initializes all the Broadcom Phy registers 1891 * 1892 * Note: 1893 * 1894 * Returns: 1895 * nothing 1896 */ 1897static void SkXmInitPhyBcom( 1898SK_AC *pAC, /* adapter context */ 1899SK_IOC IoC, /* IO context */ 1900int Port, /* Port Index (MAC_1 + n) */ 1901SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ 1902{ 1903 SK_GEPORT *pPrt; 1904 SK_U16 Ctrl1; 1905 SK_U16 Ctrl2; 1906 SK_U16 Ctrl3; 1907 SK_U16 Ctrl4; 1908 SK_U16 Ctrl5; 1909 1910 Ctrl1 = PHY_CT_SP1000; 1911 Ctrl2 = 0; 1912 Ctrl3 = PHY_SEL_TYPE; 1913 Ctrl4 = PHY_B_PEC_EN_LTR; 1914 Ctrl5 = PHY_B_AC_TX_TST; 1915 1916 pPrt = &pAC->GIni.GP[Port]; 1917 1918 /* manually Master/Slave ? */ 1919 if (pPrt->PMSMode != SK_MS_MODE_AUTO) { 1920 Ctrl2 |= PHY_B_1000C_MSE; 1921 1922 if (pPrt->PMSMode == SK_MS_MODE_MASTER) { 1923 Ctrl2 |= PHY_B_1000C_MSC; 1924 } 1925 } 1926 /* Auto-negotiation ? */ 1927 if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) { 1928 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 1929 ("InitPhyBcom: no auto-negotiation Port %d\n", Port)); 1930 /* Set DuplexMode in Config register */ 1931 if (pPrt->PLinkMode == SK_LMODE_FULL) { 1932 Ctrl1 |= PHY_CT_DUP_MD; 1933 } 1934 1935 /* Determine Master/Slave manually if not already done */ 1936 if (pPrt->PMSMode == SK_MS_MODE_AUTO) { 1937 Ctrl2 |= PHY_B_1000C_MSE; /* set it to Slave */ 1938 } 1939 1940 /* 1941 * Do NOT enable Auto-negotiation here. This would hold 1942 * the link down because no IDLES are transmitted 1943 */ 1944 } 1945 else { 1946 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 1947 ("InitPhyBcom: with auto-negotiation Port %d\n", Port)); 1948 /* Set Auto-negotiation advertisement */ 1949 1950 Ctrl2 |= PHY_B_1000C_RD; 1951 1952 /* Set Full/half duplex capabilities */ 1953 switch (pPrt->PLinkMode) { 1954 case SK_LMODE_AUTOHALF: 1955 Ctrl2 |= PHY_B_1000C_AHD; 1956 break; 1957 case SK_LMODE_AUTOFULL: 1958 Ctrl2 |= PHY_B_1000C_AFD; 1959 break; 1960 case SK_LMODE_AUTOBOTH: 1961 Ctrl2 |= PHY_B_1000C_AFD | PHY_B_1000C_AHD; 1962 break; 1963 default: 1964 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015, 1965 SKERR_HWI_E015MSG); 1966 } 1967 1968 /* Set Flow-control capabilities */ 1969 switch (pPrt->PFlowCtrlMode) { 1970 case SK_FLOW_MODE_NONE: 1971 Ctrl3 |= PHY_B_P_NO_PAUSE; 1972 break; 1973 case SK_FLOW_MODE_LOC_SEND: 1974 Ctrl3 |= PHY_B_P_ASYM_MD; 1975 break; 1976 case SK_FLOW_MODE_SYMMETRIC: 1977 Ctrl3 |= PHY_B_P_SYM_MD; 1978 break; 1979 case SK_FLOW_MODE_SYM_OR_REM: 1980 Ctrl3 |= PHY_B_P_BOTH_MD; 1981 break; 1982 default: 1983 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016, 1984 SKERR_HWI_E016MSG); 1985 } 1986 1987 /* Restart Auto-negotiation */ 1988 Ctrl1 |= PHY_CT_ANE | PHY_CT_RE_CFG; 1989 } 1990 1991 /* Initialize LED register here? */ 1992 /* No. Please do it in SkDgXmitLed() (if required) and swap 1993 init order of LEDs and XMAC. (MAl) */ 1994 1995 /* Write 1000Base-T Control Register */ 1996 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, Ctrl2); 1997 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 1998 ("Set 1000B-T Ctrl Reg=0x%04X\n", Ctrl2)); 1999 2000 /* Write AutoNeg Advertisement Register */ 2001 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, Ctrl3); 2002 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 2003 ("Set Auto-Neg.Adv.Reg=0x%04X\n", Ctrl3)); 2004 2005 if (DoLoop) { 2006 /* Set the Phy Loopback bit, too */ 2007 Ctrl1 |= PHY_CT_LOOP; 2008 } 2009 2010 if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) { 2011 /* configure FIFO to high latency for transmission of ext. packets */ 2012 Ctrl4 |= PHY_B_PEC_HIGH_LA; 2013 2014 /* configure reception of extended packets */ 2015 Ctrl5 |= PHY_B_AC_LONG_PACK; 2016 2017 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, Ctrl5); 2018 } 2019 2020 /* Configure LED Traffic Mode and Jumbo Frame usage if specified */ 2021 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, Ctrl4); 2022 2023 /* Write to the Phy control register */ 2024 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL, Ctrl1); 2025 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 2026 ("PHY Control Reg=0x%04X\n", Ctrl1)); 2027} /* SkXmInitPhyBcom */ 2028#endif /* GENESIS */ 2029 2030#ifdef YUKON 2031/****************************************************************************** 2032 * 2033 * SkGmInitPhyMarv() - Initialize the Marvell Phy registers 2034 * 2035 * Description: initializes all the Marvell Phy registers 2036 * 2037 * Note: 2038 * 2039 * Returns: 2040 * nothing 2041 */ 2042static void SkGmInitPhyMarv( 2043SK_AC *pAC, /* adapter context */ 2044SK_IOC IoC, /* IO context */ 2045int Port, /* Port Index (MAC_1 + n) */ 2046SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ 2047{ 2048 SK_GEPORT *pPrt; 2049 SK_U16 PhyCtrl; 2050 SK_U16 C1000BaseT; 2051 SK_U16 AutoNegAdv; 2052 SK_U16 ExtPhyCtrl; 2053 SK_U16 LedCtrl; 2054 SK_BOOL AutoNeg; 2055#if defined(SK_DIAG) || defined(DEBUG) 2056 SK_U16 PhyStat; 2057 SK_U16 PhyStat1; 2058 SK_U16 PhySpecStat; 2059#endif /* SK_DIAG || DEBUG */ 2060 2061 pPrt = &pAC->GIni.GP[Port]; 2062 2063 /* Auto-negotiation ? */ 2064 if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) { 2065 AutoNeg = SK_FALSE; 2066 } 2067 else { 2068 AutoNeg = SK_TRUE; 2069 } 2070 2071 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 2072 ("InitPhyMarv: Port %d, auto-negotiation %s\n", 2073 Port, AutoNeg ? "ON" : "OFF")); 2074 2075#ifdef VCPU 2076 VCPUprintf(0, "SkGmInitPhyMarv(), Port=%u, DoLoop=%u\n", 2077 Port, DoLoop); 2078#else /* VCPU */ 2079 if (DoLoop) { 2080 /* Set 'MAC Power up'-bit, set Manual MDI configuration */ 2081 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, 2082 PHY_M_PC_MAC_POW_UP); 2083 } 2084 else if (AutoNeg && pPrt->PLinkSpeed == SK_LSPEED_AUTO) { 2085 /* Read Ext. PHY Specific Control */ 2086 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL, &ExtPhyCtrl); 2087 2088 ExtPhyCtrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK | 2089 PHY_M_EC_MAC_S_MSK); 2090 2091 ExtPhyCtrl |= PHY_M_EC_MAC_S(MAC_TX_CLK_25_MHZ) | 2092 PHY_M_EC_M_DSC(0) | PHY_M_EC_S_DSC(1); 2093 2094 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_CTRL, ExtPhyCtrl); 2095 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 2096 ("Set Ext. PHY Ctrl=0x%04X\n", ExtPhyCtrl)); 2097 } 2098 2099 /* Read PHY Control */ 2100 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &PhyCtrl); 2101 2102 if (!AutoNeg) { 2103 /* Disable Auto-negotiation */ 2104 PhyCtrl &= ~PHY_CT_ANE; 2105 } 2106 2107 PhyCtrl |= PHY_CT_RESET; 2108 /* Assert software reset */ 2109 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PhyCtrl); 2110#endif /* VCPU */ 2111 2112 PhyCtrl = 0 /* PHY_CT_COL_TST */; 2113 C1000BaseT = 0; 2114 AutoNegAdv = PHY_SEL_TYPE; 2115 2116 /* manually Master/Slave ? */ 2117 if (pPrt->PMSMode != SK_MS_MODE_AUTO) { 2118 /* enable Manual Master/Slave */ 2119 C1000BaseT |= PHY_M_1000C_MSE; 2120 2121 if (pPrt->PMSMode == SK_MS_MODE_MASTER) { 2122 C1000BaseT |= PHY_M_1000C_MSC; /* set it to Master */ 2123 } 2124 } 2125 2126 /* Auto-negotiation ? */ 2127 if (!AutoNeg) { 2128 2129 if (pPrt->PLinkMode == SK_LMODE_FULL) { 2130 /* Set Full Duplex Mode */ 2131 PhyCtrl |= PHY_CT_DUP_MD; 2132 } 2133 2134 /* Set Master/Slave manually if not already done */ 2135 if (pPrt->PMSMode == SK_MS_MODE_AUTO) { 2136 C1000BaseT |= PHY_M_1000C_MSE; /* set it to Slave */ 2137 } 2138 2139 /* Set Speed */ 2140 switch (pPrt->PLinkSpeed) { 2141 case SK_LSPEED_AUTO: 2142 case SK_LSPEED_1000MBPS: 2143 PhyCtrl |= PHY_CT_SP1000; 2144 break; 2145 case SK_LSPEED_100MBPS: 2146 PhyCtrl |= PHY_CT_SP100; 2147 break; 2148 case SK_LSPEED_10MBPS: 2149 break; 2150 default: 2151 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E019, 2152 SKERR_HWI_E019MSG); 2153 } 2154 2155 if (!DoLoop) { 2156 PhyCtrl |= PHY_CT_RESET; 2157 } 2158 } 2159 else { 2160 /* Set Auto-negotiation advertisement */ 2161 2162 if (pAC->GIni.GICopperType) { 2163 /* Set Speed capabilities */ 2164 switch (pPrt->PLinkSpeed) { 2165 case SK_LSPEED_AUTO: 2166 C1000BaseT |= PHY_M_1000C_AHD | PHY_M_1000C_AFD; 2167 AutoNegAdv |= PHY_M_AN_100_FD | PHY_M_AN_100_HD | 2168 PHY_M_AN_10_FD | PHY_M_AN_10_HD; 2169 break; 2170 case SK_LSPEED_1000MBPS: 2171 C1000BaseT |= PHY_M_1000C_AHD | PHY_M_1000C_AFD; 2172 break; 2173 case SK_LSPEED_100MBPS: 2174 AutoNegAdv |= PHY_M_AN_100_FD | PHY_M_AN_100_HD | 2175 /* advertise 10Base-T also */ 2176 PHY_M_AN_10_FD | PHY_M_AN_10_HD; 2177 break; 2178 case SK_LSPEED_10MBPS: 2179 AutoNegAdv |= PHY_M_AN_10_FD | PHY_M_AN_10_HD; 2180 break; 2181 default: 2182 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E019, 2183 SKERR_HWI_E019MSG); 2184 } 2185 2186 /* Set Full/half duplex capabilities */ 2187 switch (pPrt->PLinkMode) { 2188 case SK_LMODE_AUTOHALF: 2189 C1000BaseT &= ~PHY_M_1000C_AFD; 2190 AutoNegAdv &= ~(PHY_M_AN_100_FD | PHY_M_AN_10_FD); 2191 break; 2192 case SK_LMODE_AUTOFULL: 2193 C1000BaseT &= ~PHY_M_1000C_AHD; 2194 AutoNegAdv &= ~(PHY_M_AN_100_HD | PHY_M_AN_10_HD); 2195 break; 2196 case SK_LMODE_AUTOBOTH: 2197 break; 2198 default: 2199 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015, 2200 SKERR_HWI_E015MSG); 2201 } 2202 2203 /* Set Flow-control capabilities */ 2204 switch (pPrt->PFlowCtrlMode) { 2205 case SK_FLOW_MODE_NONE: 2206 AutoNegAdv |= PHY_B_P_NO_PAUSE; 2207 break; 2208 case SK_FLOW_MODE_LOC_SEND: 2209 AutoNegAdv |= PHY_B_P_ASYM_MD; 2210 break; 2211 case SK_FLOW_MODE_SYMMETRIC: 2212 AutoNegAdv |= PHY_B_P_SYM_MD; 2213 break; 2214 case SK_FLOW_MODE_SYM_OR_REM: 2215 AutoNegAdv |= PHY_B_P_BOTH_MD; 2216 break; 2217 default: 2218 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016, 2219 SKERR_HWI_E016MSG); 2220 } 2221 } 2222 else { /* special defines for FIBER (88E1011S only) */ 2223 2224 /* Set Full/half duplex capabilities */ 2225 switch (pPrt->PLinkMode) { 2226 case SK_LMODE_AUTOHALF: 2227 AutoNegAdv |= PHY_M_AN_1000X_AHD; 2228 break; 2229 case SK_LMODE_AUTOFULL: 2230 AutoNegAdv |= PHY_M_AN_1000X_AFD; 2231 break; 2232 case SK_LMODE_AUTOBOTH: 2233 AutoNegAdv |= PHY_M_AN_1000X_AHD | PHY_M_AN_1000X_AFD; 2234 break; 2235 default: 2236 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015, 2237 SKERR_HWI_E015MSG); 2238 } 2239 2240 /* Set Flow-control capabilities */ 2241 switch (pPrt->PFlowCtrlMode) { 2242 case SK_FLOW_MODE_NONE: 2243 AutoNegAdv |= PHY_M_P_NO_PAUSE_X; 2244 break; 2245 case SK_FLOW_MODE_LOC_SEND: 2246 AutoNegAdv |= PHY_M_P_ASYM_MD_X; 2247 break; 2248 case SK_FLOW_MODE_SYMMETRIC: 2249 AutoNegAdv |= PHY_M_P_SYM_MD_X; 2250 break; 2251 case SK_FLOW_MODE_SYM_OR_REM: 2252 AutoNegAdv |= PHY_M_P_BOTH_MD_X; 2253 break; 2254 default: 2255 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016, 2256 SKERR_HWI_E016MSG); 2257 } 2258 } 2259 2260 if (!DoLoop) { 2261 /* Restart Auto-negotiation */ 2262 PhyCtrl |= PHY_CT_ANE | PHY_CT_RE_CFG; 2263 } 2264 } 2265 2266#ifdef VCPU 2267 /* 2268 * E-mail from Gu Lin (08-03-2002): 2269 */ 2270 2271 /* Program PHY register 30 as 16'h0708 for simulation speed up */ 2272 SkGmPhyWrite(pAC, IoC, Port, 30, 0x0700 /* 0x0708 */); 2273 2274 VCpuWait(2000); 2275 2276#else /* VCPU */ 2277 2278 /* Write 1000Base-T Control Register */ 2279 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_1000T_CTRL, C1000BaseT); 2280 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 2281 ("Set 1000B-T Ctrl =0x%04X\n", C1000BaseT)); 2282 2283 /* Write AutoNeg Advertisement Register */ 2284 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_AUNE_ADV, AutoNegAdv); 2285 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 2286 ("Set Auto-Neg.Adv.=0x%04X\n", AutoNegAdv)); 2287#endif /* VCPU */ 2288 2289 if (DoLoop) { 2290 /* Set the PHY Loopback bit */ 2291 PhyCtrl |= PHY_CT_LOOP; 2292 2293#ifdef XXX 2294 /* Program PHY register 16 as 16'h0400 to force link good */ 2295 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, PHY_M_PC_FL_GOOD); 2296#endif 2297 2298#ifndef VCPU 2299 if (pPrt->PLinkSpeed != SK_LSPEED_AUTO) { 2300 /* Write Ext. PHY Specific Control */ 2301 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_CTRL, 2302 (SK_U16)((pPrt->PLinkSpeed + 2) << 4)); 2303 } 2304#endif /* VCPU */ 2305 } 2306#ifdef TEST_ONLY 2307 else if (pPrt->PLinkSpeed == SK_LSPEED_10MBPS) { 2308 /* Write PHY Specific Control */ 2309 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, 2310 PHY_M_PC_EN_DET_MSK); 2311 } 2312#endif 2313 2314 /* Write to the PHY Control register */ 2315 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PhyCtrl); 2316 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 2317 ("Set PHY Ctrl Reg.=0x%04X\n", PhyCtrl)); 2318 2319#ifdef VCPU 2320 VCpuWait(2000); 2321#else 2322 2323 LedCtrl = PHY_M_LED_PULS_DUR(PULS_170MS) | PHY_M_LED_BLINK_RT(BLINK_84MS); 2324 2325 if ((pAC->GIni.GILedBlinkCtrl & SK_ACT_LED_BLINK) != 0) { 2326 LedCtrl |= PHY_M_LEDC_RX_CTRL | PHY_M_LEDC_TX_CTRL; 2327 } 2328 2329 if ((pAC->GIni.GILedBlinkCtrl & SK_DUP_LED_NORMAL) != 0) { 2330 LedCtrl |= PHY_M_LEDC_DP_CTRL; 2331 } 2332 2333 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_LED_CTRL, LedCtrl); 2334 2335 if ((pAC->GIni.GILedBlinkCtrl & SK_LED_LINK100_ON) != 0) { 2336 /* only in forced 100 Mbps mode */ 2337 if (!AutoNeg && pPrt->PLinkSpeed == SK_LSPEED_100MBPS) { 2338 2339 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_LED_OVER, 2340 PHY_M_LED_MO_100(MO_LED_ON)); 2341 } 2342 } 2343 2344#ifdef SK_DIAG 2345 c_print("Set PHY Ctrl=0x%04X\n", PhyCtrl); 2346 c_print("Set 1000 B-T=0x%04X\n", C1000BaseT); 2347 c_print("Set Auto-Neg=0x%04X\n", AutoNegAdv); 2348 c_print("Set Ext Ctrl=0x%04X\n", ExtPhyCtrl); 2349#endif /* SK_DIAG */ 2350 2351#if defined(SK_DIAG) || defined(DEBUG) 2352 /* Read PHY Control */ 2353 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &PhyCtrl); 2354 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 2355 ("PHY Ctrl Reg.=0x%04X\n", PhyCtrl)); 2356 2357 /* Read 1000Base-T Control Register */ 2358 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_CTRL, &C1000BaseT); 2359 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 2360 ("1000B-T Ctrl =0x%04X\n", C1000BaseT)); 2361 2362 /* Read AutoNeg Advertisement Register */ 2363 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_ADV, &AutoNegAdv); 2364 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 2365 ("Auto-Neg.Adv.=0x%04X\n", AutoNegAdv)); 2366 2367 /* Read Ext. PHY Specific Control */ 2368 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL, &ExtPhyCtrl); 2369 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 2370 ("Ext. PHY Ctrl=0x%04X\n", ExtPhyCtrl)); 2371 2372 /* Read PHY Status */ 2373 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat); 2374 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 2375 ("PHY Stat Reg.=0x%04X\n", PhyStat)); 2376 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat1); 2377 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 2378 ("PHY Stat Reg.=0x%04X\n", PhyStat1)); 2379 2380 /* Read PHY Specific Status */ 2381 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &PhySpecStat); 2382 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 2383 ("PHY Spec Stat=0x%04X\n", PhySpecStat)); 2384#endif /* SK_DIAG || DEBUG */ 2385 2386#ifdef SK_DIAG 2387 c_print("PHY Ctrl Reg=0x%04X\n", PhyCtrl); 2388 c_print("PHY 1000 Reg=0x%04X\n", C1000BaseT); 2389 c_print("PHY AnAd Reg=0x%04X\n", AutoNegAdv); 2390 c_print("Ext Ctrl Reg=0x%04X\n", ExtPhyCtrl); 2391 c_print("PHY Stat Reg=0x%04X\n", PhyStat); 2392 c_print("PHY Stat Reg=0x%04X\n", PhyStat1); 2393 c_print("PHY Spec Reg=0x%04X\n", PhySpecStat); 2394#endif /* SK_DIAG */ 2395 2396#endif /* VCPU */ 2397 2398} /* SkGmInitPhyMarv */ 2399#endif /* YUKON */ 2400 2401 2402#ifdef OTHER_PHY 2403/****************************************************************************** 2404 * 2405 * SkXmInitPhyLone() - Initialize the Level One Phy registers 2406 * 2407 * Description: initializes all the Level One Phy registers 2408 * 2409 * Note: 2410 * 2411 * Returns: 2412 * nothing 2413 */ 2414static void SkXmInitPhyLone( 2415SK_AC *pAC, /* adapter context */ 2416SK_IOC IoC, /* IO context */ 2417int Port, /* Port Index (MAC_1 + n) */ 2418SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ 2419{ 2420 SK_GEPORT *pPrt; 2421 SK_U16 Ctrl1; 2422 SK_U16 Ctrl2; 2423 SK_U16 Ctrl3; 2424 2425 Ctrl1 = PHY_CT_SP1000; 2426 Ctrl2 = 0; 2427 Ctrl3 = PHY_SEL_TYPE; 2428 2429 pPrt = &pAC->GIni.GP[Port]; 2430 2431 /* manually Master/Slave ? */ 2432 if (pPrt->PMSMode != SK_MS_MODE_AUTO) { 2433 Ctrl2 |= PHY_L_1000C_MSE; 2434 2435 if (pPrt->PMSMode == SK_MS_MODE_MASTER) { 2436 Ctrl2 |= PHY_L_1000C_MSC; 2437 } 2438 } 2439 /* Auto-negotiation ? */ 2440 if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) { 2441 /* 2442 * level one spec say: "1000 Mbps: manual mode not allowed" 2443 * but lets see what happens... 2444 */ 2445 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 2446 ("InitPhyLone: no auto-negotiation Port %d\n", Port)); 2447 /* Set DuplexMode in Config register */ 2448 if (pPrt->PLinkMode == SK_LMODE_FULL) { 2449 Ctrl1 |= PHY_CT_DUP_MD; 2450 } 2451 2452 /* Determine Master/Slave manually if not already done */ 2453 if (pPrt->PMSMode == SK_MS_MODE_AUTO) { 2454 Ctrl2 |= PHY_L_1000C_MSE; /* set it to Slave */ 2455 } 2456 2457 /* 2458 * Do NOT enable Auto-negotiation here. This would hold 2459 * the link down because no IDLES are transmitted 2460 */ 2461 } 2462 else { 2463 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 2464 ("InitPhyLone: with auto-negotiation Port %d\n", Port)); 2465 /* Set Auto-negotiation advertisement */ 2466 2467 /* Set Full/half duplex capabilities */ 2468 switch (pPrt->PLinkMode) { 2469 case SK_LMODE_AUTOHALF: 2470 Ctrl2 |= PHY_L_1000C_AHD; 2471 break; 2472 case SK_LMODE_AUTOFULL: 2473 Ctrl2 |= PHY_L_1000C_AFD; 2474 break; 2475 case SK_LMODE_AUTOBOTH: 2476 Ctrl2 |= PHY_L_1000C_AFD | PHY_L_1000C_AHD; 2477 break; 2478 default: 2479 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015, 2480 SKERR_HWI_E015MSG); 2481 } 2482 2483 /* Set Flow-control capabilities */ 2484 switch (pPrt->PFlowCtrlMode) { 2485 case SK_FLOW_MODE_NONE: 2486 Ctrl3 |= PHY_L_P_NO_PAUSE; 2487 break; 2488 case SK_FLOW_MODE_LOC_SEND: 2489 Ctrl3 |= PHY_L_P_ASYM_MD; 2490 break; 2491 case SK_FLOW_MODE_SYMMETRIC: 2492 Ctrl3 |= PHY_L_P_SYM_MD; 2493 break; 2494 case SK_FLOW_MODE_SYM_OR_REM: 2495 Ctrl3 |= PHY_L_P_BOTH_MD; 2496 break; 2497 default: 2498 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016, 2499 SKERR_HWI_E016MSG); 2500 } 2501 2502 /* Restart Auto-negotiation */ 2503 Ctrl1 = PHY_CT_ANE | PHY_CT_RE_CFG; 2504 } 2505 2506 /* Write 1000Base-T Control Register */ 2507 SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_1000T_CTRL, Ctrl2); 2508 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 2509 ("1000B-T Ctrl Reg=0x%04X\n", Ctrl2)); 2510 2511 /* Write AutoNeg Advertisement Register */ 2512 SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_AUNE_ADV, Ctrl3); 2513 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 2514 ("Auto-Neg.Adv.Reg=0x%04X\n", Ctrl3)); 2515 2516 if (DoLoop) { 2517 /* Set the Phy Loopback bit, too */ 2518 Ctrl1 |= PHY_CT_LOOP; 2519 } 2520 2521 /* Write to the Phy control register */ 2522 SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_CTRL, Ctrl1); 2523 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 2524 ("PHY Control Reg=0x%04X\n", Ctrl1)); 2525} /* SkXmInitPhyLone */ 2526 2527 2528/****************************************************************************** 2529 * 2530 * SkXmInitPhyNat() - Initialize the National Phy registers 2531 * 2532 * Description: initializes all the National Phy registers 2533 * 2534 * Note: 2535 * 2536 * Returns: 2537 * nothing 2538 */ 2539static void SkXmInitPhyNat( 2540SK_AC *pAC, /* adapter context */ 2541SK_IOC IoC, /* IO context */ 2542int Port, /* Port Index (MAC_1 + n) */ 2543SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ 2544{ 2545/* todo: National */ 2546} /* SkXmInitPhyNat */ 2547#endif /* OTHER_PHY */ 2548 2549 2550/****************************************************************************** 2551 * 2552 * SkMacInitPhy() - Initialize the PHY registers 2553 * 2554 * Description: calls the Init PHY routines dep. on board type 2555 * 2556 * Note: 2557 * 2558 * Returns: 2559 * nothing 2560 */ 2561void SkMacInitPhy( 2562SK_AC *pAC, /* adapter context */ 2563SK_IOC IoC, /* IO context */ 2564int Port, /* Port Index (MAC_1 + n) */ 2565SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ 2566{ 2567 SK_GEPORT *pPrt; 2568 2569 pPrt = &pAC->GIni.GP[Port]; 2570 2571#ifdef GENESIS 2572 if (pAC->GIni.GIGenesis) { 2573 2574 switch (pPrt->PhyType) { 2575 case SK_PHY_XMAC: 2576 SkXmInitPhyXmac(pAC, IoC, Port, DoLoop); 2577 break; 2578 case SK_PHY_BCOM: 2579 SkXmInitPhyBcom(pAC, IoC, Port, DoLoop); 2580 break; 2581#ifdef OTHER_PHY 2582 case SK_PHY_LONE: 2583 SkXmInitPhyLone(pAC, IoC, Port, DoLoop); 2584 break; 2585 case SK_PHY_NAT: 2586 SkXmInitPhyNat(pAC, IoC, Port, DoLoop); 2587 break; 2588#endif /* OTHER_PHY */ 2589 } 2590 } 2591#endif /* GENESIS */ 2592 2593#ifdef YUKON 2594 if (pAC->GIni.GIYukon) { 2595 2596 SkGmInitPhyMarv(pAC, IoC, Port, DoLoop); 2597 } 2598#endif /* YUKON */ 2599 2600} /* SkMacInitPhy */ 2601 2602 2603#ifdef GENESIS 2604/****************************************************************************** 2605 * 2606 * SkXmAutoNegDoneXmac() - Auto-negotiation handling 2607 * 2608 * Description: 2609 * This function handles the auto-negotiation if the Done bit is set. 2610 * 2611 * Returns: 2612 * SK_AND_OK o.k. 2613 * SK_AND_DUP_CAP Duplex capability error happened 2614 * SK_AND_OTHER Other error happened 2615 */ 2616static int SkXmAutoNegDoneXmac( 2617SK_AC *pAC, /* adapter context */ 2618SK_IOC IoC, /* IO context */ 2619int Port) /* Port Index (MAC_1 + n) */ 2620{ 2621 SK_GEPORT *pPrt; 2622 SK_U16 ResAb; /* Resolved Ability */ 2623 SK_U16 LPAb; /* Link Partner Ability */ 2624 2625 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 2626 ("AutoNegDoneXmac, Port %d\n", Port)); 2627 2628 pPrt = &pAC->GIni.GP[Port]; 2629 2630 /* Get PHY parameters */ 2631 SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_LP, &LPAb); 2632 SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_RES_ABI, &ResAb); 2633 2634 if ((LPAb & PHY_X_AN_RFB) != 0) { 2635 /* At least one of the remote fault bit is set */ 2636 /* Error */ 2637 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 2638 ("AutoNegFail: Remote fault bit set Port %d\n", Port)); 2639 pPrt->PAutoNegFail = SK_TRUE; 2640 return(SK_AND_OTHER); 2641 } 2642 2643 /* Check Duplex mismatch */ 2644 if ((ResAb & (PHY_X_RS_HD | PHY_X_RS_FD)) == PHY_X_RS_FD) { 2645 pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL; 2646 } 2647 else if ((ResAb & (PHY_X_RS_HD | PHY_X_RS_FD)) == PHY_X_RS_HD) { 2648 pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF; 2649 } 2650 else { 2651 /* Error */ 2652 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 2653 ("AutoNegFail: Duplex mode mismatch Port %d\n", Port)); 2654 pPrt->PAutoNegFail = SK_TRUE; 2655 return(SK_AND_DUP_CAP); 2656 } 2657 2658 /* Check PAUSE mismatch */ 2659 /* We are NOT using chapter 4.23 of the Xaqti manual */ 2660 /* We are using IEEE 802.3z/D5.0 Table 37-4 */ 2661 if ((pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYMMETRIC || 2662 pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM) && 2663 (LPAb & PHY_X_P_SYM_MD) != 0) { 2664 /* Symmetric PAUSE */ 2665 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC; 2666 } 2667 else if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM && 2668 (LPAb & PHY_X_RS_PAUSE) == PHY_X_P_ASYM_MD) { 2669 /* Enable PAUSE receive, disable PAUSE transmit */ 2670 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND; 2671 } 2672 else if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_LOC_SEND && 2673 (LPAb & PHY_X_RS_PAUSE) == PHY_X_P_BOTH_MD) { 2674 /* Disable PAUSE receive, enable PAUSE transmit */ 2675 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND; 2676 } 2677 else { 2678 /* PAUSE mismatch -> no PAUSE */ 2679 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE; 2680 } 2681 pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS; 2682 2683 return(SK_AND_OK); 2684} /* SkXmAutoNegDoneXmac */ 2685 2686 2687/****************************************************************************** 2688 * 2689 * SkXmAutoNegDoneBcom() - Auto-negotiation handling 2690 * 2691 * Description: 2692 * This function handles the auto-negotiation if the Done bit is set. 2693 * 2694 * Returns: 2695 * SK_AND_OK o.k. 2696 * SK_AND_DUP_CAP Duplex capability error happened 2697 * SK_AND_OTHER Other error happened 2698 */ 2699static int SkXmAutoNegDoneBcom( 2700SK_AC *pAC, /* adapter context */ 2701SK_IOC IoC, /* IO context */ 2702int Port) /* Port Index (MAC_1 + n) */ 2703{ 2704 SK_GEPORT *pPrt; 2705 SK_U16 LPAb; /* Link Partner Ability */ 2706 SK_U16 AuxStat; /* Auxiliary Status */ 2707 2708#ifdef TEST_ONLY 270901-Sep-2000 RA;:;: 2710 SK_U16 ResAb; /* Resolved Ability */ 2711#endif /* 0 */ 2712 2713 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 2714 ("AutoNegDoneBcom, Port %d\n", Port)); 2715 pPrt = &pAC->GIni.GP[Port]; 2716 2717 /* Get PHY parameters */ 2718 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &LPAb); 2719#ifdef TEST_ONLY 272001-Sep-2000 RA;:;: 2721 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb); 2722#endif /* 0 */ 2723 2724 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &AuxStat); 2725 2726 if ((LPAb & PHY_B_AN_RF) != 0) { 2727 /* Remote fault bit is set: Error */ 2728 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 2729 ("AutoNegFail: Remote fault bit set Port %d\n", Port)); 2730 pPrt->PAutoNegFail = SK_TRUE; 2731 return(SK_AND_OTHER); 2732 } 2733 2734 /* Check Duplex mismatch */ 2735 if ((AuxStat & PHY_B_AS_AN_RES_MSK) == PHY_B_RES_1000FD) { 2736 pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL; 2737 } 2738 else if ((AuxStat & PHY_B_AS_AN_RES_MSK) == PHY_B_RES_1000HD) { 2739 pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF; 2740 } 2741 else { 2742 /* Error */ 2743 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 2744 ("AutoNegFail: Duplex mode mismatch Port %d\n", Port)); 2745 pPrt->PAutoNegFail = SK_TRUE; 2746 return(SK_AND_DUP_CAP); 2747 } 2748 2749#ifdef TEST_ONLY 275001-Sep-2000 RA;:;: 2751 /* Check Master/Slave resolution */ 2752 if ((ResAb & PHY_B_1000S_MSF) != 0) { 2753 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 2754 ("Master/Slave Fault Port %d\n", Port)); 2755 pPrt->PAutoNegFail = SK_TRUE; 2756 pPrt->PMSStatus = SK_MS_STAT_FAULT; 2757 return(SK_AND_OTHER); 2758 } 2759 2760 pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ? 2761 SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE; 2762#endif /* 0 */ 2763 2764 /* Check PAUSE mismatch ??? */ 2765 /* We are using IEEE 802.3z/D5.0 Table 37-4 */ 2766 if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PAUSE_MSK) { 2767 /* Symmetric PAUSE */ 2768 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC; 2769 } 2770 else if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PRR) { 2771 /* Enable PAUSE receive, disable PAUSE transmit */ 2772 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND; 2773 } 2774 else if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PRT) { 2775 /* Disable PAUSE receive, enable PAUSE transmit */ 2776 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND; 2777 } 2778 else { 2779 /* PAUSE mismatch -> no PAUSE */ 2780 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE; 2781 } 2782 pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS; 2783 2784 return(SK_AND_OK); 2785} /* SkXmAutoNegDoneBcom */ 2786#endif /* GENESIS */ 2787 2788 2789#ifdef YUKON 2790/****************************************************************************** 2791 * 2792 * SkGmAutoNegDoneMarv() - Auto-negotiation handling 2793 * 2794 * Description: 2795 * This function handles the auto-negotiation if the Done bit is set. 2796 * 2797 * Returns: 2798 * SK_AND_OK o.k. 2799 * SK_AND_DUP_CAP Duplex capability error happened 2800 * SK_AND_OTHER Other error happened 2801 */ 2802static int SkGmAutoNegDoneMarv( 2803SK_AC *pAC, /* adapter context */ 2804SK_IOC IoC, /* IO context */ 2805int Port) /* Port Index (MAC_1 + n) */ 2806{ 2807 SK_GEPORT *pPrt; 2808 SK_U16 LPAb; /* Link Partner Ability */ 2809 SK_U16 ResAb; /* Resolved Ability */ 2810 SK_U16 AuxStat; /* Auxiliary Status */ 2811 2812 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 2813 ("AutoNegDoneMarv, Port %d\n", Port)); 2814 pPrt = &pAC->GIni.GP[Port]; 2815 2816 /* Get PHY parameters */ 2817 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_LP, &LPAb); 2818 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 2819 ("Link P.Abil.=0x%04X\n", LPAb)); 2820 2821 if ((LPAb & PHY_M_AN_RF) != 0) { 2822 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 2823 ("AutoNegFail: Remote fault bit set Port %d\n", Port)); 2824 pPrt->PAutoNegFail = SK_TRUE; 2825 return(SK_AND_OTHER); 2826 } 2827 2828 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_STAT, &ResAb); 2829 2830 /* Check Master/Slave resolution */ 2831 if ((ResAb & PHY_B_1000S_MSF) != 0) { 2832 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 2833 ("Master/Slave Fault Port %d\n", Port)); 2834 pPrt->PAutoNegFail = SK_TRUE; 2835 pPrt->PMSStatus = SK_MS_STAT_FAULT; 2836 return(SK_AND_OTHER); 2837 } 2838 2839 pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ? 2840 (SK_U8)SK_MS_STAT_MASTER : (SK_U8)SK_MS_STAT_SLAVE; 2841 2842 /* Read PHY Specific Status */ 2843 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &AuxStat); 2844 2845 /* Check Speed & Duplex resolved */ 2846 if ((AuxStat & PHY_M_PS_SPDUP_RES) == 0) { 2847 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 2848 ("AutoNegFail: Speed & Duplex not resolved, Port %d\n", Port)); 2849 pPrt->PAutoNegFail = SK_TRUE; 2850 pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN; 2851 return(SK_AND_DUP_CAP); 2852 } 2853 2854 if ((AuxStat & PHY_M_PS_FULL_DUP) != 0) { 2855 pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL; 2856 } 2857 else { 2858 pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF; 2859 } 2860 2861 /* Check PAUSE mismatch ??? */ 2862 /* We are using IEEE 802.3z/D5.0 Table 37-4 */ 2863 if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_PAUSE_MSK) { 2864 /* Symmetric PAUSE */ 2865 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC; 2866 } 2867 else if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_RX_P_EN) { 2868 /* Enable PAUSE receive, disable PAUSE transmit */ 2869 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND; 2870 } 2871 else if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_TX_P_EN) { 2872 /* Disable PAUSE receive, enable PAUSE transmit */ 2873 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND; 2874 } 2875 else { 2876 /* PAUSE mismatch -> no PAUSE */ 2877 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE; 2878 } 2879 2880 /* set used link speed */ 2881 switch ((unsigned)(AuxStat & PHY_M_PS_SPEED_MSK)) { 2882 case (unsigned)PHY_M_PS_SPEED_1000: 2883 pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS; 2884 break; 2885 case PHY_M_PS_SPEED_100: 2886 pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_100MBPS; 2887 break; 2888 default: 2889 pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_10MBPS; 2890 } 2891 2892 return(SK_AND_OK); 2893} /* SkGmAutoNegDoneMarv */ 2894#endif /* YUKON */ 2895 2896 2897#ifdef OTHER_PHY 2898/****************************************************************************** 2899 * 2900 * SkXmAutoNegDoneLone() - Auto-negotiation handling 2901 * 2902 * Description: 2903 * This function handles the auto-negotiation if the Done bit is set. 2904 * 2905 * Returns: 2906 * SK_AND_OK o.k. 2907 * SK_AND_DUP_CAP Duplex capability error happened 2908 * SK_AND_OTHER Other error happened 2909 */ 2910static int SkXmAutoNegDoneLone( 2911SK_AC *pAC, /* adapter context */ 2912SK_IOC IoC, /* IO context */ 2913int Port) /* Port Index (MAC_1 + n) */ 2914{ 2915 SK_GEPORT *pPrt; 2916 SK_U16 ResAb; /* Resolved Ability */ 2917 SK_U16 LPAb; /* Link Partner Ability */ 2918 SK_U16 QuickStat; /* Auxiliary Status */ 2919 2920 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 2921 ("AutoNegDoneLone, Port %d\n", Port)); 2922 pPrt = &pAC->GIni.GP[Port]; 2923 2924 /* Get PHY parameters */ 2925 SkXmPhyRead(pAC, IoC, Port, PHY_LONE_AUNE_LP, &LPAb); 2926 SkXmPhyRead(pAC, IoC, Port, PHY_LONE_1000T_STAT, &ResAb); 2927 SkXmPhyRead(pAC, IoC, Port, PHY_LONE_Q_STAT, &QuickStat); 2928 2929 if ((LPAb & PHY_L_AN_RF) != 0) { 2930 /* Remote fault bit is set */ 2931 /* Error */ 2932 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 2933 ("AutoNegFail: Remote fault bit set Port %d\n", Port)); 2934 pPrt->PAutoNegFail = SK_TRUE; 2935 return(SK_AND_OTHER); 2936 } 2937 2938 /* Check Duplex mismatch */ 2939 if ((QuickStat & PHY_L_QS_DUP_MOD) != 0) { 2940 pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL; 2941 } 2942 else { 2943 pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF; 2944 } 2945 2946 /* Check Master/Slave resolution */ 2947 if ((ResAb & PHY_L_1000S_MSF) != 0) { 2948 /* Error */ 2949 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 2950 ("Master/Slave Fault Port %d\n", Port)); 2951 pPrt->PAutoNegFail = SK_TRUE; 2952 pPrt->PMSStatus = SK_MS_STAT_FAULT; 2953 return(SK_AND_OTHER); 2954 } 2955 else if (ResAb & PHY_L_1000S_MSR) { 2956 pPrt->PMSStatus = SK_MS_STAT_MASTER; 2957 } 2958 else { 2959 pPrt->PMSStatus = SK_MS_STAT_SLAVE; 2960 } 2961 2962 /* Check PAUSE mismatch */ 2963 /* We are using IEEE 802.3z/D5.0 Table 37-4 */ 2964 /* we must manually resolve the abilities here */ 2965 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE; 2966 2967 switch (pPrt->PFlowCtrlMode) { 2968 case SK_FLOW_MODE_NONE: 2969 /* default */ 2970 break; 2971 case SK_FLOW_MODE_LOC_SEND: 2972 if ((QuickStat & (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) == 2973 (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) { 2974 /* Disable PAUSE receive, enable PAUSE transmit */ 2975 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND; 2976 } 2977 break; 2978 case SK_FLOW_MODE_SYMMETRIC: 2979 if ((QuickStat & PHY_L_QS_PAUSE) != 0) { 2980 /* Symmetric PAUSE */ 2981 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC; 2982 } 2983 break; 2984 case SK_FLOW_MODE_SYM_OR_REM: 2985 if ((QuickStat & (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) == 2986 PHY_L_QS_AS_PAUSE) { 2987 /* Enable PAUSE receive, disable PAUSE transmit */ 2988 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND; 2989 } 2990 else if ((QuickStat & PHY_L_QS_PAUSE) != 0) { 2991 /* Symmetric PAUSE */ 2992 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC; 2993 } 2994 break; 2995 default: 2996 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016, 2997 SKERR_HWI_E016MSG); 2998 } 2999 3000 return(SK_AND_OK); 3001} /* SkXmAutoNegDoneLone */ 3002 3003 3004/****************************************************************************** 3005 * 3006 * SkXmAutoNegDoneNat() - Auto-negotiation handling 3007 * 3008 * Description: 3009 * This function handles the auto-negotiation if the Done bit is set. 3010 * 3011 * Returns: 3012 * SK_AND_OK o.k. 3013 * SK_AND_DUP_CAP Duplex capability error happened 3014 * SK_AND_OTHER Other error happened 3015 */ 3016static int SkXmAutoNegDoneNat( 3017SK_AC *pAC, /* adapter context */ 3018SK_IOC IoC, /* IO context */ 3019int Port) /* Port Index (MAC_1 + n) */ 3020{ 3021/* todo: National */ 3022 return(SK_AND_OK); 3023} /* SkXmAutoNegDoneNat */ 3024#endif /* OTHER_PHY */ 3025 3026 3027/****************************************************************************** 3028 * 3029 * SkMacAutoNegDone() - Auto-negotiation handling 3030 * 3031 * Description: calls the auto-negotiation done routines dep. on board type 3032 * 3033 * Returns: 3034 * SK_AND_OK o.k. 3035 * SK_AND_DUP_CAP Duplex capability error happened 3036 * SK_AND_OTHER Other error happened 3037 */ 3038int SkMacAutoNegDone( 3039SK_AC *pAC, /* adapter context */ 3040SK_IOC IoC, /* IO context */ 3041int Port) /* Port Index (MAC_1 + n) */ 3042{ 3043 SK_GEPORT *pPrt; 3044 int Rtv; 3045 3046 Rtv = SK_AND_OK; 3047 3048 pPrt = &pAC->GIni.GP[Port]; 3049 3050#ifdef GENESIS 3051 if (pAC->GIni.GIGenesis) { 3052 3053 switch (pPrt->PhyType) { 3054 3055 case SK_PHY_XMAC: 3056 Rtv = SkXmAutoNegDoneXmac(pAC, IoC, Port); 3057 break; 3058 case SK_PHY_BCOM: 3059 Rtv = SkXmAutoNegDoneBcom(pAC, IoC, Port); 3060 break; 3061#ifdef OTHER_PHY 3062 case SK_PHY_LONE: 3063 Rtv = SkXmAutoNegDoneLone(pAC, IoC, Port); 3064 break; 3065 case SK_PHY_NAT: 3066 Rtv = SkXmAutoNegDoneNat(pAC, IoC, Port); 3067 break; 3068#endif /* OTHER_PHY */ 3069 default: 3070 return(SK_AND_OTHER); 3071 } 3072 } 3073#endif /* GENESIS */ 3074 3075#ifdef YUKON 3076 if (pAC->GIni.GIYukon) { 3077 3078 Rtv = SkGmAutoNegDoneMarv(pAC, IoC, Port); 3079 } 3080#endif /* YUKON */ 3081 3082 if (Rtv != SK_AND_OK) { 3083 return(Rtv); 3084 } 3085 3086 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 3087 ("AutoNeg done Port %d\n", Port)); 3088 3089 /* We checked everything and may now enable the link */ 3090 pPrt->PAutoNegFail = SK_FALSE; 3091 3092 SkMacRxTxEnable(pAC, IoC, Port); 3093 3094 return(SK_AND_OK); 3095} /* SkMacAutoNegDone */ 3096 3097 3098/****************************************************************************** 3099 * 3100 * SkMacRxTxEnable() - Enable Rx/Tx activity if port is up 3101 * 3102 * Description: enables Rx/Tx dep. on board type 3103 * 3104 * Returns: 3105 * 0 o.k. 3106 * != 0 Error happened 3107 */ 3108int SkMacRxTxEnable( 3109SK_AC *pAC, /* adapter context */ 3110SK_IOC IoC, /* IO context */ 3111int Port) /* Port Index (MAC_1 + n) */ 3112{ 3113 SK_GEPORT *pPrt; 3114 SK_U16 Reg; /* 16-bit register value */ 3115 SK_U16 IntMask; /* MAC interrupt mask */ 3116#ifdef GENESIS 3117 SK_U16 SWord; 3118#endif 3119 3120 pPrt = &pAC->GIni.GP[Port]; 3121 3122 if (!pPrt->PHWLinkUp) { 3123 /* The Hardware link is NOT up */ 3124 return(0); 3125 } 3126 3127 if ((pPrt->PLinkMode == SK_LMODE_AUTOHALF || 3128 pPrt->PLinkMode == SK_LMODE_AUTOFULL || 3129 pPrt->PLinkMode == SK_LMODE_AUTOBOTH) && 3130 pPrt->PAutoNegFail) { 3131 /* Auto-negotiation is not done or failed */ 3132 return(0); 3133 } 3134 3135#ifdef GENESIS 3136 if (pAC->GIni.GIGenesis) { 3137 /* set Duplex Mode and Pause Mode */ 3138 SkXmInitDupMd(pAC, IoC, Port); 3139 3140 SkXmInitPauseMd(pAC, IoC, Port); 3141 3142 /* 3143 * Initialize the Interrupt Mask Register. Default IRQs are... 3144 * - Link Asynchronous Event 3145 * - Link Partner requests config 3146 * - Auto Negotiation Done 3147 * - Rx Counter Event Overflow 3148 * - Tx Counter Event Overflow 3149 * - Transmit FIFO Underrun 3150 */ 3151 IntMask = XM_DEF_MSK; 3152 3153#ifdef DEBUG 3154 /* add IRQ for Receive FIFO Overflow */ 3155 IntMask &= ~XM_IS_RXF_OV; 3156#endif /* DEBUG */ 3157 3158 if (pPrt->PhyType != SK_PHY_XMAC) { 3159 /* disable GP0 interrupt bit */ 3160 IntMask |= XM_IS_INP_ASS; 3161 } 3162 XM_OUT16(IoC, Port, XM_IMSK, IntMask); 3163 3164 /* get MMU Command Reg. */ 3165 XM_IN16(IoC, Port, XM_MMU_CMD, &Reg); 3166 3167 if (pPrt->PhyType != SK_PHY_XMAC && 3168 (pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL || 3169 pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL)) { 3170 /* set to Full Duplex */ 3171 Reg |= XM_MMU_GMII_FD; 3172 } 3173 3174 switch (pPrt->PhyType) { 3175 case SK_PHY_BCOM: 3176 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &SWord); 3177 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, 3178 (SK_U16)(SWord & ~PHY_B_AC_DIS_PM)); 3179 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, 3180 (SK_U16)PHY_B_DEF_MSK); 3181 break; 3182#ifdef OTHER_PHY 3183 case SK_PHY_LONE: 3184 SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, PHY_L_DEF_MSK); 3185 break; 3186 case SK_PHY_NAT: 3187 /* todo National: 3188 SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, PHY_N_DEF_MSK); */ 3189 /* no interrupts possible from National ??? */ 3190 break; 3191#endif /* OTHER_PHY */ 3192 } 3193 3194 /* enable Rx/Tx */ 3195 XM_OUT16(IoC, Port, XM_MMU_CMD, Reg | XM_MMU_ENA_RX | XM_MMU_ENA_TX); 3196 } 3197#endif /* GENESIS */ 3198 3199#ifdef YUKON 3200 if (pAC->GIni.GIYukon) { 3201 /* 3202 * Initialize the Interrupt Mask Register. Default IRQs are... 3203 * - Rx Counter Event Overflow 3204 * - Tx Counter Event Overflow 3205 * - Transmit FIFO Underrun 3206 */ 3207 IntMask = GMAC_DEF_MSK; 3208 3209#ifdef DEBUG 3210 /* add IRQ for Receive FIFO Overrun */ 3211 IntMask |= GM_IS_RX_FF_OR; 3212#endif /* DEBUG */ 3213 3214 SK_OUT8(IoC, GMAC_IRQ_MSK, (SK_U8)IntMask); 3215 3216 /* get General Purpose Control */ 3217 GM_IN16(IoC, Port, GM_GP_CTRL, &Reg); 3218 3219 if (pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL || 3220 pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL) { 3221 /* set to Full Duplex */ 3222 Reg |= GM_GPCR_DUP_FULL; 3223 } 3224 3225 /* enable Rx/Tx */ 3226 GM_OUT16(IoC, Port, GM_GP_CTRL, (SK_U16)(Reg | GM_GPCR_RX_ENA | 3227 GM_GPCR_TX_ENA)); 3228 3229#ifndef VCPU 3230 /* Enable all PHY interrupts */ 3231 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, 3232 (SK_U16)PHY_M_DEF_MSK); 3233#endif /* VCPU */ 3234 } 3235#endif /* YUKON */ 3236 3237 return(0); 3238 3239} /* SkMacRxTxEnable */ 3240 3241 3242/****************************************************************************** 3243 * 3244 * SkMacRxTxDisable() - Disable Receiver and Transmitter 3245 * 3246 * Description: disables Rx/Tx dep. on board type 3247 * 3248 * Returns: N/A 3249 */ 3250void SkMacRxTxDisable( 3251SK_AC *pAC, /* Adapter Context */ 3252SK_IOC IoC, /* IO context */ 3253int Port) /* Port Index (MAC_1 + n) */ 3254{ 3255 SK_U16 Word; 3256 3257#ifdef GENESIS 3258 if (pAC->GIni.GIGenesis) { 3259 3260 XM_IN16(IoC, Port, XM_MMU_CMD, &Word); 3261 3262 XM_OUT16(IoC, Port, XM_MMU_CMD, Word & ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX)); 3263 3264 /* dummy read to ensure writing */ 3265 XM_IN16(IoC, Port, XM_MMU_CMD, &Word); 3266 } 3267#endif /* GENESIS */ 3268 3269#ifdef YUKON 3270 if (pAC->GIni.GIYukon) { 3271 3272 GM_IN16(IoC, Port, GM_GP_CTRL, &Word); 3273 3274 GM_OUT16(IoC, Port, GM_GP_CTRL, (SK_U16)(Word & ~(GM_GPCR_RX_ENA | 3275 GM_GPCR_TX_ENA))); 3276 3277 /* dummy read to ensure writing */ 3278 GM_IN16(IoC, Port, GM_GP_CTRL, &Word); 3279 } 3280#endif /* YUKON */ 3281 3282} /* SkMacRxTxDisable */ 3283 3284 3285/****************************************************************************** 3286 * 3287 * SkMacIrqDisable() - Disable IRQ from MAC 3288 * 3289 * Description: sets the IRQ-mask to disable IRQ dep. on board type 3290 * 3291 * Returns: N/A 3292 */ 3293void SkMacIrqDisable( 3294SK_AC *pAC, /* Adapter Context */ 3295SK_IOC IoC, /* IO context */ 3296int Port) /* Port Index (MAC_1 + n) */ 3297{ 3298 SK_GEPORT *pPrt; 3299#ifdef GENESIS 3300 SK_U16 Word; 3301#endif 3302 3303 pPrt = &pAC->GIni.GP[Port]; 3304 3305#ifdef GENESIS 3306 if (pAC->GIni.GIGenesis) { 3307 3308 /* disable all XMAC IRQs */ 3309 XM_OUT16(IoC, Port, XM_IMSK, 0xffff); 3310 3311 /* Disable all PHY interrupts */ 3312 switch (pPrt->PhyType) { 3313 case SK_PHY_BCOM: 3314 /* Make sure that PHY is initialized */ 3315 if (pPrt->PState != SK_PRT_RESET) { 3316 /* NOT allowed if BCOM is in RESET state */ 3317 /* Disable Power Management if link is down */ 3318 SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Word); 3319 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, 3320 (SK_U16)(Word | PHY_B_AC_DIS_PM)); 3321 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, 0xffff); 3322 } 3323 break; 3324#ifdef OTHER_PHY 3325 case SK_PHY_LONE: 3326 SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, 0); 3327 break; 3328 case SK_PHY_NAT: 3329 /* todo: National 3330 SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, 0xffff); */ 3331 break; 3332#endif /* OTHER_PHY */ 3333 } 3334 } 3335#endif /* GENESIS */ 3336 3337#ifdef YUKON 3338 if (pAC->GIni.GIYukon) { 3339 /* disable all GMAC IRQs */ 3340 SK_OUT8(IoC, GMAC_IRQ_MSK, 0); 3341 3342#ifndef VCPU 3343 /* Disable all PHY interrupts */ 3344 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, 0); 3345#endif /* VCPU */ 3346 } 3347#endif /* YUKON */ 3348 3349} /* SkMacIrqDisable */ 3350 3351 3352#ifdef SK_DIAG 3353/****************************************************************************** 3354 * 3355 * SkXmSendCont() - Enable / Disable Send Continuous Mode 3356 * 3357 * Description: enable / disable Send Continuous Mode on XMAC 3358 * 3359 * Returns: 3360 * nothing 3361 */ 3362void SkXmSendCont( 3363SK_AC *pAC, /* adapter context */ 3364SK_IOC IoC, /* IO context */ 3365int Port, /* Port Index (MAC_1 + n) */ 3366SK_BOOL Enable) /* Enable / Disable */ 3367{ 3368 SK_U32 MdReg; 3369 3370 XM_IN32(IoC, Port, XM_MODE, &MdReg); 3371 3372 if (Enable) { 3373 MdReg |= XM_MD_TX_CONT; 3374 } 3375 else { 3376 MdReg &= ~XM_MD_TX_CONT; 3377 } 3378 /* setup Mode Register */ 3379 XM_OUT32(IoC, Port, XM_MODE, MdReg); 3380 3381} /* SkXmSendCont */ 3382 3383 3384/****************************************************************************** 3385 * 3386 * SkMacTimeStamp() - Enable / Disable Time Stamp 3387 * 3388 * Description: enable / disable Time Stamp generation for Rx packets 3389 * 3390 * Returns: 3391 * nothing 3392 */ 3393void SkMacTimeStamp( 3394SK_AC *pAC, /* adapter context */ 3395SK_IOC IoC, /* IO context */ 3396int Port, /* Port Index (MAC_1 + n) */ 3397SK_BOOL Enable) /* Enable / Disable */ 3398{ 3399 SK_U32 MdReg; 3400 SK_U8 TimeCtrl; 3401 3402 if (pAC->GIni.GIGenesis) { 3403 3404 XM_IN32(IoC, Port, XM_MODE, &MdReg); 3405 3406 if (Enable) { 3407 MdReg |= XM_MD_ATS; 3408 } 3409 else { 3410 MdReg &= ~XM_MD_ATS; 3411 } 3412 /* setup Mode Register */ 3413 XM_OUT32(IoC, Port, XM_MODE, MdReg); 3414 } 3415 else { 3416 if (Enable) { 3417 TimeCtrl = GMT_ST_START | GMT_ST_CLR_IRQ; 3418 } 3419 else { 3420 TimeCtrl = GMT_ST_STOP | GMT_ST_CLR_IRQ; 3421 } 3422 /* Start/Stop Time Stamp Timer */ 3423 SK_OUT8(IoC, GMAC_TI_ST_CTRL, TimeCtrl); 3424 } 3425 3426} /* SkMacTimeStamp*/ 3427 3428#else /* !SK_DIAG */ 3429 3430#ifdef GENESIS 3431/****************************************************************************** 3432 * 3433 * SkXmAutoNegLipaXmac() - Decides whether Link Partner could do auto-neg 3434 * 3435 * This function analyses the Interrupt status word. If any of the 3436 * Auto-negotiating interrupt bits are set, the PLipaAutoNeg variable 3437 * is set true. 3438 */ 3439void SkXmAutoNegLipaXmac( 3440SK_AC *pAC, /* adapter context */ 3441SK_IOC IoC, /* IO context */ 3442int Port, /* Port Index (MAC_1 + n) */ 3443SK_U16 IStatus) /* Interrupt Status word to analyse */ 3444{ 3445 SK_GEPORT *pPrt; 3446 3447 pPrt = &pAC->GIni.GP[Port]; 3448 3449 if (pPrt->PLipaAutoNeg != SK_LIPA_AUTO && 3450 (IStatus & (XM_IS_LIPA_RC | XM_IS_RX_PAGE | XM_IS_AND)) != 0) { 3451 3452 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 3453 ("AutoNegLipa: AutoNeg detected on Port %d, IStatus=0x%04X\n", 3454 Port, IStatus)); 3455 pPrt->PLipaAutoNeg = SK_LIPA_AUTO; 3456 } 3457} /* SkXmAutoNegLipaXmac */ 3458#endif /* GENESIS */ 3459 3460 3461/****************************************************************************** 3462 * 3463 * SkMacAutoNegLipaPhy() - Decides whether Link Partner could do auto-neg 3464 * 3465 * This function analyses the PHY status word. 3466 * If any of the Auto-negotiating bits are set, the PLipaAutoNeg variable 3467 * is set true. 3468 */ 3469void SkMacAutoNegLipaPhy( 3470SK_AC *pAC, /* adapter context */ 3471SK_IOC IoC, /* IO context */ 3472int Port, /* Port Index (MAC_1 + n) */ 3473SK_U16 PhyStat) /* PHY Status word to analyse */ 3474{ 3475 SK_GEPORT *pPrt; 3476 3477 pPrt = &pAC->GIni.GP[Port]; 3478 3479 if (pPrt->PLipaAutoNeg != SK_LIPA_AUTO && 3480 (PhyStat & PHY_ST_AN_OVER) != 0) { 3481 3482 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 3483 ("AutoNegLipa: AutoNeg detected on Port %d, PhyStat=0x%04X\n", 3484 Port, PhyStat)); 3485 pPrt->PLipaAutoNeg = SK_LIPA_AUTO; 3486 } 3487} /* SkMacAutoNegLipaPhy */ 3488 3489 3490#ifdef GENESIS 3491/****************************************************************************** 3492 * 3493 * SkXmIrq() - Interrupt Service Routine 3494 * 3495 * Description: services an Interrupt Request of the XMAC 3496 * 3497 * Note: 3498 * With an external PHY, some interrupt bits are not meaningfull any more: 3499 * - LinkAsyncEvent (bit #14) XM_IS_LNK_AE 3500 * - LinkPartnerReqConfig (bit #10) XM_IS_LIPA_RC 3501 * - Page Received (bit #9) XM_IS_RX_PAGE 3502 * - NextPageLoadedForXmt (bit #8) XM_IS_TX_PAGE 3503 * - AutoNegDone (bit #7) XM_IS_AND 3504 * Also probably not valid any more is the GP0 input bit: 3505 * - GPRegisterBit0set XM_IS_INP_ASS 3506 * 3507 * Returns: 3508 * nothing 3509 */ 3510static void SkXmIrq( 3511SK_AC *pAC, /* adapter context */ 3512SK_IOC IoC, /* IO context */ 3513int Port) /* Port Index (MAC_1 + n) */ 3514{ 3515 SK_GEPORT *pPrt; 3516 SK_EVPARA Para; 3517 SK_U16 IStatus; /* Interrupt status read from the XMAC */ 3518 SK_U16 IStatus2; 3519#ifdef SK_SLIM 3520 SK_U64 OverflowStatus; 3521#endif 3522 3523 pPrt = &pAC->GIni.GP[Port]; 3524 3525 XM_IN16(IoC, Port, XM_ISRC, &IStatus); 3526 3527 /* LinkPartner Auto-negable? */ 3528 if (pPrt->PhyType == SK_PHY_XMAC) { 3529 SkXmAutoNegLipaXmac(pAC, IoC, Port, IStatus); 3530 } 3531 else { 3532 /* mask bits that are not used with ext. PHY */ 3533 IStatus &= ~(XM_IS_LNK_AE | XM_IS_LIPA_RC | 3534 XM_IS_RX_PAGE | XM_IS_TX_PAGE | 3535 XM_IS_AND | XM_IS_INP_ASS); 3536 } 3537 3538 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, 3539 ("XmacIrq Port %d Isr 0x%04X\n", Port, IStatus)); 3540 3541 if (!pPrt->PHWLinkUp) { 3542 /* Spurious XMAC interrupt */ 3543 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, 3544 ("SkXmIrq: spurious interrupt on Port %d\n", Port)); 3545 return; 3546 } 3547 3548 if ((IStatus & XM_IS_INP_ASS) != 0) { 3549 /* Reread ISR Register if link is not in sync */ 3550 XM_IN16(IoC, Port, XM_ISRC, &IStatus2); 3551 3552 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, 3553 ("SkXmIrq: Link async. Double check Port %d 0x%04X 0x%04X\n", 3554 Port, IStatus, IStatus2)); 3555 IStatus &= ~XM_IS_INP_ASS; 3556 IStatus |= IStatus2; 3557 } 3558 3559 if ((IStatus & XM_IS_LNK_AE) != 0) { 3560 /* not used, GP0 is used instead */ 3561 } 3562 3563 if ((IStatus & XM_IS_TX_ABORT) != 0) { 3564 /* not used */ 3565 } 3566 3567 if ((IStatus & XM_IS_FRC_INT) != 0) { 3568 /* not used, use ASIC IRQ instead if needed */ 3569 } 3570 3571 if ((IStatus & (XM_IS_INP_ASS | XM_IS_LIPA_RC | XM_IS_RX_PAGE)) != 0) { 3572 SkHWLinkDown(pAC, IoC, Port); 3573 3574 /* Signal to RLMT */ 3575 Para.Para32[0] = (SK_U32)Port; 3576 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); 3577 3578 SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME, 3579 SKGE_HWAC, SK_HWEV_WATIM, Para); 3580 } 3581 3582 if ((IStatus & XM_IS_RX_PAGE) != 0) { 3583 /* not used */ 3584 } 3585 3586 if ((IStatus & XM_IS_TX_PAGE) != 0) { 3587 /* not used */ 3588 } 3589 3590 if ((IStatus & XM_IS_AND) != 0) { 3591 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, 3592 ("SkXmIrq: AND on link that is up Port %d\n", Port)); 3593 } 3594 3595 if ((IStatus & XM_IS_TSC_OV) != 0) { 3596 /* not used */ 3597 } 3598 3599 /* Combined Tx & Rx Counter Overflow SIRQ Event */ 3600 if ((IStatus & (XM_IS_RXC_OV | XM_IS_TXC_OV)) != 0) { 3601#ifdef SK_SLIM 3602 SkXmOverflowStatus(pAC, IoC, Port, IStatus, &OverflowStatus); 3603#else 3604 Para.Para32[0] = (SK_U32)Port; 3605 Para.Para32[1] = (SK_U32)IStatus; 3606 SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_SIRQ_OVERFLOW, Para); 3607#endif /* SK_SLIM */ 3608 } 3609 3610 if ((IStatus & XM_IS_RXF_OV) != 0) { 3611 /* normal situation -> no effect */ 3612#ifdef DEBUG 3613 pPrt->PRxOverCnt++; 3614#endif /* DEBUG */ 3615 } 3616 3617 if ((IStatus & XM_IS_TXF_UR) != 0) { 3618 /* may NOT happen -> error log */ 3619 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E020, SKERR_SIRQ_E020MSG); 3620 } 3621 3622 if ((IStatus & XM_IS_TX_COMP) != 0) { 3623 /* not served here */ 3624 } 3625 3626 if ((IStatus & XM_IS_RX_COMP) != 0) { 3627 /* not served here */ 3628 } 3629} /* SkXmIrq */ 3630#endif /* GENESIS */ 3631 3632 3633#ifdef YUKON 3634/****************************************************************************** 3635 * 3636 * SkGmIrq() - Interrupt Service Routine 3637 * 3638 * Description: services an Interrupt Request of the GMAC 3639 * 3640 * Note: 3641 * 3642 * Returns: 3643 * nothing 3644 */ 3645static void SkGmIrq( 3646SK_AC *pAC, /* adapter context */ 3647SK_IOC IoC, /* IO context */ 3648int Port) /* Port Index (MAC_1 + n) */ 3649{ 3650 SK_GEPORT *pPrt; 3651 SK_U8 IStatus; /* Interrupt status */ 3652#ifdef SK_SLIM 3653 SK_U64 OverflowStatus; 3654#else 3655 SK_EVPARA Para; 3656#endif 3657 3658 pPrt = &pAC->GIni.GP[Port]; 3659 3660 SK_IN8(IoC, GMAC_IRQ_SRC, &IStatus); 3661 3662#ifdef XXX 3663 /* LinkPartner Auto-negable? */ 3664 SkMacAutoNegLipaPhy(pAC, IoC, Port, IStatus); 3665#endif 3666 3667 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, 3668 ("GmacIrq Port %d Isr 0x%04X\n", Port, IStatus)); 3669 3670 /* Combined Tx & Rx Counter Overflow SIRQ Event */ 3671 if (IStatus & (GM_IS_RX_CO_OV | GM_IS_TX_CO_OV)) { 3672 /* these IRQs will be cleared by reading GMACs register */ 3673#ifdef SK_SLIM 3674 SkGmOverflowStatus(pAC, IoC, Port, IStatus, &OverflowStatus); 3675#else 3676 Para.Para32[0] = (SK_U32)Port; 3677 Para.Para32[1] = (SK_U32)IStatus; 3678 SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_SIRQ_OVERFLOW, Para); 3679#endif 3680 } 3681 3682 if (IStatus & GM_IS_RX_FF_OR) { 3683 /* clear GMAC Rx FIFO Overrun IRQ */ 3684 SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_CLI_RX_FO); 3685#ifdef DEBUG 3686 pPrt->PRxOverCnt++; 3687#endif /* DEBUG */ 3688 } 3689 3690 if (IStatus & GM_IS_TX_FF_UR) { 3691 /* clear GMAC Tx FIFO Underrun IRQ */ 3692 SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_CLI_TX_FU); 3693 /* may NOT happen -> error log */ 3694 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E020, SKERR_SIRQ_E020MSG); 3695 } 3696 3697 if (IStatus & GM_IS_TX_COMPL) { 3698 /* not served here */ 3699 } 3700 3701 if (IStatus & GM_IS_RX_COMPL) { 3702 /* not served here */ 3703 } 3704} /* SkGmIrq */ 3705#endif /* YUKON */ 3706 3707 3708/****************************************************************************** 3709 * 3710 * SkMacIrq() - Interrupt Service Routine for MAC 3711 * 3712 * Description: calls the Interrupt Service Routine dep. on board type 3713 * 3714 * Returns: 3715 * nothing 3716 */ 3717void SkMacIrq( 3718SK_AC *pAC, /* adapter context */ 3719SK_IOC IoC, /* IO context */ 3720int Port) /* Port Index (MAC_1 + n) */ 3721{ 3722#ifdef GENESIS 3723 if (pAC->GIni.GIGenesis) { 3724 /* IRQ from XMAC */ 3725 SkXmIrq(pAC, IoC, Port); 3726 } 3727#endif /* GENESIS */ 3728 3729#ifdef YUKON 3730 if (pAC->GIni.GIYukon) { 3731 /* IRQ from GMAC */ 3732 SkGmIrq(pAC, IoC, Port); 3733 } 3734#endif /* YUKON */ 3735 3736} /* SkMacIrq */ 3737 3738#endif /* !SK_DIAG */ 3739 3740#ifdef GENESIS 3741/****************************************************************************** 3742 * 3743 * SkXmUpdateStats() - Force the XMAC to output the current statistic 3744 * 3745 * Description: 3746 * The XMAC holds its statistic internally. To obtain the current 3747 * values a command must be sent so that the statistic data will 3748 * be written to a predefined memory area on the adapter. 3749 * 3750 * Returns: 3751 * 0: success 3752 * 1: something went wrong 3753 */ 3754int SkXmUpdateStats( 3755SK_AC *pAC, /* adapter context */ 3756SK_IOC IoC, /* IO context */ 3757unsigned int Port) /* Port Index (MAC_1 + n) */ 3758{ 3759 SK_GEPORT *pPrt; 3760 SK_U16 StatReg; 3761 int WaitIndex; 3762 3763 pPrt = &pAC->GIni.GP[Port]; 3764 WaitIndex = 0; 3765 3766 /* Send an update command to XMAC specified */ 3767 XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_SNP_TXC | XM_SC_SNP_RXC); 3768 3769 /* 3770 * It is an auto-clearing register. If the command bits 3771 * went to zero again, the statistics are transferred. 3772 * Normally the command should be executed immediately. 3773 * But just to be sure we execute a loop. 3774 */ 3775 do { 3776 3777 XM_IN16(IoC, Port, XM_STAT_CMD, &StatReg); 3778 3779 if (++WaitIndex > 10) { 3780 3781 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E021, SKERR_HWI_E021MSG); 3782 3783 return(1); 3784 } 3785 } while ((StatReg & (XM_SC_SNP_TXC | XM_SC_SNP_RXC)) != 0); 3786 3787 return(0); 3788} /* SkXmUpdateStats */ 3789 3790 3791/****************************************************************************** 3792 * 3793 * SkXmMacStatistic() - Get XMAC counter value 3794 * 3795 * Description: 3796 * Gets the 32bit counter value. Except for the octet counters 3797 * the lower 32bit are counted in hardware and the upper 32bit 3798 * must be counted in software by monitoring counter overflow interrupts. 3799 * 3800 * Returns: 3801 * 0: success 3802 * 1: something went wrong 3803 */ 3804int SkXmMacStatistic( 3805SK_AC *pAC, /* adapter context */ 3806SK_IOC IoC, /* IO context */ 3807unsigned int Port, /* Port Index (MAC_1 + n) */ 3808SK_U16 StatAddr, /* MIB counter base address */ 3809SK_U32 SK_FAR *pVal) /* ptr to return statistic value */ 3810{ 3811 if ((StatAddr < XM_TXF_OK) || (StatAddr > XM_RXF_MAX_SZ)) { 3812 3813 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E022, SKERR_HWI_E022MSG); 3814 3815 return(1); 3816 } 3817 3818 XM_IN32(IoC, Port, StatAddr, pVal); 3819 3820 return(0); 3821} /* SkXmMacStatistic */ 3822 3823 3824/****************************************************************************** 3825 * 3826 * SkXmResetCounter() - Clear MAC statistic counter 3827 * 3828 * Description: 3829 * Force the XMAC to clear its statistic counter. 3830 * 3831 * Returns: 3832 * 0: success 3833 * 1: something went wrong 3834 */ 3835int SkXmResetCounter( 3836SK_AC *pAC, /* adapter context */ 3837SK_IOC IoC, /* IO context */ 3838unsigned int Port) /* Port Index (MAC_1 + n) */ 3839{ 3840 XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_CLR_RXC | XM_SC_CLR_TXC); 3841 /* Clear two times according to Errata #3 */ 3842 XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_CLR_RXC | XM_SC_CLR_TXC); 3843 3844 return(0); 3845} /* SkXmResetCounter */ 3846 3847 3848/****************************************************************************** 3849 * 3850 * SkXmOverflowStatus() - Gets the status of counter overflow interrupt 3851 * 3852 * Description: 3853 * Checks the source causing an counter overflow interrupt. On success the 3854 * resulting counter overflow status is written to <pStatus>, whereas the 3855 * upper dword stores the XMAC ReceiveCounterEvent register and the lower 3856 * dword the XMAC TransmitCounterEvent register. 3857 * 3858 * Note: 3859 * For XMAC the interrupt source is a self-clearing register, so the source 3860 * must be checked only once. SIRQ module does another check to be sure 3861 * that no interrupt get lost during process time. 3862 * 3863 * Returns: 3864 * 0: success 3865 * 1: something went wrong 3866 */ 3867int SkXmOverflowStatus( 3868SK_AC *pAC, /* adapter context */ 3869SK_IOC IoC, /* IO context */ 3870unsigned int Port, /* Port Index (MAC_1 + n) */ 3871SK_U16 IStatus, /* Interupt Status from MAC */ 3872SK_U64 SK_FAR *pStatus) /* ptr for return overflow status value */ 3873{ 3874 SK_U64 Status; /* Overflow status */ 3875 SK_U32 RegVal; 3876 3877 Status = 0; 3878 3879 if ((IStatus & XM_IS_RXC_OV) != 0) { 3880 3881 XM_IN32(IoC, Port, XM_RX_CNT_EV, &RegVal); 3882 Status |= (SK_U64)RegVal << 32; 3883 } 3884 3885 if ((IStatus & XM_IS_TXC_OV) != 0) { 3886 3887 XM_IN32(IoC, Port, XM_TX_CNT_EV, &RegVal); 3888 Status |= (SK_U64)RegVal; 3889 } 3890 3891 *pStatus = Status; 3892 3893 return(0); 3894} /* SkXmOverflowStatus */ 3895#endif /* GENESIS */ 3896 3897 3898#ifdef YUKON 3899/****************************************************************************** 3900 * 3901 * SkGmUpdateStats() - Force the GMAC to output the current statistic 3902 * 3903 * Description: 3904 * Empty function for GMAC. Statistic data is accessible in direct way. 3905 * 3906 * Returns: 3907 * 0: success 3908 * 1: something went wrong 3909 */ 3910int SkGmUpdateStats( 3911SK_AC *pAC, /* adapter context */ 3912SK_IOC IoC, /* IO context */ 3913unsigned int Port) /* Port Index (MAC_1 + n) */ 3914{ 3915 return(0); 3916} 3917 3918 3919/****************************************************************************** 3920 * 3921 * SkGmMacStatistic() - Get GMAC counter value 3922 * 3923 * Description: 3924 * Gets the 32bit counter value. Except for the octet counters 3925 * the lower 32bit are counted in hardware and the upper 32bit 3926 * must be counted in software by monitoring counter overflow interrupts. 3927 * 3928 * Returns: 3929 * 0: success 3930 * 1: something went wrong 3931 */ 3932int SkGmMacStatistic( 3933SK_AC *pAC, /* adapter context */ 3934SK_IOC IoC, /* IO context */ 3935unsigned int Port, /* Port Index (MAC_1 + n) */ 3936SK_U16 StatAddr, /* MIB counter base address */ 3937SK_U32 SK_FAR *pVal) /* ptr to return statistic value */ 3938{ 3939 3940 if ((StatAddr < GM_RXF_UC_OK) || (StatAddr > GM_TXE_FIFO_UR)) { 3941 3942 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E022, SKERR_HWI_E022MSG); 3943 3944 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 3945 ("SkGmMacStat: wrong MIB counter 0x%04X\n", StatAddr)); 3946 return(1); 3947 } 3948 3949 GM_IN32(IoC, Port, StatAddr, pVal); 3950 3951 return(0); 3952} /* SkGmMacStatistic */ 3953 3954 3955/****************************************************************************** 3956 * 3957 * SkGmResetCounter() - Clear MAC statistic counter 3958 * 3959 * Description: 3960 * Force GMAC to clear its statistic counter. 3961 * 3962 * Returns: 3963 * 0: success 3964 * 1: something went wrong 3965 */ 3966int SkGmResetCounter( 3967SK_AC *pAC, /* adapter context */ 3968SK_IOC IoC, /* IO context */ 3969unsigned int Port) /* Port Index (MAC_1 + n) */ 3970{ 3971 SK_U16 Reg; /* Phy Address Register */ 3972 SK_U16 Word; 3973 int i; 3974 3975 GM_IN16(IoC, Port, GM_PHY_ADDR, &Reg); 3976 3977 /* set MIB Clear Counter Mode */ 3978 GM_OUT16(IoC, Port, GM_PHY_ADDR, Reg | GM_PAR_MIB_CLR); 3979 3980 /* read all MIB Counters with Clear Mode set */ 3981 for (i = 0; i < GM_MIB_CNT_SIZE; i++) { 3982 /* the reset is performed only when the lower 16 bits are read */ 3983 GM_IN16(IoC, Port, GM_MIB_CNT_BASE + 8*i, &Word); 3984 } 3985 3986 /* clear MIB Clear Counter Mode */ 3987 GM_OUT16(IoC, Port, GM_PHY_ADDR, Reg); 3988 3989 return(0); 3990} /* SkGmResetCounter */ 3991 3992 3993/****************************************************************************** 3994 * 3995 * SkGmOverflowStatus() - Gets the status of counter overflow interrupt 3996 * 3997 * Description: 3998 * Checks the source causing an counter overflow interrupt. On success the 3999 * resulting counter overflow status is written to <pStatus>, whereas the 4000 * the following bit coding is used: 4001 * 63:56 - unused 4002 * 55:48 - TxRx interrupt register bit7:0 4003 * 32:47 - Rx interrupt register 4004 * 31:24 - unused 4005 * 23:16 - TxRx interrupt register bit15:8 4006 * 15:0 - Tx interrupt register 4007 * 4008 * Returns: 4009 * 0: success 4010 * 1: something went wrong 4011 */ 4012int SkGmOverflowStatus( 4013SK_AC *pAC, /* adapter context */ 4014SK_IOC IoC, /* IO context */ 4015unsigned int Port, /* Port Index (MAC_1 + n) */ 4016SK_U16 IStatus, /* Interupt Status from MAC */ 4017SK_U64 SK_FAR *pStatus) /* ptr for return overflow status value */ 4018{ 4019 SK_U64 Status; /* Overflow status */ 4020 SK_U16 RegVal; 4021 4022 Status = 0; 4023 4024 if ((IStatus & GM_IS_RX_CO_OV) != 0) { 4025 /* this register is self-clearing after read */ 4026 GM_IN16(IoC, Port, GM_RX_IRQ_SRC, &RegVal); 4027 Status |= (SK_U64)RegVal << 32; 4028 } 4029 4030 if ((IStatus & GM_IS_TX_CO_OV) != 0) { 4031 /* this register is self-clearing after read */ 4032 GM_IN16(IoC, Port, GM_TX_IRQ_SRC, &RegVal); 4033 Status |= (SK_U64)RegVal; 4034 } 4035 4036 /* this register is self-clearing after read */ 4037 GM_IN16(IoC, Port, GM_TR_IRQ_SRC, &RegVal); 4038 /* Rx overflow interrupt register bits (LoByte)*/ 4039 Status |= (SK_U64)((SK_U8)RegVal) << 48; 4040 /* Tx overflow interrupt register bits (HiByte)*/ 4041 Status |= (SK_U64)(RegVal >> 8) << 16; 4042 4043 *pStatus = Status; 4044 4045 return(0); 4046} /* SkGmOverflowStatus */ 4047 4048 4049#ifndef SK_SLIM 4050/****************************************************************************** 4051 * 4052 * SkGmCableDiagStatus() - Starts / Gets status of cable diagnostic test 4053 * 4054 * Description: 4055 * starts the cable diagnostic test if 'StartTest' is true 4056 * gets the results if 'StartTest' is true 4057 * 4058 * NOTE: this test is meaningful only when link is down 4059 * 4060 * Returns: 4061 * 0: success 4062 * 1: no YUKON copper 4063 * 2: test in progress 4064 */ 4065int SkGmCableDiagStatus( 4066SK_AC *pAC, /* adapter context */ 4067SK_IOC IoC, /* IO context */ 4068int Port, /* Port Index (MAC_1 + n) */ 4069SK_BOOL StartTest) /* flag for start / get result */ 4070{ 4071 int i; 4072 SK_U16 RegVal; 4073 SK_GEPORT *pPrt; 4074 4075 pPrt = &pAC->GIni.GP[Port]; 4076 4077 if (pPrt->PhyType != SK_PHY_MARV_COPPER) { 4078 4079 return(1); 4080 } 4081 4082 if (StartTest) { 4083 /* only start the cable test */ 4084 if ((pPrt->PhyId1 & PHY_I1_REV_MSK) < 4) { 4085 SkGmPhyWrite(pAC, IoC, Port, 29, 0x001e); 4086 4087 SkGmPhyWrite(pAC, IoC, Port, 30, 0xcc00); 4088 SkGmPhyWrite(pAC, IoC, Port, 30, 0xc800); 4089 SkGmPhyWrite(pAC, IoC, Port, 30, 0xc400); 4090 SkGmPhyWrite(pAC, IoC, Port, 30, 0xc000); 4091 SkGmPhyWrite(pAC, IoC, Port, 30, 0xc100); 4092 } 4093 4094 /* set address to 0 for MDI[0] */ 4095 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 0); 4096 4097 /* Read Cable Diagnostic Reg */ 4098 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal); 4099 4100 /* start Cable Diagnostic Test */ 4101 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, 4102 (SK_U16)(RegVal | PHY_M_CABD_ENA_TEST)); 4103 4104 return(0); 4105 } 4106 4107 /* Read Cable Diagnostic Reg */ 4108 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal); 4109 4110 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, 4111 ("PHY Cable Diag.=0x%04X\n", RegVal)); 4112 4113 if ((RegVal & PHY_M_CABD_ENA_TEST) != 0) { 4114 /* test is running */ 4115 return(2); 4116 } 4117 4118 /* get the test results */ 4119 for (i = 0; i < 4; i++) { 4120 /* set address to i for MDI[i] */ 4121 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, (SK_U16)i); 4122 4123 /* get Cable Diagnostic values */ 4124 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal); 4125 4126 pPrt->PMdiPairLen[i] = (SK_U8)(RegVal & PHY_M_CABD_DIST_MSK); 4127 4128 pPrt->PMdiPairSts[i] = (SK_U8)((RegVal & PHY_M_CABD_STAT_MSK) >> 13); 4129 } 4130 4131 return(0); 4132} /* SkGmCableDiagStatus */ 4133#endif /* !SK_SLIM */ 4134#endif /* YUKON */ 4135 4136/* End of file */ 4137