1 /******************************************************************************
 
   4  * Project:     Gigabit Ethernet Adapters, Common Modules
 
   5  * Version:     $Revision: 1.102 $
 
   6  * Date:        $Date: 2003/10/02 16:53:58 $
 
   7  * Purpose:     Contains functions to initialize the MACs and PHYs
 
   9  ******************************************************************************/
 
  11 /******************************************************************************
 
  13  *      (C)Copyright 1998-2002 SysKonnect.
 
  14  *      (C)Copyright 2002-2003 Marvell.
 
  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.
 
  21  *      The information in this file is provided "AS IS" without warranty.
 
  23  ******************************************************************************/
 
  25 #include "h/skdrv1st.h"
 
  26 #include "h/skdrv2nd.h"
 
  28 /* typedefs *******************************************************************/
 
  30 /* BCOM PHY magic pattern list */
 
  31 typedef struct s_PhyHack {
 
  32         int             PhyReg;         /* Phy register */
 
  33         SK_U16  PhyVal;         /* Value to write */
 
  36 /* local variables ************************************************************/
 
  38 #if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
 
  39 static const char SysKonnectFileId[] =
 
  40         "@(#) $Id: skxmac2.c,v 1.102 2003/10/02 16:53:58 rschmidt Exp $ (C) Marvell.";
 
  44 static 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 },
 
  50 static BCOM_HACK BcomRegC0Hack[] = {
 
  51  { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1204 }, { 0x17, 0x0013 },
 
  52  { 0x15, 0x0A04 }, { 0x18, 0x0420 },
 
  57 /* function prototypes ********************************************************/
 
  59 static void     SkXmInitPhyXmac(SK_AC*, SK_IOC, int, SK_BOOL);
 
  60 static void     SkXmInitPhyBcom(SK_AC*, SK_IOC, int, SK_BOOL);
 
  61 static int      SkXmAutoNegDoneXmac(SK_AC*, SK_IOC, int);
 
  62 static int      SkXmAutoNegDoneBcom(SK_AC*, SK_IOC, int);
 
  65 static void     SkGmInitPhyMarv(SK_AC*, SK_IOC, int, SK_BOOL);
 
  66 static int      SkGmAutoNegDoneMarv(SK_AC*, SK_IOC, int);
 
  69 static void     SkXmInitPhyLone(SK_AC*, SK_IOC, int, SK_BOOL);
 
  70 static void     SkXmInitPhyNat (SK_AC*, SK_IOC, int, SK_BOOL);
 
  71 static int      SkXmAutoNegDoneLone(SK_AC*, SK_IOC, int);
 
  72 static int      SkXmAutoNegDoneNat (SK_AC*, SK_IOC, int);
 
  73 #endif /* OTHER_PHY */
 
  77 /******************************************************************************
 
  79  *      SkXmPhyRead() - Read from XMAC PHY register
 
  81  * Description: reads a 16-bit word from XMAC PHY or ext. PHY
 
  87 SK_AC   *pAC,                   /* Adapter Context */
 
  88 SK_IOC  IoC,                    /* I/O Context */
 
  89 int             Port,                   /* Port Index (MAC_1 + n) */
 
  90 int             PhyReg,                 /* Register Address (Offset) */
 
  91 SK_U16  SK_FAR *pVal)   /* Pointer to Value */
 
  96         pPrt = &pAC->GIni.GP[Port];
 
  98         /* write the PHY register's address */
 
  99         XM_OUT16(IoC, Port, XM_PHY_ADDR, PhyReg | pPrt->PhyAddr);
 
 101         /* get the PHY register's value */
 
 102         XM_IN16(IoC, Port, XM_PHY_DATA, pVal);
 
 104         if (pPrt->PhyType != SK_PHY_XMAC) {
 
 106                         XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu);
 
 107                         /* wait until 'Ready' is set */
 
 108                 } while ((Mmu & XM_MMU_PHY_RDY) == 0);
 
 110                 /* get the PHY register's value */
 
 111                 XM_IN16(IoC, Port, XM_PHY_DATA, pVal);
 
 116 /******************************************************************************
 
 118  *      SkXmPhyWrite() - Write to XMAC PHY register
 
 120  * Description: writes a 16-bit word to XMAC PHY or ext. PHY
 
 126 SK_AC   *pAC,           /* Adapter Context */
 
 127 SK_IOC  IoC,            /* I/O Context */
 
 128 int             Port,           /* Port Index (MAC_1 + n) */
 
 129 int             PhyReg,         /* Register Address (Offset) */
 
 130 SK_U16  Val)            /* Value */
 
 135         pPrt = &pAC->GIni.GP[Port];
 
 137         if (pPrt->PhyType != SK_PHY_XMAC) {
 
 139                         XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu);
 
 140                         /* wait until 'Busy' is cleared */
 
 141                 } while ((Mmu & XM_MMU_PHY_BUSY) != 0);
 
 144         /* write the PHY register's address */
 
 145         XM_OUT16(IoC, Port, XM_PHY_ADDR, PhyReg | pPrt->PhyAddr);
 
 147         /* write the PHY register's value */
 
 148         XM_OUT16(IoC, Port, XM_PHY_DATA, Val);
 
 150         if (pPrt->PhyType != SK_PHY_XMAC) {
 
 152                         XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu);
 
 153                         /* wait until 'Busy' is cleared */
 
 154                 } while ((Mmu & XM_MMU_PHY_BUSY) != 0);
 
 161 /******************************************************************************
 
 163  *      SkGmPhyRead() - Read from GPHY register
 
 165  * Description: reads a 16-bit word from GPHY through MDIO
 
 171 SK_AC   *pAC,                   /* Adapter Context */
 
 172 SK_IOC  IoC,                    /* I/O Context */
 
 173 int             Port,                   /* Port Index (MAC_1 + n) */
 
 174 int             PhyReg,                 /* Register Address (Offset) */
 
 175 SK_U16  SK_FAR *pVal)   /* Pointer to Value */
 
 183         VCPUgetTime(&SimCyle, &SimLowTime);
 
 184         VCPUprintf(0, "SkGmPhyRead(%u), SimCyle=%u, SimLowTime=%u\n",
 
 185                 PhyReg, SimCyle, SimLowTime);
 
 188         pPrt = &pAC->GIni.GP[Port];
 
 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);
 
 194         GM_OUT16(IoC, Port, GM_SMI_CTRL, *pVal);
 
 196         GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
 
 198         /* additional check for MDC/MDIO activity */
 
 199         if ((Ctrl & GM_SMI_CT_BUSY) == 0) {
 
 204         *pVal |= GM_SMI_CT_BUSY;
 
 211                 GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
 
 213         /* wait until 'ReadValid' is set */
 
 214         } while (Ctrl == *pVal);
 
 216         /* get the PHY register's value */
 
 217         GM_IN16(IoC, Port, GM_SMI_DATA, pVal);
 
 220         VCPUgetTime(&SimCyle, &SimLowTime);
 
 221         VCPUprintf(0, "VCPUgetTime(), SimCyle=%u, SimLowTime=%u\n",
 
 222                 SimCyle, SimLowTime);
 
 228 /******************************************************************************
 
 230  *      SkGmPhyWrite() - Write to GPHY register
 
 232  * Description: writes a 16-bit word to GPHY through MDIO
 
 238 SK_AC   *pAC,           /* Adapter Context */
 
 239 SK_IOC  IoC,            /* I/O Context */
 
 240 int             Port,           /* Port Index (MAC_1 + n) */
 
 241 int             PhyReg,         /* Register Address (Offset) */
 
 242 SK_U16  Val)            /* Value */
 
 251         VCPUgetTime(&SimCyle, &SimLowTime);
 
 252         VCPUprintf(0, "SkGmPhyWrite(Reg=%u, Val=0x%04x), SimCyle=%u, SimLowTime=%u\n",
 
 253                 PhyReg, Val, SimCyle, SimLowTime);
 
 256         pPrt = &pAC->GIni.GP[Port];
 
 258         /* write the PHY register's value */
 
 259         GM_OUT16(IoC, Port, GM_SMI_DATA, Val);
 
 261         /* set PHY-Register offset and 'Write' OpCode (= 0) */
 
 262         Val = GM_SMI_CT_PHY_AD(pPrt->PhyAddr) | GM_SMI_CT_REG_AD(PhyReg);
 
 264         GM_OUT16(IoC, Port, GM_SMI_CTRL, Val);
 
 266         GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
 
 268         /* additional check for MDC/MDIO activity */
 
 269         if ((Ctrl & GM_SMI_CT_BUSY) == 0) {
 
 273         Val |= GM_SMI_CT_BUSY;
 
 277                 /* read Timer value */
 
 278                 SK_IN32(IoC, B2_TI_VAL, &DWord);
 
 283                 GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
 
 285         /* wait until 'Busy' is cleared */
 
 286         } while (Ctrl == Val);
 
 289         VCPUgetTime(&SimCyle, &SimLowTime);
 
 290         VCPUprintf(0, "VCPUgetTime(), SimCyle=%u, SimLowTime=%u\n",
 
 291                 SimCyle, SimLowTime);
 
 299 /******************************************************************************
 
 301  *      SkGePhyRead() - Read from PHY register
 
 303  * Description: calls a read PHY routine dep. on board type
 
 309 SK_AC   *pAC,           /* Adapter Context */
 
 310 SK_IOC  IoC,            /* I/O Context */
 
 311 int             Port,           /* Port Index (MAC_1 + n) */
 
 312 int             PhyReg,         /* Register Address (Offset) */
 
 313 SK_U16  *pVal)          /* Pointer to Value */
 
 315         void (*r_func)(SK_AC *pAC, SK_IOC IoC, int Port, int Reg, SK_U16 *pVal);
 
 317         if (pAC->GIni.GIGenesis) {
 
 318                 r_func = SkXmPhyRead;
 
 321                 r_func = SkGmPhyRead;
 
 324         r_func(pAC, IoC, Port, PhyReg, pVal);
 
 328 /******************************************************************************
 
 330  *      SkGePhyWrite() - Write to PHY register
 
 332  * Description: calls a write PHY routine dep. on board type
 
 338 SK_AC   *pAC,           /* Adapter Context */
 
 339 SK_IOC  IoC,            /* I/O Context */
 
 340 int             Port,           /* Port Index (MAC_1 + n) */
 
 341 int             PhyReg,         /* Register Address (Offset) */
 
 342 SK_U16  Val)            /* Value */
 
 344         void (*w_func)(SK_AC *pAC, SK_IOC IoC, int Port, int Reg, SK_U16 Val);
 
 346         if (pAC->GIni.GIGenesis) {
 
 347                 w_func = SkXmPhyWrite;
 
 350                 w_func = SkGmPhyWrite;
 
 353         w_func(pAC, IoC, Port, PhyReg, Val);
 
 358 /******************************************************************************
 
 360  *      SkMacPromiscMode() - Enable / Disable Promiscuous Mode
 
 363  *   enables / disables promiscuous mode by setting Mode Register (XMAC) or
 
 364  *   Receive Control Register (GMAC) dep. on board type         
 
 369 void SkMacPromiscMode(
 
 370 SK_AC   *pAC,   /* adapter context */
 
 371 SK_IOC  IoC,    /* IO context */
 
 372 int             Port,   /* Port Index (MAC_1 + n) */
 
 373 SK_BOOL Enable) /* Enable / Disable */
 
 383         if (pAC->GIni.GIGenesis) {
 
 385                 XM_IN32(IoC, Port, XM_MODE, &MdReg);
 
 386                 /* enable or disable promiscuous mode */
 
 388                         MdReg |= XM_MD_ENA_PROM;
 
 391                         MdReg &= ~XM_MD_ENA_PROM;
 
 393                 /* setup Mode Register */
 
 394                 XM_OUT32(IoC, Port, XM_MODE, MdReg);
 
 399         if (pAC->GIni.GIYukon) {
 
 401                 GM_IN16(IoC, Port, GM_RX_CTRL, &RcReg);
 
 403                 /* enable or disable unicast and multicast filtering */
 
 405                         RcReg &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
 
 408                         RcReg |= (GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
 
 410                 /* setup Receive Control Register */
 
 411                 GM_OUT16(IoC, Port, GM_RX_CTRL, RcReg);
 
 415 }       /* SkMacPromiscMode*/
 
 418 /******************************************************************************
 
 420  *      SkMacHashing() - Enable / Disable Hashing
 
 423  *   enables / disables hashing by setting Mode Register (XMAC) or
 
 424  *   Receive Control Register (GMAC) dep. on board type         
 
 430 SK_AC   *pAC,   /* adapter context */
 
 431 SK_IOC  IoC,    /* IO context */
 
 432 int             Port,   /* Port Index (MAC_1 + n) */
 
 433 SK_BOOL Enable) /* Enable / Disable */
 
 443         if (pAC->GIni.GIGenesis) {
 
 445                 XM_IN32(IoC, Port, XM_MODE, &MdReg);
 
 446                 /* enable or disable hashing */
 
 448                         MdReg |= XM_MD_ENA_HASH;
 
 451                         MdReg &= ~XM_MD_ENA_HASH;
 
 453                 /* setup Mode Register */
 
 454                 XM_OUT32(IoC, Port, XM_MODE, MdReg);
 
 459         if (pAC->GIni.GIYukon) {
 
 461                 GM_IN16(IoC, Port, GM_RX_CTRL, &RcReg);
 
 463                 /* enable or disable multicast filtering */
 
 465                         RcReg |= GM_RXCR_MCF_ENA;
 
 468                         RcReg &= ~GM_RXCR_MCF_ENA;
 
 470                 /* setup Receive Control Register */
 
 471                 GM_OUT16(IoC, Port, GM_RX_CTRL, RcReg);
 
 479 /******************************************************************************
 
 481  *      SkXmSetRxCmd() - Modify the value of the XMAC's Rx Command Register
 
 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
 
 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.
 
 501 static void SkXmSetRxCmd(
 
 502 SK_AC   *pAC,           /* adapter context */
 
 503 SK_IOC  IoC,            /* IO context */
 
 504 int             Port,           /* Port Index (MAC_1 + n) */
 
 505 int             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 */
 
 511         XM_IN16(IoC, Port, XM_RX_CMD, &OldRxCmd);
 
 515         switch (Mode & (SK_STRIP_FCS_ON | SK_STRIP_FCS_OFF)) {
 
 516         case SK_STRIP_FCS_ON:
 
 517                 RxCmd |= XM_RX_STRIP_FCS;
 
 519         case SK_STRIP_FCS_OFF:
 
 520                 RxCmd &= ~XM_RX_STRIP_FCS;
 
 524         switch (Mode & (SK_STRIP_PAD_ON | SK_STRIP_PAD_OFF)) {
 
 525         case SK_STRIP_PAD_ON:
 
 526                 RxCmd |= XM_RX_STRIP_PAD;
 
 528         case SK_STRIP_PAD_OFF:
 
 529                 RxCmd &= ~XM_RX_STRIP_PAD;
 
 533         switch (Mode & (SK_LENERR_OK_ON | SK_LENERR_OK_OFF)) {
 
 534         case SK_LENERR_OK_ON:
 
 535                 RxCmd |= XM_RX_LENERR_OK;
 
 537         case SK_LENERR_OK_OFF:
 
 538                 RxCmd &= ~XM_RX_LENERR_OK;
 
 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;
 
 546         case SK_BIG_PK_OK_OFF:
 
 547                 RxCmd &= ~XM_RX_BIG_PK_OK;
 
 551         switch (Mode & (SK_SELF_RX_ON | SK_SELF_RX_OFF)) {
 
 553                 RxCmd |= XM_RX_SELF_RX;
 
 556                 RxCmd &= ~XM_RX_SELF_RX;
 
 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);
 
 567 /******************************************************************************
 
 569  *      SkGmSetRxCmd() - Modify the value of the GMAC's Rx Control Register
 
 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
 
 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.
 
 586 static void SkGmSetRxCmd(
 
 587 SK_AC   *pAC,           /* adapter context */
 
 588 SK_IOC  IoC,            /* IO context */
 
 589 int             Port,           /* Port Index (MAC_1 + n) */
 
 590 int             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 */
 
 596         if ((Mode & (SK_STRIP_FCS_ON | SK_STRIP_FCS_OFF)) != 0) {
 
 598                 GM_IN16(IoC, Port, GM_RX_CTRL, &OldRxCmd);
 
 602                 if ((Mode & SK_STRIP_FCS_ON) != 0) {
 
 603                         RxCmd |= GM_RXCR_CRC_DIS;
 
 606                         RxCmd &= ~GM_RXCR_CRC_DIS;
 
 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);
 
 614         if ((Mode & (SK_BIG_PK_OK_ON | SK_BIG_PK_OK_OFF)) != 0) {
 
 616                 GM_IN16(IoC, Port, GM_SERIAL_MODE, &OldRxCmd);
 
 620                 if ((Mode & SK_BIG_PK_OK_ON) != 0) {
 
 621                         RxCmd |= GM_SMOD_JUMBO_ENA;
 
 624                         RxCmd &= ~GM_SMOD_JUMBO_ENA;
 
 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);
 
 634 /******************************************************************************
 
 636  *      SkMacSetRxCmd() - Modify the value of the MAC's Rx Control Register
 
 638  * Description: modifies the MAC's Rx Control reg. dep. on board type
 
 644 SK_AC   *pAC,           /* adapter context */
 
 645 SK_IOC  IoC,            /* IO context */
 
 646 int             Port,           /* Port Index (MAC_1 + n) */
 
 647 int             Mode)           /* Rx Mode */
 
 649         if (pAC->GIni.GIGenesis) {
 
 651                 SkXmSetRxCmd(pAC, IoC, Port, Mode);
 
 655                 SkGmSetRxCmd(pAC, IoC, Port, Mode);
 
 658 }       /* SkMacSetRxCmd */
 
 661 /******************************************************************************
 
 663  *      SkMacCrcGener() - Enable / Disable CRC Generation
 
 665  * Description: enables / disables CRC generation dep. on board type
 
 671 SK_AC   *pAC,   /* adapter context */
 
 672 SK_IOC  IoC,    /* IO context */
 
 673 int             Port,   /* Port Index (MAC_1 + n) */
 
 674 SK_BOOL Enable) /* Enable / Disable */
 
 678         if (pAC->GIni.GIGenesis) {
 
 680                 XM_IN16(IoC, Port, XM_TX_CMD, &Word);
 
 683                         Word &= ~XM_TX_NO_CRC;
 
 686                         Word |= XM_TX_NO_CRC;
 
 688                 /* setup Tx Command Register */
 
 689                 XM_OUT16(IoC, Port, XM_TX_CMD, Word);
 
 693                 GM_IN16(IoC, Port, GM_TX_CTRL, &Word);
 
 696                         Word &= ~GM_TXCR_CRC_DIS;
 
 699                         Word |= GM_TXCR_CRC_DIS;
 
 701                 /* setup Tx Control Register */
 
 702                 GM_OUT16(IoC, Port, GM_TX_CTRL, Word);
 
 711 /******************************************************************************
 
 713  *      SkXmClrExactAddr() - Clear Exact Match Address Registers
 
 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'.
 
 723 void SkXmClrExactAddr(
 
 724 SK_AC   *pAC,           /* adapter context */
 
 725 SK_IOC  IoC,            /* IO context */
 
 726 int             Port,           /* Port Index (MAC_1 + n) */
 
 727 int             StartNum,       /* Begin with this Address Register Index (0..15) */
 
 728 int             StopNum)        /* Stop after finished with this Register Idx (0..15) */
 
 731         SK_U16  ZeroAddr[3] = {0x0000, 0x0000, 0x0000};
 
 733         if ((unsigned)StartNum > 15 || (unsigned)StopNum > 15 ||
 
 734                 StartNum > StopNum) {
 
 736                 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E001, SKERR_HWI_E001MSG);
 
 740         for (i = StartNum; i <= StopNum; i++) {
 
 741                 XM_OUTADDR(IoC, Port, XM_EXM(i), &ZeroAddr[0]);
 
 743 }       /* SkXmClrExactAddr */
 
 747 /******************************************************************************
 
 749  *      SkMacFlushTxFifo() - Flush the MAC's transmit FIFO
 
 752  *      Flush the transmit FIFO of the MAC specified by the index 'Port'
 
 757 void SkMacFlushTxFifo(
 
 758 SK_AC   *pAC,   /* adapter context */
 
 759 SK_IOC  IoC,    /* IO context */
 
 760 int             Port)   /* Port Index (MAC_1 + n) */
 
 765         if (pAC->GIni.GIGenesis) {
 
 767                 XM_IN32(IoC, Port, XM_MODE, &MdReg);
 
 769                 XM_OUT32(IoC, Port, XM_MODE, MdReg | XM_MD_FTF);
 
 774         if (pAC->GIni.GIYukon) {
 
 775                 /* no way to flush the FIFO we have to issue a reset */
 
 780 }       /* SkMacFlushTxFifo */
 
 783 /******************************************************************************
 
 785  *      SkMacFlushRxFifo() - Flush the MAC's receive FIFO
 
 788  *      Flush the receive FIFO of the MAC specified by the index 'Port'
 
 793 static void SkMacFlushRxFifo(
 
 794 SK_AC   *pAC,   /* adapter context */
 
 795 SK_IOC  IoC,    /* IO context */
 
 796 int             Port)   /* Port Index (MAC_1 + n) */
 
 801         if (pAC->GIni.GIGenesis) {
 
 803                 XM_IN32(IoC, Port, XM_MODE, &MdReg);
 
 805                 XM_OUT32(IoC, Port, XM_MODE, MdReg | XM_MD_FRF);
 
 810         if (pAC->GIni.GIYukon) {
 
 811                 /* no way to flush the FIFO we have to issue a reset */
 
 816 }       /* SkMacFlushRxFifo */
 
 820 /******************************************************************************
 
 822  *      SkXmSoftRst() - Do a XMAC software reset
 
 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!
 
 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.
 
 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.
 
 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.
 
 855 static void SkXmSoftRst(
 
 856 SK_AC   *pAC,   /* adapter context */
 
 857 SK_IOC  IoC,    /* IO context */
 
 858 int             Port)   /* Port Index (MAC_1 + n) */
 
 860         SK_U16  ZeroAddr[4] = {0x0000, 0x0000, 0x0000, 0x0000};
 
 862         /* reset the statistics module */
 
 863         XM_OUT32(IoC, Port, XM_GP_PORT, XM_GP_RES_STAT);
 
 865         /* disable all XMAC IRQs */
 
 866         XM_OUT16(IoC, Port, XM_IMSK, 0xffff);
 
 868         XM_OUT32(IoC, Port, XM_MODE, 0);                /* clear Mode Reg */
 
 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 */
 
 873         /* disable all PHY IRQs */
 
 874         switch (pAC->GIni.GP[Port].PhyType) {
 
 876                         SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, 0xffff);
 
 880                         SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, 0);
 
 884                          SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, 0xffff); */
 
 886 #endif /* OTHER_PHY */
 
 889         /* clear the Hash Register */
 
 890         XM_OUTHASH(IoC, Port, XM_HSM, &ZeroAddr);
 
 892         /* clear the Exact Match Address registers */
 
 893         SkXmClrExactAddr(pAC, IoC, Port, 0, 15);
 
 895         /* clear the Source Check Address registers */
 
 896         XM_OUTHASH(IoC, Port, XM_SRC_CHK, &ZeroAddr);
 
 901 /******************************************************************************
 
 903  *      SkXmHardRst() - Do a XMAC hardware reset
 
 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).
 
 912  *      It is absolutely necessary to reset the SW_RST Bit first
 
 913  *      before calling this function.
 
 918 static void SkXmHardRst(
 
 919 SK_AC   *pAC,   /* adapter context */
 
 920 SK_IOC  IoC,    /* IO context */
 
 921 int             Port)   /* Port Index (MAC_1 + n) */
 
 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);
 
 934                         if (TOut++ > 10000) {
 
 936                                  * Adapter seems to be in RESET state.
 
 937                                  * Registers cannot be written.
 
 942                         SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_SET_MAC_RST);
 
 944                         SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &Word);
 
 946                 } while ((Word & MFF_SET_MAC_RST) == 0);
 
 949         /* For external PHYs there must be special handling */
 
 950         if (pAC->GIni.GP[Port].PhyType != SK_PHY_XMAC) {
 
 952                 SK_IN32(IoC, B2_GP_IO, &Reg);
 
 955                         Reg |= GP_DIR_0;        /* set to output */
 
 956                         Reg &= ~GP_IO_0;        /* set PHY reset (active low) */
 
 959                         Reg |= GP_DIR_2;        /* set to output */
 
 960                         Reg &= ~GP_IO_2;        /* set PHY reset (active low) */
 
 962                 /* reset external PHY */
 
 963                 SK_OUT32(IoC, B2_GP_IO, Reg);
 
 966                 SK_IN32(IoC, B2_GP_IO, &Reg);
 
 971 /******************************************************************************
 
 973  *      SkXmClearRst() - Release the PHY & XMAC reset
 
 980 static void SkXmClearRst(
 
 981 SK_AC   *pAC,   /* adapter context */
 
 982 SK_IOC  IoC,    /* IO context */
 
 983 int             Port)   /* Port Index (MAC_1 + n) */
 
 988         SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_MAC_RST);
 
 990         if (pAC->GIni.GP[Port].PhyType != SK_PHY_XMAC) {
 
 992                 SK_IN32(IoC, B2_GP_IO, &DWord);
 
 995                         DWord |= (GP_DIR_0 | GP_IO_0); /* set to output */
 
 998                         DWord |= (GP_DIR_2 | GP_IO_2); /* set to output */
 
1000                 /* Clear PHY reset */
 
1001                 SK_OUT32(IoC, B2_GP_IO, DWord);
 
1003                 /* Enable GMII interface */
 
1004                 XM_OUT16(IoC, Port, XM_HW_CFG, XM_HW_GMII_MD);
 
1006 }       /* SkXmClearRst */
 
