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