linux-old/drivers/net/sk98lin/skgesirq.c
<<
>>
Prefs
   1/******************************************************************************
   2 *
   3 * Name:        skgesirq.c
   4 * Project:     Gigabit Ethernet Adapters, Common Modules
   5 * Purpose:     Special IRQ module
   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/*
  24 *      Special Interrupt handler
  25 *
  26 *      The following abstract should show how this module is included
  27 *      in the driver path:
  28 *
  29 *      In the ISR of the driver the bits for frame transmission complete and
  30 *      for receive complete are checked and handled by the driver itself.
  31 *      The bits of the slow path mask are checked after that and then the
  32 *      entry into the so-called "slow path" is prepared. It is an implementors
  33 *      decision whether this is executed directly or just scheduled by
  34 *      disabling the mask. In the interrupt service routine some events may be
  35 *      generated, so it would be a good idea to call the EventDispatcher
  36 *      right after this ISR.
  37 *
  38 *      The Interrupt source register of the adapter is NOT read by this module.
  39 *  SO if the drivers implementor needs a while loop around the
  40 *      slow data paths interrupt bits, he needs to call the SkGeSirqIsr() for
  41 *      each loop entered.
  42 *
  43 *      However, the MAC Interrupt status registers are read in a while loop.
  44 *
  45 */
  46
  47#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
  48static const char SysKonnectFileId[] =
  49        "@(#) $Id: skgesirq.c,v 1.92 2003/09/16 14:37:07 rschmidt Exp $ (C) Marvell.";
  50#endif
  51
  52#include "h/skdrv1st.h"         /* Driver Specific Definitions */
  53#ifndef SK_SLIM
  54#include "h/skgepnmi.h"         /* PNMI Definitions */
  55#include "h/skrlmt.h"           /* RLMT Definitions */
  56#endif
  57#include "h/skdrv2nd.h"         /* Adapter Control and Driver specific Def. */
  58
  59/* local function prototypes */
  60#ifdef GENESIS
  61static int      SkGePortCheckUpXmac(SK_AC*, SK_IOC, int, SK_BOOL);
  62static int      SkGePortCheckUpBcom(SK_AC*, SK_IOC, int, SK_BOOL);
  63static void     SkPhyIsrBcom(SK_AC*, SK_IOC, int, SK_U16);
  64#endif /* GENESIS */
  65#ifdef YUKON
  66static int      SkGePortCheckUpGmac(SK_AC*, SK_IOC, int, SK_BOOL);
  67static void     SkPhyIsrGmac(SK_AC*, SK_IOC, int, SK_U16);
  68#endif /* YUKON */
  69#ifdef OTHER_PHY
  70static int      SkGePortCheckUpLone(SK_AC*, SK_IOC, int, SK_BOOL);
  71static int      SkGePortCheckUpNat(SK_AC*, SK_IOC, int, SK_BOOL);
  72static void     SkPhyIsrLone(SK_AC*, SK_IOC, int, SK_U16);
  73#endif /* OTHER_PHY */
  74
  75#ifdef GENESIS
  76/*
  77 * array of Rx counter from XMAC which are checked
  78 * in AutoSense mode to check whether a link is not able to auto-negotiate.
  79 */
  80static const SK_U16 SkGeRxRegs[]= {
  81        XM_RXF_64B,
  82        XM_RXF_127B,
  83        XM_RXF_255B,
  84        XM_RXF_511B,
  85        XM_RXF_1023B,
  86        XM_RXF_MAX_SZ
  87} ;
  88#endif /* GENESIS */
  89
  90#ifdef __C2MAN__
  91/*
  92 *      Special IRQ function
  93 *
  94 *      General Description:
  95 *
  96 */
  97intro()
  98{}
  99#endif
 100
 101/******************************************************************************
 102 *
 103 *      SkHWInitDefSense() - Default Autosensing mode initialization
 104 *
 105 * Description: sets the PLinkMode for HWInit
 106 *
 107 * Returns: N/A
 108 */
 109static void SkHWInitDefSense(
 110SK_AC   *pAC,   /* adapter context */
 111SK_IOC  IoC,    /* IO context */
 112int             Port)   /* Port Index (MAC_1 + n) */
 113{
 114        SK_GEPORT       *pPrt;          /* GIni Port struct pointer */
 115
 116        pPrt = &pAC->GIni.GP[Port];
 117
 118        pPrt->PAutoNegTimeOut = 0;
 119
 120        if (pPrt->PLinkModeConf != SK_LMODE_AUTOSENSE) {
 121                pPrt->PLinkMode = pPrt->PLinkModeConf;
 122                return;
 123        }
 124
 125        SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
 126                ("AutoSensing: First mode %d on Port %d\n",
 127                (int)SK_LMODE_AUTOFULL, Port));
 128
 129        pPrt->PLinkMode = (SK_U8)SK_LMODE_AUTOFULL;
 130
 131        return;
 132}       /* SkHWInitDefSense */
 133
 134
 135#ifdef GENESIS
 136/******************************************************************************
 137 *
 138 *      SkHWSenseGetNext() - Get Next Autosensing Mode
 139 *
 140 * Description: gets the appropriate next mode
 141 *
 142 * Note:
 143 *
 144 */
 145static SK_U8 SkHWSenseGetNext(
 146SK_AC   *pAC,   /* adapter context */
 147SK_IOC  IoC,    /* IO context */
 148int             Port)   /* Port Index (MAC_1 + n) */
 149{
 150        SK_GEPORT       *pPrt;          /* GIni Port struct pointer */
 151
 152        pPrt = &pAC->GIni.GP[Port];
 153
 154        pPrt->PAutoNegTimeOut = 0;
 155
 156    if (pPrt->PLinkModeConf != (SK_U8)SK_LMODE_AUTOSENSE) {
 157                /* Leave all as configured */
 158                return(pPrt->PLinkModeConf);
 159        }
 160
 161    if (pPrt->PLinkMode == (SK_U8)SK_LMODE_AUTOFULL) {
 162                /* Return next mode AUTOBOTH */
 163        return ((SK_U8)SK_LMODE_AUTOBOTH);
 164        }
 165
 166        /* Return default autofull */
 167    return ((SK_U8)SK_LMODE_AUTOFULL);
 168}       /* SkHWSenseGetNext */
 169
 170
 171/******************************************************************************
 172 *
 173 *      SkHWSenseSetNext() - Autosensing Set next mode
 174 *
 175 * Description: sets the appropriate next mode
 176 *
 177 * Returns: N/A
 178 */
 179static void SkHWSenseSetNext(
 180SK_AC   *pAC,           /* adapter context */
 181SK_IOC  IoC,            /* IO context */
 182int             Port,           /* Port Index (MAC_1 + n) */
 183SK_U8   NewMode)        /* New Mode to be written in sense mode */
 184{
 185        SK_GEPORT       *pPrt;          /* GIni Port struct pointer */
 186
 187        pPrt = &pAC->GIni.GP[Port];
 188
 189        pPrt->PAutoNegTimeOut = 0;
 190
 191    if (pPrt->PLinkModeConf != (SK_U8)SK_LMODE_AUTOSENSE) {
 192                return;
 193        }
 194
 195        SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
 196                ("AutoSensing: next mode %d on Port %d\n",
 197                (int)NewMode, Port));
 198
 199        pPrt->PLinkMode = NewMode;
 200
 201        return;
 202}       /* SkHWSenseSetNext */
 203#endif /* GENESIS */
 204
 205
 206/******************************************************************************
 207 *
 208 *      SkHWLinkDown() - Link Down handling
 209 *
 210 * Description: handles the hardware link down signal
 211 *
 212 * Returns: N/A
 213 */
 214void SkHWLinkDown(
 215SK_AC   *pAC,           /* adapter context */
 216SK_IOC  IoC,            /* IO context */
 217int             Port)           /* Port Index (MAC_1 + n) */
 218{
 219        SK_GEPORT       *pPrt;          /* GIni Port struct pointer */
 220
 221        pPrt = &pAC->GIni.GP[Port];
 222
 223        /* Disable all MAC interrupts */
 224        SkMacIrqDisable(pAC, IoC, Port);
 225
 226        /* Disable Receiver and Transmitter */
 227        SkMacRxTxDisable(pAC, IoC, Port);
 228        
 229        /* Init default sense mode */
 230        SkHWInitDefSense(pAC, IoC, Port);
 231
 232        if (pPrt->PHWLinkUp == SK_FALSE) {
 233                return;
 234        }
 235
 236        SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
 237                ("Link down Port %d\n", Port));
 238
 239        /* Set Link to DOWN */
 240        pPrt->PHWLinkUp = SK_FALSE;
 241
 242        /* Reset Port stati */
 243    pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN;
 244    pPrt->PFlowCtrlStatus = (SK_U8)SK_FLOW_STAT_NONE;
 245        pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_INDETERMINATED;
 246
 247        /* Re-init Phy especially when the AutoSense default is set now */
 248        SkMacInitPhy(pAC, IoC, Port, SK_FALSE);
 249
 250        /* GP0: used for workaround of Rev. C Errata 2 */
 251
 252        /* Do NOT signal to RLMT */
 253
 254        /* Do NOT start the timer here */
 255}       /* SkHWLinkDown */
 256
 257
 258/******************************************************************************
 259 *
 260 *      SkHWLinkUp() - Link Up handling
 261 *
 262 * Description: handles the hardware link up signal
 263 *
 264 * Returns: N/A
 265 */
 266void SkHWLinkUp(
 267SK_AC   *pAC,   /* adapter context */
 268SK_IOC  IoC,    /* IO context */
 269int             Port)   /* Port Index (MAC_1 + n) */
 270{
 271        SK_GEPORT       *pPrt;          /* GIni Port struct pointer */
 272
 273        pPrt = &pAC->GIni.GP[Port];
 274
 275        if (pPrt->PHWLinkUp) {
 276                /* We do NOT need to proceed on active link */
 277                return;
 278        }
 279
 280        pPrt->PHWLinkUp = SK_TRUE;
 281        pPrt->PAutoNegFail = SK_FALSE;
 282    pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN;
 283
 284    if (pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOHALF &&
 285        pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOFULL &&
 286        pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOBOTH) {
 287                /* Link is up and no Auto-negotiation should be done */
 288
 289                /* Link speed should be the configured one */
 290                switch (pPrt->PLinkSpeed) {
 291                case SK_LSPEED_AUTO:
 292                        /* default is 1000 Mbps */
 293                case SK_LSPEED_1000MBPS:
 294                        pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS;
 295                        break;
 296                case SK_LSPEED_100MBPS:
 297                        pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_100MBPS;
 298                        break;
 299                case SK_LSPEED_10MBPS:
 300                        pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_10MBPS;
 301                        break;
 302                }
 303
 304                /* Set Link Mode Status */
 305                if (pPrt->PLinkMode == SK_LMODE_FULL) {
 306                        pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_FULL;
 307                }
 308                else {
 309            pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_HALF;
 310                }
 311
 312                /* No flow control without auto-negotiation */
 313        pPrt->PFlowCtrlStatus = (SK_U8)SK_FLOW_STAT_NONE;
 314
 315                /* enable Rx/Tx */
 316        (void)SkMacRxTxEnable(pAC, IoC, Port);
 317        }
 318}       /* SkHWLinkUp */
 319
 320
 321/******************************************************************************
 322 *
 323 *      SkMacParity() - MAC parity workaround
 324 *
 325 * Description: handles MAC parity errors correctly
 326 *
 327 * Returns: N/A
 328 */
 329static void SkMacParity(
 330SK_AC   *pAC,   /* adapter context */
 331SK_IOC  IoC,    /* IO context */
 332int             Port)   /* Port Index of the port failed */
 333{
 334        SK_EVPARA       Para;
 335        SK_GEPORT       *pPrt;          /* GIni Port struct pointer */
 336        SK_U32          TxMax;          /* Tx Max Size Counter */
 337
 338        pPrt = &pAC->GIni.GP[Port];
 339
 340        /* Clear IRQ Tx Parity Error */
 341#ifdef GENESIS
 342        if (pAC->GIni.GIGenesis) {
 343
 344                SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_PERR);
 345        }
 346#endif /* GENESIS */
 347        
 348#ifdef YUKON
 349        if (pAC->GIni.GIYukon) {
 350                /* HW-Bug #8: cleared by GMF_CLI_TX_FC instead of GMF_CLI_TX_PE */
 351                SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T),
 352                        (SK_U8)((pAC->GIni.GIChipId == CHIP_ID_YUKON &&
 353                        pAC->GIni.GIChipRev == 0) ? GMF_CLI_TX_FC : GMF_CLI_TX_PE));
 354        }
 355#endif /* YUKON */
 356        
 357        if (pPrt->PCheckPar) {
 358
 359                if (Port == MAC_1) {
 360                        SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E016, SKERR_SIRQ_E016MSG);
 361                }
 362                else {
 363                        SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E017, SKERR_SIRQ_E017MSG);
 364                }
 365                Para.Para64 = Port;
 366                SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
 367                
 368                Para.Para32[0] = Port;
 369                SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
 370
 371                return;
 372        }
 373
 374        /* Check whether frames with a size of 1k were sent */
 375#ifdef GENESIS
 376        if (pAC->GIni.GIGenesis) {
 377                /* Snap statistic counters */
 378                (void)SkXmUpdateStats(pAC, IoC, Port);
 379                
 380                (void)SkXmMacStatistic(pAC, IoC, Port, XM_TXF_MAX_SZ, &TxMax);
 381        }
 382#endif /* GENESIS */
 383        
 384#ifdef YUKON
 385        if (pAC->GIni.GIYukon) {
 386
 387                (void)SkGmMacStatistic(pAC, IoC, Port, GM_TXF_1518B, &TxMax);
 388        }
 389#endif /* YUKON */
 390        
 391        if (TxMax > 0) {
 392                /* From now on check the parity */
 393                pPrt->PCheckPar = SK_TRUE;
 394        }
 395}       /* SkMacParity */
 396
 397
 398/******************************************************************************
 399 *
 400 *      SkGeHwErr() - Hardware Error service routine
 401 *
 402 * Description: handles all HW Error interrupts
 403 *
 404 * Returns: N/A
 405 */
 406static void SkGeHwErr(
 407SK_AC   *pAC,           /* adapter context */
 408SK_IOC  IoC,            /* IO context */
 409SK_U32  HwStatus)       /* Interrupt status word */
 410{
 411        SK_EVPARA       Para;
 412        SK_U16          Word;
 413
 414        if ((HwStatus & (IS_IRQ_MST_ERR | IS_IRQ_STAT)) != 0) {
 415                /* PCI Errors occured */
 416                if ((HwStatus & IS_IRQ_STAT) != 0) {
 417                        SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E013, SKERR_SIRQ_E013MSG);
 418                }
 419                else {
 420                        SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E012, SKERR_SIRQ_E012MSG);
 421                }
 422
 423                /* Reset all bits in the PCI STATUS register */
 424                SK_IN16(IoC, PCI_C(PCI_STATUS), &Word);
 425                
 426                SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON);
 427        SK_OUT16(IoC, PCI_C(PCI_STATUS), (SK_U16)(Word | PCI_ERRBITS));
 428                SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
 429
 430                Para.Para64 = 0;
 431                SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);
 432        }
 433
 434#ifdef GENESIS
 435        if (pAC->GIni.GIGenesis) {
 436
 437                if ((HwStatus & IS_NO_STAT_M1) != 0) {
 438                        /* Ignore it */
 439                        /* This situation is also indicated in the descriptor */
 440                        SK_OUT16(IoC, MR_ADDR(MAC_1, RX_MFF_CTRL1), MFF_CLR_INSTAT);
 441                }
 442
 443                if ((HwStatus & IS_NO_STAT_M2) != 0) {
 444                        /* Ignore it */
 445                        /* This situation is also indicated in the descriptor */
 446                        SK_OUT16(IoC, MR_ADDR(MAC_2, RX_MFF_CTRL1), MFF_CLR_INSTAT);
 447                }
 448
 449                if ((HwStatus & IS_NO_TIST_M1) != 0) {
 450                        /* Ignore it */
 451                        /* This situation is also indicated in the descriptor */
 452                        SK_OUT16(IoC, MR_ADDR(MAC_1, RX_MFF_CTRL1), MFF_CLR_INTIST);
 453                }
 454
 455                if ((HwStatus & IS_NO_TIST_M2) != 0) {
 456                        /* Ignore it */
 457                        /* This situation is also indicated in the descriptor */
 458                        SK_OUT16(IoC, MR_ADDR(MAC_2, RX_MFF_CTRL1), MFF_CLR_INTIST);
 459                }
 460        }
 461#endif /* GENESIS */
 462        
 463#ifdef YUKON
 464        if (pAC->GIni.GIYukon) {
 465                /* This is necessary only for Rx timing measurements */
 466                if ((HwStatus & IS_IRQ_TIST_OV) != 0) {
 467                        /* increment Time Stamp Timer counter (high) */
 468                        pAC->GIni.GITimeStampCnt++;
 469
 470                        /* Clear Time Stamp Timer IRQ */
 471                        SK_OUT8(IoC, GMAC_TI_ST_CTRL, (SK_U8)GMT_ST_CLR_IRQ);
 472                }
 473
 474                if ((HwStatus & IS_IRQ_SENSOR) != 0) {
 475                        /* no sensors on 32-bit Yukon */
 476                        if (pAC->GIni.GIYukon32Bit) {
 477                                /* disable HW Error IRQ */
 478                                pAC->GIni.GIValIrqMask &= ~IS_HW_ERR;
 479                        }
 480                }
 481        }
 482#endif /* YUKON */
 483
 484        if ((HwStatus & IS_RAM_RD_PAR) != 0) {
 485                SK_OUT16(IoC, B3_RI_CTRL, RI_CLR_RD_PERR);
 486                SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E014, SKERR_SIRQ_E014MSG);
 487                Para.Para64 = 0;
 488                SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);
 489        }
 490
 491        if ((HwStatus & IS_RAM_WR_PAR) != 0) {
 492                SK_OUT16(IoC, B3_RI_CTRL, RI_CLR_WR_PERR);
 493                SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E015, SKERR_SIRQ_E015MSG);
 494                Para.Para64 = 0;
 495                SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);
 496        }
 497
 498        if ((HwStatus & IS_M1_PAR_ERR) != 0) {
 499                SkMacParity(pAC, IoC, MAC_1);
 500        }
 501
 502        if ((HwStatus & IS_M2_PAR_ERR) != 0) {
 503                SkMacParity(pAC, IoC, MAC_2);
 504        }
 505
 506        if ((HwStatus & IS_R1_PAR_ERR) != 0) {
 507                /* Clear IRQ */
 508                SK_OUT32(IoC, B0_R1_CSR, CSR_IRQ_CL_P);
 509
 510                SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E018, SKERR_SIRQ_E018MSG);
 511                Para.Para64 = MAC_1;
 512                SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
 513                
 514                Para.Para32[0] = MAC_1;
 515                SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
 516        }
 517
 518        if ((HwStatus & IS_R2_PAR_ERR) != 0) {
 519                /* Clear IRQ */
 520                SK_OUT32(IoC, B0_R2_CSR, CSR_IRQ_CL_P);
 521
 522                SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E019, SKERR_SIRQ_E019MSG);
 523                Para.Para64 = MAC_2;
 524                SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
 525                
 526                Para.Para32[0] = MAC_2;
 527                SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
 528        }
 529}       /* SkGeHwErr */
 530
 531
 532/******************************************************************************
 533 *
 534 *      SkGeSirqIsr() - Special Interrupt Service Routine
 535 *
 536 * Description: handles all non data transfer specific interrupts (slow path)
 537 *
 538 * Returns: N/A
 539 */
 540void SkGeSirqIsr(
 541SK_AC   *pAC,           /* adapter context */
 542SK_IOC  IoC,            /* IO context */
 543SK_U32  Istatus)        /* Interrupt status word */
 544{
 545        SK_EVPARA       Para;
 546        SK_U32          RegVal32;       /* Read register value */
 547        SK_GEPORT       *pPrt;          /* GIni Port struct pointer */
 548        SK_U16          PhyInt;
 549        int                     i;
 550
 551        if (((Istatus & IS_HW_ERR) & pAC->GIni.GIValIrqMask) != 0) {
 552                /* read the HW Error Interrupt source */
 553                SK_IN32(IoC, B0_HWE_ISRC, &RegVal32);
 554                
 555                SkGeHwErr(pAC, IoC, RegVal32);
 556        }
 557
 558        /*
 559         * Packet Timeout interrupts
 560         */
 561        /* Check whether MACs are correctly initialized */
 562        if (((Istatus & (IS_PA_TO_RX1 | IS_PA_TO_TX1)) != 0) &&
 563                pAC->GIni.GP[MAC_1].PState == SK_PRT_RESET) {
 564                /* MAC 1 was not initialized but Packet timeout occured */
 565                SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E004,
 566                        SKERR_SIRQ_E004MSG);
 567        }
 568
 569        if (((Istatus & (IS_PA_TO_RX2 | IS_PA_TO_TX2)) != 0) &&
 570            pAC->GIni.GP[MAC_2].PState == SK_PRT_RESET) {
 571                /* MAC 2 was not initialized but Packet timeout occured */
 572                SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E005,
 573                        SKERR_SIRQ_E005MSG);
 574        }
 575
 576        if ((Istatus & IS_PA_TO_RX1) != 0) {
 577                /* Means network is filling us up */
 578                SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E002,
 579                        SKERR_SIRQ_E002MSG);
 580                SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_RX1);
 581        }
 582
 583        if ((Istatus & IS_PA_TO_RX2) != 0) {
 584                /* Means network is filling us up */
 585                SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E003,
 586                        SKERR_SIRQ_E003MSG);
 587                SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_RX2);
 588        }
 589
 590        if ((Istatus & IS_PA_TO_TX1) != 0) {
 591                
 592                pPrt = &pAC->GIni.GP[0];
 593
 594                /* May be a normal situation in a server with a slow network */
 595                SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_TX1);
 596
 597#ifdef GENESIS
 598                if (pAC->GIni.GIGenesis) {
 599                        /*
 600                         * workaround: if in half duplex mode, check for Tx hangup.
 601                         * Read number of TX'ed bytes, wait for 10 ms, then compare
 602                         * the number with current value. If nothing changed, we assume
 603                         * that Tx is hanging and do a FIFO flush (see event routine).
 604                         */
 605                        if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF ||
 606                                pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) &&
 607                                !pPrt->HalfDupTimerActive) {
 608                                /*
 609                                 * many more pack. arb. timeouts may come in between,
 610                                 * we ignore those
 611                                 */
 612                                pPrt->HalfDupTimerActive = SK_TRUE;
 613#ifdef XXX
 614                                Len = sizeof(SK_U64);
 615                                SkPnmiGetVar(pAC, IoC, OID_SKGE_STAT_TX_OCTETS, (char *)&Octets,
 616                                        &Len, (SK_U32)SK_PNMI_PORT_PHYS2INST(pAC, 0),
 617                                        pAC->Rlmt.Port[0].Net->NetNumber);
 618                                
 619                                pPrt->LastOctets = Octets;
 620#endif /* XXX */
 621                                /* Snap statistic counters */
 622                                (void)SkXmUpdateStats(pAC, IoC, 0);
 623
 624                                (void)SkXmMacStatistic(pAC, IoC, 0, XM_TXO_OK_HI, &RegVal32);
 625
 626                                pPrt->LastOctets = (SK_U64)RegVal32 << 32;
 627                                
 628                                (void)SkXmMacStatistic(pAC, IoC, 0, XM_TXO_OK_LO, &RegVal32);
 629
 630                                pPrt->LastOctets += RegVal32;
 631                                
 632                                Para.Para32[0] = 0;
 633                                SkTimerStart(pAC, IoC, &pPrt->HalfDupChkTimer, SK_HALFDUP_CHK_TIME,
 634                                        SKGE_HWAC, SK_HWEV_HALFDUP_CHK, Para);
 635                        }
 636                }
 637#endif /* GENESIS */
 638        }
 639
 640        if ((Istatus & IS_PA_TO_TX2) != 0) {
 641                
 642                pPrt = &pAC->GIni.GP[1];
 643
 644                /* May be a normal situation in a server with a slow network */
 645                SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_TX2);
 646
 647#ifdef GENESIS
 648                if (pAC->GIni.GIGenesis) {
 649                        /* workaround: see above */
 650                        if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF ||
 651                                 pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) &&
 652                                !pPrt->HalfDupTimerActive) {
 653                                pPrt->HalfDupTimerActive = SK_TRUE;
 654#ifdef XXX
 655                                Len = sizeof(SK_U64);
 656                                SkPnmiGetVar(pAC, IoC, OID_SKGE_STAT_TX_OCTETS, (char *)&Octets,
 657                                        &Len, (SK_U32)SK_PNMI_PORT_PHYS2INST(pAC, 1),
 658                                        pAC->Rlmt.Port[1].Net->NetNumber);
 659                                
 660                                pPrt->LastOctets = Octets;
 661#endif /* XXX */
 662                                /* Snap statistic counters */
 663                                (void)SkXmUpdateStats(pAC, IoC, 1);
 664
 665                                (void)SkXmMacStatistic(pAC, IoC, 1, XM_TXO_OK_HI, &RegVal32);
 666
 667                                pPrt->LastOctets = (SK_U64)RegVal32 << 32;
 668                                
 669                                (void)SkXmMacStatistic(pAC, IoC, 1, XM_TXO_OK_LO, &RegVal32);
 670
 671                                pPrt->LastOctets += RegVal32;
 672                                
 673                                Para.Para32[0] = 1;
 674                                SkTimerStart(pAC, IoC, &pPrt->HalfDupChkTimer, SK_HALFDUP_CHK_TIME,
 675                                        SKGE_HWAC, SK_HWEV_HALFDUP_CHK, Para);
 676                        }
 677                }
 678#endif /* GENESIS */
 679        }
 680
 681        /* Check interrupts of the particular queues */
 682        if ((Istatus & IS_R1_C) != 0) {
 683                /* Clear IRQ */
 684                SK_OUT32(IoC, B0_R1_CSR, CSR_IRQ_CL_C);
 685                SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E006,
 686                        SKERR_SIRQ_E006MSG);
 687                Para.Para64 = MAC_1;
 688                SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
 689                Para.Para32[0] = MAC_1;
 690                SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
 691        }
 692
 693        if ((Istatus & IS_R2_C) != 0) {
 694                /* Clear IRQ */
 695                SK_OUT32(IoC, B0_R2_CSR, CSR_IRQ_CL_C);
 696                SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E007,
 697                        SKERR_SIRQ_E007MSG);
 698                Para.Para64 = MAC_2;
 699                SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
 700                Para.Para32[0] = MAC_2;
 701                SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
 702        }
 703
 704        if ((Istatus & IS_XS1_C) != 0) {
 705                /* Clear IRQ */
 706                SK_OUT32(IoC, B0_XS1_CSR, CSR_IRQ_CL_C);
 707                SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E008,
 708                        SKERR_SIRQ_E008MSG);
 709                Para.Para64 = MAC_1;
 710                SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
 711                Para.Para32[0] = MAC_1;
 712                SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
 713        }
 714
 715        if ((Istatus & IS_XA1_C) != 0) {
 716                /* Clear IRQ */
 717                SK_OUT32(IoC, B0_XA1_CSR, CSR_IRQ_CL_C);
 718                SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E009,
 719                        SKERR_SIRQ_E009MSG);
 720                Para.Para64 = MAC_1;
 721                SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
 722                Para.Para32[0] = MAC_1;
 723                SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
 724        }
 725
 726        if ((Istatus & IS_XS2_C) != 0) {
 727                /* Clear IRQ */
 728                SK_OUT32(IoC, B0_XS2_CSR, CSR_IRQ_CL_C);
 729                SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E010,
 730                        SKERR_SIRQ_E010MSG);
 731                Para.Para64 = MAC_2;
 732                SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
 733                Para.Para32[0] = MAC_2;
 734                SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
 735        }
 736
 737        if ((Istatus & IS_XA2_C) != 0) {
 738                /* Clear IRQ */
 739                SK_OUT32(IoC, B0_XA2_CSR, CSR_IRQ_CL_C);
 740                SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E011,
 741                        SKERR_SIRQ_E011MSG);
 742                Para.Para64 = MAC_2;
 743                SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
 744                Para.Para32[0] = MAC_2;
 745                SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
 746        }
 747
 748        /* External reg interrupt */
 749        if ((Istatus & IS_EXT_REG) != 0) {
 750                /* Test IRQs from PHY */
 751                for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
 752                        
 753                        pPrt = &pAC->GIni.GP[i];
 754                        
 755                        if (pPrt->PState == SK_PRT_RESET) {
 756                                continue;
 757                        }
 758                        
 759#ifdef GENESIS
 760                        if (pAC->GIni.GIGenesis) {
 761                                
 762                                switch (pPrt->PhyType) {
 763                                
 764                                case SK_PHY_XMAC:
 765                                        break;
 766                                
 767                                case SK_PHY_BCOM:
 768                                        SkXmPhyRead(pAC, IoC, i, PHY_BCOM_INT_STAT, &PhyInt);
 769        
 770                                        if ((PhyInt & ~PHY_B_DEF_MSK) != 0) {
 771                                                SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
 772                                                        ("Port %d Bcom Int: 0x%04X\n",
 773                                                        i, PhyInt));
 774                                                SkPhyIsrBcom(pAC, IoC, i, PhyInt);
 775                                        }
 776                                        break;
 777#ifdef OTHER_PHY
 778                                case SK_PHY_LONE:
 779                                        SkXmPhyRead(pAC, IoC, i, PHY_LONE_INT_STAT, &PhyInt);
 780                                        
 781                                        if ((PhyInt & PHY_L_DEF_MSK) != 0) {
 782                                                SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
 783                                                        ("Port %d Lone Int: %x\n",
 784                                                        i, PhyInt));
 785                                                SkPhyIsrLone(pAC, IoC, i, PhyInt);
 786                                        }
 787                                        break;
 788#endif /* OTHER_PHY */
 789                                }
 790                        }
 791#endif /* GENESIS */
 792        
 793#ifdef YUKON
 794                        if (pAC->GIni.GIYukon) {
 795                                /* Read PHY Interrupt Status */
 796                                SkGmPhyRead(pAC, IoC, i, PHY_MARV_INT_STAT, &PhyInt);
 797
 798                                if ((PhyInt & PHY_M_DEF_MSK) != 0) {
 799                                        SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
 800                                                ("Port %d Marv Int: 0x%04X\n",
 801                                                i, PhyInt));
 802                                        SkPhyIsrGmac(pAC, IoC, i, PhyInt);
 803                                }
 804                        }
 805#endif /* YUKON */
 806                }
 807        }
 808
 809        /* I2C Ready interrupt */
 810        if ((Istatus & IS_I2C_READY) != 0) {
 811#ifdef SK_SLIM
 812        SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ);
 813#else           
 814                SkI2cIsr(pAC, IoC);
 815#endif          
 816        }
 817
 818        /* SW forced interrupt */
 819        if ((Istatus & IS_IRQ_SW) != 0) {
 820                /* clear the software IRQ */
 821                SK_OUT8(IoC, B0_CTST, CS_CL_SW_IRQ);
 822        }
 823
 824        if ((Istatus & IS_LNK_SYNC_M1) != 0) {
 825                /*
 826                 * We do NOT need the Link Sync interrupt, because it shows
 827                 * us only a link going down.
 828                 */
 829                /* clear interrupt */
 830                SK_OUT8(IoC, MR_ADDR(MAC_1, LNK_SYNC_CTRL), LED_CLR_IRQ);
 831        }
 832
 833        /* Check MAC after link sync counter */
 834        if ((Istatus & IS_MAC1) != 0) {
 835                /* IRQ from MAC 1 */
 836                SkMacIrq(pAC, IoC, MAC_1);
 837        }
 838
 839        if ((Istatus & IS_LNK_SYNC_M2) != 0) {
 840                /*
 841                 * We do NOT need the Link Sync interrupt, because it shows
 842                 * us only a link going down.
 843                 */
 844                /* clear interrupt */
 845                SK_OUT8(IoC, MR_ADDR(MAC_2, LNK_SYNC_CTRL), LED_CLR_IRQ);
 846        }
 847
 848        /* Check MAC after link sync counter */
 849        if ((Istatus & IS_MAC2) != 0) {
 850                /* IRQ from MAC 2 */
 851                SkMacIrq(pAC, IoC, MAC_2);
 852        }
 853
 854        /* Timer interrupt (served last) */
 855        if ((Istatus & IS_TIMINT) != 0) {
 856                /* check for HW Errors */
 857                if (((Istatus & IS_HW_ERR) & ~pAC->GIni.GIValIrqMask) != 0) {
 858                        /* read the HW Error Interrupt source */
 859                        SK_IN32(IoC, B0_HWE_ISRC, &RegVal32);
 860
 861                        SkGeHwErr(pAC, IoC, RegVal32);
 862                }
 863
 864                SkHwtIsr(pAC, IoC);
 865        }
 866
 867}       /* SkGeSirqIsr */
 868
 869
 870#ifdef GENESIS
 871/******************************************************************************
 872 *
 873 * SkGePortCheckShorts() - Implementing XMAC Workaround Errata # 2
 874 *
 875 * return:
 876 *      0       o.k. nothing needed
 877 *      1       Restart needed on this port
 878 */
 879static int SkGePortCheckShorts(
 880SK_AC   *pAC,           /* Adapter Context */
 881SK_IOC  IoC,            /* IO Context */
 882int             Port)           /* Which port should be checked */
 883{
 884        SK_U32          Shorts;                 /* Short Event Counter */
 885        SK_U32          CheckShorts;    /* Check value for Short Event Counter */
 886        SK_U64          RxCts;                  /* Rx Counter (packets on network) */
 887        SK_U32          RxTmp;                  /* Rx temp. Counter */
 888        SK_U32          FcsErrCts;              /* FCS Error Counter */
 889        SK_GEPORT       *pPrt;                  /* GIni Port struct pointer */
 890        int                     Rtv;                    /* Return value */
 891        int                     i;
 892
 893        pPrt = &pAC->GIni.GP[Port];
 894
 895        /* Default: no action */
 896        Rtv = SK_HW_PS_NONE;
 897
 898        (void)SkXmUpdateStats(pAC, IoC, Port);
 899
 900        /* Extra precaution: check for short Event counter */
 901        (void)SkXmMacStatistic(pAC, IoC, Port, XM_RXE_SHT_ERR, &Shorts);
 902
 903        /*
 904         * Read Rx counters (packets seen on the network and not necessarily
 905         * really received.
 906         */
 907        RxCts = 0;
 908
 909        for (i = 0; i < sizeof(SkGeRxRegs)/sizeof(SkGeRxRegs[0]); i++) {
 910                
 911                (void)SkXmMacStatistic(pAC, IoC, Port, SkGeRxRegs[i], &RxTmp);
 912                
 913                RxCts += (SK_U64)RxTmp;
 914        }
 915
 916        /* On default: check shorts against zero */
 917        CheckShorts = 0;
 918
 919        /* Extra precaution on active links */
 920        if (pPrt->PHWLinkUp) {
 921                /* Reset Link Restart counter */
 922                pPrt->PLinkResCt = 0;
 923                pPrt->PAutoNegTOCt = 0;
 924
 925                /* If link is up check for 2 */
 926                CheckShorts = 2;
 927
 928                (void)SkXmMacStatistic(pAC, IoC, Port, XM_RXF_FCS_ERR, &FcsErrCts);
 929                
 930                if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE &&
 931                    pPrt->PLipaAutoNeg == SK_LIPA_UNKNOWN &&
 932                    (pPrt->PLinkMode == SK_LMODE_HALF ||
 933                         pPrt->PLinkMode == SK_LMODE_FULL)) {
 934                        /*
 935                         * This is autosensing and we are in the fallback
 936                         * manual full/half duplex mode.
 937                         */
 938                        if (RxCts == pPrt->PPrevRx) {
 939                                /* Nothing received, restart link */
 940                                pPrt->PPrevFcs = FcsErrCts;
 941                                pPrt->PPrevShorts = Shorts;
 942                                
 943                                return(SK_HW_PS_RESTART);
 944                        }
 945                        else {
 946                                pPrt->PLipaAutoNeg = SK_LIPA_MANUAL;
 947                        }
 948                }
 949
 950                if (((RxCts - pPrt->PPrevRx) > pPrt->PRxLim) ||
 951                    (!(FcsErrCts - pPrt->PPrevFcs))) {
 952                        /*
 953                         * Note: The compare with zero above has to be done the way shown,
 954                         * otherwise the Linux driver will have a problem.
 955                         */
 956                        /*
 957                         * We received a bunch of frames or no CRC error occured on the
 958                         * network -> ok.
 959                         */
 960                        pPrt->PPrevRx = RxCts;
 961                        pPrt->PPrevFcs = FcsErrCts;
 962                        pPrt->PPrevShorts = Shorts;
 963
 964                        return(SK_HW_PS_NONE);
 965                }
 966
 967                pPrt->PPrevFcs = FcsErrCts;
 968        }
 969
 970
 971        if ((Shorts - pPrt->PPrevShorts) > CheckShorts) {
 972                SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
 973                        ("Short Event Count Restart Port %d \n", Port));
 974                Rtv = SK_HW_PS_RESTART;
 975        }
 976
 977        pPrt->PPrevShorts = Shorts;
 978        pPrt->PPrevRx = RxCts;
 979
 980        return(Rtv);
 981}       /* SkGePortCheckShorts */
 982#endif /* GENESIS */
 983
 984
 985/******************************************************************************
 986 *
 987 * SkGePortCheckUp() - Check if the link is up
 988 *
 989 * return:
 990 *      0       o.k. nothing needed
 991 *      1       Restart needed on this port
 992 *      2       Link came up
 993 */
 994static int SkGePortCheckUp(
 995SK_AC   *pAC,           /* Adapter Context */
 996SK_IOC  IoC,            /* IO Context */
 997int             Port)           /* Which port should be checked */
 998{
 999        SK_GEPORT       *pPrt;          /* GIni Port struct pointer */
1000        SK_BOOL         AutoNeg;        /* Is Auto-negotiation used ? */
1001        int                     Rtv;            /* Return value */
1002
1003        Rtv = SK_HW_PS_NONE;
1004        
1005        pPrt = &pAC->GIni.GP[Port];
1006
1007        if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
1008                AutoNeg = SK_FALSE;
1009        }
1010        else {
1011                AutoNeg = SK_TRUE;
1012        }
1013
1014#ifdef GENESIS
1015        if (pAC->GIni.GIGenesis) {
1016
1017                switch (pPrt->PhyType) {
1018                
1019                case SK_PHY_XMAC:
1020                        Rtv = SkGePortCheckUpXmac(pAC, IoC, Port, AutoNeg);
1021                        break;
1022                case SK_PHY_BCOM:
1023                        Rtv = SkGePortCheckUpBcom(pAC, IoC, Port, AutoNeg);
1024                        break;
1025#ifdef OTHER_PHY
1026                case SK_PHY_LONE:
1027                        Rtv = SkGePortCheckUpLone(pAC, IoC, Port, AutoNeg);
1028                        break;
1029                case SK_PHY_NAT:
1030                        Rtv = SkGePortCheckUpNat(pAC, IoC, Port, AutoNeg);
1031                        break;
1032#endif /* OTHER_PHY */
1033                }
1034        }
1035#endif /* GENESIS */
1036        
1037#ifdef YUKON
1038        if (pAC->GIni.GIYukon) {
1039                
1040                Rtv = SkGePortCheckUpGmac(pAC, IoC, Port, AutoNeg);
1041        }
1042#endif /* YUKON */
1043
1044        return(Rtv);    
1045}       /* SkGePortCheckUp */
1046
1047
1048#ifdef GENESIS
1049/******************************************************************************
1050 *
1051 * SkGePortCheckUpXmac() - Implementing of the Workaround Errata # 2
1052 *
1053 * return:
1054 *      0       o.k. nothing needed
1055 *      1       Restart needed on this port
1056 *      2       Link came up
1057 */
1058static int SkGePortCheckUpXmac(
1059SK_AC   *pAC,           /* Adapter Context */
1060SK_IOC  IoC,            /* IO Context */
1061int             Port,           /* Which port should be checked */
1062SK_BOOL AutoNeg)        /* Is Auto-negotiation used ? */
1063{
1064        SK_U32          Shorts;         /* Short Event Counter */
1065        SK_GEPORT       *pPrt;          /* GIni Port struct pointer */
1066        int                     Done;
1067        SK_U32          GpReg;          /* General Purpose register value */
1068        SK_U16          Isrc;           /* Interrupt source register */
1069        SK_U16          IsrcSum;        /* Interrupt source register sum */
1070        SK_U16          LpAb;           /* Link Partner Ability */
1071        SK_U16          ResAb;          /* Resolved Ability */
1072        SK_U16          ExtStat;        /* Extended Status Register */
1073        SK_U8           NextMode;       /* Next AutoSensing Mode */
1074
1075        pPrt = &pAC->GIni.GP[Port];
1076
1077        if (pPrt->PHWLinkUp) {
1078                if (pPrt->PhyType != SK_PHY_XMAC) {
1079                        return(SK_HW_PS_NONE);
1080                }
1081                else {
1082                        return(SkGePortCheckShorts(pAC, IoC, Port));
1083                }
1084        }
1085
1086        IsrcSum = pPrt->PIsave;
1087        pPrt->PIsave = 0;
1088
1089        /* Now wait for each port's link */
1090        if (pPrt->PLinkBroken) {
1091                /* Link was broken */
1092                XM_IN32(IoC, Port, XM_GP_PORT, &GpReg);
1093
1094                if ((GpReg & XM_GP_INP_ASS) == 0) {
1095                        /* The Link is in sync */
1096                        XM_IN16(IoC, Port, XM_ISRC, &Isrc);
1097                        IsrcSum |= Isrc;
1098                        SkXmAutoNegLipaXmac(pAC, IoC, Port, IsrcSum);
1099                        
1100                        if ((Isrc & XM_IS_INP_ASS) == 0) {
1101                                /* It has been in sync since last time */
1102                                /* Restart the PORT */
1103                                SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
1104                                        ("Link in sync Restart Port %d\n", Port));
1105
1106                                (void)SkXmUpdateStats(pAC, IoC, Port);
1107
1108                                /* We now need to reinitialize the PrevShorts counter */
1109                                (void)SkXmMacStatistic(pAC, IoC, Port, XM_RXE_SHT_ERR, &Shorts);
1110                                pPrt->PPrevShorts = Shorts;
1111
1112                                pPrt->PLinkBroken = SK_FALSE;
1113
1114                                /*
1115                                 * Link Restart Workaround:
1116                                 *  it may be possible that the other Link side
1117                                 *  restarts its link as well an we detect
1118                                 *  another LinkBroken. To prevent this
1119                                 *  happening we check for a maximum number
1120                                 *  of consecutive restart. If those happens,
1121                                 *  we do NOT restart the active link and
1122                                 *  check whether the link is now o.k.
1123                                 */
1124                                pPrt->PLinkResCt++;
1125                                
1126                                pPrt->PAutoNegTimeOut = 0;
1127
1128                                if (pPrt->PLinkResCt < SK_MAX_LRESTART) {
1129                                        return(SK_HW_PS_RESTART);
1130                                }
1131
1132                                pPrt->PLinkResCt = 0;
1133                                
1134                                SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1135                                        ("Do NOT restart on Port %d %x %x\n", Port, Isrc, IsrcSum));
1136                        }
1137                        else {
1138                                pPrt->PIsave = (SK_U16)(IsrcSum & XM_IS_AND);
1139                                
1140                                SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1141                                        ("Save Sync/nosync Port %d %x %x\n", Port, Isrc, IsrcSum));
1142
1143                                /* Do nothing more if link is broken */
1144                                return(SK_HW_PS_NONE);
1145                        }
1146                }
1147                else {
1148                        /* Do nothing more if link is broken */
1149                        return(SK_HW_PS_NONE);
1150                }
1151
1152        }
1153        else {
1154                /* Link was not broken, check if it is */
1155                XM_IN16(IoC, Port, XM_ISRC, &Isrc);
1156                IsrcSum |= Isrc;
1157                if ((Isrc & XM_IS_INP_ASS) != 0) {
1158                        XM_IN16(IoC, Port, XM_ISRC, &Isrc);
1159                        IsrcSum |= Isrc;
1160                        if ((Isrc & XM_IS_INP_ASS) != 0) {
1161                                XM_IN16(IoC, Port, XM_ISRC, &Isrc);
1162                                IsrcSum |= Isrc;
1163                                if ((Isrc & XM_IS_INP_ASS) != 0) {
1164                                        pPrt->PLinkBroken = SK_TRUE;
1165                                        /* Re-Init Link partner Autoneg flag */
1166                                        pPrt->PLipaAutoNeg = SK_LIPA_UNKNOWN;
1167                                        SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
1168                                                ("Link broken Port %d\n", Port));
1169
1170                                        /* Cable removed-> reinit sense mode */
1171                                        SkHWInitDefSense(pAC, IoC, Port);
1172
1173                                        return(SK_HW_PS_RESTART);
1174                                }
1175                        }
1176                }
1177                else {
1178                        SkXmAutoNegLipaXmac(pAC, IoC, Port, Isrc);
1179                        
1180                        if (SkGePortCheckShorts(pAC, IoC, Port) == SK_HW_PS_RESTART) {
1181                                return(SK_HW_PS_RESTART);
1182                        }
1183                }
1184        }
1185
1186        /*
1187         * here we usually can check whether the link is in sync and
1188         * auto-negotiation is done.
1189         */
1190        XM_IN32(IoC, Port, XM_GP_PORT, &GpReg);
1191        XM_IN16(IoC, Port, XM_ISRC, &Isrc);
1192        IsrcSum |= Isrc;
1193
1194        SkXmAutoNegLipaXmac(pAC, IoC, Port, IsrcSum);
1195        
1196        if ((GpReg & XM_GP_INP_ASS) != 0 || (IsrcSum & XM_IS_INP_ASS) != 0) {
1197                if ((GpReg & XM_GP_INP_ASS) == 0) {
1198                        /* Save Auto-negotiation Done interrupt only if link is in sync */
1199                        pPrt->PIsave = (SK_U16)(IsrcSum & XM_IS_AND);
1200                }
1201#ifdef DEBUG
1202                if ((pPrt->PIsave & XM_IS_AND) != 0) {
1203                        SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1204                                ("AutoNeg done rescheduled Port %d\n", Port));
1205                }
1206#endif /* DEBUG */
1207                return(SK_HW_PS_NONE);
1208        }
1209
1210        if (AutoNeg) {
1211                if ((IsrcSum & XM_IS_AND) != 0) {
1212                        SkHWLinkUp(pAC, IoC, Port);
1213                        Done = SkMacAutoNegDone(pAC, IoC, Port);
1214                        if (Done != SK_AND_OK) {
1215                                /* Get PHY parameters, for debugging only */
1216                                SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_LP, &LpAb);
1217                                SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_RES_ABI, &ResAb);
1218                                SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1219                                        ("AutoNeg FAIL Port %d (LpAb %x, ResAb %x)\n",
1220                                         Port, LpAb, ResAb));
1221                                        
1222                                /* Try next possible mode */
1223                                NextMode = SkHWSenseGetNext(pAC, IoC, Port);
1224                                SkHWLinkDown(pAC, IoC, Port);
1225                                if (Done == SK_AND_DUP_CAP) {
1226                                        /* GoTo next mode */
1227                                        SkHWSenseSetNext(pAC, IoC, Port, NextMode);
1228                                }
1229
1230                                return(SK_HW_PS_RESTART);
1231                        }
1232                        /*
1233                         * Dummy Read extended status to prevent extra link down/ups
1234                         * (clear Page Received bit if set)
1235                         */
1236                        SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_EXP, &ExtStat);
1237                        
1238                        return(SK_HW_PS_LINK);
1239                }
1240                
1241                /* AutoNeg not done, but HW link is up. Check for timeouts */
1242                pPrt->PAutoNegTimeOut++;
1243                if (pPrt->PAutoNegTimeOut >= SK_AND_MAX_TO) {
1244                        /* Increase the Timeout counter */
1245                        pPrt->PAutoNegTOCt++;
1246
1247                        /* Timeout occured */
1248                        SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
1249                                ("AutoNeg timeout Port %d\n", Port));
1250                        if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE &&
1251                                pPrt->PLipaAutoNeg != SK_LIPA_AUTO) {
1252                                /* Set Link manually up */
1253                                SkHWSenseSetNext(pAC, IoC, Port, SK_LMODE_FULL);
1254                                SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
1255                                        ("Set manual full duplex Port %d\n", Port));
1256                        }
1257
1258                        if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE &&
1259                                pPrt->PLipaAutoNeg == SK_LIPA_AUTO &&
1260                                pPrt->PAutoNegTOCt >= SK_MAX_ANEG_TO) {
1261                                /*
1262                                 * This is rather complicated.
1263                                 * we need to check here whether the LIPA_AUTO
1264                                 * we saw before is false alert. We saw at one
1265                                 * switch ( SR8800) that on boot time it sends
1266                                 * just one auto-neg packet and does no further
1267                                 * auto-negotiation.
1268                                 * Solution: we restart the autosensing after
1269                                 * a few timeouts.
1270                                 */
1271                                pPrt->PAutoNegTOCt = 0;
1272                                pPrt->PLipaAutoNeg = SK_LIPA_UNKNOWN;
1273                                SkHWInitDefSense(pAC, IoC, Port);
1274                        }
1275
1276                        /* Do the restart */
1277                        return(SK_HW_PS_RESTART);
1278                }
1279        }
1280        else {
1281                /* Link is up and we don't need more */
1282#ifdef DEBUG
1283                if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) {
1284                        SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1285                                ("ERROR: Lipa auto detected on port %d\n", Port));
1286                }
1287#endif /* DEBUG */
1288                SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
1289                        ("Link sync(GP), Port %d\n", Port));
1290                SkHWLinkUp(pAC, IoC, Port);
1291                
1292                /*
1293                 * Link sync (GP) and so assume a good connection. But if not received
1294                 * a bunch of frames received in a time slot (maybe broken tx cable)
1295                 * the port is restart.
1296                 */
1297                return(SK_HW_PS_LINK);
1298        }
1299
1300        return(SK_HW_PS_NONE);
1301}       /* SkGePortCheckUpXmac */
1302
1303
1304/******************************************************************************
1305 *
1306 * SkGePortCheckUpBcom() - Check if the link is up on Bcom PHY
1307 *
1308 * return:
1309 *      0       o.k. nothing needed
1310 *      1       Restart needed on this port
1311 *      2       Link came up
1312 */
1313static int SkGePortCheckUpBcom(
1314SK_AC   *pAC,           /* Adapter Context */
1315SK_IOC  IoC,            /* IO Context */
1316int             Port,           /* Which port should be checked */
1317SK_BOOL AutoNeg)        /* Is Auto-negotiation used ? */
1318{
1319        SK_GEPORT       *pPrt;          /* GIni Port struct pointer */
1320        int                     Done;
1321        SK_U16          Isrc;           /* Interrupt source register */
1322        SK_U16          PhyStat;        /* Phy Status Register */
1323        SK_U16          ResAb;          /* Master/Slave resolution */
1324        SK_U16          Ctrl;           /* Broadcom control flags */
1325#ifdef DEBUG
1326        SK_U16          LpAb;
1327        SK_U16          ExtStat;
1328#endif /* DEBUG */
1329
1330        pPrt = &pAC->GIni.GP[Port];
1331
1332        /* Check for No HCD Link events (#10523) */
1333        SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &Isrc);
1334
1335#ifdef xDEBUG
1336        if ((Isrc & ~(PHY_B_IS_HCT | PHY_B_IS_LCT) ==
1337                (PHY_B_IS_SCR_S_ER | PHY_B_IS_RRS_CHANGE | PHY_B_IS_LRS_CHANGE)) {
1338
1339                SK_U32  Stat1, Stat2, Stat3;
1340
1341                Stat1 = 0;
1342                SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_MASK, &Stat1);
1343                CMSMPrintString(
1344                        pAC->pConfigTable,
1345                        MSG_TYPE_RUNTIME_INFO,
1346                        "CheckUp1 - Stat: %x, Mask: %x",
1347                        (void *)Isrc,
1348                        (void *)Stat1);
1349
1350                Stat1 = 0;
1351                SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Stat1);
1352                Stat2 = 0;
1353                SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &Stat2);
1354                Stat1 = Stat1 << 16 | Stat2;
1355                Stat2 = 0;
1356                SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, &Stat2);
1357                Stat3 = 0;
1358                SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &Stat3);
1359                Stat2 = Stat2 << 16 | Stat3;
1360                CMSMPrintString(
1361                        pAC->pConfigTable,
1362                        MSG_TYPE_RUNTIME_INFO,
1363                        "Ctrl/Stat: %x, AN Adv/LP: %x",
1364                        (void *)Stat1,
1365                        (void *)Stat2);
1366
1367                Stat1 = 0;
1368                SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_EXP, &Stat1);
1369                Stat2 = 0;
1370                SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_EXT_STAT, &Stat2);
1371                Stat1 = Stat1 << 16 | Stat2;
1372                Stat2 = 0;
1373                SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, &Stat2);
1374                Stat3 = 0;
1375                SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &Stat3);
1376                Stat2 = Stat2 << 16 | Stat3;
1377                CMSMPrintString(
1378                        pAC->pConfigTable,
1379                        MSG_TYPE_RUNTIME_INFO,
1380                        "AN Exp/IEEE Ext: %x, 1000T Ctrl/Stat: %x",
1381                        (void *)Stat1,
1382                        (void *)Stat2);
1383
1384                Stat1 = 0;
1385                SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, &Stat1);
1386                Stat2 = 0;
1387                SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_STAT, &Stat2);
1388                Stat1 = Stat1 << 16 | Stat2;
1389                Stat2 = 0;
1390                SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Stat2);
1391                Stat3 = 0;
1392                SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &Stat3);
1393                Stat2 = Stat2 << 16 | Stat3;
1394                CMSMPrintString(
1395                        pAC->pConfigTable,
1396                        MSG_TYPE_RUNTIME_INFO,
1397                        "PHY Ext Ctrl/Stat: %x, Aux Ctrl/Stat: %x",
1398                        (void *)Stat1,
1399                        (void *)Stat2);
1400        }
1401#endif /* DEBUG */
1402
1403        if ((Isrc & (PHY_B_IS_NO_HDCL /* | PHY_B_IS_NO_HDC */)) != 0) {
1404                /*
1405                 * Workaround BCom Errata:
1406                 *      enable and disable loopback mode if "NO HCD" occurs.
1407                 */
1408                SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Ctrl);
1409                SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL,
1410                        (SK_U16)(Ctrl | PHY_CT_LOOP));
1411                SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL,
1412                        (SK_U16)(Ctrl & ~PHY_CT_LOOP));
1413                SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1414                        ("No HCD Link event, Port %d\n", Port));
1415#ifdef xDEBUG
1416                CMSMPrintString(
1417                        pAC->pConfigTable,
1418                        MSG_TYPE_RUNTIME_INFO,
1419                        "No HCD link event, port %d.",
1420                        (void *)Port,
1421                        (void *)NULL);
1422#endif /* DEBUG */
1423        }
1424
1425        /* Not obsolete: link status bit is latched to 0 and autoclearing! */
1426        SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat);
1427
1428        if (pPrt->PHWLinkUp) {
1429                return(SK_HW_PS_NONE);
1430        }
1431
1432#ifdef xDEBUG
1433        {
1434                SK_U32  Stat1, Stat2, Stat3;
1435
1436                Stat1 = 0;
1437                SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_MASK, &Stat1);
1438                CMSMPrintString(
1439                        pAC->pConfigTable,
1440                        MSG_TYPE_RUNTIME_INFO,
1441                        "CheckUp1a - Stat: %x, Mask: %x",
1442                        (void *)Isrc,
1443                        (void *)Stat1);
1444
1445                Stat1 = 0;
1446                SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Stat1);
1447                Stat2 = 0;
1448                SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat);
1449                Stat1 = Stat1 << 16 | PhyStat;
1450                Stat2 = 0;
1451                SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, &Stat2);
1452                Stat3 = 0;
1453                SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &Stat3);
1454                Stat2 = Stat2 << 16 | Stat3;
1455                CMSMPrintString(
1456                        pAC->pConfigTable,
1457                        MSG_TYPE_RUNTIME_INFO,
1458                        "Ctrl/Stat: %x, AN Adv/LP: %x",
1459                        (void *)Stat1,
1460                        (void *)Stat2);
1461
1462                Stat1 = 0;
1463                SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_EXP, &Stat1);
1464                Stat2 = 0;
1465                SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_EXT_STAT, &Stat2);
1466                Stat1 = Stat1 << 16 | Stat2;
1467                Stat2 = 0;
1468                SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, &Stat2);
1469                Stat3 = 0;
1470                SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb);
1471                Stat2 = Stat2 << 16 | ResAb;
1472                CMSMPrintString(
1473                        pAC->pConfigTable,
1474                        MSG_TYPE_RUNTIME_INFO,
1475                        "AN Exp/IEEE Ext: %x, 1000T Ctrl/Stat: %x",
1476                        (void *)Stat1,
1477                        (void *)Stat2);
1478
1479                Stat1 = 0;
1480                SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, &Stat1);
1481                Stat2 = 0;
1482                SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_STAT, &Stat2);
1483                Stat1 = Stat1 << 16 | Stat2;
1484                Stat2 = 0;
1485                SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Stat2);
1486                Stat3 = 0;
1487                SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &Stat3);
1488                Stat2 = Stat2 << 16 | Stat3;
1489                CMSMPrintString(
1490                        pAC->pConfigTable,
1491                        MSG_TYPE_RUNTIME_INFO,
1492                        "PHY Ext Ctrl/Stat: %x, Aux Ctrl/Stat: %x",
1493                        (void *)Stat1,
1494                        (void *)Stat2);
1495        }
1496#endif /* DEBUG */
1497
1498        /*
1499         * Here we usually can check whether the link is in sync and
1500         * auto-negotiation is done.
1501         */
1502
1503        SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat);
1504
1505        SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat);
1506        
1507        SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1508                ("CheckUp Port %d, PhyStat: 0x%04X\n", Port, PhyStat));
1509
1510        SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb);
1511
1512        if ((ResAb & PHY_B_1000S_MSF) != 0) {
1513                /* Error */
1514                SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1515                        ("Master/Slave Fault port %d\n", Port));
1516                
1517                pPrt->PAutoNegFail = SK_TRUE;
1518                pPrt->PMSStatus = SK_MS_STAT_FAULT;
1519                
1520                return(SK_HW_PS_RESTART);
1521        }
1522
1523        if ((PhyStat & PHY_ST_LSYNC) == 0) {
1524                return(SK_HW_PS_NONE);
1525        }
1526        
1527        pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
1528                SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE;
1529        
1530        SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1531                ("Port %d, ResAb: 0x%04X\n", Port, ResAb));
1532
1533        if (AutoNeg) {
1534                if ((PhyStat & PHY_ST_AN_OVER) != 0) {
1535                        
1536                        SkHWLinkUp(pAC, IoC, Port);
1537                        
1538                        Done = SkMacAutoNegDone(pAC, IoC, Port);
1539                        
1540                        if (Done != SK_AND_OK) {
1541#ifdef DEBUG
1542                                /* Get PHY parameters, for debugging only */
1543                                SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &LpAb);
1544                                SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ExtStat);
1545                                SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1546                                        ("AutoNeg FAIL Port %d (LpAb %x, 1000TStat %x)\n",
1547                                        Port, LpAb, ExtStat));
1548#endif /* DEBUG */
1549                                return(SK_HW_PS_RESTART);
1550                        }
1551                        else {
1552#ifdef xDEBUG
1553                                /* Dummy read ISR to prevent extra link downs/ups */
1554                                SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &ExtStat);
1555
1556                                if ((ExtStat & ~(PHY_B_IS_HCT | PHY_B_IS_LCT)) != 0) {
1557                                        CMSMPrintString(
1558                                                pAC->pConfigTable,
1559                                                MSG_TYPE_RUNTIME_INFO,
1560                                                "CheckUp2 - Stat: %x",
1561                                                (void *)ExtStat,
1562                                                (void *)NULL);
1563                                }
1564#endif /* DEBUG */
1565                                return(SK_HW_PS_LINK);
1566                        }
1567                }
1568        }
1569        else {  /* !AutoNeg */
1570                /* Link is up and we don't need more. */
1571#ifdef DEBUG
1572                if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) {
1573                        SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1574                                ("ERROR: Lipa auto detected on port %d\n", Port));
1575                }
1576#endif /* DEBUG */
1577
1578#ifdef xDEBUG
1579                /* Dummy read ISR to prevent extra link downs/ups */
1580                SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &ExtStat);
1581
1582                if ((ExtStat & ~(PHY_B_IS_HCT | PHY_B_IS_LCT)) != 0) {
1583                        CMSMPrintString(
1584                                pAC->pConfigTable,
1585                                MSG_TYPE_RUNTIME_INFO,
1586                                "CheckUp3 - Stat: %x",
1587                                (void *)ExtStat,
1588                                (void *)NULL);
1589                }
1590#endif /* DEBUG */
1591                
1592                SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
1593                        ("Link sync(GP), Port %d\n", Port));
1594                SkHWLinkUp(pAC, IoC, Port);
1595                
1596                return(SK_HW_PS_LINK);
1597        }
1598
1599        return(SK_HW_PS_NONE);
1600}       /* SkGePortCheckUpBcom */
1601#endif /* GENESIS */
1602
1603
1604#ifdef YUKON
1605/******************************************************************************
1606 *
1607 * SkGePortCheckUpGmac() - Check if the link is up on Marvell PHY
1608 *
1609 * return:
1610 *      0       o.k. nothing needed
1611 *      1       Restart needed on this port
1612 *      2       Link came up
1613 */
1614static int SkGePortCheckUpGmac(
1615SK_AC   *pAC,           /* Adapter Context */
1616SK_IOC  IoC,            /* IO Context */
1617int             Port,           /* Which port should be checked */
1618SK_BOOL AutoNeg)        /* Is Auto-negotiation used ? */
1619{
1620        SK_GEPORT       *pPrt;          /* GIni Port struct pointer */
1621        int                     Done;
1622        SK_U16          PhyIsrc;        /* PHY Interrupt source */
1623        SK_U16          PhyStat;        /* PPY Status */
1624        SK_U16          PhySpecStat;/* PHY Specific Status */
1625        SK_U16          ResAb;          /* Master/Slave resolution */
1626        SK_EVPARA       Para;
1627#ifdef DEBUG
1628        SK_U16          Word;           /* I/O helper */
1629#endif /* DEBUG */
1630
1631        pPrt = &pAC->GIni.GP[Port];
1632
1633        if (pPrt->PHWLinkUp) {
1634                return(SK_HW_PS_NONE);
1635        }
1636
1637        /* Read PHY Status */
1638        SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat);
1639
1640        SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1641                ("CheckUp Port %d, PhyStat: 0x%04X\n", Port, PhyStat));
1642
1643        /* Read PHY Interrupt Status */
1644        SkGmPhyRead(pAC, IoC, Port, PHY_MARV_INT_STAT, &PhyIsrc);
1645
1646        if ((PhyIsrc & PHY_M_IS_AN_COMPL) != 0) {
1647                SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1648                        ("Auto-Negotiation Completed, PhyIsrc: 0x%04X\n", PhyIsrc));
1649        }
1650
1651        if ((PhyIsrc & PHY_M_IS_LSP_CHANGE) != 0) {
1652                SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1653                        ("Link Speed Changed, PhyIsrc: 0x%04X\n", PhyIsrc));
1654        }
1655
1656        SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat);
1657        
1658        SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_STAT, &ResAb);
1659
1660        if ((ResAb & PHY_B_1000S_MSF) != 0) {
1661                /* Error */
1662                SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1663                        ("Master/Slave Fault port %d\n", Port));
1664                
1665                pPrt->PAutoNegFail = SK_TRUE;
1666                pPrt->PMSStatus = SK_MS_STAT_FAULT;
1667                
1668                return(SK_HW_PS_RESTART);
1669        }
1670
1671        /* Read PHY Specific Status */
1672        SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &PhySpecStat);
1673        
1674        SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1675                ("Phy1000BT: 0x%04X, PhySpecStat: 0x%04X\n", ResAb, PhySpecStat));
1676
1677#ifdef DEBUG
1678        SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_EXP, &Word);
1679
1680        if ((PhyIsrc & PHY_M_IS_AN_PR) != 0 || (Word & PHY_ANE_RX_PG) != 0 ||
1681                (PhySpecStat & PHY_M_PS_PAGE_REC) != 0)  {
1682                /* Read PHY Next Page Link Partner */
1683                SkGmPhyRead(pAC, IoC, Port, PHY_MARV_NEPG_LP, &Word);
1684
1685                SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1686                        ("Page Received, NextPage: 0x%04X\n", Word));
1687        }
1688#endif /* DEBUG */
1689
1690        if ((PhySpecStat & PHY_M_PS_LINK_UP) == 0) {
1691                return(SK_HW_PS_NONE);
1692        }
1693        
1694        if ((PhySpecStat & PHY_M_PS_DOWNS_STAT) != 0 ||
1695                (PhyIsrc & PHY_M_IS_DOWNSH_DET) != 0) {
1696                /* Downshift detected */
1697                SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E025, SKERR_SIRQ_E025MSG);
1698                
1699                Para.Para64 = Port;
1700                SkEventQueue(pAC, SKGE_DRV, SK_DRV_DOWNSHIFT_DET, Para);
1701                
1702                SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1703                        ("Downshift detected, PhyIsrc: 0x%04X\n", PhyIsrc));
1704        }
1705
1706        pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
1707                SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE;
1708        
1709        pPrt->PCableLen = (SK_U8)((PhySpecStat & PHY_M_PS_CABLE_MSK) >> 7);
1710        
1711        if (AutoNeg) {
1712                /* Auto-Negotiation Over ? */
1713                if ((PhyStat & PHY_ST_AN_OVER) != 0) {
1714                        
1715                        SkHWLinkUp(pAC, IoC, Port);
1716                        
1717                        Done = SkMacAutoNegDone(pAC, IoC, Port);
1718                        
1719                        if (Done != SK_AND_OK) {
1720                                return(SK_HW_PS_RESTART);
1721                        }
1722                        
1723                        return(SK_HW_PS_LINK);
1724                }
1725        }
1726        else {  /* !AutoNeg */
1727                /* Link is up and we don't need more */
1728#ifdef DEBUG
1729                if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) {
1730                        SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1731                                ("ERROR: Lipa auto detected on port %d\n", Port));
1732                }
1733#endif /* DEBUG */
1734
1735                SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
1736                        ("Link sync, Port %d\n", Port));
1737                SkHWLinkUp(pAC, IoC, Port);
1738                
1739                return(SK_HW_PS_LINK);
1740        }
1741
1742        return(SK_HW_PS_NONE);
1743}       /* SkGePortCheckUpGmac */
1744#endif /* YUKON */
1745
1746
1747#ifdef OTHER_PHY
1748/******************************************************************************
1749 *
1750 * SkGePortCheckUpLone() - Check if the link is up on Level One PHY
1751 *
1752 * return:
1753 *      0       o.k. nothing needed
1754 *      1       Restart needed on this port
1755 *      2       Link came up
1756 */
1757static int SkGePortCheckUpLone(
1758SK_AC   *pAC,           /* Adapter Context */
1759SK_IOC  IoC,            /* IO Context */
1760int             Port,           /* Which port should be checked */
1761SK_BOOL AutoNeg)        /* Is Auto-negotiation used ? */
1762{
1763        SK_GEPORT       *pPrt;          /* GIni Port struct pointer */
1764        int                     Done;
1765        SK_U16          Isrc;           /* Interrupt source register */
1766        SK_U16          LpAb;           /* Link Partner Ability */
1767        SK_U16          ExtStat;        /* Extended Status Register */
1768        SK_U16          PhyStat;        /* Phy Status Register */
1769        SK_U16          StatSum;
1770        SK_U8           NextMode;       /* Next AutoSensing Mode */
1771
1772        pPrt = &pAC->GIni.GP[Port];
1773
1774        if (pPrt->PHWLinkUp) {
1775                return(SK_HW_PS_NONE);
1776        }
1777
1778        StatSum = pPrt->PIsave;
1779        pPrt->PIsave = 0;
1780
1781        /*
1782         * here we usually can check whether the link is in sync and
1783         * auto-negotiation is done.
1784         */
1785        SkXmPhyRead(pAC, IoC, Port, PHY_LONE_STAT, &PhyStat);
1786        StatSum |= PhyStat;
1787
1788        SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat);
1789        
1790        if ((PhyStat & PHY_ST_LSYNC) == 0) {
1791                /* Save Auto-negotiation Done bit */
1792                pPrt->PIsave = (SK_U16)(StatSum & PHY_ST_AN_OVER);
1793#ifdef DEBUG
1794                if ((pPrt->PIsave & PHY_ST_AN_OVER) != 0) {
1795                        SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1796                                ("AutoNeg done rescheduled Port %d\n", Port));
1797                }
1798#endif /* DEBUG */
1799                return(SK_HW_PS_NONE);
1800        }
1801
1802        if (AutoNeg) {
1803                if ((StatSum & PHY_ST_AN_OVER) != 0) {
1804                        SkHWLinkUp(pAC, IoC, Port);
1805                        Done = SkMacAutoNegDone(pAC, IoC, Port);
1806                        if (Done != SK_AND_OK) {
1807                                /* Get PHY parameters, for debugging only */
1808                                SkXmPhyRead(pAC, IoC, Port, PHY_LONE_AUNE_LP, &LpAb);
1809                                SkXmPhyRead(pAC, IoC, Port, PHY_LONE_1000T_STAT, &ExtStat);
1810                                SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1811                                        ("AutoNeg FAIL Port %d (LpAb %x, 1000TStat %x)\n",
1812                                         Port, LpAb, ExtStat));
1813                                        
1814                                /* Try next possible mode */
1815                                NextMode = SkHWSenseGetNext(pAC, IoC, Port);
1816                                SkHWLinkDown(pAC, IoC, Port);
1817                                if (Done == SK_AND_DUP_CAP) {
1818                                        /* GoTo next mode */
1819                                        SkHWSenseSetNext(pAC, IoC, Port, NextMode);
1820                                }
1821
1822                                return(SK_HW_PS_RESTART);
1823
1824                        }
1825                        else {
1826                                /*
1827                                 * Dummy Read interrupt status to prevent
1828                                 * extra link down/ups
1829                                 */
1830                                SkXmPhyRead(pAC, IoC, Port, PHY_LONE_INT_STAT, &ExtStat);
1831                                return(SK_HW_PS_LINK);
1832                        }
1833                }
1834                
1835                /* AutoNeg not done, but HW link is up. Check for timeouts */
1836                pPrt->PAutoNegTimeOut++;
1837                if (pPrt->PAutoNegTimeOut >= SK_AND_MAX_TO) {
1838                        /* Timeout occured */
1839                        SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
1840                                ("AutoNeg timeout Port %d\n", Port));
1841                        if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE &&
1842                                pPrt->PLipaAutoNeg != SK_LIPA_AUTO) {
1843                                /* Set Link manually up */
1844                                SkHWSenseSetNext(pAC, IoC, Port, SK_LMODE_FULL);
1845                                SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
1846                                        ("Set manual full duplex Port %d\n", Port));
1847                        }
1848
1849                        /* Do the restart */
1850                        return(SK_HW_PS_RESTART);
1851                }
1852        }
1853        else {
1854                /* Link is up and we don't need more */
1855#ifdef DEBUG
1856                if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) {
1857                        SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
1858                                ("ERROR: Lipa auto detected on port %d\n", Port));
1859                }
1860#endif /* DEBUG */
1861
1862                /*
1863                 * Dummy Read interrupt status to prevent
1864                 * extra link down/ups
1865                 */
1866                SkXmPhyRead(pAC, IoC, Port, PHY_LONE_INT_STAT, &ExtStat);
1867                
1868                SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
1869                        ("Link sync(GP), Port %d\n", Port));
1870                SkHWLinkUp(pAC, IoC, Port);
1871                
1872                return(SK_HW_PS_LINK);
1873        }
1874
1875        return(SK_HW_PS_NONE);
1876}       /* SkGePortCheckUpLone */
1877
1878
1879/******************************************************************************
1880 *
1881 * SkGePortCheckUpNat() - Check if the link is up on National PHY
1882 *
1883 * return:
1884 *      0       o.k. nothing needed
1885 *      1       Restart needed on this port
1886 *      2       Link came up
1887 */
1888static int SkGePortCheckUpNat(
1889SK_AC   *pAC,           /* Adapter Context */
1890SK_IOC  IoC,            /* IO Context */
1891int             Port,           /* Which port should be checked */
1892SK_BOOL AutoNeg)        /* Is Auto-negotiation used ? */
1893{
1894        /* todo: National */
1895        return(SK_HW_PS_NONE);
1896}       /* SkGePortCheckUpNat */
1897#endif /* OTHER_PHY */
1898
1899
1900/******************************************************************************
1901 *
1902 *      SkGeSirqEvent() - Event Service Routine
1903 *
1904 * Description:
1905 *
1906 * Notes:
1907 */
1908int     SkGeSirqEvent(
1909SK_AC           *pAC,           /* Adapter Context */
1910SK_IOC          IoC,            /* Io Context */
1911SK_U32          Event,          /* Module specific Event */
1912SK_EVPARA       Para)           /* Event specific Parameter */
1913{
1914        SK_GEPORT       *pPrt;          /* GIni Port struct pointer */
1915        SK_U32          Port;
1916        SK_U32          Val32;
1917        int                     PortStat;
1918        SK_U8           Val8;
1919#ifdef GENESIS
1920        SK_U64          Octets;
1921#endif /* GENESIS */
1922
1923        Port = Para.Para32[0];
1924        pPrt = &pAC->GIni.GP[Port];
1925
1926        switch (Event) {
1927        case SK_HWEV_WATIM:
1928                if (pPrt->PState == SK_PRT_RESET) {
1929                
1930                        PortStat = SK_HW_PS_NONE;
1931                }
1932                else {
1933                        /* Check whether port came up */
1934                        PortStat = SkGePortCheckUp(pAC, IoC, (int)Port);
1935                }
1936
1937                switch (PortStat) {
1938                case SK_HW_PS_RESTART:
1939                        if (pPrt->PHWLinkUp) {
1940                                /* Set Link to down */
1941                                SkHWLinkDown(pAC, IoC, (int)Port);
1942
1943                                /*
1944                                 * Signal directly to RLMT to ensure correct
1945                                 * sequence of SWITCH and RESET event.
1946                                 */
1947                                SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para);
1948                        }
1949
1950                        /* Restart needed */
1951                        SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para);
1952                        break;
1953
1954                case SK_HW_PS_LINK:
1955                        /* Signal to RLMT */
1956                        SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_UP, Para);
1957                        break;
1958                }
1959                
1960                /* Start again the check Timer */
1961                if (pPrt->PHWLinkUp) {
1962                        Val32 = SK_WA_ACT_TIME;
1963                }
1964                else {
1965                        Val32 = SK_WA_INA_TIME;
1966                }
1967
1968                /* Todo: still needed for non-XMAC PHYs??? */
1969                /* Start workaround Errata #2 timer */
1970                SkTimerStart(pAC, IoC, &pPrt->PWaTimer, Val32,
1971                        SKGE_HWAC, SK_HWEV_WATIM, Para);
1972                break;
1973
1974        case SK_HWEV_PORT_START:
1975                if (pPrt->PHWLinkUp) {
1976                        /*
1977                         * Signal directly to RLMT to ensure correct
1978                         * sequence of SWITCH and RESET event.
1979                         */
1980                        SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para);
1981                }
1982
1983                SkHWLinkDown(pAC, IoC, (int)Port);
1984
1985                /* Schedule Port RESET */
1986                SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para);
1987
1988                /* Start workaround Errata #2 timer */
1989                SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME,
1990                        SKGE_HWAC, SK_HWEV_WATIM, Para);
1991                break;
1992
1993        case SK_HWEV_PORT_STOP:
1994                if (pPrt->PHWLinkUp) {
1995                        /*
1996                         * Signal directly to RLMT to ensure correct
1997                         * sequence of SWITCH and RESET event.
1998                         */
1999                        SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para);
2000                }
2001
2002                /* Stop Workaround Timer */
2003                SkTimerStop(pAC, IoC, &pPrt->PWaTimer);
2004
2005                SkHWLinkDown(pAC, IoC, (int)Port);
2006                break;
2007
2008        case SK_HWEV_UPDATE_STAT:
2009                /* We do NOT need to update any statistics */
2010                break;
2011
2012        case SK_HWEV_CLEAR_STAT:
2013                /* We do NOT need to clear any statistics */
2014                for (Port = 0; Port < (SK_U32)pAC->GIni.GIMacsFound; Port++) {
2015                        pPrt->PPrevRx = 0;
2016                        pPrt->PPrevFcs = 0;
2017                        pPrt->PPrevShorts = 0;
2018                }
2019                break;
2020
2021        case SK_HWEV_SET_LMODE:
2022                Val8 = (SK_U8)Para.Para32[1];
2023                if (pPrt->PLinkModeConf != Val8) {
2024                        /* Set New link mode */
2025                        pPrt->PLinkModeConf = Val8;
2026
2027                        /* Restart Port */
2028                        SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
2029                        SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
2030                }
2031                break;
2032
2033        case SK_HWEV_SET_FLOWMODE:
2034                Val8 = (SK_U8)Para.Para32[1];
2035                if (pPrt->PFlowCtrlMode != Val8) {
2036                        /* Set New Flow Control mode */
2037                        pPrt->PFlowCtrlMode = Val8;
2038
2039                        /* Restart Port */
2040                        SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
2041                        SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
2042                }
2043                break;
2044
2045        case SK_HWEV_SET_ROLE:
2046                /* not possible for fiber */
2047                if (!pAC->GIni.GICopperType) {
2048                        break;
2049                }
2050                Val8 = (SK_U8)Para.Para32[1];
2051                if (pPrt->PMSMode != Val8) {
2052                        /* Set New Role (Master/Slave) mode */
2053                        pPrt->PMSMode = Val8;
2054
2055                        /* Restart Port */
2056                        SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
2057                        SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
2058                }
2059                break;
2060
2061        case SK_HWEV_SET_SPEED:
2062                if (pPrt->PhyType != SK_PHY_MARV_COPPER) {
2063                        break;
2064                }
2065                Val8 = (SK_U8)Para.Para32[1];
2066                if (pPrt->PLinkSpeed != Val8) {
2067                        /* Set New Speed parameter */
2068                        pPrt->PLinkSpeed = Val8;
2069
2070                        /* Restart Port */
2071                        SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para);
2072                        SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para);
2073                }
2074                break;
2075
2076#ifdef GENESIS
2077        case SK_HWEV_HALFDUP_CHK:
2078                if (pAC->GIni.GIGenesis) {
2079                        /*
2080                         * half duplex hangup workaround.
2081                         * See packet arbiter timeout interrupt for description
2082                         */
2083                        pPrt->HalfDupTimerActive = SK_FALSE;
2084                        if (pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF ||
2085                                pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) {
2086#ifdef XXX
2087                                Len = sizeof(SK_U64);
2088                                SkPnmiGetVar(pAC, IoC, OID_SKGE_STAT_TX_OCTETS, (char *)&Octets,
2089                                        &Len, (SK_U32)SK_PNMI_PORT_PHYS2INST(pAC, Port),
2090                                        pAC->Rlmt.Port[Port].Net->NetNumber);
2091#endif /* XXX */
2092                                /* Snap statistic counters */
2093                                (void)SkXmUpdateStats(pAC, IoC, Port);
2094
2095                                (void)SkXmMacStatistic(pAC, IoC, Port, XM_TXO_OK_HI, &Val32);
2096
2097                                Octets = (SK_U64)Val32 << 32;
2098                                
2099                                (void)SkXmMacStatistic(pAC, IoC, Port, XM_TXO_OK_LO, &Val32);
2100
2101                                Octets += Val32;
2102                                
2103                                if (pPrt->LastOctets == Octets) {
2104                                        /* Tx hanging, a FIFO flush restarts it */
2105                                        SkMacFlushTxFifo(pAC, IoC, Port);
2106                                }
2107                        }
2108                }
2109                break;
2110#endif /* GENESIS */
2111        
2112        default:
2113                SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_SIRQ_E001, SKERR_SIRQ_E001MSG);
2114                break;
2115        }
2116
2117        return(0);
2118}       /* SkGeSirqEvent */
2119
2120
2121#ifdef GENESIS
2122/******************************************************************************
2123 *
2124 *      SkPhyIsrBcom() - PHY interrupt service routine
2125 *
2126 * Description: handles all interrupts from BCom PHY
2127 *
2128 * Returns: N/A
2129 */
2130static void SkPhyIsrBcom(
2131SK_AC           *pAC,           /* Adapter Context */
2132SK_IOC          IoC,            /* Io Context */
2133int                     Port,           /* Port Num = PHY Num */
2134SK_U16          IStatus)        /* Interrupt Status */
2135{
2136        SK_GEPORT       *pPrt;          /* GIni Port struct pointer */
2137        SK_EVPARA       Para;
2138
2139        pPrt = &pAC->GIni.GP[Port];
2140
2141        if ((IStatus & PHY_B_IS_PSE) != 0) {
2142                /* Incorrectable pair swap error */
2143                SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E022,
2144                        SKERR_SIRQ_E022MSG);
2145        }
2146        
2147        if ((IStatus & (PHY_B_IS_AN_PR | PHY_B_IS_LST_CHANGE)) != 0) {
2148
2149                SkHWLinkDown(pAC, IoC, Port);
2150
2151                Para.Para32[0] = (SK_U32)Port;
2152                /* Signal to RLMT */
2153                SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
2154
2155                /* Start workaround Errata #2 timer */
2156                SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME,
2157                        SKGE_HWAC, SK_HWEV_WATIM, Para);
2158        }
2159
2160}       /* SkPhyIsrBcom */
2161#endif /* GENESIS */
2162
2163
2164#ifdef YUKON
2165/******************************************************************************
2166 *
2167 *      SkPhyIsrGmac() - PHY interrupt service routine
2168 *
2169 * Description: handles all interrupts from Marvell PHY
2170 *
2171 * Returns: N/A
2172 */
2173static void SkPhyIsrGmac(
2174SK_AC           *pAC,           /* Adapter Context */
2175SK_IOC          IoC,            /* Io Context */
2176int                     Port,           /* Port Num = PHY Num */
2177SK_U16          IStatus)        /* Interrupt Status */
2178{
2179        SK_GEPORT       *pPrt;          /* GIni Port struct pointer */
2180        SK_EVPARA       Para;
2181        SK_U16          Word;
2182
2183        pPrt = &pAC->GIni.GP[Port];
2184
2185        if ((IStatus & (PHY_M_IS_AN_PR | PHY_M_IS_LST_CHANGE)) != 0) {
2186
2187                SkHWLinkDown(pAC, IoC, Port);
2188
2189                SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_ADV, &Word);
2190
2191                SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
2192                        ("AutoNeg.Adv: 0x%04X\n", Word));
2193                
2194                /* Set Auto-negotiation advertisement */
2195                if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM) {
2196                        /* restore Asymmetric Pause bit */
2197                        SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_AUNE_ADV,
2198                                (SK_U16)(Word | PHY_M_AN_ASP));
2199                }
2200                
2201                Para.Para32[0] = (SK_U32)Port;
2202                /* Signal to RLMT */
2203                SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
2204        }
2205        
2206        if ((IStatus & PHY_M_IS_AN_ERROR) != 0) {
2207                /* Auto-Negotiation Error */
2208                SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E023, SKERR_SIRQ_E023MSG);
2209        }
2210        
2211        if ((IStatus & PHY_M_IS_FIFO_ERROR) != 0) {
2212                /* FIFO Overflow/Underrun Error */
2213                SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E024, SKERR_SIRQ_E024MSG);
2214        }
2215        
2216}       /* SkPhyIsrGmac */
2217#endif /* YUKON */
2218
2219
2220#ifdef OTHER_PHY
2221/******************************************************************************
2222 *
2223 *      SkPhyIsrLone() - PHY interrupt service routine
2224 *
2225 * Description: handles all interrupts from LONE PHY
2226 *
2227 * Returns: N/A
2228 */
2229static void SkPhyIsrLone(
2230SK_AC   *pAC,           /* Adapter Context */
2231SK_IOC  IoC,            /* Io Context */
2232int             Port,           /* Port Num = PHY Num */
2233SK_U16  IStatus)        /* Interrupt Status */
2234{
2235        SK_EVPARA       Para;
2236
2237        if (IStatus & (PHY_L_IS_DUP | PHY_L_IS_ISOL)) {
2238                
2239                SkHWLinkDown(pAC, IoC, Port);
2240
2241                Para.Para32[0] = (SK_U32)Port;
2242                /* Signal to RLMT */
2243                SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
2244        }
2245
2246}       /* SkPhyIsrLone */
2247#endif /* OTHER_PHY */
2248
2249/* End of File */
2250
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.