1007 #endif /* GENESIS */
 
1011 /******************************************************************************
 
1013  *      SkGmSoftRst() - Do a GMAC software reset
 
1016  *      The GPHY registers should not be destroyed during this
 
1017  *      kind of software reset.
 
1022 static void SkGmSoftRst(
 
1023 SK_AC   *pAC,   /* adapter context */
 
1024 SK_IOC  IoC,    /* IO context */
 
1025 int             Port)   /* Port Index (MAC_1 + n) */
 
1027         SK_U16  EmptyHash[4] = {0x0000, 0x0000, 0x0000, 0x0000};
 
1030         /* reset the statistics module */
 
1032         /* disable all GMAC IRQs */
 
1033         SK_OUT8(IoC, GMAC_IRQ_MSK, 0);
 
1035         /* disable all PHY IRQs */
 
1036         SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, 0);
 
1038         /* clear the Hash Register */
 
1039         GM_OUTHASH(IoC, Port, GM_MC_ADDR_H1, EmptyHash);
 
1041         /* Enable Unicast and Multicast filtering */
 
1042         GM_IN16(IoC, Port, GM_RX_CTRL, &RxCtrl);
 
1044         GM_OUT16(IoC, Port, GM_RX_CTRL,
 
1045                 (SK_U16)(RxCtrl | GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA));
 
1050 /******************************************************************************
 
1052  *      SkGmHardRst() - Do a GMAC hardware reset
 
1059 static void SkGmHardRst(
 
1060 SK_AC   *pAC,   /* adapter context */
 
1061 SK_IOC  IoC,    /* IO context */
 
1062 int             Port)   /* Port Index (MAC_1 + n) */
 
1066         /* WA code for COMA mode */
 
1067         if (pAC->GIni.GIYukonLite &&
 
1068                 pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) {
 
1070                 SK_IN32(IoC, B2_GP_IO, &DWord);
 
1072                 DWord |= (GP_DIR_9 | GP_IO_9);
 
1075                 SK_OUT32(IoC, B2_GP_IO, DWord);
 
1078         /* set GPHY Control reset */
 
1079         SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), GPC_RST_SET);
 
1081         /* set GMAC Control reset */
 
1082         SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET);
 
1087 /******************************************************************************
 
1089  *      SkGmClearRst() - Release the GPHY & GMAC reset
 
1096 static void SkGmClearRst(
 
1097 SK_AC   *pAC,   /* adapter context */
 
1098 SK_IOC  IoC,    /* IO context */
 
1099 int             Port)   /* Port Index (MAC_1 + n) */
 
1104                 /* clear GMAC Control reset */
 
1105                 SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_CLR);
 
1107                 /* set GMAC Control reset */
 
1108                 SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET);
 
1111         /* WA code for COMA mode */
 
1112         if (pAC->GIni.GIYukonLite &&
 
1113                 pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) {
 
1115                 SK_IN32(IoC, B2_GP_IO, &DWord);
 
1117                 DWord |= GP_DIR_9;              /* set to output */
 
1118                 DWord &= ~GP_IO_9;              /* clear PHY reset (active high) */
 
1120                 /* clear PHY reset */
 
1121                 SK_OUT32(IoC, B2_GP_IO, DWord);
 
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);
 
1130         /* set GPHY Control reset */
 
1131         SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_SET);
 
1133         /* release GPHY Control reset */
 
1134         SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_CLR);
 
1140         /* clear GMAC Control reset */
 
1141         SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_PAUSE_ON | GMC_RST_CLR);
 
1146         SK_IN32(IoC, MR_ADDR(Port, GPHY_CTRL), &DWord);
 
1148         SK_IN32(IoC, B0_ISRC, &DWord);
 
1151 }       /* SkGmClearRst */
 
1155 /******************************************************************************
 
1157  *      SkMacSoftRst() - Do a MAC software reset
 
1159  * Description: calls a MAC software reset routine dep. on board type
 
1165 SK_AC   *pAC,   /* adapter context */
 
1166 SK_IOC  IoC,    /* IO context */
 
1167 int             Port)   /* Port Index (MAC_1 + n) */
 
1171         pPrt = &pAC->GIni.GP[Port];
 
1173         /* disable receiver and transmitter */
 
1174         SkMacRxTxDisable(pAC, IoC, Port);
 
1177         if (pAC->GIni.GIGenesis) {
 
1179                 SkXmSoftRst(pAC, IoC, Port);
 
1181 #endif /* GENESIS */
 
1184         if (pAC->GIni.GIYukon) {
 
1186                 SkGmSoftRst(pAC, IoC, Port);
 
1190         /* flush the MAC's Rx and Tx FIFOs */
 
1191         SkMacFlushTxFifo(pAC, IoC, Port);
 
1193         SkMacFlushRxFifo(pAC, IoC, Port);
 
1195         pPrt->PState = SK_PRT_STOP;
 
1197 }       /* SkMacSoftRst */
 
1200 /******************************************************************************
 
1202  *      SkMacHardRst() - Do a MAC hardware reset
 
1204  * Description: calls a MAC hardware reset routine dep. on board type
 
1210 SK_AC   *pAC,   /* adapter context */
 
1211 SK_IOC  IoC,    /* IO context */
 
1212 int             Port)   /* Port Index (MAC_1 + n) */
 
1216         if (pAC->GIni.GIGenesis) {
 
1218                 SkXmHardRst(pAC, IoC, Port);
 
1220 #endif /* GENESIS */
 
1223         if (pAC->GIni.GIYukon) {
 
1225                 SkGmHardRst(pAC, IoC, Port);
 
1229         pAC->GIni.GP[Port].PState = SK_PRT_RESET;
 
1231 }       /* SkMacHardRst */
 
1235 /******************************************************************************
 
1237  *      SkXmInitMac() - Initialize the XMAC II
 
1240  *      Initialize the XMAC of the specified port.
 
1241  *      The XMAC must be reset or stopped before calling this function.
 
1244  *      The XMAC's Rx and Tx state machine is still disabled when returning.
 
1250 SK_AC   *pAC,           /* adapter context */
 
1251 SK_IOC  IoC,            /* IO context */
 
1252 int             Port)           /* Port Index (MAC_1 + n) */
 
1258         pPrt = &pAC->GIni.GP[Port];
 
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);
 
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);
 
1269                         pPrt->PState = SK_PRT_RESET;
 
1273         if (pPrt->PState == SK_PRT_RESET) {
 
1275                 SkXmClearRst(pAC, IoC, Port);
 
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);
 
1282                          * Optimize MDIO transfer by suppressing preamble.
 
1283                          * Must be done AFTER first access to BCOM chip.
 
1285                         XM_IN16(IoC, Port, XM_MMU_CMD, &SWord);
 
1287                         XM_OUT16(IoC, Port, XM_MMU_CMD, SWord | XM_MMU_NO_PRE);
 
1289                         if (pPrt->PhyId1 == PHY_BCOM_ID1_C0) {
 
1291                                  * Workaround BCOM Errata for the C0 type.
 
1292                                  * Write magic patterns to reserved registers.
 
1295                                 while (BcomRegC0Hack[i].PhyReg != 0) {
 
1296                                         SkXmPhyWrite(pAC, IoC, Port, BcomRegC0Hack[i].PhyReg,
 
1297                                                 BcomRegC0Hack[i].PhyVal);
 
1301                         else if (pPrt->PhyId1 == PHY_BCOM_ID1_A1) {
 
1303                                  * Workaround BCOM Errata for the A1 type.
 
1304                                  * Write magic patterns to reserved registers.
 
1307                                 while (BcomRegA1Hack[i].PhyReg != 0) {
 
1308                                         SkXmPhyWrite(pAC, IoC, Port, BcomRegA1Hack[i].PhyReg,
 
1309                                                 BcomRegA1Hack[i].PhyVal);
 
1315                          * Workaround BCOM Errata (#10523) for all BCom PHYs.
 
1316                          * Disable Power Management after reset.
 
1318                         SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &SWord);
 
1320                         SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
 
1321                                 (SK_U16)(SWord | PHY_B_AC_DIS_PM));
 
1323                         /* PHY LED initialization is done in SkGeXmitLED() */
 
1326                 /* Dummy read the Interrupt source register */
 
1327                 XM_IN16(IoC, Port, XM_ISRC, &SWord);
 
1330                  * The auto-negotiation process starts immediately after
 
1331                  * clearing the reset. The auto-negotiation process should be
 
1332                  * started by the SIRQ, therefore stop it here immediately.
 
1334                 SkMacInitPhy(pAC, IoC, Port, SK_FALSE);
 
1337                 /* temp. code: enable signal detect */
 
1338                 /* WARNING: do not override GMII setting above */
 
1339                 XM_OUT16(IoC, Port, XM_HW_CFG, XM_HW_COM4SIG);
 
1344          * configure the XMACs Station Address
 
1345          * B2_MAC_2 = xx xx xx xx xx x1 is programmed to XMAC A
 
1346          * B2_MAC_3 = xx xx xx xx xx x2 is programmed to XMAC B
 
1348         for (i = 0; i < 3; i++) {
 
1350                  * The following 2 statements are together endianess
 
1351                  * independent. Remember this when changing.
 
1353                 SK_IN16(IoC, (B2_MAC_2 + Port * 8 + i * 2), &SWord);
 
1355                 XM_OUT16(IoC, Port, (XM_SA + i * 2), SWord);
 
1358         /* Tx Inter Packet Gap (XM_TX_IPG):     use default */
 
1359         /* Tx High Water Mark (XM_TX_HI_WM):    use default */
 
1360         /* Tx Low Water Mark (XM_TX_LO_WM):     use default */
 
1361         /* Host Request Threshold (XM_HT_THR):  use default */
 
1362         /* Rx Request Threshold (XM_RX_THR):    use default */
 
1363         /* Rx Low Water Mark (XM_RX_LO_WM):     use default */
 
1365         /* configure Rx High Water Mark (XM_RX_HI_WM) */
 
1366         XM_OUT16(IoC, Port, XM_RX_HI_WM, SK_XM_RX_HI_WM);
 
1368         /* Configure Tx Request Threshold */
 
1369         SWord = SK_XM_THR_SL;                           /* for single port */
 
1371         if (pAC->GIni.GIMacsFound > 1) {
 
1372                 switch (pAC->GIni.GIPortUsage) {
 
1374                         SWord = SK_XM_THR_REDL;         /* redundant link */
 
1377                         SWord = SK_XM_THR_MULL;         /* load balancing */
 
1380                         SWord = SK_XM_THR_JUMBO;        /* jumbo frames */
 
1383                         SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E014, SKERR_HWI_E014MSG);
 
1387         XM_OUT16(IoC, Port, XM_TX_THR, SWord);
 
1389         /* setup register defaults for the Tx Command Register */
 
1390         XM_OUT16(IoC, Port, XM_TX_CMD, XM_TX_AUTO_PAD);
 
1392         /* setup register defaults for the Rx Command Register */
 
1393         SWord = XM_RX_STRIP_FCS | XM_RX_LENERR_OK;
 
1395         if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
 
1396                 SWord |= XM_RX_BIG_PK_OK;
 
1399         if (pPrt->PLinkMode == SK_LMODE_HALF) {
 
1401                  * If in manual half duplex mode the other side might be in
 
1402                  * full duplex mode, so ignore if a carrier extension is not seen
 
1403                  * on frames received
 
1405                 SWord |= XM_RX_DIS_CEXT;
 
1408         XM_OUT16(IoC, Port, XM_RX_CMD, SWord);
 
1411          * setup register defaults for the Mode Register
 
1412          *      - Don't strip error frames to avoid Store & Forward
 
1414          *      - Enable 'Check Station Address' bit
 
1415          *      - Enable 'Check Address Array' bit
 
1417         XM_OUT32(IoC, Port, XM_MODE, XM_DEF_MODE);
 
1420          * Initialize the Receive Counter Event Mask (XM_RX_EV_MSK)
 
1421          *      - Enable all bits excepting 'Octets Rx OK Low CntOv'
 
1422          *        and 'Octets Rx OK Hi Cnt Ov'.
 
1424         XM_OUT32(IoC, Port, XM_RX_EV_MSK, XMR_DEF_MSK);
 
1427          * Initialize the Transmit Counter Event Mask (XM_TX_EV_MSK)
 
1428          *      - Enable all bits excepting 'Octets Tx OK Low CntOv'
 
1429          *        and 'Octets Tx OK Hi Cnt Ov'.
 
1431         XM_OUT32(IoC, Port, XM_TX_EV_MSK, XMT_DEF_MSK);
 
1434          * Do NOT init XMAC interrupt mask here.
 
1435          * All interrupts remain disable until link comes up!
 
1439          * Any additional configuration changes may be done now.
 
1440          * The last action is to enable the Rx and Tx state machine.
 
1441          * This should be done after the auto-negotiation process
 
1442          * has been completed successfully.
 
1445 #endif /* GENESIS */
 
1449 /******************************************************************************
 
1451  *      SkGmInitMac() - Initialize the GMAC
 
1454  *      Initialize the GMAC of the specified port.
 
1455  *      The GMAC must be reset or stopped before calling this function.
 
1458  *      The GMAC's Rx and Tx state machine is still disabled when returning.
 
1464 SK_AC   *pAC,           /* adapter context */
 
1465 SK_IOC  IoC,            /* IO context */
 
1466 int             Port)           /* Port Index (MAC_1 + n) */
 
1473         pPrt = &pAC->GIni.GP[Port];
 
1475         if (pPrt->PState == SK_PRT_STOP) {
 
1476                 /* Port State: SK_PRT_STOP */
 
1477                 /* Verify that the reset bit is cleared */
 
1478                 SK_IN32(IoC, MR_ADDR(Port, GMAC_CTRL), &DWord);
 
1480                 if ((DWord & GMC_RST_SET) != 0) {
 
1481                         /* PState does not match HW state */
 
1482                         SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E006, SKERR_HWI_E006MSG);
 
1484                         pPrt->PState = SK_PRT_RESET;
 
1488         if (pPrt->PState == SK_PRT_RESET) {
 
1490                 SkGmHardRst(pAC, IoC, Port);
 
1492                 SkGmClearRst(pAC, IoC, Port);
 
1494                 /* Auto-negotiation ? */
 
1495                 if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
 
1496                         /* Auto-negotiation disabled */
 
1498                         /* get General Purpose Control */
 
1499                         GM_IN16(IoC, Port, GM_GP_CTRL, &SWord);
 
1501                         /* disable auto-update for speed, duplex and flow-control */
 
1502                         SWord |= GM_GPCR_AU_ALL_DIS;
 
1504                         /* setup General Purpose Control Register */
 
1505                         GM_OUT16(IoC, Port, GM_GP_CTRL, SWord);
 
1507                         SWord = GM_GPCR_AU_ALL_DIS;
 
1513                 /* speed settings */
 
1514                 switch (pPrt->PLinkSpeed) {
 
1515                 case SK_LSPEED_AUTO:
 
1516                 case SK_LSPEED_1000MBPS:
 
1517                         SWord |= GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100;
 
1519                 case SK_LSPEED_100MBPS:
 
1520                         SWord |= GM_GPCR_SPEED_100;
 
1522                 case SK_LSPEED_10MBPS:
 
1526                 /* duplex settings */
 
1527                 if (pPrt->PLinkMode != SK_LMODE_HALF) {
 
1528                         /* set full duplex */
 
1529                         SWord |= GM_GPCR_DUP_FULL;
 
1532                 /* flow-control settings */
 
1533                 switch (pPrt->PFlowCtrlMode) {
 
1534                 case SK_FLOW_MODE_NONE:
 
1536                         SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_PAUSE_OFF);
 
1537                         /* disable Tx & Rx flow-control */
 
1538                         SWord |= GM_GPCR_FC_TX_DIS | GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS;
 
1540                 case SK_FLOW_MODE_LOC_SEND:
 
1541                         /* disable Rx flow-control */
 
1542                         SWord |= GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS;
 
1544                 case SK_FLOW_MODE_SYMMETRIC:
 
1545                 case SK_FLOW_MODE_SYM_OR_REM:
 
1546                         /* enable Tx & Rx flow-control */
 
1550                 /* setup General Purpose Control Register */
 
1551                 GM_OUT16(IoC, Port, GM_GP_CTRL, SWord);
 
1553                 /* dummy read the Interrupt Source Register */
 
1554                 SK_IN16(IoC, GMAC_IRQ_SRC, &SWord);
 
1557                 /* read Id from PHY */
 
1558                 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_ID1, &pPrt->PhyId1);
 
1560                 SkGmInitPhyMarv(pAC, IoC, Port, SK_FALSE);
 
1564         (void)SkGmResetCounter(pAC, IoC, Port);
 
1566         /* setup Transmit Control Register */
 
1567         GM_OUT16(IoC, Port, GM_TX_CTRL, TX_COL_THR(pPrt->PMacColThres));
 
1569         /* setup Receive Control Register */
 
1570         GM_OUT16(IoC, Port, GM_RX_CTRL, GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA |
 
1573         /* setup Transmit Flow Control Register */
 
1574         GM_OUT16(IoC, Port, GM_TX_FLOW_CTRL, 0xffff);
 
1576         /* setup Transmit Parameter Register */
 
1578         GM_IN16(IoC, Port, GM_TX_PARAM, &SWord);
 
1581     SWord = TX_JAM_LEN_VAL(pPrt->PMacJamLen) |
 
1582                         TX_JAM_IPG_VAL(pPrt->PMacJamIpgVal) |
 
1583                         TX_IPG_JAM_DATA(pPrt->PMacJamIpgData);
 
1585         GM_OUT16(IoC, Port, GM_TX_PARAM, SWord);
 
1587         /* configure the Serial Mode Register */
 
1589         GM_IN16(IoC, Port, GM_SERIAL_MODE, &SWord);
 
1592         SWord = GM_SMOD_VLAN_ENA | IPG_DATA_VAL(pPrt->PMacIpgData);
 
1594         if (pPrt->PMacLimit4) {
 
1595                 /* reset of collision counter after 4 consecutive collisions */
 
1596                 SWord |= GM_SMOD_LIMIT_4;
 
1599         if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
 
1600                 /* enable jumbo mode (Max. Frame Length = 9018) */
 
1601                 SWord |= GM_SMOD_JUMBO_ENA;
 
1604         GM_OUT16(IoC, Port, GM_SERIAL_MODE, SWord);
 
1607          * configure the GMACs Station Addresses
 
1608          * in PROM you can find our addresses at:
 
1609          * B2_MAC_1 = xx xx xx xx xx x0 virtual address
 
1610          * B2_MAC_2 = xx xx xx xx xx x1 is programmed to GMAC A
 
1611          * B2_MAC_3 = xx xx xx xx xx x2 is reserved for DualPort
 
1614         for (i = 0; i < 3; i++) {
 
1616                  * The following 2 statements are together endianess
 
1617                  * independent. Remember this when changing.
 
1619                 /* physical address: will be used for pause frames */
 
1620                 SK_IN16(IoC, (B2_MAC_2 + Port * 8 + i * 2), &SWord);
 
1623                 /* WA for deviation #16 */
 
1624                 if (pAC->GIni.GIChipId == CHIP_ID_YUKON && pAC->GIni.GIChipRev == 0) {
 
1625                         /* swap the address bytes */
 
1626                         SWord = ((SWord & 0xff00) >> 8) | ((SWord & 0x00ff) << 8);
 
1628                         /* write to register in reversed order */
 
1629                         GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + (2 - i) * 4), SWord);
 
1632                         GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + i * 4), SWord);
 
1635                 GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + i * 4), SWord);
 
1636 #endif /* WA_DEV_16 */
 
1638                 /* virtual address: will be used for data */
 
1639                 SK_IN16(IoC, (B2_MAC_1 + Port * 8 + i * 2), &SWord);
 
1641                 GM_OUT16(IoC, Port, (GM_SRC_ADDR_2L + i * 4), SWord);
 
1643                 /* reset Multicast filtering Hash registers 1-3 */
 
1644                 GM_OUT16(IoC, Port, GM_MC_ADDR_H1 + 4*i, 0);
 
1647         /* reset Multicast filtering Hash register 4 */
 
1648         GM_OUT16(IoC, Port, GM_MC_ADDR_H4, 0);
 
1650         /* enable interrupt mask for counter overflows */
 
1651         GM_OUT16(IoC, Port, GM_TX_IRQ_MSK, 0);
 
1652         GM_OUT16(IoC, Port, GM_RX_IRQ_MSK, 0);
 
1653         GM_OUT16(IoC, Port, GM_TR_IRQ_MSK, 0);
 
1655 #if defined(SK_DIAG) || defined(DEBUG)
 
1656         /* read General Purpose Status */
 
1657         GM_IN16(IoC, Port, GM_GP_STAT, &SWord);
 
1659         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
 
1660                 ("MAC Stat Reg.=0x%04X\n", SWord));
 
1661 #endif /* SK_DIAG || DEBUG */
 
1664         c_print("MAC Stat Reg=0x%04X\n", SWord);
 
1665 #endif /* SK_DIAG */
 
1672 /******************************************************************************
 
1674  *      SkXmInitDupMd() - Initialize the XMACs Duplex Mode
 
1677  *      This function initializes the XMACs Duplex Mode.
 
1678  *      It should be called after successfully finishing
 
1679  *      the Auto-negotiation Process
 
1684 static void SkXmInitDupMd(
 
1685 SK_AC   *pAC,           /* adapter context */
 
1686 SK_IOC  IoC,            /* IO context */
 
1687 int             Port)           /* Port Index (MAC_1 + n) */
 
1689         switch (pAC->GIni.GP[Port].PLinkModeStatus) {
 
1690         case SK_LMODE_STAT_AUTOHALF:
 
1691         case SK_LMODE_STAT_HALF:
 
1692                 /* Configuration Actions for Half Duplex Mode */
 
1694                  * XM_BURST = default value. We are probable not quick
 
1695                  *      enough at the 'XMAC' bus to burst 8kB.
 
1696                  *      The XMAC stops bursting if no transmit frames
 
1697                  *      are available or the burst limit is exceeded.
 
1699                 /* XM_TX_RT_LIM = default value (15) */
 
1700                 /* XM_TX_STIME = default value (0xff = 4096 bit times) */
 
1702         case SK_LMODE_STAT_AUTOFULL:
 
1703         case SK_LMODE_STAT_FULL:
 
1704                 /* Configuration Actions for Full Duplex Mode */
 
1706                  * The duplex mode is configured by the PHY,
 
1707                  * therefore it seems to be that there is nothing
 
1711         case SK_LMODE_STAT_UNKNOWN:
 
1713                 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E007, SKERR_HWI_E007MSG);
 
1716 }       /* SkXmInitDupMd */
 
1719 /******************************************************************************
 
1721  *      SkXmInitPauseMd() - initialize the Pause Mode to be used for this port
 
1724  *      This function initializes the Pause Mode which should
 
1725  *      be used for this port.
 
1726  *      It should be called after successfully finishing
 
1727  *      the Auto-negotiation Process
 
1732 static void SkXmInitPauseMd(
 
1733 SK_AC   *pAC,           /* adapter context */
 
1734 SK_IOC  IoC,            /* IO context */
 
1735 int             Port)           /* Port Index (MAC_1 + n) */
 
1741         pPrt = &pAC->GIni.GP[Port];
 
1743         XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
 
1745         if (pPrt->PFlowCtrlStatus == SK_FLOW_STAT_NONE ||
 
1746                 pPrt->PFlowCtrlStatus == SK_FLOW_STAT_LOC_SEND) {
 
1748                 /* Disable Pause Frame Reception */
 
1749                 Word |= XM_MMU_IGN_PF;
 
1753                  * enabling pause frame reception is required for 1000BT
 
1754                  * because the XMAC is not reset if the link is going down
 
1756                 /* Enable Pause Frame Reception */
 
1757                 Word &= ~XM_MMU_IGN_PF;
 
1760         XM_OUT16(IoC, Port, XM_MMU_CMD, Word);
 
1762         XM_IN32(IoC, Port, XM_MODE, &DWord);
 
1764         if (pPrt->PFlowCtrlStatus == SK_FLOW_STAT_SYMMETRIC ||
 
1765                 pPrt->PFlowCtrlStatus == SK_FLOW_STAT_LOC_SEND) {
 
1768                  * Configure Pause Frame Generation
 
1769                  * Use internal and external Pause Frame Generation.
 
1770                  * Sending pause frames is edge triggered.
 
1771                  * Send a Pause frame with the maximum pause time if
 
1772                  * internal oder external FIFO full condition occurs.
 
1773                  * Send a zero pause time frame to re-start transmission.
 
1776                 /* XM_PAUSE_DA = '010000C28001' (default) */
 
1778                 /* XM_MAC_PTIME = 0xffff (maximum) */
 
1779                 /* remember this value is defined in big endian (!) */
 
1780                 XM_OUT16(IoC, Port, XM_MAC_PTIME, 0xffff);
 
1782                 /* Set Pause Mode in Mode Register */
 
1783                 DWord |= XM_PAUSE_MODE;
 
1785                 /* Set Pause Mode in MAC Rx FIFO */
 
1786                 SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_ENA_PAUSE);
 
1790                  * disable pause frame generation is required for 1000BT
 
1791                  * because the XMAC is not reset if the link is going down
 
1793                 /* Disable Pause Mode in Mode Register */
 
1794                 DWord &= ~XM_PAUSE_MODE;
 
1796                 /* Disable Pause Mode in MAC Rx FIFO */
 
1797                 SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_DIS_PAUSE);
 
1800         XM_OUT32(IoC, Port, XM_MODE, DWord);
 
1801 }       /* SkXmInitPauseMd*/
 
1804 /******************************************************************************
 
1806  *      SkXmInitPhyXmac() - Initialize the XMAC Phy registers
 
1808  * Description: initializes all the XMACs Phy registers
 
1815 static void SkXmInitPhyXmac(
 
1816 SK_AC   *pAC,           /* adapter context */
 
1817 SK_IOC  IoC,            /* IO context */
 
1818 int             Port,           /* Port Index (MAC_1 + n) */
 
1819 SK_BOOL DoLoop)         /* Should a Phy LoopBack be set-up? */
 
1824         pPrt = &pAC->GIni.GP[Port];
 
1827         /* Auto-negotiation ? */
 
1828         if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
 
1829                 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
 
1830                         ("InitPhyXmac: no auto-negotiation Port %d\n", Port));
 
1831                 /* Set DuplexMode in Config register */
 
1832                 if (pPrt->PLinkMode == SK_LMODE_FULL) {
 
1833                         Ctrl |= PHY_CT_DUP_MD;
 
1837                  * Do NOT enable Auto-negotiation here. This would hold
 
1838                  * the link down because no IDLEs are transmitted
 
1842                 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
 
1843                         ("InitPhyXmac: with auto-negotiation Port %d\n", Port));
 
1844                 /* Set Auto-negotiation advertisement */
 
1846                 /* Set Full/half duplex capabilities */
 
1847                 switch (pPrt->PLinkMode) {
 
1848                 case SK_LMODE_AUTOHALF:
 
1849                         Ctrl |= PHY_X_AN_HD;
 
1851                 case SK_LMODE_AUTOFULL:
 
1852                         Ctrl |= PHY_X_AN_FD;
 
1854                 case SK_LMODE_AUTOBOTH:
 
1855                         Ctrl |= PHY_X_AN_FD | PHY_X_AN_HD;
 
1858                         SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
 
1862                 /* Set Flow-control capabilities */
 
1863                 switch (pPrt->PFlowCtrlMode) {
 
1864                 case SK_FLOW_MODE_NONE:
 
1865                         Ctrl |= PHY_X_P_NO_PAUSE;
 
1867                 case SK_FLOW_MODE_LOC_SEND:
 
1868                         Ctrl |= PHY_X_P_ASYM_MD;
 
1870                 case SK_FLOW_MODE_SYMMETRIC:
 
1871                         Ctrl |= PHY_X_P_SYM_MD;
 
1873                 case SK_FLOW_MODE_SYM_OR_REM:
 
1874                         Ctrl |= PHY_X_P_BOTH_MD;
 
1877                         SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
 
1881                 /* Write AutoNeg Advertisement Register */
 
1882                 SkXmPhyWrite(pAC, IoC, Port, PHY_XMAC_AUNE_ADV, Ctrl);
 
1884                 /* Restart Auto-negotiation */
 
1885                 Ctrl = PHY_CT_ANE | PHY_CT_RE_CFG;
 
1889                 /* Set the Phy Loopback bit, too */
 
1890                 Ctrl |= PHY_CT_LOOP;
 
1893         /* Write to the Phy control register */
 
1894         SkXmPhyWrite(pAC, IoC, Port, PHY_XMAC_CTRL, Ctrl);
 
1895 }       /* SkXmInitPhyXmac */
 
1898 /******************************************************************************
 
1900  *      SkXmInitPhyBcom() - Initialize the Broadcom Phy registers
 
1902  * Description: initializes all the Broadcom Phy registers
 
1909 static void SkXmInitPhyBcom(
 
1910 SK_AC   *pAC,           /* adapter context */
 
1911 SK_IOC  IoC,            /* IO context */
 
1912 int             Port,           /* Port Index (MAC_1 + n) */
 
1913 SK_BOOL DoLoop)         /* Should a Phy LoopBack be set-up? */
 
1922         Ctrl1 = PHY_CT_SP1000;
 
1924         Ctrl3 = PHY_SEL_TYPE;
 
1925         Ctrl4 = PHY_B_PEC_EN_LTR;
 
1926         Ctrl5 = PHY_B_AC_TX_TST;
 
1928         pPrt = &pAC->GIni.GP[Port];
 
1930         /* manually Master/Slave ? */
 
1931         if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
 
1932                 Ctrl2 |= PHY_B_1000C_MSE;
 
1934                 if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
 
1935                         Ctrl2 |= PHY_B_1000C_MSC;
 
1938         /* Auto-negotiation ? */
 
1939         if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
 
1940                 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
 
1941                         ("InitPhyBcom: no auto-negotiation Port %d\n", Port));
 
1942                 /* Set DuplexMode in Config register */
 
1943                 if (pPrt->PLinkMode == SK_LMODE_FULL) {
 
1944                         Ctrl1 |= PHY_CT_DUP_MD;
 
1947                 /* Determine Master/Slave manually if not already done */
 
1948                 if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
 
1949                         Ctrl2 |= PHY_B_1000C_MSE;       /* set it to Slave */
 
1953                  * Do NOT enable Auto-negotiation here. This would hold
 
1954                  * the link down because no IDLES are transmitted
 
1958                 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
 
1959                         ("InitPhyBcom: with auto-negotiation Port %d\n", Port));
 
1960                 /* Set Auto-negotiation advertisement */
 
1963                  * Workaround BCOM Errata #1 for the C5 type.
 
1964                  * 1000Base-T Link Acquisition Failure in Slave Mode
 
1965                  * Set Repeater/DTE bit 10 of the 1000Base-T Control Register
 
1967                 Ctrl2 |= PHY_B_1000C_RD;
 
1969                  /* Set Full/half duplex capabilities */
 
1970                 switch (pPrt->PLinkMode) {
 
1971                 case SK_LMODE_AUTOHALF:
 
1972                         Ctrl2 |= PHY_B_1000C_AHD;
 
1974                 case SK_LMODE_AUTOFULL:
 
1975                         Ctrl2 |= PHY_B_1000C_AFD;
 
1977                 case SK_LMODE_AUTOBOTH:
 
1978                         Ctrl2 |= PHY_B_1000C_AFD | PHY_B_1000C_AHD;
 
1981                         SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
 
1985                 /* Set Flow-control capabilities */
 
1986                 switch (pPrt->PFlowCtrlMode) {
 
1987                 case SK_FLOW_MODE_NONE:
 
1988                         Ctrl3 |= PHY_B_P_NO_PAUSE;
 
1990                 case SK_FLOW_MODE_LOC_SEND:
 
1991                         Ctrl3 |= PHY_B_P_ASYM_MD;
 
1993                 case SK_FLOW_MODE_SYMMETRIC:
 
1994                         Ctrl3 |= PHY_B_P_SYM_MD;
 
1996                 case SK_FLOW_MODE_SYM_OR_REM:
 
1997                         Ctrl3 |= PHY_B_P_BOTH_MD;
 
2000                         SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
 
2004                 /* Restart Auto-negotiation */
 
2005                 Ctrl1 |= PHY_CT_ANE | PHY_CT_RE_CFG;
 
2008         /* Initialize LED register here? */
 
2009         /* No. Please do it in SkDgXmitLed() (if required) and swap
 
2010            init order of LEDs and XMAC. (MAl) */
 
2012         /* Write 1000Base-T Control Register */
 
2013         SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, Ctrl2);
 
2014         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
 
2015                 ("Set 1000B-T Ctrl Reg=0x%04X\n", Ctrl2));
 
2017         /* Write AutoNeg Advertisement Register */
 
2018         SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, Ctrl3);
 
2019         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
 
2020                 ("Set Auto-Neg.Adv.Reg=0x%04X\n", Ctrl3));
 
2023                 /* Set the Phy Loopback bit, too */
 
2024                 Ctrl1 |= PHY_CT_LOOP;
 
2027         if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
 
2028                 /* configure FIFO to high latency for transmission of ext. packets */
 
2029                 Ctrl4 |= PHY_B_PEC_HIGH_LA;
 
2031                 /* configure reception of extended packets */
 
2032                 Ctrl5 |= PHY_B_AC_LONG_PACK;
 
2034                 SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, Ctrl5);
 
2037         /* Configure LED Traffic Mode and Jumbo Frame usage if specified */
 
2038         SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, Ctrl4);
 
2040         /* Write to the Phy control register */
 
2041         SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL, Ctrl1);
 
2042         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
 
2043                 ("PHY Control Reg=0x%04X\n", Ctrl1));
 
2044 }       /* SkXmInitPhyBcom */
 
2045 #endif /* GENESIS */
 
2048 /******************************************************************************
 
2050  *      SkGmInitPhyMarv() - Initialize the Marvell Phy registers
 
2052  * Description: initializes all the Marvell Phy registers
 
2059 static void SkGmInitPhyMarv(
 
2060 SK_AC   *pAC,           /* adapter context */
 
2061 SK_IOC  IoC,            /* IO context */
 
2062 int             Port,           /* Port Index (MAC_1 + n) */
 
2063 SK_BOOL DoLoop)         /* Should a Phy LoopBack be set-up? */
 
2072 #if defined(SK_DIAG) || defined(DEBUG)
 
2076 #endif /* SK_DIAG || DEBUG */
 
2078         pPrt = &pAC->GIni.GP[Port];
 
2080         /* Auto-negotiation ? */
 
2081         if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
 
2088         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
 
2089                 ("InitPhyMarv: Port %d, auto-negotiation %s\n",
 
2090                  Port, AutoNeg ? "ON" : "OFF"));
 
2093         VCPUprintf(0, "SkGmInitPhyMarv(), Port=%u, DoLoop=%u\n",
 
2097                 /* Set 'MAC Power up'-bit, set Manual MDI configuration */
 
2098                 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL,
 
2099                         PHY_M_PC_MAC_POW_UP);
 
2101         else if (AutoNeg && pPrt->PLinkSpeed == SK_LSPEED_AUTO) {
 
2102                 /* Read Ext. PHY Specific Control */
 
2103                 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL, &ExtPhyCtrl);
 
2105                 ExtPhyCtrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK |
 
2106                         PHY_M_EC_MAC_S_MSK);
 
2108                 ExtPhyCtrl |= PHY_M_EC_MAC_S(MAC_TX_CLK_25_MHZ) |
 
2109                         PHY_M_EC_M_DSC(0) | PHY_M_EC_S_DSC(1);
 
2111                 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_CTRL, ExtPhyCtrl);
 
2112                 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
 
2113                         ("Set Ext. PHY Ctrl=0x%04X\n", ExtPhyCtrl));
 
2116         /* Read PHY Control */
 
2117         SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &PhyCtrl);
 
2120                 /* Disable Auto-negotiation */
 
2121                 PhyCtrl &= ~PHY_CT_ANE;
 
2124         PhyCtrl |= PHY_CT_RESET;
 
2125         /* Assert software reset */
 
2126         SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PhyCtrl);
 
2129         PhyCtrl = 0 /* PHY_CT_COL_TST */;
 
2131         AutoNegAdv = PHY_SEL_TYPE;
 
2133         /* manually Master/Slave ? */
 
2134         if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
 
2135                 /* enable Manual Master/Slave */
 
2136                 C1000BaseT |= PHY_M_1000C_MSE;
 
2138                 if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
 
2139                         C1000BaseT |= PHY_M_1000C_MSC;  /* set it to Master */
 
2143         /* Auto-negotiation ? */
 
2146                 if (pPrt->PLinkMode == SK_LMODE_FULL) {
 
2147                         /* Set Full Duplex Mode */
 
2148                         PhyCtrl |= PHY_CT_DUP_MD;
 
2151                 /* Set Master/Slave manually if not already done */
 
2152                 if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
 
2153                         C1000BaseT |= PHY_M_1000C_MSE;  /* set it to Slave */
 
2157                 switch (pPrt->PLinkSpeed) {
 
2158                 case SK_LSPEED_AUTO:
 
2159                 case SK_LSPEED_1000MBPS:
 
2160                         PhyCtrl |= PHY_CT_SP1000;
 
2162                 case SK_LSPEED_100MBPS:
 
2163                         PhyCtrl |= PHY_CT_SP100;
 
2165                 case SK_LSPEED_10MBPS:
 
2168                         SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E019,
 
2173                         PhyCtrl |= PHY_CT_RESET;
 
2177                 /* Set Auto-negotiation advertisement */
 
2179                 if (pAC->GIni.GICopperType) {
 
2180                         /* Set Speed capabilities */
 
2181                         switch (pPrt->PLinkSpeed) {
 
2182                         case SK_LSPEED_AUTO:
 
2183                                 C1000BaseT |= PHY_M_1000C_AHD | PHY_M_1000C_AFD;
 
2184                                 AutoNegAdv |= PHY_M_AN_100_FD | PHY_M_AN_100_HD |
 
2185                                         PHY_M_AN_10_FD | PHY_M_AN_10_HD;
 
2187                         case SK_LSPEED_1000MBPS:
 
2188                                 C1000BaseT |= PHY_M_1000C_AHD | PHY_M_1000C_AFD;
 
2190                         case SK_LSPEED_100MBPS:
 
2191                                 AutoNegAdv |= PHY_M_AN_100_FD | PHY_M_AN_100_HD |
 
2192                                         /* advertise 10Base-T also */
 
2193                                         PHY_M_AN_10_FD | PHY_M_AN_10_HD;
 
2195                         case SK_LSPEED_10MBPS:
 
2196                                 AutoNegAdv |= PHY_M_AN_10_FD | PHY_M_AN_10_HD;
 
2199                                 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E019,
 
2203                         /* Set Full/half duplex capabilities */
 
2204                         switch (pPrt->PLinkMode) {
 
2205                         case SK_LMODE_AUTOHALF:
 
2206                                 C1000BaseT &= ~PHY_M_1000C_AFD;
 
2207                                 AutoNegAdv &= ~(PHY_M_AN_100_FD | PHY_M_AN_10_FD);
 
2209                         case SK_LMODE_AUTOFULL:
 
2210                                 C1000BaseT &= ~PHY_M_1000C_AHD;
 
2211                                 AutoNegAdv &= ~(PHY_M_AN_100_HD | PHY_M_AN_10_HD);
 
2213                         case SK_LMODE_AUTOBOTH:
 
2216                                 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
 
2220                         /* Set Flow-control capabilities */
 
2221                         switch (pPrt->PFlowCtrlMode) {
 
2222                         case SK_FLOW_MODE_NONE:
 
2223                                 AutoNegAdv |= PHY_B_P_NO_PAUSE;
 
2225                         case SK_FLOW_MODE_LOC_SEND:
 
2226                                 AutoNegAdv |= PHY_B_P_ASYM_MD;
 
2228                         case SK_FLOW_MODE_SYMMETRIC:
 
2229                                 AutoNegAdv |= PHY_B_P_SYM_MD;
 
2231                         case SK_FLOW_MODE_SYM_OR_REM:
 
2232                                 AutoNegAdv |= PHY_B_P_BOTH_MD;
 
2235                                 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
 
2239                 else {  /* special defines for FIBER (88E1011S only) */
 
2241                         /* Set Full/half duplex capabilities */
 
2242                         switch (pPrt->PLinkMode) {
 
2243                         case SK_LMODE_AUTOHALF:
 
2244                                 AutoNegAdv |= PHY_M_AN_1000X_AHD;
 
2246                         case SK_LMODE_AUTOFULL:
 
2247                                 AutoNegAdv |= PHY_M_AN_1000X_AFD;
 
2249                         case SK_LMODE_AUTOBOTH:
 
2250                                 AutoNegAdv |= PHY_M_AN_1000X_AHD | PHY_M_AN_1000X_AFD;
 
2253                                 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
 
2257                         /* Set Flow-control capabilities */
 
2258                         switch (pPrt->PFlowCtrlMode) {
 
2259                         case SK_FLOW_MODE_NONE:
 
2260                                 AutoNegAdv |= PHY_M_P_NO_PAUSE_X;
 
2262                         case SK_FLOW_MODE_LOC_SEND:
 
2263                                 AutoNegAdv |= PHY_M_P_ASYM_MD_X;
 
2265                         case SK_FLOW_MODE_SYMMETRIC:
 
2266                                 AutoNegAdv |= PHY_M_P_SYM_MD_X;
 
2268                         case SK_FLOW_MODE_SYM_OR_REM:
 
2269                                 AutoNegAdv |= PHY_M_P_BOTH_MD_X;
 
2272                                 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
 
2278                         /* Restart Auto-negotiation */
 
2279                         PhyCtrl |= PHY_CT_ANE | PHY_CT_RE_CFG;
 
2285          * E-mail from Gu Lin (08-03-2002):
 
2288         /* Program PHY register 30 as 16'h0708 for simulation speed up */
 
2289         SkGmPhyWrite(pAC, IoC, Port, 30, 0x0700 /* 0x0708 */);
 
2295         /* Write 1000Base-T Control Register */
 
2296         SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_1000T_CTRL, C1000BaseT);
 
2297         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
 
2298                 ("Set 1000B-T Ctrl =0x%04X\n", C1000BaseT));
 
2300         /* Write AutoNeg Advertisement Register */
 
2301         SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_AUNE_ADV, AutoNegAdv);
 
2302         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
 
2303                 ("Set Auto-Neg.Adv.=0x%04X\n", AutoNegAdv));
 
2307                 /* Set the PHY Loopback bit */
 
2308                 PhyCtrl |= PHY_CT_LOOP;
 
2311                 /* Program PHY register 16 as 16'h0400 to force link good */
 
2312                 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, PHY_M_PC_FL_GOOD);
 
2316                 if (pPrt->PLinkSpeed != SK_LSPEED_AUTO) {
 
2317                         /* Write Ext. PHY Specific Control */
 
2318                         SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_CTRL,
 
2319                                 (SK_U16)((pPrt->PLinkSpeed + 2) << 4));
 
2324         else if (pPrt->PLinkSpeed == SK_LSPEED_10MBPS) {
 
2325                         /* Write PHY Specific Control */
 
2326                         SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL,
 
2327                                 PHY_M_PC_EN_DET_MSK);
 
2331         /* Write to the PHY Control register */
 
2332         SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PhyCtrl);
 
2333         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
 
2334                 ("Set PHY Ctrl Reg.=0x%04X\n", PhyCtrl));
 
2340         LedCtrl = PHY_M_LED_PULS_DUR(PULS_170MS) | PHY_M_LED_BLINK_RT(BLINK_84MS);
 
2342         if ((pAC->GIni.GILedBlinkCtrl & SK_ACT_LED_BLINK) != 0) {
 
2343                 LedCtrl |= PHY_M_LEDC_RX_CTRL | PHY_M_LEDC_TX_CTRL;
 
2346         if ((pAC->GIni.GILedBlinkCtrl & SK_DUP_LED_NORMAL) != 0) {
 
2347                 LedCtrl |= PHY_M_LEDC_DP_CTRL;
 
2350         SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_LED_CTRL, LedCtrl);
 
2352         if ((pAC->GIni.GILedBlinkCtrl & SK_LED_LINK100_ON) != 0) {
 
2353                 /* only in forced 100 Mbps mode */
 
2354                 if (!AutoNeg && pPrt->PLinkSpeed == SK_LSPEED_100MBPS) {
 
2356                         SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_LED_OVER,
 
2357                                 PHY_M_LED_MO_100(MO_LED_ON));
 
2362         c_print("Set PHY Ctrl=0x%04X\n", PhyCtrl);
 
2363         c_print("Set 1000 B-T=0x%04X\n", C1000BaseT);
 
2364         c_print("Set Auto-Neg=0x%04X\n", AutoNegAdv);
 
2365         c_print("Set Ext Ctrl=0x%04X\n", ExtPhyCtrl);
 
2366 #endif /* SK_DIAG */
 
2368 #if defined(SK_DIAG) || defined(DEBUG)
 
2369         /* Read PHY Control */
 
2370         SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &PhyCtrl);
 
2371         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
 
2372                 ("PHY Ctrl Reg.=0x%04X\n", PhyCtrl));
 
2374         /* Read 1000Base-T Control Register */
 
2375         SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_CTRL, &C1000BaseT);
 
2376         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
 
2377                 ("1000B-T Ctrl =0x%04X\n", C1000BaseT));
 
2379         /* Read AutoNeg Advertisement Register */
 
2380         SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_ADV, &AutoNegAdv);
 
2381         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
 
2382                 ("Auto-Neg.Adv.=0x%04X\n", AutoNegAdv));
 
2384         /* Read Ext. PHY Specific Control */
 
2385         SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL, &ExtPhyCtrl);
 
2386         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
 
2387                 ("Ext. PHY Ctrl=0x%04X\n", ExtPhyCtrl));
 
2389         /* Read PHY Status */
 
2390         SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat);
 
2391         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
 
2392                 ("PHY Stat Reg.=0x%04X\n", PhyStat));
 
2393         SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat1);
 
2394         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
 
2395                 ("PHY Stat Reg.=0x%04X\n", PhyStat1));
 
2397         /* Read PHY Specific Status */
 
2398         SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &PhySpecStat);
 
2399         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
 
2400                 ("PHY Spec Stat=0x%04X\n", PhySpecStat));
 
2401 #endif /* SK_DIAG || DEBUG */
 
2404         c_print("PHY Ctrl Reg=0x%04X\n", PhyCtrl);
 
2405         c_print("PHY 1000 Reg=0x%04X\n", C1000BaseT);
 
2406         c_print("PHY AnAd Reg=0x%04X\n", AutoNegAdv);
 
2407         c_print("Ext Ctrl Reg=0x%04X\n", ExtPhyCtrl);
 
2408         c_print("PHY Stat Reg=0x%04X\n", PhyStat);
 
2409         c_print("PHY Stat Reg=0x%04X\n", PhyStat1);
 
2410         c_print("PHY Spec Reg=0x%04X\n", PhySpecStat);
 
2411 #endif /* SK_DIAG */
 
2415 }       /* SkGmInitPhyMarv */
 
2420 /******************************************************************************
 
2422  *      SkXmInitPhyLone() - Initialize the Level One Phy registers
 
2424  * Description: initializes all the Level One Phy registers
 
2431 static void SkXmInitPhyLone(
 
2432 SK_AC   *pAC,           /* adapter context */
 
2433 SK_IOC  IoC,            /* IO context */
 
2434 int             Port,           /* Port Index (MAC_1 + n) */
 
2435 SK_BOOL DoLoop)         /* Should a Phy LoopBack be set-up? */
 
2442         Ctrl1 = PHY_CT_SP1000;
 
2444         Ctrl3 = PHY_SEL_TYPE;
 
2446         pPrt = &pAC->GIni.GP[Port];
 
2448         /* manually Master/Slave ? */
 
2449         if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
 
2450                 Ctrl2 |= PHY_L_1000C_MSE;
 
2452                 if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
 
2453                         Ctrl2 |= PHY_L_1000C_MSC;
 
2456         /* Auto-negotiation ? */
 
2457         if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
 
2459                  * level one spec say: "1000 Mbps: manual mode not allowed"
 
2460                  * but lets see what happens...
 
2462                 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
 
2463                         ("InitPhyLone: no auto-negotiation Port %d\n", Port));
 
2464                 /* Set DuplexMode in Config register */
 
2465                 if (pPrt->PLinkMode == SK_LMODE_FULL) {
 
2466                         Ctrl1 |= PHY_CT_DUP_MD;
 
2469                 /* Determine Master/Slave manually if not already done */
 
2470                 if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
 
2471                         Ctrl2 |= PHY_L_1000C_MSE;       /* set it to Slave */
 
2475                  * Do NOT enable Auto-negotiation here. This would hold
 
2476                  * the link down because no IDLES are transmitted
 
2480                 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
 
2481                         ("InitPhyLone: with auto-negotiation Port %d\n", Port));
 
2482                 /* Set Auto-negotiation advertisement */
 
2484                 /* Set Full/half duplex capabilities */
 
2485                 switch (pPrt->PLinkMode) {
 
2486                 case SK_LMODE_AUTOHALF:
 
2487                         Ctrl2 |= PHY_L_1000C_AHD;
 
2489                 case SK_LMODE_AUTOFULL:
 
2490                         Ctrl2 |= PHY_L_1000C_AFD;
 
2492                 case SK_LMODE_AUTOBOTH:
 
2493                         Ctrl2 |= PHY_L_1000C_AFD | PHY_L_1000C_AHD;
 
2496                         SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
 
2500                 /* Set Flow-control capabilities */
 
2501                 switch (pPrt->PFlowCtrlMode) {
 
2502                 case SK_FLOW_MODE_NONE:
 
2503                         Ctrl3 |= PHY_L_P_NO_PAUSE;
 
2505                 case SK_FLOW_MODE_LOC_SEND:
 
2506                         Ctrl3 |= PHY_L_P_ASYM_MD;
 
2508                 case SK_FLOW_MODE_SYMMETRIC:
 
2509                         Ctrl3 |= PHY_L_P_SYM_MD;
 
2511                 case SK_FLOW_MODE_SYM_OR_REM:
 
2512                         Ctrl3 |= PHY_L_P_BOTH_MD;
 
2515                         SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
 
2519                 /* Restart Auto-negotiation */
 
2520                 Ctrl1 = PHY_CT_ANE | PHY_CT_RE_CFG;
 
2523         /* Write 1000Base-T Control Register */
 
2524         SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_1000T_CTRL, Ctrl2);
 
2525         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
 
2526                 ("1000B-T Ctrl Reg=0x%04X\n", Ctrl2));
 
2528         /* Write AutoNeg Advertisement Register */
 
2529         SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_AUNE_ADV, Ctrl3);
 
2530         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
 
2531                 ("Auto-Neg.Adv.Reg=0x%04X\n", Ctrl3));
 
2534                 /* Set the Phy Loopback bit, too */
 
2535                 Ctrl1 |= PHY_CT_LOOP;
 
2538         /* Write to the Phy control register */
 
2539         SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_CTRL, Ctrl1);
 
2540         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
 
2541                 ("PHY Control Reg=0x%04X\n", Ctrl1));
 
2542 }       /* SkXmInitPhyLone */
 
2545 /******************************************************************************
 
2547  *      SkXmInitPhyNat() - Initialize the National Phy registers
 
2549  * Description: initializes all the National Phy registers
 
2556 static void SkXmInitPhyNat(
 
2557 SK_AC   *pAC,           /* adapter context */
 
2558 SK_IOC  IoC,            /* IO context */
 
2559 int             Port,           /* Port Index (MAC_1 + n) */
 
2560 SK_BOOL DoLoop)         /* Should a Phy LoopBack be set-up? */
 
2562 /* todo: National */
 
2563 }       /* SkXmInitPhyNat */
 
2564 #endif /* OTHER_PHY */
 
2567 /******************************************************************************
 
2569  *      SkMacInitPhy() - Initialize the PHY registers
 
2571  * Description: calls the Init PHY routines dep. on board type
 
2579 SK_AC   *pAC,           /* adapter context */
 
2580 SK_IOC  IoC,            /* IO context */
 
2581 int             Port,           /* Port Index (MAC_1 + n) */
 
2582 SK_BOOL DoLoop)         /* Should a Phy LoopBack be set-up? */
 
2586         pPrt = &pAC->GIni.GP[Port];
 
2589         if (pAC->GIni.GIGenesis) {
 
2591                 switch (pPrt->PhyType) {
 
2593                         SkXmInitPhyXmac(pAC, IoC, Port, DoLoop);
 
2596                         SkXmInitPhyBcom(pAC, IoC, Port, DoLoop);
 
2600                         SkXmInitPhyLone(pAC, IoC, Port, DoLoop);
 
2603                         SkXmInitPhyNat(pAC, IoC, Port, DoLoop);
 
2605 #endif /* OTHER_PHY */
 
2608 #endif /* GENESIS */
 
2611         if (pAC->GIni.GIYukon) {
 
2613                 SkGmInitPhyMarv(pAC, IoC, Port, DoLoop);
 
2617 }       /* SkMacInitPhy */
 
2621 /******************************************************************************
 
2623  *      SkXmAutoNegDoneXmac() - Auto-negotiation handling
 
2626  *      This function handles the auto-negotiation if the Done bit is set.
 
2630  *      SK_AND_DUP_CAP  Duplex capability error happened
 
2631  *      SK_AND_OTHER    Other error happened
 
2633 static int SkXmAutoNegDoneXmac(
 
2634 SK_AC   *pAC,           /* adapter context */
 
2635 SK_IOC  IoC,            /* IO context */
 
2636 int             Port)           /* Port Index (MAC_1 + n) */
 
2639         SK_U16          ResAb;          /* Resolved Ability */
 
2640         SK_U16          LPAb;           /* Link Partner Ability */
 
2642         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
 
2643                 ("AutoNegDoneXmac, Port %d\n", Port));
 
2645         pPrt = &pAC->GIni.GP[Port];
 
2647         /* Get PHY parameters */
 
2648         SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_LP, &LPAb);
 
2649         SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_RES_ABI, &ResAb);
 
2651         if ((LPAb & PHY_X_AN_RFB) != 0) {
 
2652                 /* At least one of the remote fault bit is set */
 
2654                 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
 
2655                         ("AutoNegFail: Remote fault bit set Port %d\n", Port));
 
2656                 pPrt->PAutoNegFail = SK_TRUE;
 
2657                 return(SK_AND_OTHER);
 
2660         /* Check Duplex mismatch */
 
2661         if ((ResAb & (PHY_X_RS_HD | PHY_X_RS_FD)) == PHY_X_RS_FD) {
 
2662                 pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL;
 
2664         else if ((ResAb & (PHY_X_RS_HD | PHY_X_RS_FD)) == PHY_X_RS_HD) {
 
2665                 pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF;
 
2669                 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
 
2670                         ("AutoNegFail: Duplex mode mismatch Port %d\n", Port));
 
2671                 pPrt->PAutoNegFail = SK_TRUE;
 
2672                 return(SK_AND_DUP_CAP);
 
2675         /* Check PAUSE mismatch */
 
2676         /* We are NOT using chapter 4.23 of the Xaqti manual */
 
2677         /* We are using IEEE 802.3z/D5.0 Table 37-4 */
 
2678         if ((pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYMMETRIC ||
 
2679              pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM) &&
 
2680             (LPAb & PHY_X_P_SYM_MD) != 0) {
 
2681                 /* Symmetric PAUSE */
 
2682                 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
 
2684         else if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM &&
 
2685                    (LPAb & PHY_X_RS_PAUSE) == PHY_X_P_ASYM_MD) {
 
2686                 /* Enable PAUSE receive, disable PAUSE transmit */
 
2687                 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
 
2689         else if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_LOC_SEND &&
 
2690                    (LPAb & PHY_X_RS_PAUSE) == PHY_X_P_BOTH_MD) {
 
2691                 /* Disable PAUSE receive, enable PAUSE transmit */
 
2692                 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
 
2695                 /* PAUSE mismatch -> no PAUSE */
 
2696                 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
 
2698         pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS;
 
2701 }       /* SkXmAutoNegDoneXmac */
 
2704 /******************************************************************************
 
2706  *      SkXmAutoNegDoneBcom() - Auto-negotiation handling
 
2709  *      This function handles the auto-negotiation if the Done bit is set.
 
2713  *      SK_AND_DUP_CAP  Duplex capability error happened
 
2714  *      SK_AND_OTHER    Other error happened
 
2716 static int SkXmAutoNegDoneBcom(
 
2717 SK_AC   *pAC,           /* adapter context */
 
2718 SK_IOC  IoC,            /* IO context */
 
2719 int             Port)           /* Port Index (MAC_1 + n) */
 
2722         SK_U16          LPAb;           /* Link Partner Ability */
 
2723         SK_U16          AuxStat;        /* Auxiliary Status */
 
2727         SK_U16          ResAb;          /* Resolved Ability */
 
2730         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
 
2731                 ("AutoNegDoneBcom, Port %d\n", Port));
 
2732         pPrt = &pAC->GIni.GP[Port];
 
2734         /* Get PHY parameters */
 
2735         SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &LPAb);
 
2738         SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb);
 
2741         SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &AuxStat);
 
2743         if ((LPAb & PHY_B_AN_RF) != 0) {
 
2744                 /* Remote fault bit is set: Error */
 
2745                 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
 
2746                         ("AutoNegFail: Remote fault bit set Port %d\n", Port));
 
2747                 pPrt->PAutoNegFail = SK_TRUE;
 
2748                 return(SK_AND_OTHER);
 
2751         /* Check Duplex mismatch */
 
2752         if ((AuxStat & PHY_B_AS_AN_RES_MSK) == PHY_B_RES_1000FD) {
 
2753                 pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL;
 
2755         else if ((AuxStat & PHY_B_AS_AN_RES_MSK) == PHY_B_RES_1000HD) {
 
2756                 pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF;
 
2760                 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
 
2761                         ("AutoNegFail: Duplex mode mismatch Port %d\n", Port));
 
2762                 pPrt->PAutoNegFail = SK_TRUE;
 
2763                 return(SK_AND_DUP_CAP);
 
2768         /* Check Master/Slave resolution */
 
2769         if ((ResAb & PHY_B_1000S_MSF) != 0) {
 
2770                 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
 
2771                         ("Master/Slave Fault Port %d\n", Port));
 
2772                 pPrt->PAutoNegFail = SK_TRUE;
 
2773                 pPrt->PMSStatus = SK_MS_STAT_FAULT;
 
2774                 return(SK_AND_OTHER);
 
2777         pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
 
2778                 SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE;
 
2781         /* Check PAUSE mismatch ??? */
 
2782         /* We are using IEEE 802.3z/D5.0 Table 37-4 */
 
2783         if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PAUSE_MSK) {
 
2784                 /* Symmetric PAUSE */
 
2785                 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
 
2787         else if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PRR) {
 
2788                 /* Enable PAUSE receive, disable PAUSE transmit */
 
2789                 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
 
2791         else if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PRT) {
 
2792                 /* Disable PAUSE receive, enable PAUSE transmit */
 
2793                 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
 
2796                 /* PAUSE mismatch -> no PAUSE */
 
2797                 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
 
2799         pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS;
 
2802 }       /* SkXmAutoNegDoneBcom */
 
2803 #endif /* GENESIS */
 
2807 /******************************************************************************
 
2809  *      SkGmAutoNegDoneMarv() - Auto-negotiation handling
 
2812  *      This function handles the auto-negotiation if the Done bit is set.
 
2816  *      SK_AND_DUP_CAP  Duplex capability error happened
 
2817  *      SK_AND_OTHER    Other error happened
 
2819 static int SkGmAutoNegDoneMarv(
 
2820 SK_AC   *pAC,           /* adapter context */
 
2821 SK_IOC  IoC,            /* IO context */
 
2822 int             Port)           /* Port Index (MAC_1 + n) */
 
2825         SK_U16          LPAb;           /* Link Partner Ability */
 
2826         SK_U16          ResAb;          /* Resolved Ability */
 
2827         SK_U16          AuxStat;        /* Auxiliary Status */
 
2829         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
 
2830                 ("AutoNegDoneMarv, Port %d\n", Port));
 
2831         pPrt = &pAC->GIni.GP[Port];
 
2833         /* Get PHY parameters */
 
2834         SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_LP, &LPAb);
 
2835         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
 
2836                 ("Link P.Abil.=0x%04X\n", LPAb));
 
2838         if ((LPAb & PHY_M_AN_RF) != 0) {
 
2839                 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
 
2840                         ("AutoNegFail: Remote fault bit set Port %d\n", Port));
 
2841                 pPrt->PAutoNegFail = SK_TRUE;
 
2842                 return(SK_AND_OTHER);
 
2845         SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_STAT, &ResAb);
 
2847         /* Check Master/Slave resolution */
 
2848         if ((ResAb & PHY_B_1000S_MSF) != 0) {
 
2849                 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
 
2850                         ("Master/Slave Fault Port %d\n", Port));
 
2851                 pPrt->PAutoNegFail = SK_TRUE;
 
2852                 pPrt->PMSStatus = SK_MS_STAT_FAULT;
 
2853                 return(SK_AND_OTHER);
 
2856         pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
 
2857                 (SK_U8)SK_MS_STAT_MASTER : (SK_U8)SK_MS_STAT_SLAVE;
 
2859         /* Read PHY Specific Status */
 
2860         SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &AuxStat);
 
2862         /* Check Speed & Duplex resolved */
 
2863         if ((AuxStat & PHY_M_PS_SPDUP_RES) == 0) {
 
2864                 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
 
2865                         ("AutoNegFail: Speed & Duplex not resolved, Port %d\n", Port));
 
2866                 pPrt->PAutoNegFail = SK_TRUE;
 
2867                 pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN;
 
2868                 return(SK_AND_DUP_CAP);
 
2871         if ((AuxStat & PHY_M_PS_FULL_DUP) != 0) {
 
2872                 pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL;
 
2875                 pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF;
 
2878         /* Check PAUSE mismatch ??? */
 
2879         /* We are using IEEE 802.3z/D5.0 Table 37-4 */
 
2880         if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_PAUSE_MSK) {
 
2881                 /* Symmetric PAUSE */
 
2882                 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
 
2884         else if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_RX_P_EN) {
 
2885                 /* Enable PAUSE receive, disable PAUSE transmit */
 
2886                 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
 
2888         else if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_TX_P_EN) {
 
2889                 /* Disable PAUSE receive, enable PAUSE transmit */
 
2890                 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
 
2893                 /* PAUSE mismatch -> no PAUSE */
 
2894                 pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
 
2897         /* set used link speed */
 
2898         switch ((unsigned)(AuxStat & PHY_M_PS_SPEED_MSK)) {
 
2899         case (unsigned)PHY_M_PS_SPEED_1000:
 
2900                 pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS;
 
2902         case PHY_M_PS_SPEED_100:
 
2903                 pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_100MBPS;
 
2906                 pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_10MBPS;
 
2910 }       /* SkGmAutoNegDoneMarv */
 
2915 /******************************************************************************
 
2917  *      SkXmAutoNegDoneLone() - Auto-negotiation handling
 
2920  *      This function handles the auto-negotiation if the Done bit is set.
 
2924  *      SK_AND_DUP_CAP  Duplex capability error happened
 
2925  *      SK_AND_OTHER    Other error happened
 
2927 static int SkXmAutoNegDoneLone(
 
2928 SK_AC   *pAC,           /* adapter context */
 
2929 SK_IOC  IoC,            /* IO context */
 
2930 int             Port)           /* Port Index (MAC_1 + n) */
 
2933         SK_U16          ResAb;          /* Resolved Ability */
 
2934         SK_U16          LPAb;           /* Link Partner Ability */
 
2935         SK_U16          QuickStat;      /* Auxiliary Status */
 
2937         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
 
2938                 ("AutoNegDoneLone, Port %d\n", Port));
 
2939         pPrt = &pAC->GIni.GP[Port];
 
2941         /* Get PHY parameters */
 
2942         SkXmPhyRead(pAC, IoC, Port, PHY_LONE_AUNE_LP, &LPAb);
 
2943         SkXmPhyRead(pAC, IoC, Port, PHY_LONE_1000T_STAT, &ResAb);
 
2944         SkXmPhyRead(pAC, IoC, Port, PHY_LONE_Q_STAT, &QuickStat);
 
2946         if ((LPAb & PHY_L_AN_RF) != 0) {
 
2947                 /* Remote fault bit is set */
 
2949                 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
 
2950                         ("AutoNegFail: Remote fault bit set Port %d\n", Port));
 
2951                 pPrt->PAutoNegFail = SK_TRUE;
 
2952                 return(SK_AND_OTHER);
 
2955         /* Check Duplex mismatch */
 
2956         if ((QuickStat & PHY_L_QS_DUP_MOD) != 0) {
 
2957                 pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL;
 
2960                 pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF;
 
2963         /* Check Master/Slave resolution */
 
2964         if ((ResAb & PHY_L_1000S_MSF) != 0) {
 
2966                 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
 
2967                         ("Master/Slave Fault Port %d\n", Port));
 
2968                 pPrt->PAutoNegFail = SK_TRUE;
 
2969                 pPrt->PMSStatus = SK_MS_STAT_FAULT;
 
2970                 return(SK_AND_OTHER);
 
2972         else if (ResAb & PHY_L_1000S_MSR) {
 
2973                 pPrt->PMSStatus = SK_MS_STAT_MASTER;
 
2976                 pPrt->PMSStatus = SK_MS_STAT_SLAVE;
 
2979         /* Check PAUSE mismatch */
 
2980         /* We are using IEEE 802.3z/D5.0 Table 37-4 */
 
2981         /* we must manually resolve the abilities here */
 
2982         pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
 
2984         switch (pPrt->PFlowCtrlMode) {
 
2985         case SK_FLOW_MODE_NONE:
 
2988         case SK_FLOW_MODE_LOC_SEND:
 
2989                 if ((QuickStat & (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) ==
 
2990                         (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) {
 
2991                         /* Disable PAUSE receive, enable PAUSE transmit */
 
2992                         pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
 
2995         case SK_FLOW_MODE_SYMMETRIC:
 
2996                 if ((QuickStat & PHY_L_QS_PAUSE) != 0) {
 
2997                         /* Symmetric PAUSE */
 
2998                         pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
 
3001         case SK_FLOW_MODE_SYM_OR_REM:
 
3002                 if ((QuickStat & (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) ==
 
3003                         PHY_L_QS_AS_PAUSE) {
 
3004                         /* Enable PAUSE receive, disable PAUSE transmit */
 
3005                         pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
 
3007                 else if ((QuickStat & PHY_L_QS_PAUSE) != 0) {
 
3008                         /* Symmetric PAUSE */
 
3009                         pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
 
3013                 SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
 
3018 }       /* SkXmAutoNegDoneLone */
 
3021 /******************************************************************************
 
3023  *      SkXmAutoNegDoneNat() - Auto-negotiation handling
 
3026  *      This function handles the auto-negotiation if the Done bit is set.
 
3030  *      SK_AND_DUP_CAP  Duplex capability error happened
 
3031  *      SK_AND_OTHER    Other error happened
 
3033 static int SkXmAutoNegDoneNat(
 
3034 SK_AC   *pAC,           /* adapter context */
 
3035 SK_IOC  IoC,            /* IO context */
 
3036 int             Port)           /* Port Index (MAC_1 + n) */
 
3038 /* todo: National */
 
3040 }       /* SkXmAutoNegDoneNat */
 
3041 #endif /* OTHER_PHY */
 
3044 /******************************************************************************
 
3046  *      SkMacAutoNegDone() - Auto-negotiation handling
 
3048  * Description: calls the auto-negotiation done routines dep. on board type
 
3052  *      SK_AND_DUP_CAP  Duplex capability error happened
 
3053  *      SK_AND_OTHER    Other error happened
 
3055 int     SkMacAutoNegDone(
 
3056 SK_AC   *pAC,           /* adapter context */
 
3057 SK_IOC  IoC,            /* IO context */
 
3058 int             Port)           /* Port Index (MAC_1 + n) */
 
3065         pPrt = &pAC->GIni.GP[Port];
 
3068         if (pAC->GIni.GIGenesis) {
 
3070                 switch (pPrt->PhyType) {
 
3073                         Rtv = SkXmAutoNegDoneXmac(pAC, IoC, Port);
 
3076                         Rtv = SkXmAutoNegDoneBcom(pAC, IoC, Port);
 
3080                         Rtv = SkXmAutoNegDoneLone(pAC, IoC, Port);
 
3083                         Rtv = SkXmAutoNegDoneNat(pAC, IoC, Port);
 
3085 #endif /* OTHER_PHY */
 
3087                         return(SK_AND_OTHER);
 
3090 #endif /* GENESIS */
 
3093         if (pAC->GIni.GIYukon) {
 
3095                 Rtv = SkGmAutoNegDoneMarv(pAC, IoC, Port);
 
3099         if (Rtv != SK_AND_OK) {
 
3103         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
 
3104                 ("AutoNeg done Port %d\n", Port));
 
3106         /* We checked everything and may now enable the link */
 
3107         pPrt->PAutoNegFail = SK_FALSE;
 
3109         SkMacRxTxEnable(pAC, IoC, Port);
 
3112 }       /* SkMacAutoNegDone */
 
3115 /******************************************************************************
 
3117  *      SkMacRxTxEnable() - Enable Rx/Tx activity if port is up
 
3119  * Description: enables Rx/Tx dep. on board type
 
3123  *      != 0    Error happened
 
3125 int SkMacRxTxEnable(
 
3126 SK_AC   *pAC,           /* adapter context */
 
3127 SK_IOC  IoC,            /* IO context */
 
3128 int             Port)           /* Port Index (MAC_1 + n) */
 
3131         SK_U16          Reg;            /* 16-bit register value */
 
3132         SK_U16          IntMask;        /* MAC interrupt mask */
 
3137         pPrt = &pAC->GIni.GP[Port];
 
3139         if (!pPrt->PHWLinkUp) {
 
3140                 /* The Hardware link is NOT up */
 
3144         if ((pPrt->PLinkMode == SK_LMODE_AUTOHALF ||
 
3145              pPrt->PLinkMode == SK_LMODE_AUTOFULL ||
 
3146              pPrt->PLinkMode == SK_LMODE_AUTOBOTH) &&
 
3147              pPrt->PAutoNegFail) {
 
3148                 /* Auto-negotiation is not done or failed */
 
3153         if (pAC->GIni.GIGenesis) {
 
3154                 /* set Duplex Mode and Pause Mode */
 
3155                 SkXmInitDupMd(pAC, IoC, Port);
 
3157                 SkXmInitPauseMd(pAC, IoC, Port);
 
3160                  * Initialize the Interrupt Mask Register. Default IRQs are...
 
3161                  *      - Link Asynchronous Event
 
3162                  *      - Link Partner requests config
 
3163                  *      - Auto Negotiation Done
 
3164                  *      - Rx Counter Event Overflow
 
3165                  *      - Tx Counter Event Overflow
 
3166                  *      - Transmit FIFO Underrun
 
3168                 IntMask = XM_DEF_MSK;
 
3171                 /* add IRQ for Receive FIFO Overflow */
 
3172                 IntMask &= ~XM_IS_RXF_OV;
 
3175                 if (pPrt->PhyType != SK_PHY_XMAC) {
 
3176                         /* disable GP0 interrupt bit */
 
3177                         IntMask |= XM_IS_INP_ASS;
 
3179                 XM_OUT16(IoC, Port, XM_IMSK, IntMask);
 
3181                 /* get MMU Command Reg. */
 
3182                 XM_IN16(IoC, Port, XM_MMU_CMD, &Reg);
 
3184                 if (pPrt->PhyType != SK_PHY_XMAC &&
 
3185                         (pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL ||
 
3186                          pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL)) {
 
3187                         /* set to Full Duplex */
 
3188                         Reg |= XM_MMU_GMII_FD;
 
3191                 switch (pPrt->PhyType) {
 
3194                          * Workaround BCOM Errata (#10523) for all BCom Phys
 
3195                          * Enable Power Management after link up
 
3197                         SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &SWord);
 
3198                         SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
 
3199                                 (SK_U16)(SWord & ~PHY_B_AC_DIS_PM));
 
3200             SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK,
 
3201                                 (SK_U16)PHY_B_DEF_MSK);
 
3205                         SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, PHY_L_DEF_MSK);
 
3209                         SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, PHY_N_DEF_MSK); */
 
3210                         /* no interrupts possible from National ??? */
 
3212 #endif /* OTHER_PHY */
 
3216                 XM_OUT16(IoC, Port, XM_MMU_CMD, Reg | XM_MMU_ENA_RX | XM_MMU_ENA_TX);
 
3218 #endif /* GENESIS */
 
3221         if (pAC->GIni.GIYukon) {
 
3223                  * Initialize the Interrupt Mask Register. Default IRQs are...
 
3224                  *      - Rx Counter Event Overflow
 
3225                  *      - Tx Counter Event Overflow
 
3226                  *      - Transmit FIFO Underrun
 
3228                 IntMask = GMAC_DEF_MSK;
 
3231                 /* add IRQ for Receive FIFO Overrun */
 
3232                 IntMask |= GM_IS_RX_FF_OR;
 
3235                 SK_OUT8(IoC, GMAC_IRQ_MSK, (SK_U8)IntMask);
 
3237                 /* get General Purpose Control */
 
3238                 GM_IN16(IoC, Port, GM_GP_CTRL, &Reg);
 
3240                 if (pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL ||
 
3241                         pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL) {
 
3242                         /* set to Full Duplex */
 
3243                         Reg |= GM_GPCR_DUP_FULL;
 
3247         GM_OUT16(IoC, Port, GM_GP_CTRL, (SK_U16)(Reg | GM_GPCR_RX_ENA |
 
3251                 /* Enable all PHY interrupts */
 
3252         SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK,
 
3253                         (SK_U16)PHY_M_DEF_MSK);
 
3260 }       /* SkMacRxTxEnable */
 
3263 /******************************************************************************
 
3265  *      SkMacRxTxDisable() - Disable Receiver and Transmitter
 
3267  * Description: disables Rx/Tx dep. on board type
 
3271 void SkMacRxTxDisable(
 
3272 SK_AC   *pAC,           /* Adapter Context */
 
3273 SK_IOC  IoC,            /* IO context */
 
3274 int             Port)           /* Port Index (MAC_1 + n) */
 
3279         if (pAC->GIni.GIGenesis) {
 
3281                 XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
 
3283                 XM_OUT16(IoC, Port, XM_MMU_CMD, Word & ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX));
 
3285                 /* dummy read to ensure writing */
 
3286                 XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
 
3288 #endif /* GENESIS */
 
3291         if (pAC->GIni.GIYukon) {
 
3293                 GM_IN16(IoC, Port, GM_GP_CTRL, &Word);
 
3295         GM_OUT16(IoC, Port, GM_GP_CTRL, (SK_U16)(Word & ~(GM_GPCR_RX_ENA |
 
3298                 /* dummy read to ensure writing */
 
3299                 GM_IN16(IoC, Port, GM_GP_CTRL, &Word);
 
3303 }       /* SkMacRxTxDisable */
 
3306 /******************************************************************************
 
3308  *      SkMacIrqDisable() - Disable IRQ from MAC
 
3310  * Description: sets the IRQ-mask to disable IRQ dep. on board type
 
3314 void SkMacIrqDisable(
 
3315 SK_AC   *pAC,           /* Adapter Context */
 
3316 SK_IOC  IoC,            /* IO context */
 
3317 int             Port)           /* Port Index (MAC_1 + n) */
 
3324         pPrt = &pAC->GIni.GP[Port];
 
3327         if (pAC->GIni.GIGenesis) {
 
3329                 /* disable all XMAC IRQs */
 
3330                 XM_OUT16(IoC, Port, XM_IMSK, 0xffff);   
 
3332                 /* Disable all PHY interrupts */
 
3333                 switch (pPrt->PhyType) {
 
3335                                 /* Make sure that PHY is initialized */
 
3336                                 if (pPrt->PState != SK_PRT_RESET) {
 
3337                                         /* NOT allowed if BCOM is in RESET state */
 
3338                                         /* Workaround BCOM Errata (#10523) all BCom */
 
3339                                         /* Disable Power Management if link is down */
 
3340                                         SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Word);
 
3341                                         SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
 
3342                                                 (SK_U16)(Word | PHY_B_AC_DIS_PM));
 
3343                                         SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, 0xffff);
 
3348                                 SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, 0);
 
3352                                 SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, 0xffff); */
 
3354 #endif /* OTHER_PHY */
 
3357 #endif /* GENESIS */
 
3360         if (pAC->GIni.GIYukon) {
 
3361                 /* disable all GMAC IRQs */
 
3362                 SK_OUT8(IoC, GMAC_IRQ_MSK, 0);
 
3365                 /* Disable all PHY interrupts */
 
3366                 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, 0);
 
3371 }       /* SkMacIrqDisable */
 
3375 /******************************************************************************
 
3377  *      SkXmSendCont() - Enable / Disable Send Continuous Mode
 
3379  * Description: enable / disable Send Continuous Mode on XMAC
 
3385 SK_AC   *pAC,   /* adapter context */
 
3386 SK_IOC  IoC,    /* IO context */
 
3387 int             Port,   /* Port Index (MAC_1 + n) */
 
3388 SK_BOOL Enable) /* Enable / Disable */
 
3392         XM_IN32(IoC, Port, XM_MODE, &MdReg);
 
3395                 MdReg |= XM_MD_TX_CONT;
 
3398                 MdReg &= ~XM_MD_TX_CONT;
 
3400         /* setup Mode Register */
 
3401         XM_OUT32(IoC, Port, XM_MODE, MdReg);
 
3403 }       /* SkXmSendCont */
 
3406 /******************************************************************************
 
3408  *      SkMacTimeStamp() - Enable / Disable Time Stamp
 
3410  * Description: enable / disable Time Stamp generation for Rx packets
 
3415 void SkMacTimeStamp(
 
3416 SK_AC   *pAC,   /* adapter context */
 
3417 SK_IOC  IoC,    /* IO context */
 
3418 int             Port,   /* Port Index (MAC_1 + n) */
 
3419 SK_BOOL Enable) /* Enable / Disable */
 
3424         if (pAC->GIni.GIGenesis) {
 
3426                 XM_IN32(IoC, Port, XM_MODE, &MdReg);
 
3432                         MdReg &= ~XM_MD_ATS;
 
3434                 /* setup Mode Register */
 
3435                 XM_OUT32(IoC, Port, XM_MODE, MdReg);
 
3439                         TimeCtrl = GMT_ST_START | GMT_ST_CLR_IRQ;
 
3442                         TimeCtrl = GMT_ST_STOP | GMT_ST_CLR_IRQ;
 
3444                 /* Start/Stop Time Stamp Timer */
 
3445                 SK_OUT8(IoC, GMAC_TI_ST_CTRL, TimeCtrl);
 
3448 }       /* SkMacTimeStamp*/
 
3450 #else /* !SK_DIAG */
 
3453 /******************************************************************************
 
3455  *      SkXmAutoNegLipaXmac() - Decides whether Link Partner could do auto-neg
 
3457  *      This function analyses the Interrupt status word. If any of the
 
3458  *      Auto-negotiating interrupt bits are set, the PLipaAutoNeg variable
 
3461 void SkXmAutoNegLipaXmac(
 
3462 SK_AC   *pAC,           /* adapter context */
 
3463 SK_IOC  IoC,            /* IO context */
 
3464 int             Port,           /* Port Index (MAC_1 + n) */
 
3465 SK_U16  IStatus)        /* Interrupt Status word to analyse */
 
3469         pPrt = &pAC->GIni.GP[Port];
 
3471         if (pPrt->PLipaAutoNeg != SK_LIPA_AUTO &&
 
3472                 (IStatus & (XM_IS_LIPA_RC | XM_IS_RX_PAGE | XM_IS_AND)) != 0) {
 
3474                 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
 
3475                         ("AutoNegLipa: AutoNeg detected on Port %d, IStatus=0x%04X\n",
 
3477                 pPrt->PLipaAutoNeg = SK_LIPA_AUTO;
 
3479 }       /* SkXmAutoNegLipaXmac */
 
3480 #endif /* GENESIS */
 
3483 /******************************************************************************
 
3485  *      SkMacAutoNegLipaPhy() - Decides whether Link Partner could do auto-neg
 
3487  *      This function analyses the PHY status word.
 
3488  *  If any of the Auto-negotiating bits are set, the PLipaAutoNeg variable
 
3491 void SkMacAutoNegLipaPhy(
 
3492 SK_AC   *pAC,           /* adapter context */
 
3493 SK_IOC  IoC,            /* IO context */
 
3494 int             Port,           /* Port Index (MAC_1 + n) */
 
3495 SK_U16  PhyStat)        /* PHY Status word to analyse */
 
3499         pPrt = &pAC->GIni.GP[Port];
 
3501         if (pPrt->PLipaAutoNeg != SK_LIPA_AUTO &&
 
3502                 (PhyStat & PHY_ST_AN_OVER) != 0) {
 
3504                 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
 
3505                         ("AutoNegLipa: AutoNeg detected on Port %d, PhyStat=0x%04X\n",
 
3507                 pPrt->PLipaAutoNeg = SK_LIPA_AUTO;
 
3509 }       /* SkMacAutoNegLipaPhy */
 
3513 /******************************************************************************
 
3515  *      SkXmIrq() - Interrupt Service Routine
 
3517  * Description: services an Interrupt Request of the XMAC
 
3520  *      With an external PHY, some interrupt bits are not meaningfull any more:
 
3521  *      - LinkAsyncEvent (bit #14)              XM_IS_LNK_AE
 
3522  *      - LinkPartnerReqConfig (bit #10)        XM_IS_LIPA_RC
 
3523  *      - Page Received (bit #9)                XM_IS_RX_PAGE
 
3524  *      - NextPageLoadedForXmt (bit #8)         XM_IS_TX_PAGE
 
3525  *      - AutoNegDone (bit #7)                  XM_IS_AND
 
3526  *      Also probably not valid any more is the GP0 input bit:
 
3527  *      - GPRegisterBit0set                     XM_IS_INP_ASS
 
3532 static void SkXmIrq(
 
3533 SK_AC   *pAC,           /* adapter context */
 
3534 SK_IOC  IoC,            /* IO context */
 
3535 int             Port)           /* Port Index (MAC_1 + n) */
 
3539         SK_U16          IStatus;        /* Interrupt status read from the XMAC */
 
3542     SK_U64      OverflowStatus;
 
3545         pPrt = &pAC->GIni.GP[Port];
 
3547         XM_IN16(IoC, Port, XM_ISRC, &IStatus);
 
3549         /* LinkPartner Auto-negable? */
 
3550         if (pPrt->PhyType == SK_PHY_XMAC) {
 
3551                 SkXmAutoNegLipaXmac(pAC, IoC, Port, IStatus);
 
3554                 /* mask bits that are not used with ext. PHY */
 
3555                 IStatus &= ~(XM_IS_LNK_AE | XM_IS_LIPA_RC |
 
3556                         XM_IS_RX_PAGE | XM_IS_TX_PAGE |
 
3557                         XM_IS_AND | XM_IS_INP_ASS);
 
3560         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
 
3561                 ("XmacIrq Port %d Isr 0x%04X\n", Port, IStatus));
 
3563         if (!pPrt->PHWLinkUp) {
 
3564                 /* Spurious XMAC interrupt */
 
3565                 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
 
3566                         ("SkXmIrq: spurious interrupt on Port %d\n", Port));
 
3570         if ((IStatus & XM_IS_INP_ASS) != 0) {
 
3571                 /* Reread ISR Register if link is not in sync */
 
3572                 XM_IN16(IoC, Port, XM_ISRC, &IStatus2);
 
3574                 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
 
3575                         ("SkXmIrq: Link async. Double check Port %d 0x%04X 0x%04X\n",
 
3576                          Port, IStatus, IStatus2));
 
3577                 IStatus &= ~XM_IS_INP_ASS;
 
3578                 IStatus |= IStatus2;
 
3581         if ((IStatus & XM_IS_LNK_AE) != 0) {
 
3582                 /* not used, GP0 is used instead */
 
3585         if ((IStatus & XM_IS_TX_ABORT) != 0) {
 
3589         if ((IStatus & XM_IS_FRC_INT) != 0) {
 
3590                 /* not used, use ASIC IRQ instead if needed */
 
3593         if ((IStatus & (XM_IS_INP_ASS | XM_IS_LIPA_RC | XM_IS_RX_PAGE)) != 0) {
 
3594                 SkHWLinkDown(pAC, IoC, Port);
 
3596                 /* Signal to RLMT */
 
3597                 Para.Para32[0] = (SK_U32)Port;
 
3598                 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
 
3600                 /* Start workaround Errata #2 timer */
 
3601                 SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME,
 
3602                         SKGE_HWAC, SK_HWEV_WATIM, Para);
 
3605         if ((IStatus & XM_IS_RX_PAGE) != 0) {
 
3609         if ((IStatus & XM_IS_TX_PAGE) != 0) {
 
3613         if ((IStatus & XM_IS_AND) != 0) {
 
3614                 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
 
3615                         ("SkXmIrq: AND on link that is up Port %d\n", Port));
 
3618         if ((IStatus & XM_IS_TSC_OV) != 0) {
 
3622         /* Combined Tx & Rx Counter Overflow SIRQ Event */
 
3623         if ((IStatus & (XM_IS_RXC_OV | XM_IS_TXC_OV)) != 0) {
 
3625                 SkXmOverflowStatus(pAC, IoC, Port, IStatus, &OverflowStatus);
 
3627                 Para.Para32[0] = (SK_U32)Port;
 
3628                 Para.Para32[1] = (SK_U32)IStatus;
 
3629                 SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_SIRQ_OVERFLOW, Para);
 
3630 #endif /* SK_SLIM */
 
3633         if ((IStatus & XM_IS_RXF_OV) != 0) {
 
3634                 /* normal situation -> no effect */
 
3640         if ((IStatus & XM_IS_TXF_UR) != 0) {
 
3641                 /* may NOT happen -> error log */
 
3642                 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E020, SKERR_SIRQ_E020MSG);
 
3645         if ((IStatus & XM_IS_TX_COMP) != 0) {
 
3646                 /* not served here */
 
3649         if ((IStatus & XM_IS_RX_COMP) != 0) {
 
3650                 /* not served here */
 
3653 #endif /* GENESIS */
 
3657 /******************************************************************************
 
3659  *      SkGmIrq() - Interrupt Service Routine
 
3661  * Description: services an Interrupt Request of the GMAC
 
3668 static void SkGmIrq(
 
3669 SK_AC   *pAC,           /* adapter context */
 
3670 SK_IOC  IoC,            /* IO context */
 
3671 int             Port)           /* Port Index (MAC_1 + n) */
 
3674         SK_U8           IStatus;        /* Interrupt status */
 
3676     SK_U64      OverflowStatus;
 
3681         pPrt = &pAC->GIni.GP[Port];
 
3683         SK_IN8(IoC, GMAC_IRQ_SRC, &IStatus);
 
3686         /* LinkPartner Auto-negable? */
 
3687         SkMacAutoNegLipaPhy(pAC, IoC, Port, IStatus);
 
3690         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
 
3691                 ("GmacIrq Port %d Isr 0x%04X\n", Port, IStatus));
 
3693         /* Combined Tx & Rx Counter Overflow SIRQ Event */
 
3694         if (IStatus & (GM_IS_RX_CO_OV | GM_IS_TX_CO_OV)) {
 
3695                 /* these IRQs will be cleared by reading GMACs register */
 
3697         SkGmOverflowStatus(pAC, IoC, Port, IStatus, &OverflowStatus);
 
3699                 Para.Para32[0] = (SK_U32)Port;
 
3700                 Para.Para32[1] = (SK_U32)IStatus;
 
3701                 SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_SIRQ_OVERFLOW, Para);
 
3705         if (IStatus & GM_IS_RX_FF_OR) {
 
3706                 /* clear GMAC Rx FIFO Overrun IRQ */
 
3707                 SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_CLI_RX_FO);
 
3713         if (IStatus & GM_IS_TX_FF_UR) {
 
3714                 /* clear GMAC Tx FIFO Underrun IRQ */
 
3715                 SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_CLI_TX_FU);
 
3716                 /* may NOT happen -> error log */
 
3717                 SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E020, SKERR_SIRQ_E020MSG);
 
3720         if (IStatus & GM_IS_TX_COMPL) {
 
3721                 /* not served here */
 
3724         if (IStatus & GM_IS_RX_COMPL) {
 
3725                 /* not served here */
 
3731 /******************************************************************************
 
3733  *      SkMacIrq() - Interrupt Service Routine for MAC
 
3735  * Description: calls the Interrupt Service Routine dep. on board type
 
3741 SK_AC   *pAC,           /* adapter context */
 
3742 SK_IOC  IoC,            /* IO context */
 
3743 int             Port)           /* Port Index (MAC_1 + n) */
 
3746         if (pAC->GIni.GIGenesis) {
 
3748                 SkXmIrq(pAC, IoC, Port);
 
3750 #endif /* GENESIS */
 
3753         if (pAC->GIni.GIYukon) {
 
3755                 SkGmIrq(pAC, IoC, Port);
 
3761 #endif /* !SK_DIAG */
 
3764 /******************************************************************************
 
3766  *      SkXmUpdateStats() - Force the XMAC to output the current statistic
 
3769  *      The XMAC holds its statistic internally. To obtain the current
 
3770  *      values a command must be sent so that the statistic data will
 
3771  *      be written to a predefined memory area on the adapter.
 
3775  *      1:  something went wrong
 
3777 int SkXmUpdateStats(
 
3778 SK_AC   *pAC,           /* adapter context */
 
3779 SK_IOC  IoC,            /* IO context */
 
3780 unsigned int Port)      /* Port Index (MAC_1 + n) */
 
3786         pPrt = &pAC->GIni.GP[Port];
 
3789         /* Send an update command to XMAC specified */
 
3790         XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_SNP_TXC | XM_SC_SNP_RXC);
 
3793          * It is an auto-clearing register. If the command bits
 
3794          * went to zero again, the statistics are transferred.
 
3795          * Normally the command should be executed immediately.
 
3796          * But just to be sure we execute a loop.
 
3800                 XM_IN16(IoC, Port, XM_STAT_CMD, &StatReg);
 
3802                 if (++WaitIndex > 10) {
 
3804                         SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E021, SKERR_HWI_E021MSG);
 
3808         } while ((StatReg & (XM_SC_SNP_TXC | XM_SC_SNP_RXC)) != 0);
 
3811 }       /* SkXmUpdateStats */
 
3814 /******************************************************************************
 
3816  *      SkXmMacStatistic() - Get XMAC counter value
 
3819  *      Gets the 32bit counter value. Except for the octet counters
 
3820  *      the lower 32bit are counted in hardware and the upper 32bit
 
3821  *      must be counted in software by monitoring counter overflow interrupts.
 
3825  *      1:  something went wrong
 
3827 int SkXmMacStatistic(
 
3828 SK_AC   *pAC,                   /* adapter context */
 
3829 SK_IOC  IoC,                    /* IO context */
 
3830 unsigned int Port,              /* Port Index (MAC_1 + n) */
 
3831 SK_U16  StatAddr,               /* MIB counter base address */
 
3832 SK_U32  SK_FAR *pVal)   /* ptr to return statistic value */
 
3834         if ((StatAddr < XM_TXF_OK) || (StatAddr > XM_RXF_MAX_SZ)) {
 
3836                 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E022, SKERR_HWI_E022MSG);
 
3841         XM_IN32(IoC, Port, StatAddr, pVal);
 
3844 }       /* SkXmMacStatistic */
 
3847 /******************************************************************************
 
3849  *      SkXmResetCounter() - Clear MAC statistic counter
 
3852  *      Force the XMAC to clear its statistic counter.
 
3856  *      1:  something went wrong
 
3858 int SkXmResetCounter(
 
3859 SK_AC   *pAC,           /* adapter context */
 
3860 SK_IOC  IoC,            /* IO context */
 
3861 unsigned int Port)      /* Port Index (MAC_1 + n) */
 
3863         XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_CLR_RXC | XM_SC_CLR_TXC);
 
3864         /* Clear two times according to Errata #3 */
 
3865         XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_CLR_RXC | XM_SC_CLR_TXC);
 
3868 }       /* SkXmResetCounter */
 
3871 /******************************************************************************
 
3873  *      SkXmOverflowStatus() - Gets the status of counter overflow interrupt
 
3876  *      Checks the source causing an counter overflow interrupt. On success the
 
3877  *      resulting counter overflow status is written to <pStatus>, whereas the
 
3878  *      upper dword stores the XMAC ReceiveCounterEvent register and the lower
 
3879  *      dword the XMAC TransmitCounterEvent register.
 
3882  *      For XMAC the interrupt source is a self-clearing register, so the source
 
3883  *      must be checked only once. SIRQ module does another check to be sure
 
3884  *      that no interrupt get lost during process time.
 
3888  *      1:  something went wrong
 
3890 int SkXmOverflowStatus(
 
3891 SK_AC   *pAC,                           /* adapter context */
 
3892 SK_IOC  IoC,                            /* IO context */
 
3893 unsigned int Port,                      /* Port Index (MAC_1 + n) */
 
3894 SK_U16  IStatus,                        /* Interupt Status from MAC */
 
3895 SK_U64  SK_FAR *pStatus)        /* ptr for return overflow status value */
 
3897         SK_U64  Status; /* Overflow status */
 
3902         if ((IStatus & XM_IS_RXC_OV) != 0) {
 
3904                 XM_IN32(IoC, Port, XM_RX_CNT_EV, &RegVal);
 
3905                 Status |= (SK_U64)RegVal << 32;
 
3908         if ((IStatus & XM_IS_TXC_OV) != 0) {
 
3910                 XM_IN32(IoC, Port, XM_TX_CNT_EV, &RegVal);
 
3911                 Status |= (SK_U64)RegVal;
 
3917 }       /* SkXmOverflowStatus */
 
3918 #endif /* GENESIS */
 
3922 /******************************************************************************
 
3924  *      SkGmUpdateStats() - Force the GMAC to output the current statistic
 
3927  *      Empty function for GMAC. Statistic data is accessible in direct way.
 
3931  *      1:  something went wrong
 
3933 int SkGmUpdateStats(
 
3934 SK_AC   *pAC,           /* adapter context */
 
3935 SK_IOC  IoC,            /* IO context */
 
3936 unsigned int Port)      /* Port Index (MAC_1 + n) */
 
3942 /******************************************************************************
 
3944  *      SkGmMacStatistic() - Get GMAC counter value
 
3947  *      Gets the 32bit counter value. Except for the octet counters
 
3948  *      the lower 32bit are counted in hardware and the upper 32bit
 
3949  *      must be counted in software by monitoring counter overflow interrupts.
 
3953  *      1:  something went wrong
 
3955 int SkGmMacStatistic(
 
3956 SK_AC   *pAC,                   /* adapter context */
 
3957 SK_IOC  IoC,                    /* IO context */
 
3958 unsigned int Port,              /* Port Index (MAC_1 + n) */
 
3959 SK_U16  StatAddr,               /* MIB counter base address */
 
3960 SK_U32  SK_FAR *pVal)   /* ptr to return statistic value */
 
3963         if ((StatAddr < GM_RXF_UC_OK) || (StatAddr > GM_TXE_FIFO_UR)) {
 
3965                 SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E022, SKERR_HWI_E022MSG);
 
3967                 SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
 
3968                         ("SkGmMacStat: wrong MIB counter 0x%04X\n", StatAddr));
 
3972         GM_IN32(IoC, Port, StatAddr, pVal);
 
3975 }       /* SkGmMacStatistic */
 
3978 /******************************************************************************
 
3980  *      SkGmResetCounter() - Clear MAC statistic counter
 
3983  *      Force GMAC to clear its statistic counter.
 
3987  *      1:  something went wrong
 
3989 int SkGmResetCounter(
 
3990 SK_AC   *pAC,           /* adapter context */
 
3991 SK_IOC  IoC,            /* IO context */
 
3992 unsigned int Port)      /* Port Index (MAC_1 + n) */
 
3994         SK_U16  Reg;    /* Phy Address Register */
 
3998         GM_IN16(IoC, Port, GM_PHY_ADDR, &Reg);
 
4000         /* set MIB Clear Counter Mode */
 
4001         GM_OUT16(IoC, Port, GM_PHY_ADDR, Reg | GM_PAR_MIB_CLR);
 
4003         /* read all MIB Counters with Clear Mode set */
 
4004         for (i = 0; i < GM_MIB_CNT_SIZE; i++) {
 
4005                 /* the reset is performed only when the lower 16 bits are read */
 
4006                 GM_IN16(IoC, Port, GM_MIB_CNT_BASE + 8*i, &Word);
 
4009         /* clear MIB Clear Counter Mode */
 
4010         GM_OUT16(IoC, Port, GM_PHY_ADDR, Reg);
 
4013 }       /* SkGmResetCounter */
 
4016 /******************************************************************************
 
4018  *      SkGmOverflowStatus() - Gets the status of counter overflow interrupt
 
4021  *      Checks the source causing an counter overflow interrupt. On success the
 
4022  *      resulting counter overflow status is written to <pStatus>, whereas the
 
4023  *      the following bit coding is used:
 
4025  *      55:48 - TxRx interrupt register bit7:0
 
4026  *      32:47 - Rx interrupt register
 
4028  *      23:16 - TxRx interrupt register bit15:8
 
4029  *      15:0  - Tx interrupt register
 
4033  *      1:  something went wrong
 
4035 int SkGmOverflowStatus(
 
4036 SK_AC   *pAC,                           /* adapter context */
 
4037 SK_IOC  IoC,                            /* IO context */
 
4038 unsigned int Port,                      /* Port Index (MAC_1 + n) */
 
4039 SK_U16  IStatus,                        /* Interupt Status from MAC */
 
4040 SK_U64  SK_FAR *pStatus)        /* ptr for return overflow status value */
 
4042         SK_U64  Status;         /* Overflow status */
 
4047         if ((IStatus & GM_IS_RX_CO_OV) != 0) {
 
4048                 /* this register is self-clearing after read */
 
4049                 GM_IN16(IoC, Port, GM_RX_IRQ_SRC, &RegVal);
 
4050                 Status |= (SK_U64)RegVal << 32;
 
4053         if ((IStatus & GM_IS_TX_CO_OV) != 0) {
 
4054                 /* this register is self-clearing after read */
 
4055                 GM_IN16(IoC, Port, GM_TX_IRQ_SRC, &RegVal);
 
4056                 Status |= (SK_U64)RegVal;
 
4059         /* this register is self-clearing after read */
 
4060         GM_IN16(IoC, Port, GM_TR_IRQ_SRC, &RegVal);
 
4061         /* Rx overflow interrupt register bits (LoByte)*/
 
4062         Status |= (SK_U64)((SK_U8)RegVal) << 48;
 
4063         /* Tx overflow interrupt register bits (HiByte)*/
 
4064         Status |= (SK_U64)(RegVal >> 8) << 16;
 
4069 }       /* SkGmOverflowStatus */
 
4073 /******************************************************************************
 
4075  *      SkGmCableDiagStatus() - Starts / Gets status of cable diagnostic test
 
4078  *  starts the cable diagnostic test if 'StartTest' is true
 
4079  *  gets the results if 'StartTest' is true
 
4081  * NOTE:        this test is meaningful only when link is down
 
4085  *      1:      no YUKON copper
 
4086  *      2:      test in progress
 
4088 int SkGmCableDiagStatus(
 
4089 SK_AC   *pAC,           /* adapter context */
 
4090 SK_IOC  IoC,            /* IO context */
 
4091 int             Port,           /* Port Index (MAC_1 + n) */
 
4092 SK_BOOL StartTest)      /* flag for start / get result */
 
4098         pPrt = &pAC->GIni.GP[Port];
 
4100         if (pPrt->PhyType != SK_PHY_MARV_COPPER) {
 
4106                 /* only start the cable test */
 
4107                 if ((pPrt->PhyId1 & PHY_I1_REV_MSK) < 4) {
 
4108                         /* apply TDR workaround from Marvell */
 
4109                         SkGmPhyWrite(pAC, IoC, Port, 29, 0x001e);
 
4111                         SkGmPhyWrite(pAC, IoC, Port, 30, 0xcc00);
 
4112                         SkGmPhyWrite(pAC, IoC, Port, 30, 0xc800);
 
4113                         SkGmPhyWrite(pAC, IoC, Port, 30, 0xc400);
 
4114                         SkGmPhyWrite(pAC, IoC, Port, 30, 0xc000);
 
4115                         SkGmPhyWrite(pAC, IoC, Port, 30, 0xc100);
 
4118                 /* set address to 0 for MDI[0] */
 
4119                 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 0);
 
4121                 /* Read Cable Diagnostic Reg */
 
4122                 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal);
 
4124                 /* start Cable Diagnostic Test */
 
4125                 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CABLE_DIAG,
 
4126                         (SK_U16)(RegVal | PHY_M_CABD_ENA_TEST));
 
4131         /* Read Cable Diagnostic Reg */
 
4132         SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal);
 
4134         SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
 
4135                 ("PHY Cable Diag.=0x%04X\n", RegVal));
 
4137         if ((RegVal & PHY_M_CABD_ENA_TEST) != 0) {
 
4138                 /* test is running */
 
4142         /* get the test results */
 
4143         for (i = 0; i < 4; i++)  {
 
4144                 /* set address to i for MDI[i] */
 
4145                 SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, (SK_U16)i);
 
4147                 /* get Cable Diagnostic values */
 
4148                 SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal);
 
4150                 pPrt->PMdiPairLen[i] = (SK_U8)(RegVal & PHY_M_CABD_DIST_MSK);
 
4152                 pPrt->PMdiPairSts[i] = (SK_U8)((RegVal & PHY_M_CABD_STAT_MSK) >> 13);
 
4156 }       /* SkGmCableDiagStatus */
 
4157 #endif /* !SK_SLIM */