!C99Shell v. 1.0 pre-release build #13!

Software: Apache/2.0.54 (Unix) mod_perl/1.99_09 Perl/v5.8.0 mod_ssl/2.0.54 OpenSSL/0.9.7l DAV/2 FrontPage/5.0.2.2635 PHP/4.4.0 mod_gzip/2.0.26.1a 

uname -a: Linux snow.he.net 4.4.276-v2-mono-1 #1 SMP Wed Jul 21 11:21:17 PDT 2021 i686 

uid=99(nobody) gid=98(nobody) groups=98(nobody) 

Safe-mode: OFF (not secure)

/usr/src/linux-2.4.18-xfs-1.1/drivers/net/sk98lin/   drwxr-xr-x
Free 318.38 GB of 458.09 GB (69.5%)
Home    Back    Forward    UPDIR    Refresh    Search    Buffer    Encoder    Tools    Proc.    FTP brute    Sec.    SQL    PHP-code    Update    Feedback    Self remove    Logout    


Viewing file:     skxmac2.c (60.29 KB)      -rw-r--r--
Select action/file-type:
(+) | (+) | (+) | Code (+) | Session (+) | (+) | SDB (+) | (+) | (+) | (+) | (+) | (+) |
/******************************************************************************
 *
 * Name:    skxmac2.c
 * Project:    GEnesis, PCI Gigabit Ethernet Adapter
 * Version:    $Revision: 1.61 $
 * Date:    $Date: 2001/02/09 15:40:59 $
 * Purpose:    Contains functions to initialize the XMAC II
 *
 ******************************************************************************/

/******************************************************************************
 *
 *    (C)Copyright 1998-2001 SysKonnect GmbH.
 *
 *    This program is free software; you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation; either version 2 of the License, or
 *    (at your option) any later version.
 *
 *    The information in this file is provided "AS IS" without warranty.
 *
 ******************************************************************************/

/******************************************************************************
 *
 * History:
 *
 *    $Log: skxmac2.c,v $
 *    Revision 1.61  2001/02/09 15:40:59  rassmann
 *    Editorial changes.
 *    
 *    Revision 1.60  2001/02/07 15:02:01  cgoos
 *    Added workaround for Fujitsu switch link down.
 *    
 *    Revision 1.59  2001/01/10 09:38:06  cgoos
 *    Fixed Broadcom C0/A1 Id check for workaround.
 *    
 *    Revision 1.58  2000/11/29 11:30:38  cgoos
 *    Changed DEBUG sections with NW output to xDEBUG
 *    
 *    Revision 1.57  2000/11/27 12:40:40  rassmann
 *    Suppressing preamble after first access to BCom, not before (#10556).
 *    
 *    Revision 1.56  2000/11/09 12:32:48  rassmann
 *    Renamed variables.
 *    
 *    Revision 1.55  2000/11/09 11:30:10  rassmann
 *    WA: Waiting after releasing reset until BCom chip is accessible.
 *    
 *    Revision 1.54  2000/10/02 14:10:27  rassmann
 *    Reading BCOM PHY after releasing reset until it returns a valid value.
 *    
 *    Revision 1.53  2000/07/27 12:22:11  gklug
 *    fix: possible endless loop in XmHardRst.
 *    
 *    Revision 1.52  2000/05/22 08:48:31  malthoff
 *    Fix: #10523 errata valid for all BCOM PHYs.
 *    
 *    Revision 1.51  2000/05/17 12:52:18  malthoff
 *    Fixes BCom link errata (#10523).
 *    
 *    Revision 1.50  1999/11/22 13:40:14  cgoos
 *    Changed license header to GPL.
 *    
 *    Revision 1.49  1999/11/22 08:12:13  malthoff
 *    Add workaround for power consumption feature of BCom C0 chip.
 *    
 *    Revision 1.48  1999/11/16 08:39:01  malthoff
 *    Fix: MDIO preamble suppression is port dependent.
 *    
 *    Revision 1.47  1999/08/27 08:55:35  malthoff
 *    1000BT: Optimizing MDIO transfer by oppressing MDIO preamble.
 *    
 *    Revision 1.46  1999/08/13 11:01:12  malthoff
 *    Fix for 1000BT: pFlowCtrlMode was not set correctly.
 *    
 *    Revision 1.45  1999/08/12 19:18:28  malthoff
 *    1000BT Fixes: Do not owerwrite XM_MMU_CMD.
 *    Do not execute BCOM A1 workaround for B1 chips.
 *    Fix pause frame setting.
 *    Always set PHY_B_AC_TX_TST in PHY_BCOM_AUX_CTRL.
 *    
 *    Revision 1.44  1999/08/03 15:23:48  cgoos
 *    Fixed setting of PHY interrupt mask in half duplex mode.
 *    
 *    Revision 1.43  1999/08/03 15:22:17  cgoos
 *    Added some debug output.
 *    Disabled XMac GP0 interrupt for external PHYs.
 *    
 *    Revision 1.42  1999/08/02 08:39:23  malthoff
 *    BCOM PHY: TX LED: To get the mono flop behaviour it is required
 *    to set the LED Traffic Mode bit in PHY_BCOM_P_EXT_CTRL.
 *    
 *    Revision 1.41  1999/07/30 06:54:31  malthoff
 *    Add temp. workarounds for the BCOM Phy revision A1.
 *    
 *    Revision 1.40  1999/06/01 07:43:26  cgoos
 *    Changed Link Mode Status in SkXmAutoNegDone... from FULL/HALF to
 *    AUTOFULL/AUTOHALF.
 *    
 *    Revision 1.39  1999/05/19 07:29:51  cgoos
 *    Changes for 1000Base-T.
 *    
 *    Revision 1.38  1999/04/08 14:35:10  malthoff
 *    Add code for enabling signal detect. Enabling signal detect is disabled.
 *    
 *    Revision 1.37  1999/03/12 13:42:54  malthoff
 *    Add: Jumbo Frame Support.
 *    Add: Receive modes SK_LENERR_OK_ON/OFF and
 *    SK_BIG_PK_OK_ON/OFF in SkXmSetRxCmd().
 *    
 *    Revision 1.36  1999/03/08 10:10:55  gklug
 *    fix: AutoSensing did switch to next mode even if LiPa indicated offline
 *
 *    Revision 1.35  1999/02/22 15:16:41  malthoff
 *    Remove some compiler warnings.
 *
 *    Revision 1.34  1999/01/22 09:19:59  gklug
 *    fix: Init DupMode and InitPauseMd are now called in RxTxEnable
 *
 *    Revision 1.33  1998/12/11 15:19:11  gklug
 *    chg: lipa autoneg stati
 *    chg: debug messages
 *    chg: do NOT use spurious XmIrq
 *
 *    Revision 1.32  1998/12/10 11:08:44  malthoff
 *    bug fix: pAC has been used for IOs in SkXmHardRst().
 *    SkXmInitPhy() is also called for the Diag in SkXmInitMac().
 *
 *    Revision 1.31  1998/12/10 10:39:11  gklug
 *    fix: do 4 RESETS of the XMAC at the beginning
 *    fix: dummy read interrupt source register BEFORE initializing the Phy
 *    add: debug messages
 *    fix: Linkpartners autoneg capability cannot be shown by TX_PAGE interrupt
 *
 *    Revision 1.30  1998/12/07 12:18:32  gklug
 *    add: refinement of autosense mode: take into account the autoneg cap of LiPa
 *
 *    Revision 1.29  1998/12/07 07:12:29  gklug
 *    fix: if page is received the link is  down.
 *
 *    Revision 1.28  1998/12/01 10:12:47  gklug
 *    chg: if spurious IRQ from XMAC encountered, save it
 *
 *    Revision 1.27  1998/11/26 07:33:38  gklug
 *    add: InitPhy call is now in XmInit function
 *
 *    Revision 1.26  1998/11/18 13:38:24  malthoff
 *    'Imsk' is also unused in SkXmAutoNegDone.
 *
 *    Revision 1.25  1998/11/18 13:28:01  malthoff
 *    Remove unused variable 'Reg' in SkXmAutoNegDone().
 *
 *    Revision 1.24  1998/11/18 13:18:45  gklug
 *    add: workaround for xmac errata #1
 *    add: detect Link Down also when Link partner requested config
 *    chg: XMIrq is only used when link is up
 *
 *    Revision 1.23  1998/11/04 07:07:04  cgoos
 *    Added function SkXmRxTxEnable.
 *
 *    Revision 1.22  1998/10/30 07:35:54  gklug
 *    fix: serve LinkDown interrupt when link is already down
 *
 *    Revision 1.21  1998/10/29 15:32:03  gklug
 *    fix: Link Down signaling
 *
 *    Revision 1.20  1998/10/29 11:17:27  gklug
 *    fix: AutoNegDone bug
 *
 *    Revision 1.19  1998/10/29 10:14:43  malthoff
 *    Add endainesss comment for reading/writing MAC addresses.
 *
 *    Revision 1.18  1998/10/28 07:48:55  cgoos
 *    Fix: ASS somtimes signaled although link is up.
 *
 *    Revision 1.17  1998/10/26 07:55:39  malthoff
 *    Fix in SkXmInitPauseMd(): Pause Mode
 *    was disabled and not enabled.
 *    Fix in SkXmAutoNegDone(): Checking Mode bits
 *    always failed, becaues of some missing braces.
 *
 *    Revision 1.16  1998/10/22 09:46:52  gklug
 *    fix SysKonnectFileId typo
 *
 *    Revision 1.15  1998/10/21 05:51:37  gklug
 *    add: para DoLoop to InitPhy function for loopback set-up
 *
 *    Revision 1.14  1998/10/16 10:59:23  malthoff
 *    Remove Lint warning for dummy reads.
 *
 *    Revision 1.13  1998/10/15 14:01:20  malthoff
 *    Fix: SkXmAutoNegDone() is (int) but does not return a value.
 *
 *    Revision 1.12  1998/10/14 14:45:04  malthoff
 *    Remove SKERR_SIRQ_E0xx and SKERR_SIRQ_E0xxMSG by
 *    SKERR_HWI_Exx and SKERR_HWI_E0xxMSG to be independant
 *    from the Sirq module.
 *
 *    Revision 1.11  1998/10/14 13:59:01  gklug
 *    add: InitPhy function
 *
 *    Revision 1.10  1998/10/14 11:20:57  malthoff
 *    Make SkXmAutoNegDone() public, because it's
 *    used in diagnostics, too.
 *    The Link Up event to the RLMT is issued in
 *    SkXmIrq(). SkXmIrq() is not available in
 *    diagnostics. Use PHY_READ when reading
 *    PHY registers.
 *
 *    Revision 1.9  1998/10/14 05:50:10  cgoos
 *    Added definition for Para.
 *
 *    Revision 1.8  1998/10/14 05:41:28  gklug
 *    add: Xmac IRQ
 *    add: auto negotiation done function
 *
 *    Revision 1.7  1998/10/09 06:55:20  malthoff
 *    The configuration of the XMACs Tx Request Threshold
 *    depends from the drivers port usage now. The port
 *    usage is configured in GIPortUsage.
 *
 *    Revision 1.6  1998/10/05 07:48:00  malthoff
 *    minor changes
 *
 *    Revision 1.5  1998/10/01 07:03:54  gklug
 *    add: dummy function for XMAC ISR
 *
 *    Revision 1.4  1998/09/30 12:37:44  malthoff
 *    Add SkXmSetRxCmd() and related code.
 *
 *    Revision 1.3  1998/09/28 13:26:40  malthoff
 *    Add SkXmInitMac(), SkXmInitDupMd(), and SkXmInitPauseMd()
 *
 *    Revision 1.2  1998/09/16 14:34:21  malthoff
 *    Add SkXmClrExactAddr(), SkXmClrSrcCheck(),
 *    SkXmClrHashAddr(), SkXmFlushTxFifo(),
 *    SkXmFlushRxFifo(), and SkXmHardRst().
 *    Finish Coding of SkXmSoftRst().
 *    The sources may be compiled now.
 *
 *    Revision 1.1  1998/09/04 10:05:56  malthoff
 *    Created.
 *
 *
 ******************************************************************************/

#include "h/skdrv1st.h"
#include "h/xmac_ii.h"
#include "h/skdrv2nd.h"

/* defines ********************************************************************/
/* typedefs *******************************************************************/
/* global variables ***********************************************************/

/* local variables ************************************************************/

static const char SysKonnectFileId[] =
    "@(#)$Id: skxmac2.c,v 1.61 2001/02/09 15:40:59 rassmann Exp $ (C) SK ";

/* BCOM PHY magic pattern list */
typedef struct s_PhyHack {
    int        PhyReg;        /* Phy register */
    SK_U16    PhyVal;        /* Value to write */
} BCOM_HACK;

BCOM_HACK BcomRegA1Hack[] = {
 { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1104 }, { 0x17, 0x0013 },
 { 0x15, 0x0404 }, { 0x17, 0x8006 }, { 0x15, 0x0132 }, { 0x17, 0x8006 },
 { 0x15, 0x0232 }, { 0x17, 0x800D }, { 0x15, 0x000F }, { 0x18, 0x0420 },
 { 0, 0 }
};
BCOM_HACK BcomRegC0Hack[] = {
 { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1204 }, { 0x17, 0x0013 },
 { 0x15, 0x0A04 }, { 0x18, 0x0420 },
 { 0, 0 }
};

/* function prototypes ********************************************************/
static void    SkXmInitPhyXmac(SK_AC*, SK_IOC, int, SK_BOOL);
static void    SkXmInitPhyBcom(SK_AC*, SK_IOC, int, SK_BOOL);
static void    SkXmInitPhyLone(SK_AC*, SK_IOC, int, SK_BOOL);
static void    SkXmInitPhyNat (SK_AC*, SK_IOC, int, SK_BOOL);
static int    SkXmAutoNegDoneXmac(SK_AC*, SK_IOC, int);
static int    SkXmAutoNegDoneBcom(SK_AC*, SK_IOC, int);
static int    SkXmAutoNegDoneLone(SK_AC*, SK_IOC, int);
static int    SkXmAutoNegDoneNat (SK_AC*, SK_IOC, int);

/******************************************************************************
 *
 *    SkXmSetRxCmd() - Modify the value of the XMACs Rx Command Register
 *
 * Description:
 *    The features
 *     o FCS stripping,            SK_STRIP_FCS_ON/OFF
 *     o pad byte stripping,            SK_STRIP_PAD_ON/OFF
 *     o don't set XMR_FS_ERR in frame    SK_LENERR_OK_ON/OFF
 *       status for inrange length error
 *       frames, and
 *     o don't set XMR_FS_ERR in frame    SK_BIG_PK_OK_ON/OFF
 *       status for frames > 1514 bytes
 *
 *    for incomming packets may be enabled/disabled by this function.
 *    Additional modes may be added later.
 *    Multiple modes can be enabled/disabled at the same time.
 *    The new configuration is stored into the HWAC port configuration
 *    and is written to the Receive Command register immediatlely.
 *    The new configuration is saved over any SkGePortStop() and
 *    SkGeInitPort() calls. The configured value will be overwritten
 *    when SkGeInit(Level 0) is executed.
 *
 * Returns:
 *    nothing
 */
void SkXmSetRxCmd(
SK_AC    *pAC,        /* adapter context */
SK_IOC    IoC,        /* IO context */
int        Port,        /* The XMAC to handle with belongs to this Port */
int        Mode)        /* Mode is SK_STRIP_FCS_ON/OFF, SK_STRIP_PAD_ON/OFF,
                       SK_LENERR_OK_ON/OFF, or SK_BIG_PK_OK_ON/OFF */
{
    SK_GEPORT    *pPrt;
    SK_U16        OldRxMode;

    pPrt = &pAC->GIni.GP[Port];
    OldRxMode = pPrt->PRxCmd;

    switch(Mode & (SK_STRIP_FCS_ON | SK_STRIP_FCS_OFF)) {
    case SK_STRIP_FCS_ON:
        pPrt->PRxCmd |= XM_RX_STRIP_FCS;
        break;
    case SK_STRIP_FCS_OFF:
        pPrt->PRxCmd &= ~XM_RX_STRIP_FCS;
        break;
    }

    switch(Mode & (SK_STRIP_PAD_ON | SK_STRIP_PAD_OFF)) {
    case SK_STRIP_PAD_ON:
        pPrt->PRxCmd |= XM_RX_STRIP_PAD;
        break;
    case SK_STRIP_PAD_OFF:
        pPrt->PRxCmd &= ~XM_RX_STRIP_PAD;
        break;
    }

    switch(Mode & (SK_LENERR_OK_ON | SK_LENERR_OK_OFF)) {
    case SK_LENERR_OK_ON:
        pPrt->PRxCmd |= XM_RX_LENERR_OK;
        break;
    case SK_LENERR_OK_OFF:
        pPrt->PRxCmd &= ~XM_RX_LENERR_OK;
        break;
    }

    switch(Mode & (SK_BIG_PK_OK_ON | SK_BIG_PK_OK_OFF)) {
    case SK_BIG_PK_OK_ON:
        pPrt->PRxCmd |= XM_RX_BIG_PK_OK;
        break;
    case SK_BIG_PK_OK_OFF:
        pPrt->PRxCmd &= ~XM_RX_BIG_PK_OK;
        break;
    }

    /* Write the new mode to the receive command register if required */
    if (OldRxMode != pPrt->PRxCmd) {
        XM_OUT16(IoC, Port, XM_RX_CMD, pPrt->PRxCmd);
    }
}    /* SkXmSetRxCmd*/


/******************************************************************************
 *
 *    SkXmClrExactAddr() - Clear Exact Match Address Registers
 *
 * Description:
 *    All Exact Match Address registers of the XMAC 'Port' will be
 *    cleared starting with 'StartNum' up to (and including) the
 *    Exact Match address number of 'StopNum'.
 *
 * Returns:
 *    nothing
 */
void SkXmClrExactAddr(
SK_AC    *pAC,        /* adapter context */
SK_IOC    IoC,        /* IO context */
int        Port,        /* The XMAC to handle with belongs to this Port */
int        StartNum,    /* Begin with this Address Register Index (0..15) */
int        StopNum)    /* Stop after finished with this Register Idx (0..15) */
{
    int        i;
    SK_U16    ZeroAddr[3] = {0x0000, 0x0000, 0x0000};

    if ((unsigned)StartNum > 15 || (unsigned)StopNum > 15 ||
        StartNum > StopNum) {

        SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E001, SKERR_HWI_E001MSG);
        return;
    }

    for (i = StartNum; i <= StopNum; i++) {
        XM_OUTADDR(IoC, Port, XM_EXM(i), &ZeroAddr[0]);
    }
}    /* SkXmClrExactAddr */


/******************************************************************************
 *
 *    SkXmClrSrcCheck() - Clear Source Check Address Register
 *
 * Description:
 *    The Source Check Address Register of the XMAC 'Port' number
 *    will be cleared.
 *
 * Returns:
 *    nothing
 */
static void SkXmClrSrcCheck(
SK_AC    *pAC,    /* adapter context */
SK_IOC    IoC,    /* IO context */
int        Port)    /* The XMAC to handle with belongs to this Port (MAC_1 + n) */
{
    SK_U16    ZeroAddr[3] = {0x0000, 0x0000, 0x0000};

    XM_OUTHASH(IoC, Port, XM_SRC_CHK, &ZeroAddr);
}    /* SkXmClrSrcCheck */


/******************************************************************************
 *
 *    SkXmClrHashAddr() - Clear Hash Address Registers
 *
 * Description:
 *    The Hash Address Register of the XMAC 'Port' will be cleared.
 *
 * Returns:
 *    nothing
 */
static void SkXmClrHashAddr(
SK_AC    *pAC,    /* adapter context */
SK_IOC    IoC,    /* IO context */
int        Port)    /* The XMAC to handle with belongs to this Port (MAC_1 + n) */
{
    SK_U16    ZeroAddr[4] = {0x0000, 0x0000, 0x0000, 0x0000};

    XM_OUTHASH(IoC, Port, XM_HSM, &ZeroAddr);
}    /* SkXmClrHashAddr*/


/******************************************************************************
 *
 *    SkXmFlushTxFifo() - Flush the XMACs transmit FIFO
 *
 * Description:
 *    Flush the transmit FIFO of the XMAC specified by the index 'Port'
 *
 * Returns:
 *    nothing
 */
void SkXmFlushTxFifo(
SK_AC    *pAC,    /* adapter context */
SK_IOC    IoC,    /* IO context */
int        Port)    /* The XMAC to handle with belongs to this Port (MAC_1 + n) */
{
    SK_U32    MdReg;

    XM_IN32(IoC, Port, XM_MODE, &MdReg);
    MdReg |= XM_MD_FTF;
    XM_OUT32(IoC, Port, XM_MODE, MdReg);
}    /* SkXmFlushTxFifo */


/******************************************************************************
 *
 *    SkXmFlushRxFifo() - Flush the XMACs receive FIFO
 *
 * Description:
 *    Flush the receive FIFO of the XMAC specified by the index 'Port'
 *
 * Returns:
 *    nothing
 */
void SkXmFlushRxFifo(
SK_AC    *pAC,    /* adapter context */
SK_IOC    IoC,    /* IO context */
int        Port)    /* The XMAC to handle with belongs to this Port (MAC_1 + n) */
{
    SK_U32    MdReg;

    XM_IN32(IoC, Port, XM_MODE, &MdReg);
    MdReg |= XM_MD_FRF;
    XM_OUT32(IoC, Port, XM_MODE, MdReg);
}    /* SkXmFlushRxFifo*/


/******************************************************************************
 *
 *    SkXmSoftRst() - Do a XMAC software reset
 *
 * Description:
 *    The PHY registers should not be destroyed during this
 *    kind of software reset. Therefore the XMAC Software Reset
 *    (XM_GP_RES_MAC bit in XM_GP_PORT) must not be used!
 *
 *    The software reset is done by
 *        - disabling the Rx and Tx state maschine,
 *        - reseting the statistics module,
 *        - clear all other significant XMAC Mode,
 *          Command, and Control Registers
 *        - clearing the Hash Register and the
 *          Exact Match Address registers, and
 *        - flushing the XMAC's Rx and Tx FIFOs.
 *
 * Note:
 *    Another requirement when stopping the XMAC is to
 *    avoid sending corrupted frames on the network.
 *    Disabling the Tx state maschine will NOT interrupt
 *    the currently transmitted frame. But we must take care
 *    that the tx FIFO is cleared AFTER the current frame
 *    is complete sent to the network.
 *
 *    It takes about 12ns to send a frame with 1538 bytes.
 *    One PCI clock goes at least 15ns (66MHz). Therefore
 *    after reading XM_GP_PORT back, we are sure that the
 *    transmitter is disabled AND idle. And this means
 *    we may flush the transmit FIFO now.
 *
 * Returns:
 *    nothing
 */
void SkXmSoftRst(
SK_AC    *pAC,    /* adapter context */
SK_IOC    IoC,    /* IO context */
int        Port)    /* port to stop (MAC_1 + n) */
{
    SK_GEPORT    *pPrt;
    SK_U16        Word;

    pPrt = &pAC->GIni.GP[Port];

    /* disable the receiver and transmitter */
    XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
    XM_OUT16(IoC, Port, XM_MMU_CMD, Word & ~(XM_MMU_ENA_RX|XM_MMU_ENA_TX));

    /* reset the statistics module */
    XM_OUT32(IoC, Port, XM_GP_PORT, XM_GP_RES_STAT);

    /*
     * clear all other significant XMAC Mode,
     * Command, and Control Registers
     */
    XM_OUT16(IoC, Port, XM_IMSK, 0xffff);        /* disable all IRQs */
    XM_OUT32(IoC, Port, XM_MODE, 0x00000000);    /* clear Mode Reg */
    XM_OUT16(IoC, Port, XM_TX_CMD, 0x0000);        /* reset TX CMD Reg */
    XM_OUT16(IoC, Port, XM_RX_CMD, 0x0000);        /* reset RX CMD Reg */
    
    /* disable all PHY IRQs */
    switch (pAC->GIni.GP[Port].PhyType) {
    case SK_PHY_BCOM:
            PHY_WRITE(IoC, pPrt, Port, PHY_BCOM_INT_MASK, 0xffff);
            break;
        case SK_PHY_LONE:
            PHY_WRITE(IoC, pPrt, Port, PHY_LONE_INT_ENAB, 0x0);
            break;
        case SK_PHY_NAT:
            /* todo: National
             PHY_WRITE(IoC, pPrt, Port, PHY_NAT_INT_MASK, 
                0xffff); */
            break;
    }

    /* clear the Hash Register */
    SkXmClrHashAddr(pAC, IoC, Port);

    /* clear the Exact Match Address registers */
    SkXmClrExactAddr(pAC, IoC, Port, 0, 15);
    SkXmClrSrcCheck(pAC, IoC, Port);

    /* flush the XMAC's Rx and Tx FIFOs */
    SkXmFlushTxFifo(pAC, IoC, Port);
    SkXmFlushRxFifo(pAC, IoC, Port);

    pAC->GIni.GP[Port].PState = SK_PRT_STOP;
}    /* SkXmSoftRst*/


/******************************************************************************
 *
 *    SkXmHardRst() - Do a XMAC hardware reset
 *
 * Description:
 *    The XMAC of the specified 'Port' and all connected devices
 *    (PHY and SERDES) will receive a reset signal on its *Reset
 *    pins.
 *    External PHYs must be reset be clearing a bit in the GPIO
 *    register (Timing requirements: Broadcom: 400ns, Level One:
 *    none, National: 80ns).
 *
 * ATTENTION:
 *     It is absolutely neccessary to reset the SW_RST Bit first
 *    before calling this function.
 *
 * Returns:
 *    nothing
 */
void SkXmHardRst(
SK_AC    *pAC,    /* adapter context */
SK_IOC    IoC,    /* IO context */
int        Port)    /* port to stop (MAC_1 + n) */
{
    SK_U32    Reg;
    int        i;
    int        TOut;
    SK_U16    Word;

    for (i = 0; i < 4; i++) {
        /* TX_MFF_CTRL1 is a 32 bit register but only the lowest 16 */
        /* bit contains buttoms to press */
        SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), (SK_U16)MFF_CLR_MAC_RST);

        TOut = 0;
        do {
            TOut ++;
            if (TOut > 10000) {
                /*
                 * Adapter seems to be in RESET state.
                 * Registers cannot be written.
                 */
                return;
            }

            SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1),
                (SK_U16) MFF_SET_MAC_RST);
            SK_IN16(IoC,MR_ADDR(Port,TX_MFF_CTRL1), &Word);
        } while ((Word & MFF_SET_MAC_RST) == 0);
    }

    /* For external PHYs there must be special handling */
    if (pAC->GIni.GP[Port].PhyType != SK_PHY_XMAC) {
        /* reset external PHY */
        SK_IN32(IoC, B2_GP_IO, &Reg);
        if (Port == 0) {
            Reg |= GP_DIR_0; /* set to output */
            Reg &= ~GP_IO_0;
        }
        else {
            Reg |= GP_DIR_2; /* set to output */
            Reg &= ~GP_IO_2;
        }
        SK_OUT32(IoC, B2_GP_IO, Reg);

        /* short delay */
        SK_IN32(IoC, B2_GP_IO, &Reg);
    }

    pAC->GIni.GP[Port].PState = SK_PRT_RESET;
}    /* SkXmHardRst */


/******************************************************************************
 *
 *    SkXmInitMac() - Initialize the XMAC II
 *
 * Description:
 *    Initialize all the XMAC of the specified port.
 *    The XMAC must be reset or stopped before calling this function.
 *
 * Note:
 *    The XMAC's Rx and Tx state machine is still disabled when returning.
 *
 * Returns:
 *    nothing
 */
void SkXmInitMac(
SK_AC    *pAC,        /* adapter context */
SK_IOC    IoC,        /* IO context */
int        Port)        /* Port Index (MAC_1 + n) */
{
    SK_GEPORT    *pPrt;
    SK_U32        Reg;
    int            i;
    SK_U16        SWord;
    SK_U16        PhyId;

    pPrt = &pAC->GIni.GP[Port];

    if (pPrt->PState == SK_PRT_STOP) {
        /* Port State: SK_PRT_STOP */
        /* Verify that the reset bit is cleared */
        SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &SWord);
        if (SWord & (SK_U16)MFF_SET_MAC_RST) {
            /* PState does not match HW state */
            SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E006, SKERR_HWI_E006MSG);
            /* Correct it. */
            pPrt->PState = SK_PRT_RESET;
        }
    }

    if (pPrt->PState == SK_PRT_RESET) {
        /*
         * clear HW reset
         * Note: The SW reset is self clearing, therefore there is
         *     nothing to do here.
         */
        SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), (SK_U16)MFF_CLR_MAC_RST);

        /* Ensure that XMAC reset release is done (errata from LReinbold?). */
        SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &SWord);

        /* Clear PHY reset. */
        if (pAC->GIni.GP[Port].PhyType != SK_PHY_XMAC) {
            SK_IN32(IoC, B2_GP_IO, &Reg);
            if (Port == 0) {
                Reg |= GP_DIR_0; /* Set to output. */
                Reg |= GP_IO_0;
            }
            else {
                Reg |= GP_DIR_2; /* Set to output. */
                Reg |= GP_IO_2;
            }
            SK_OUT32(IoC, B2_GP_IO, Reg);

            /* Enable GMII interface. */
            XM_OUT16(IoC, Port, XM_HW_CFG, XM_HW_GMII_MD);

            PHY_READ(IoC, pPrt, Port, PHY_XMAC_ID1, &PhyId);
#ifdef xDEBUG
            if (SWord == 0xFFFF) {
                i = 1;
                do {
                    PHY_READ(IoC, pPrt, Port, PHY_XMAC_ID1, &SWord);
                    i++;
                    /* Limit retries; else machine may hang. */
                } while (SWord == 0xFFFF && i < 500000);

                CMSMPrintString(
                    pAC->pConfigTable,
                    MSG_TYPE_RUNTIME_INFO,
                    "ID1 is %x after %d reads.",
                    (void *)SWord,
                    (void *)i);

                /* Trigger PCI analyzer */
                /* SK_IN32(IoC, 0x012c, &Reg); */
            }
#endif    /* DEBUG */

            /*
             * Optimize MDIO transfer by suppressing preamble.
             * Must be done AFTER first access to BCOM chip.
             */
            XM_IN16(IoC, Port, XM_MMU_CMD, &SWord);
            XM_OUT16(IoC, Port, XM_MMU_CMD, SWord | XM_MMU_NO_PRE);

            if (PhyId == 0x6044) {
                /* Workaround BCOM Errata for the C0 type. */
                /* Write magic patterns to reserved registers. */
                i = 0;
                while (BcomRegC0Hack[i].PhyReg != 0) {
                    PHY_WRITE(IoC, pPrt, Port, BcomRegC0Hack[i].PhyReg,
                        BcomRegC0Hack[i].PhyVal);
                    i++;
                }
            }
            else if (PhyId == 0x6041) {
                /* Workaround BCOM Errata for the A1 type. */
                /* Write magic patterns to reserved registers. */
                i = 0;
                while (BcomRegA1Hack[i].PhyReg != 0) {
                    PHY_WRITE(IoC, pPrt, Port, BcomRegA1Hack[i].PhyReg,
                        BcomRegA1Hack[i].PhyVal);
                    i++;
                }
            }

            /* Workaround BCOM Errata (#10523) for all BCom PHYs. */
            /* Disable Power Management after reset. */
            PHY_READ(IoC, pPrt, Port, PHY_BCOM_AUX_CTRL, &SWord);
#ifdef xDEBUG
            if (SWord == 0xFFFF) {
                i = 1;
                do {
                    PHY_READ(IoC, pPrt, Port, PHY_BCOM_AUX_CTRL, &SWord);
                    i++;
                    /* Limit retries; else machine may hang. */
                } while (SWord == 0xFFFF && i < 500000);

                CMSMPrintString(
                    pAC->pConfigTable,
                    MSG_TYPE_RUNTIME_INFO,
                    "AUX_CTRL is %x after %d reads.",
                    (void *)SWord,
                    (void *)i);

                /* Trigger PCI analyzer */
                /* SK_IN32(IoC, 0x012c, &Reg); */
            }
#endif    /* DEBUG */
            PHY_WRITE(IoC, pPrt, Port, PHY_BCOM_AUX_CTRL,
                SWord | PHY_B_AC_DIS_PM);

            /* PHY LED initialization is done in SkGeXmitLED(), not here. */
        }

        /* Dummy read the Interrupt source register */
        XM_IN16(IoC, Port, XM_ISRC, &SWord);
        
        /*
         * The autonegotiation process starts immediately after
         * clearing the reset. The autonegotiation process should be
         * started by the SIRQ, therefore stop it here immediately.
         */
        SkXmInitPhy(pAC, IoC, Port, SK_FALSE);

#if 0
        /* temp. code: enable signal detect */
        /* WARNING: do not override GMII setting above */
        XM_OUT16(pAC, Port, XM_HW_CFG, XM_HW_COM4SIG);
#endif
    }

    /*
     * configure the XMACs Station Address
     * B2_MAC_2 = xx xx xx xx xx x1 is programed to XMAC A
     * B2_MAC_3 = xx xx xx xx xx x2 is programed to XMAC B
     */
    for (i = 0; i < 3; i++) {
        /*
         * The following 2 statements are together endianess
         * independant. Remember this when changing.
         */
        SK_IN16(IoC, (B2_MAC_2 + Port * 8 + i * 2), &SWord);
        XM_OUT16(IoC, Port, (XM_SA + i * 2), SWord);
    }

    /* Tx Inter Packet Gap (XM_TX_IPG):    use default */
    /* Tx High Water Mark (XM_TX_HI_WM):    use default */
    /* Tx Low Water Mark (XM_TX_LO_WM):    use default */
    /* Host Request Threshold (XM_HT_THR):    use default */
    /* Rx Request Threshold (XM_RX_THR):    use default */
    /* Rx Low Water Mark (XM_RX_LO_WM):    use default */

    /* configure Rx High Water Mark (XM_RX_HI_WM) */
    XM_OUT16(IoC, Port, XM_RX_HI_WM, 0x05aa);

    if (pAC->GIni.GIMacsFound > 1) {
        switch (pAC->GIni.GIPortUsage) {
        case SK_RED_LINK:
            /* Configure Tx Request Threshold for red. link */
            XM_OUT16(IoC, Port, XM_TX_THR, SK_XM_THR_REDL);
            break;
        case SK_MUL_LINK:
            /* Configure Tx Request Threshold for load bal. */
            XM_OUT16(IoC, Port, XM_TX_THR, SK_XM_THR_MULL);
            break;
        case SK_JUMBO_LINK:
            /* Configure Tx Request Threshold for jumbo frames */
            XM_OUT16(IoC, Port, XM_TX_THR, SK_XM_THR_JUMBO);
            break;
        default:
            SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E014,
                SKERR_HWI_E014MSG);
            break;
        }
    }
    else {
        /* Configure Tx Request Threshold for single port */
        XM_OUT16(IoC, Port, XM_TX_THR, SK_XM_THR_SL);
    }

    /*
     * setup register defaults for the Rx Command Register
     *    - Enable Automatic Frame Padding on Tx side
     */
    XM_OUT16(IoC, Port, XM_TX_CMD, XM_TX_AUTO_PAD);

    /*
     * setup register defaults for the Rx Command Register,
     * program value of PRxCmd
     */
    XM_OUT16(IoC, Port, XM_RX_CMD, pPrt->PRxCmd);

    /*
     * setup register defaults for the Mode Register
     *    - Don't strip error frames to avoid Store & Forward
     *      on the rx side.
     *    - Enable 'Check Station Address' bit
     *    - Enable 'Check Address Array' bit
     */
    XM_OUT32(IoC, Port, XM_MODE, XM_DEF_MODE);

    /*
     * Initialize the Receive Counter Event Mask (XM_RX_EV_MSK)
     *    - Enable all bits excepting 'Octets Rx OK Low CntOv'
     *      and 'Octets Rx OK Hi Cnt Ov'.
     */
    XM_OUT32(IoC, Port, XM_RX_EV_MSK, XMR_DEF_MSK);

    /*
     * Initialize the Transmit Counter Event Mask (XM_TX_EV_MSK)
     *    - Enable all bits excepting 'Octets Tx OK Low CntOv'
     *      and 'Octets Tx OK Hi Cnt Ov'.
     */
    XM_OUT32(IoC, Port, XM_TX_EV_MSK, XMT_DEF_MSK);

    /*
     * Do NOT init XMAC interrupt mask here.
     * All interrupts remain disable until link comes up!
     */
    pPrt->PState = SK_PRT_INIT;

    /*
     * Any additional configuration changes may be done now.
     * The last action is to enable the rx and tx state machine.
     * This should be done after the autonegotiation process
     * has been completed successfully.
     */
}    /* SkXmInitMac*/


/******************************************************************************
 *
 *    SkXmInitDupMd() - Initialize the XMACs Duplex Mode
 *
 * Description:
 *    This function initilaizes the XMACs Duplex Mode.
 *    It should be called after successfully finishing
 *    the Autonegotiation Process
 *
 * Returns:
 *    nothing
 */
void SkXmInitDupMd(
SK_AC    *pAC,        /* adapter context */
SK_IOC    IoC,        /* IO context */
int        Port)        /* Port Index (MAC_1 + n) */
{
    switch (pAC->GIni.GP[Port].PLinkModeStatus) {
    case SK_LMODE_STAT_AUTOHALF:
    case SK_LMODE_STAT_HALF:
        /* Configuration Actions for Half Duplex Mode */
        /*
         * XM_BURST = default value. We are propable not quick
         *     enough at the 'XMAC' bus to burst 8kB.
         *    The XMAC stopps bursting if no transmit frames
         *    are available or the burst limit is exceeded.
         */
        /* XM_TX_RT_LIM = default value (15) */
        /* XM_TX_STIME = default value (0xff = 4096 bit times) */
        break;
    case SK_LMODE_STAT_AUTOFULL:
    case SK_LMODE_STAT_FULL:
        /* Configuration Actions for Full Duplex Mode */
        /*
         * The duplex mode is configured by the PHY,
         * therefore it seems to be that there is nothing
         * to do here.
         */
        break;
    case SK_LMODE_STAT_UNKNOWN:
    default:
        SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E007, SKERR_HWI_E007MSG);
        break;
    }
}    /* SkXmInitDupMd */


/******************************************************************************
 *
 *    SkXmInitPauseMd() - initialize the Pause Mode to be used for this port
 *
 * Description:
 *    This function initilaizes the Pause Mode which should
 *    be used for this port.
 *    It should be called after successfully finishing
 *    the Autonegotiation Process
 *
 * Returns:
 *    nothing
 */
void SkXmInitPauseMd(
SK_AC    *pAC,        /* adapter context */
SK_IOC    IoC,        /* IO context */
int        Port)        /* Port Index (MAC_1 + n) */
{
    SK_GEPORT    *pPrt;
    SK_U32        DWord;
    SK_U16        Word;

    pPrt = &pAC->GIni.GP[Port];

    if (pPrt->PFlowCtrlStatus == SK_FLOW_STAT_NONE ||
        pPrt->PFlowCtrlStatus == SK_FLOW_STAT_LOC_SEND) {

        /* Disable Pause Frame Reception */
        XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
        XM_OUT16(IoC, Port, XM_MMU_CMD, Word | XM_MMU_IGN_PF);
    }
    else {
        /*
         * enabling pause frame reception is required for 1000BT 
         * because the XMAC is not reset if the link is going down
         */
        /* Enable Pause Frame Reception */
        XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
        XM_OUT16(IoC, Port, XM_MMU_CMD, Word & ~XM_MMU_IGN_PF);
    }    

    if (pPrt->PFlowCtrlStatus == SK_FLOW_STAT_SYMMETRIC ||
        pPrt->PFlowCtrlStatus == SK_FLOW_STAT_LOC_SEND) {

        /*
         * Configure Pause Frame Generation
         * Use internal and external Pause Frame Generation.
         * Sending pause frames is edge triggert. Send a
         * Pause frame with the maximum pause time if
         * internal oder external FIFO full condition
         * occurs. Send a zero pause time frame to
         * start transmission again.
         */

        /* XM_PAUSE_DA = '010000C28001' (default) */

        /* XM_MAC_PTIME = 0xffff (maximum) */
        /* remember this value is defined in big endian (!) */
        XM_OUT16(IoC, Port, XM_MAC_PTIME, 0xffff);

        /* Set Pause Mode in Mode Register */
        XM_IN32(IoC, Port, XM_MODE, &DWord);
        XM_OUT32(IoC, Port, XM_MODE, DWord | XM_PAUSE_MODE);

        /* Set Pause Mode in MAC Rx FIFO */
        SK_OUT16(IoC, MR_ADDR(Port,RX_MFF_CTRL1), MFF_ENA_PAUSE);
    }
    else {
        /*
         * disable pause frame generation is required for 1000BT 
         * because the XMAC is not reset if the link is going down
         */
        /* Disable Pause Mode in Mode Register */
        XM_IN32(IoC, Port, XM_MODE, &DWord);
        XM_OUT32(IoC, Port, XM_MODE, DWord & ~XM_PAUSE_MODE);

        /* Disable Pause Mode in MAC Rx FIFO */
        SK_OUT16(IoC, MR_ADDR(Port,RX_MFF_CTRL1), MFF_DIS_PAUSE);
    }
}    /* SkXmInitPauseMd*/


/******************************************************************************
 *
 *    SkXmInitPhy() - Initialize the XMAC II Phy registers
 *
 * Description:
 *    Initialize all the XMACs Phy registers
 *
 * Note:
 *
 * Returns:
 *    nothing
 */
void SkXmInitPhy(
SK_AC    *pAC,        /* adapter context */
SK_IOC    IoC,        /* IO context */
int        Port,        /* Port Index (MAC_1 + n) */
SK_BOOL    DoLoop)        /* Should a Phy LOOback be set-up? */
{
    SK_GEPORT    *pPrt;

    pPrt = &pAC->GIni.GP[Port];
    switch (pPrt->PhyType) {
    case SK_PHY_XMAC:
        SkXmInitPhyXmac(pAC, IoC, Port, DoLoop);
        break;
    case SK_PHY_BCOM:
        SkXmInitPhyBcom(pAC, IoC, Port, DoLoop);
        break;
    case SK_PHY_LONE:
        SkXmInitPhyLone(pAC, IoC, Port, DoLoop);
        break;
    case SK_PHY_NAT:
        SkXmInitPhyNat(pAC, IoC, Port, DoLoop);
        break;
    }
}    /* SkXmInitPhy*/


/******************************************************************************
 *
 *    SkXmInitPhyXmac() - Initialize the XMAC II Phy registers
 *
 * Description:
 *    Initialize all the XMACs Phy registers
 *
 * Note:
 *
 * Returns:
 *    nothing
 */
static void SkXmInitPhyXmac(
SK_AC    *pAC,        /* adapter context */
SK_IOC    IoC,        /* IO context */
int        Port,        /* Port Index (MAC_1 + n) */
SK_BOOL    DoLoop)        /* Should a Phy LOOback be set-up? */
{
    SK_GEPORT    *pPrt;
    SK_U16        Ctrl;

    pPrt = &pAC->GIni.GP[Port];

    /* Autonegotiation ? */
    if (pPrt->PLinkMode == SK_LMODE_HALF ||
        pPrt->PLinkMode == SK_LMODE_FULL) {
        SK_DBG_MSG(pAC,SK_DBGMOD_HWM,SK_DBGCAT_CTRL,
            ("InitPhyXmac: no autonegotiation Port %d\n", Port));
        /* No Autonegiotiation */
        /* Set DuplexMode in Config register */
        Ctrl = (pPrt->PLinkMode == SK_LMODE_FULL ? PHY_CT_DUP_MD : 0);

        /*
         * Do NOT enable Autonegotiation here. This would hold
         * the link down because no IDLES are transmitted
         */
    }
    else {
        SK_DBG_MSG(pAC,SK_DBGMOD_HWM,SK_DBGCAT_CTRL,
            ("InitPhyXmac: with autonegotiation Port %d\n", Port));
        /* Set Autonegotiation advertisement */
        Ctrl = 0;

        /* Set Full/half duplex capabilities */
        switch (pPrt->PLinkMode) {
        case SK_LMODE_AUTOHALF:
            Ctrl |= PHY_X_AN_HD;
            break;
        case SK_LMODE_AUTOFULL:
            Ctrl |= PHY_X_AN_FD;
            break;
        case SK_LMODE_AUTOBOTH:
            Ctrl |= PHY_X_AN_FD | PHY_X_AN_HD;
            break;
        default:
            SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT,
                SKERR_HWI_E015, SKERR_HWI_E015MSG);
        }

        switch (pPrt->PFlowCtrlMode) {
        case SK_FLOW_MODE_NONE:
            Ctrl |= PHY_X_P_NO_PAUSE;
            break;
        case SK_FLOW_MODE_LOC_SEND:
            Ctrl |= PHY_X_P_ASYM_MD;
            break;
        case SK_FLOW_MODE_SYMMETRIC:
            Ctrl |= PHY_X_P_SYM_MD;
            break;
        case SK_FLOW_MODE_SYM_OR_REM:
            Ctrl |= PHY_X_P_BOTH_MD;
            break;
        default:
            SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT,
                SKERR_HWI_E016, SKERR_HWI_E016MSG);
        }

        /* Write AutoNeg Advertisement Register */
        PHY_WRITE(IoC, pPrt, Port, PHY_XMAC_AUNE_ADV, Ctrl);

        /* Restart Autonegotiation */
        Ctrl = PHY_CT_ANE | PHY_CT_RE_CFG;
    }

    if (DoLoop) {
        /* Set the Phy Loopback bit, too */
        Ctrl |= PHY_CT_LOOP;
    }

    /* Write to the Phy control register */
    PHY_WRITE(IoC, pPrt, Port, PHY_XMAC_CTRL, Ctrl);
}    /* SkXmInitPhyXmac*/


/******************************************************************************
 *
 *    SkXmInitPhyBcom() - Initialize the Broadcom Phy registers
 *
 * Description:
 *    Initialize all the Broadcom Phy registers
 *
 * Note:
 *
 * Returns:
 *    nothing
 */
static void SkXmInitPhyBcom(
SK_AC    *pAC,        /* adapter context */
SK_IOC    IoC,        /* IO context */
int        Port,        /* Port Index (MAC_1 + n) */
SK_BOOL    DoLoop)        /* Should a Phy LOOback be set-up? */
{
    SK_GEPORT    *pPrt;
    SK_U16        Ctrl1;
    SK_U16        Ctrl2;
    SK_U16        Ctrl3;
    SK_U16        Ctrl4;
    SK_U16        Ctrl5;

    Ctrl1 = PHY_B_CT_SP1000;
    Ctrl2 = 0;
    Ctrl3 = PHY_SEL_TYPE;
    Ctrl4 = PHY_B_PEC_EN_LTR;
    Ctrl5 = PHY_B_AC_TX_TST;

    pPrt = &pAC->GIni.GP[Port];

    /* manually Master/Slave ? */
    if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
        Ctrl2 |= PHY_B_1000C_MSE;
        if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
            Ctrl2 |= PHY_B_1000C_MSC;
        }
    }
    /* Autonegotiation ? */
    if (pPrt->PLinkMode == SK_LMODE_HALF ||
        pPrt->PLinkMode == SK_LMODE_FULL) {
        SK_DBG_MSG(pAC,SK_DBGMOD_HWM,SK_DBGCAT_CTRL,
            ("InitPhyBcom: no autonegotiation Port %d\n", Port));
        /* No Autonegiotiation */
        /* Set DuplexMode in Config register */
        Ctrl1 |= (pPrt->PLinkMode == SK_LMODE_FULL ? PHY_CT_DUP_MD : 0);

        /* Determine Master/Slave manually if not already done. */
        if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
            Ctrl2 |= PHY_B_1000C_MSE;    /* set it to Slave */
        }

        /*
         * Do NOT enable Autonegotiation here. This would hold
         * the link down because no IDLES are transmitted
         */
    }
    else {
        SK_DBG_MSG(pAC,SK_DBGMOD_HWM,SK_DBGCAT_CTRL,
            ("InitPhyBcom: with autonegotiation Port %d\n", Port));
        /* Set Autonegotiation advertisement */

        /* Set Full/half duplex capabilities */
        switch (pPrt->PLinkMode) {
        case SK_LMODE_AUTOHALF:
            Ctrl2 |= PHY_B_1000C_AHD;
            break;
        case SK_LMODE_AUTOFULL:
            Ctrl2 |= PHY_B_1000C_AFD;
            break;
        case SK_LMODE_AUTOBOTH:
            Ctrl2 |= PHY_B_1000C_AFD | PHY_B_1000C_AHD;
            break;
        default:
            SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT,
                SKERR_HWI_E015, SKERR_HWI_E015MSG);
        }

        switch (pPrt->PFlowCtrlMode) {
        case SK_FLOW_MODE_NONE:
            Ctrl3 |= PHY_B_P_NO_PAUSE;
            break;
        case SK_FLOW_MODE_LOC_SEND:
            Ctrl3 |= PHY_B_P_ASYM_MD;
            break;
        case SK_FLOW_MODE_SYMMETRIC:
            Ctrl3 |= PHY_B_P_SYM_MD;
            break;
        case SK_FLOW_MODE_SYM_OR_REM:
            Ctrl3 |= PHY_B_P_BOTH_MD;
            break;
        default:
            SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT,
                SKERR_HWI_E016, SKERR_HWI_E016MSG);
        }

        /* Restart Autonegotiation */
        Ctrl1 |= PHY_CT_ANE | PHY_CT_RE_CFG;

    }
    
    /* Initialize LED register here? */
    /* No. Please do it in SkDgXmitLed() (if required) and swap
       init order of LEDs and XMAC. (MAl) */
    
    /* Write 1000Base-T Control Register */
    PHY_WRITE(IoC, pPrt, Port, PHY_BCOM_1000T_CTRL, Ctrl2);
    SK_DBG_MSG(pAC,SK_DBGMOD_HWM,SK_DBGCAT_CTRL,
        ("1000Base-T Control Reg = %x\n", Ctrl2));
    
    /* Write AutoNeg Advertisement Register */
    PHY_WRITE(IoC, pPrt, Port, PHY_BCOM_AUNE_ADV, Ctrl3);
    SK_DBG_MSG(pAC,SK_DBGMOD_HWM,SK_DBGCAT_CTRL,
        ("AutoNeg Advertisment Reg = %x\n", Ctrl3));
    

    if (DoLoop) {
        /* Set the Phy Loopback bit, too */
        Ctrl1 |= PHY_CT_LOOP;
    }

    if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
        /* configure fifo to high latency for xmission of ext. packets*/
        Ctrl4 |= PHY_B_PEC_HIGH_LA;

        /* configure reception of extended packets */
        Ctrl5 |= PHY_B_AC_LONG_PACK;

        PHY_WRITE(IoC, pPrt, Port, PHY_BCOM_AUX_CTRL, Ctrl5);
    }

    /* Configure LED Traffic Mode and Jumbo Frame usage if specified */
    PHY_WRITE(IoC, pPrt, Port, PHY_BCOM_P_EXT_CTRL, Ctrl4);
    
    /* Write to the Phy control register */
    PHY_WRITE(IoC, pPrt, Port, PHY_BCOM_CTRL, Ctrl1);
    SK_DBG_MSG(pAC,SK_DBGMOD_HWM,SK_DBGCAT_CTRL,
        ("PHY Control Reg = %x\n", Ctrl1));
}    /* SkXmInitPhyBcom */


/******************************************************************************
 *
 *    SkXmInitPhyLone() - Initialize the Level One Phy registers
 *
 * Description:
 *    Initialize all the Level One Phy registers
 *
 * Note:
 *
 * Returns:
 *    nothing
 */
static void SkXmInitPhyLone(
SK_AC    *pAC,        /* adapter context */
SK_IOC    IoC,        /* IO context */
int        Port,        /* Port Index (MAC_1 + n) */
SK_BOOL    DoLoop)        /* Should a Phy LOOback be set-up? */
{
    SK_GEPORT    *pPrt;
    SK_U16        Ctrl1;
    SK_U16        Ctrl2;
    SK_U16        Ctrl3;

    Ctrl1 = PHY_L_CT_SP1000;
    Ctrl2 = 0;
    Ctrl3 = PHY_SEL_TYPE;

    pPrt = &pAC->GIni.GP[Port];

    /* manually Master/Slave ? */
    if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
        Ctrl2 |= PHY_L_1000C_MSE;
        if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
            Ctrl2 |= PHY_L_1000C_MSC;
        }
    }
    /* Autonegotiation ? */
    if (pPrt->PLinkMode == SK_LMODE_HALF ||
        pPrt->PLinkMode == SK_LMODE_FULL) {
        /*
         * level one spec say: "1000Mbps: manual mode not allowed"
         * but lets see what happens...
         */
        SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT,
            0, "Level One PHY only works with Autoneg");
        SK_DBG_MSG(pAC,SK_DBGMOD_HWM,SK_DBGCAT_CTRL,
            ("InitPhyLone: no autonegotiation Port %d\n", Port));
        /* No Autonegiotiation */
        /* Set DuplexMode in Config register */
        Ctrl1 = (pPrt->PLinkMode == SK_LMODE_FULL ? PHY_CT_DUP_MD : 0);

        /* Determine Master/Slave manually if not already done. */
        if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
            Ctrl2 |= PHY_L_1000C_MSE;    /* set it to Slave */
        }

        /*
         * Do NOT enable Autonegotiation here. This would hold
         * the link down because no IDLES are transmitted
         */
    }
    else {
        SK_DBG_MSG(pAC,SK_DBGMOD_HWM,SK_DBGCAT_CTRL,
            ("InitPhyLone: with autonegotiation Port %d\n", Port));
        /* Set Autonegotiation advertisement */

        /* Set Full/half duplex capabilities */
        switch (pPrt->PLinkMode) {
        case SK_LMODE_AUTOHALF:
            Ctrl2 |= PHY_L_1000C_AHD;
            break;
        case SK_LMODE_AUTOFULL:
            Ctrl2 |= PHY_L_1000C_AFD;
            break;
        case SK_LMODE_AUTOBOTH:
            Ctrl2 |= PHY_L_1000C_AFD | PHY_L_1000C_AHD;
            break;
        default:
            SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT,
                SKERR_HWI_E015, SKERR_HWI_E015MSG);
        }

        switch (pPrt->PFlowCtrlMode) {
        case SK_FLOW_MODE_NONE:
            Ctrl3 |= PHY_L_P_NO_PAUSE;
            break;
        case SK_FLOW_MODE_LOC_SEND:
            Ctrl3 |= PHY_L_P_ASYM_MD;
            break;
        case SK_FLOW_MODE_SYMMETRIC:
            Ctrl3 |= PHY_L_P_SYM_MD;
            break;
        case SK_FLOW_MODE_SYM_OR_REM:
            Ctrl3 |= PHY_L_P_BOTH_MD;
            break;
        default:
            SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT,
                SKERR_HWI_E016, SKERR_HWI_E016MSG);
        }

        /* Restart Autonegotiation */
        Ctrl1 = PHY_CT_ANE | PHY_CT_RE_CFG;

    }
    
    /* Initialize LED register here ? */
    /* No. Please do it in SkDgXmitLed() (if required) and swap
       init order of LEDs and XMAC. (MAl) */
    
    /* Write 1000Base-T Control Register */
    PHY_WRITE(IoC, pPrt, Port, PHY_LONE_1000T_CTRL, Ctrl2);
    SK_DBG_MSG(pAC,SK_DBGMOD_HWM,SK_DBGCAT_CTRL,
        ("1000Base-T Control Reg = %x\n", Ctrl2));
    
    /* Write AutoNeg Advertisement Register */
    PHY_WRITE(IoC, pPrt, Port, PHY_LONE_AUNE_ADV, Ctrl3);
    SK_DBG_MSG(pAC,SK_DBGMOD_HWM,SK_DBGCAT_CTRL,
        ("AutoNeg Advertisment Reg = %x\n", Ctrl3));
    

    if (DoLoop) {
        /* Set the Phy Loopback bit, too */
        Ctrl1 |= PHY_CT_LOOP;
    }

    if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
        /*
         * nothing to do for Level one.
         * PHY supports frames up to 10k.
         */
    }
    
    /* Write to the Phy control register */
    PHY_WRITE(IoC, pPrt, Port, PHY_LONE_CTRL, Ctrl1);
    SK_DBG_MSG(pAC,SK_DBGMOD_HWM,SK_DBGCAT_CTRL,
        ("PHY Control Reg = %x\n", Ctrl1));
}    /* SkXmInitPhyLone*/


/******************************************************************************
 *
 *    SkXmInitPhyNat() - Initialize the National Phy registers
 *
 * Description:
 *    Initialize all the National Phy registers
 *
 * Note:
 *
 * Returns:
 *    nothing
 */
static void SkXmInitPhyNat(
SK_AC    *pAC,        /* adapter context */
SK_IOC    IoC,        /* IO context */
int        Port,        /* Port Index (MAC_1 + n) */
SK_BOOL    DoLoop)        /* Should a Phy LOOback be set-up? */
{
/* todo: National */
}    /* SkXmInitPhyNat*/


/******************************************************************************
 *
 *    SkXmAutoNegLipaXmac() - Decides whether Link Partner could do autoneg
 *
 *    This function analyses the Interrupt status word. If any of the
 *    Autonegotiating interrupt bits are set, the PLipaAutoNeg variable
 *    is set true.
 */
void    SkXmAutoNegLipaXmac(
SK_AC    *pAC,        /* adapter context */
SK_IOC    IoC,        /* IO context */
int        Port,        /* Port Index (MAC_1 + n) */
SK_U16    IStatus)    /* Interrupt Status word to analyse */
{
    SK_GEPORT    *pPrt;

    pPrt = &pAC->GIni.GP[Port];

    if (pPrt->PLipaAutoNeg != SK_LIPA_AUTO &&
        (IStatus & (XM_IS_LIPA_RC|XM_IS_RX_PAGE|XM_IS_AND))) {

        SK_DBG_MSG(pAC,SK_DBGMOD_HWM,SK_DBGCAT_CTRL,
            ("AutoNegLipa: AutoNeg detected on port %d %x\n", Port, IStatus));
        pPrt->PLipaAutoNeg = SK_LIPA_AUTO;
    }
}    /* SkXmAutoNegLipaXmac*/


/******************************************************************************
 *
 *    SkXmAutoNegLipaBcom() - Decides whether Link Partner could do autoneg
 *
 *    This function analyses the PHY status word. If any of the
 *    Autonegotiating bits are set, The PLipaAutoNeg variable
 *    is set true.
 */
void    SkXmAutoNegLipaBcom(
SK_AC    *pAC,        /* adapter context */
SK_IOC    IoC,        /* IO context */
int        Port,        /* Port Index (MAC_1 + n) */
SK_U16    PhyStat)    /* PHY Status word to analyse */
{
    SK_GEPORT    *pPrt;

    pPrt = &pAC->GIni.GP[Port];

    if (pPrt->PLipaAutoNeg != SK_LIPA_AUTO && (PhyStat & PHY_ST_AN_OVER)) {
        SK_DBG_MSG(pAC,SK_DBGMOD_HWM,SK_DBGCAT_CTRL,
            ("AutoNegLipa: AutoNeg detected on port %d %x\n", Port, PhyStat));
        pPrt->PLipaAutoNeg = SK_LIPA_AUTO;
    }
}    /* SkXmAutoNegLipaBcom*/


/******************************************************************************
 *
 *    SkXmAutoNegLipaLone() - Decides whether Link Partner could do autoneg
 *
 *    This function analyses the PHY status word. If any of the
 *    Autonegotiating bits are set, The PLipaAutoNeg variable
 *    is set true.
 */
void    SkXmAutoNegLipaLone(
SK_AC    *pAC,        /* adapter context */
SK_IOC    IoC,        /* IO context */
int    Port,        /* Port Index (MAC_1 + n) */
SK_U16    PhyStat)    /* PHY Status word to analyse */
{
    SK_GEPORT    *pPrt;

    pPrt = &pAC->GIni.GP[Port];

    if (pPrt->PLipaAutoNeg != SK_LIPA_AUTO &&
        (PhyStat & (PHY_ST_AN_OVER))) {

        SK_DBG_MSG(pAC,SK_DBGMOD_HWM,SK_DBGCAT_CTRL,
            ("AutoNegLipa: AutoNeg detected on port %d %x\n", Port, PhyStat));
        pPrt->PLipaAutoNeg = SK_LIPA_AUTO;
    }
}    /* SkXmAutoNegLipaLone*/


/******************************************************************************
 *
 *    SkXmAutoNegLipaNat() - Decides whether Link Partner could do autoneg
 *
 *    This function analyses the PHY status word. If any of the
 *    Autonegotiating bits are set, The PLipaAutoNeg variable
 *    is set true.
 */
void    SkXmAutoNegLipaNat(
SK_AC    *pAC,        /* adapter context */
SK_IOC    IoC,        /* IO context */
int        Port,        /* Port Index (MAC_1 + n) */
SK_U16    PhyStat)    /* PHY Status word to analyse */
{
    SK_GEPORT    *pPrt;

    pPrt = &pAC->GIni.GP[Port];

    if (pPrt->PLipaAutoNeg != SK_LIPA_AUTO &&
        (PhyStat & (PHY_ST_AN_OVER))) {

        SK_DBG_MSG(pAC,SK_DBGMOD_HWM,SK_DBGCAT_CTRL,
            ("AutoNegLipa: AutoNeg detected on port %d %x\n", Port, PhyStat));
        pPrt->PLipaAutoNeg = SK_LIPA_AUTO;
    }
}    /* SkXmAutoNegLipaNat*/


/******************************************************************************
 *
 *    SkXmAutoNegDone() - Auto negotiation handling
 *
 * Description:
 *    This function handles the autonegotiation if the Done bit is set.
 *
 * Note:
 *    o The XMACs interrupt source register is NOT read here.
 *    o This function is public because it is used in the diagnostics
 *      tool, too.
 *
 * Returns:
 *    SK_AND_OK    o.k.
 *    SK_AND_DUP_CAP     Duplex capability error happened
 *    SK_AND_OTHER     Other error happened
 */
int    SkXmAutoNegDone(
SK_AC    *pAC,        /* adapter context */
SK_IOC    IoC,        /* IO context */
int        Port)        /* Port Index (MAC_1 + n) */
{
    switch (pAC->GIni.GP[Port].PhyType) {
    case SK_PHY_XMAC:
        return (SkXmAutoNegDoneXmac(pAC, IoC, Port));
    case SK_PHY_BCOM:
        return (SkXmAutoNegDoneBcom(pAC, IoC, Port));
    case SK_PHY_LONE:
        return (SkXmAutoNegDoneLone(pAC, IoC, Port));
    case SK_PHY_NAT:
        return (SkXmAutoNegDoneNat(pAC, IoC, Port));
    }
    return (SK_AND_OTHER);
}    /* SkXmAutoNegDone*/


/******************************************************************************
 *
 *    SkXmAutoNegDoneXmac() - Auto negotiation handling
 *
 * Description:
 *    This function handles the autonegotiation if the Done bit is set.
 *
 * Note:
 *    o The XMACs interrupt source register is NOT read here.
 *
 * Returns:
 *    SK_AND_OK    o.k.
 *    SK_AND_DUP_CAP     Duplex capability error happened
 *    SK_AND_OTHER     Other error happened
 */
static int    SkXmAutoNegDoneXmac(
SK_AC    *pAC,        /* adapter context */
SK_IOC    IoC,        /* IO context */
int        Port)        /* Port Index (MAC_1 + n) */
{
    SK_GEPORT    *pPrt;
    SK_U16        ResAb;        /* Resolved Ability */
    SK_U16        LPAb;        /* Link Partner Ability */

    SK_DBG_MSG(pAC,SK_DBGMOD_HWM,SK_DBGCAT_CTRL, ("AutoNegDoneXmac"
        "Port %d\n",Port));

    pPrt = &pAC->GIni.GP[Port];

    /* Get PHY parameters */
    PHY_READ(IoC, pPrt, Port, PHY_XMAC_AUNE_LP, &LPAb);
    PHY_READ(IoC, pPrt, Port, PHY_XMAC_RES_ABI, &ResAb);

    if (LPAb & PHY_X_AN_RFB) {
        /* At least one of the remote fault bit is set */
        /* Error */
        SK_DBG_MSG(pAC,SK_DBGMOD_HWM,SK_DBGCAT_CTRL,
            ("AutoNegFail: Remote fault bit set Port %d\n", Port));
        pPrt->PAutoNegFail = SK_TRUE;
        return (SK_AND_OTHER);
    }

    /* Check Duplex mismatch */
    if ((ResAb & (PHY_X_RS_HD | PHY_X_RS_FD)) == PHY_X_RS_FD) {
        pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOFULL;
    }
    else if ((ResAb & (PHY_X_RS_HD | PHY_X_RS_FD)) == PHY_X_RS_HD) {
        pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOHALF;
    }
    else {
        /* Error */
        SK_DBG_MSG(pAC,SK_DBGMOD_HWM,SK_DBGCAT_CTRL,
            ("AutoNegFail: Duplex mode mismatch port %d\n", Port));
        pPrt->PAutoNegFail = SK_TRUE;
        return (SK_AND_DUP_CAP);
    }

    /* Check PAUSE mismatch */
    /* We are NOT using chapter 4.23 of the Xaqti manual */
    /* We are using IEEE 802.3z/D5.0 Table 37-4 */
    if ((pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYMMETRIC ||
         pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM) &&
        (LPAb & PHY_X_P_SYM_MD)) {
        /* Symmetric PAUSE */
        pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
    }
    else if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM &&
           (LPAb & PHY_X_RS_PAUSE) == PHY_X_P_ASYM_MD) {
        /* Enable PAUSE receive, disable PAUSE transmit */
        pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
    }
    else if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_LOC_SEND &&
           (LPAb & PHY_X_RS_PAUSE) == PHY_X_P_BOTH_MD) {
        /* Disable PAUSE receive, enable PAUSE transmit */
        pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
    }
    else {
        /* PAUSE mismatch -> no PAUSE */
        pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
    }

    /* We checked everything and may now enable the link */
    pPrt->PAutoNegFail = SK_FALSE;

    SkXmRxTxEnable(pAC, IoC, Port);
    return (SK_AND_OK);
}    /* SkXmAutoNegDoneXmac*/


/******************************************************************************
 *
 *    SkXmAutoNegDoneBcom() - Auto negotiation handling
 *
 * Description:
 *    This function handles the autonegotiation if the Done bit is set.
 *
 * Note:
 *    o The XMACs interrupt source register is NOT read here.
 *
 * Returns:
 *    SK_AND_OK    o.k.
 *    SK_AND_DUP_CAP     Duplex capability error happened
 *    SK_AND_OTHER     Other error happened
 */
static int    SkXmAutoNegDoneBcom(
SK_AC    *pAC,        /* adapter context */
SK_IOC    IoC,        /* IO context */
int        Port)        /* Port Index (MAC_1 + n) */
{
    SK_GEPORT    *pPrt;
    SK_U16        LPAb;        /* Link Partner Ability */
    SK_U16        AuxStat;    /* Auxiliary Status */

#if 0
01-Sep-2000 RA;:;:
    SK_U16        ResAb;        /* Resolved Ability */
#endif    /* 0 */

    SK_DBG_MSG(pAC,SK_DBGMOD_HWM,SK_DBGCAT_CTRL,
        ("AutoNegDoneBcom, Port %d\n", Port));
    pPrt = &pAC->GIni.GP[Port];

    /* Get PHY parameters. */
    PHY_READ(IoC, pPrt, Port, PHY_BCOM_AUNE_LP, &LPAb);
#if 0
01-Sep-2000 RA;:;:
    PHY_READ(IoC, pPrt, Port, PHY_BCOM_1000T_STAT, &ResAb);
#endif    /* 0 */
    PHY_READ(IoC, pPrt, Port, PHY_BCOM_AUX_STAT, &AuxStat);

    if (LPAb & PHY_B_AN_RF) {
        /* Remote fault bit is set: Error. */
        SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
            ("AutoNegFail: Remote fault bit set Port %d\n", Port));
        pPrt->PAutoNegFail = SK_TRUE;
        return (SK_AND_OTHER);
    }

    /* Check Duplex mismatch. */
    if ((AuxStat & PHY_B_AS_AN_RES) == PHY_B_RES_1000FD) {
        pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOFULL;
    }
    else if ((AuxStat & PHY_B_AS_AN_RES) == PHY_B_RES_1000HD) {
        pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOHALF;
    }
    else {
        /* Error. */
        SK_DBG_MSG(pAC,SK_DBGMOD_HWM,SK_DBGCAT_CTRL,
            ("AutoNegFail: Duplex mode mismatch port %d\n", Port));
        pPrt->PAutoNegFail = SK_TRUE;
        return (SK_AND_DUP_CAP);
    }
    
#if 0
01-Sep-2000 RA;:;:
    /* Check Master/Slave resolution. */
    if (ResAb & PHY_B_1000S_MSF) {
        /* Error. */
        SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
            ("Master/Slave Fault port %d\n", Port));
        pPrt->PAutoNegFail = SK_TRUE;
        pPrt->PMSStatus = SK_MS_STAT_FAULT;
        return (SK_AND_OTHER);
    }
    else if (ResAb & PHY_B_1000S_MSR) {
        pPrt->PMSStatus = SK_MS_STAT_MASTER;
    }
    else {
        pPrt->PMSStatus = SK_MS_STAT_SLAVE;
    }
#endif    /* 0 */

    /* Check PAUSE mismatch. */
    /* We are NOT using chapter 4.23 of the Xaqti manual. */
    /* We are using IEEE 802.3z/D5.0 Table 37-4. */
    if ((AuxStat & (PHY_B_AS_PRR | PHY_B_AS_PRT)) == 
        (PHY_B_AS_PRR | PHY_B_AS_PRT)) {
        /* Symmetric PAUSE. */
        pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
    }
    else if ((AuxStat & (PHY_B_AS_PRR | PHY_B_AS_PRT)) == PHY_B_AS_PRR) {
        /* Enable PAUSE receive, disable PAUSE transmit. */
        pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
    }
    else if ((AuxStat & (PHY_B_AS_PRR | PHY_B_AS_PRT)) == PHY_B_AS_PRT) {
        /* Disable PAUSE receive, enable PAUSE transmit. */
        pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
    }
    else {
        /* PAUSE mismatch -> no PAUSE. */
        pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
    }

    /* We checked everything and may now enable the link. */
    pPrt->PAutoNegFail = SK_FALSE;

    SkXmRxTxEnable(pAC, IoC, Port);
    return (SK_AND_OK);
}    /* SkXmAutoNegDoneBcom*/


/******************************************************************************
 *
 *    SkXmAutoNegDoneLone() - Auto negotiation handling
 *
 * Description:
 *    This function handles the autonegotiation if the Done bit is set.
 *
 * Note:
 *    o The XMACs interrupt source register is NOT read here.
 *
 * Returns:
 *    SK_AND_OK    o.k.
 *    SK_AND_DUP_CAP     Duplex capability error happened
 *    SK_AND_OTHER     Other error happened
 */
static int    SkXmAutoNegDoneLone(
SK_AC    *pAC,        /* adapter context */
SK_IOC    IoC,        /* IO context */
int        Port)        /* Port Index (MAC_1 + n) */
{
    SK_GEPORT    *pPrt;
    SK_U16        ResAb;        /* Resolved Ability */
    SK_U16        LPAb;        /* Link Partner Ability */
    SK_U16        QuickStat;    /* Auxiliary Status */

    SK_DBG_MSG(pAC,SK_DBGMOD_HWM,SK_DBGCAT_CTRL, ("AutoNegDoneLone"
        "Port %d\n",Port));
    pPrt = &pAC->GIni.GP[Port];

    /* Get PHY parameters */
    PHY_READ(IoC, pPrt, Port, PHY_LONE_AUNE_LP, &LPAb);
    PHY_READ(IoC, pPrt, Port, PHY_LONE_1000T_STAT, &ResAb);
    PHY_READ(IoC, pPrt, Port, PHY_LONE_Q_STAT, &QuickStat);

    if (LPAb & PHY_L_AN_RF) {
        /* Remote fault bit is set */
        /* Error */
        SK_DBG_MSG(pAC,SK_DBGMOD_HWM,SK_DBGCAT_CTRL,
            ("AutoNegFail: Remote fault bit set Port %d\n", Port));
        pPrt->PAutoNegFail = SK_TRUE;
        return (SK_AND_OTHER);
    }

    /* Check Duplex mismatch */
    if (QuickStat & PHY_L_QS_DUP_MOD) {
        pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOFULL;
    }
    else {
        pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOHALF;
    }
    
    /* Check Master/Slave resolution */
    if (ResAb & (PHY_L_1000S_MSF)) {
        /* Error */
        SK_DBG_MSG(pAC,SK_DBGMOD_HWM,SK_DBGCAT_CTRL,
            ("Master/Slave Fault port %d\n", Port));
        pPrt->PAutoNegFail = SK_TRUE;
        pPrt->PMSStatus = SK_MS_STAT_FAULT;
        return (SK_AND_OTHER);
    }
    else if (ResAb & PHY_L_1000S_MSR) {
        pPrt->PMSStatus = SK_MS_STAT_MASTER;
    }
    else {
        pPrt->PMSStatus = SK_MS_STAT_SLAVE;
    }

    /* Check PAUSE mismatch */
    /* We are NOT using chapter 4.23 of the Xaqti manual */
    /* We are using IEEE 802.3z/D5.0 Table 37-4 */
    /* we must manually resolve the abilities here */
    pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
    switch (pPrt->PFlowCtrlMode) {
    case SK_FLOW_MODE_NONE:
        /* default */
        break;
    case SK_FLOW_MODE_LOC_SEND:
        if ((QuickStat & (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) ==
            (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) {
            /* Disable PAUSE receive, enable PAUSE transmit */
            pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
        }
        break;
    case SK_FLOW_MODE_SYMMETRIC:
        if ((QuickStat & PHY_L_QS_PAUSE) == PHY_L_QS_PAUSE) {
            /* Symmetric PAUSE */
            pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
        }
        break;
    case SK_FLOW_MODE_SYM_OR_REM:
        if ((QuickStat & (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) ==
            PHY_L_QS_AS_PAUSE) {
            /* Enable PAUSE receive, disable PAUSE transmit */
            pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
        }
        else if ((QuickStat & PHY_L_QS_PAUSE) == PHY_L_QS_PAUSE) {
            /* Symmetric PAUSE */
            pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
        }
        break;
    default:
        SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT,
            SKERR_HWI_E016, SKERR_HWI_E016MSG);
    }

    /* We checked everything and may now enable the link */
    pPrt->PAutoNegFail = SK_FALSE;

    SkXmRxTxEnable(pAC, IoC, Port);
    return (SK_AND_OK);
}    /* SkXmAutoNegDoneLone */


/******************************************************************************
 *
 *    SkXmAutoNegDoneNat() - Auto negotiation handling
 *
 * Description:
 *    This function handles the autonegotiation if the Done bit is set.
 *
 * Note:
 *    o The XMACs interrupt source register is NOT read here.
 *    o This function is public because it is used in the diagnostics
 *      tool, too.
 *
 * Returns:
 *    SK_AND_OK    o.k.
 *    SK_AND_DUP_CAP     Duplex capability error happened
 *    SK_AND_OTHER     Other error happened
 */
static int    SkXmAutoNegDoneNat(
SK_AC    *pAC,        /* adapter context */
SK_IOC    IoC,        /* IO context */
int        Port)        /* Port Index (MAC_1 + n) */
{
/* todo: National */
    return (SK_AND_OK);
}    /* SkXmAutoNegDoneNat*/


/******************************************************************************
 *
 *    SkXmRxTxEnable() - Enable RxTx activity if port is up
 *
 * Description:
 *
 * Note:
 *    o The XMACs interrupt source register is NOT read here.
 *
 * Returns:
 *    0    o.k.
 *    != 0    Error happened
 */
int SkXmRxTxEnable(
SK_AC    *pAC,        /* adapter context */
SK_IOC    IoC,        /* IO context */
int        Port)        /* Port Index (MAC_1 + n) */
{
    SK_GEPORT    *pPrt;
    SK_U16        Reg;        /* 16bit register value */
    SK_U16        IntMask;    /* XMac interrupt mask */
    SK_U16        SWord;

    pPrt = &pAC->GIni.GP[Port];

    if (!pPrt->PHWLinkUp) {
        /* The Hardware link is NOT up */
        return (0);
    }

    if ((pPrt->PLinkMode == SK_LMODE_AUTOHALF ||
         pPrt->PLinkMode == SK_LMODE_AUTOFULL ||
         pPrt->PLinkMode == SK_LMODE_AUTOBOTH) &&
         pPrt->PAutoNegFail) {
        /* Autonegotiation is not done or failed */
        return (0);
    }

    /* Set Dup Mode and Pause Mode */
    SkXmInitDupMd (pAC, IoC, Port);
    SkXmInitPauseMd (pAC, IoC, Port);

    /*
     * Initialize the Interrupt Mask Register. Default IRQs are...
     *    - Link Asynchronous Event
     *    - Link Partner requests config
     *    - Auto Negotiation Done
     *    - Rx Counter Event Overflow
     *    - Tx Counter Event Overflow
     *    - Transmit FIFO Underrun
     */
    if (pPrt->PhyType == SK_PHY_XMAC) {
        IntMask = XM_DEF_MSK;
    }
    else {
        /* disable GP0 interrupt bit */
        IntMask = XM_DEF_MSK | XM_IS_INP_ASS;
    }
    XM_OUT16(IoC, Port, XM_IMSK, IntMask);

    /* RX/TX enable */
    XM_IN16(IoC, Port, XM_MMU_CMD, &Reg);
    if (pPrt->PhyType != SK_PHY_XMAC &&
        (pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL || 
         pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL)) {
        Reg |= XM_MMU_GMII_FD;
    }
    switch (pPrt->PhyType) {
    case SK_PHY_BCOM:
        /* Workaround BCOM Errata (#10523) for all BCom Phys */
        /* Enable Power Management after link up */
        PHY_READ(IoC, pPrt, Port, PHY_BCOM_AUX_CTRL, &SWord);
        PHY_WRITE(IoC, pPrt, Port, PHY_BCOM_AUX_CTRL, SWord & ~PHY_B_AC_DIS_PM);
        PHY_WRITE(IoC, pPrt, Port, PHY_BCOM_INT_MASK, PHY_B_DEF_MSK);
        break;
    case SK_PHY_LONE:
        PHY_WRITE(IoC, pPrt, Port, PHY_LONE_INT_ENAB, PHY_L_DEF_MSK);
        break;
    case SK_PHY_NAT:
        /* todo National:
        PHY_WRITE(IoC, pPrt, Port, PHY_NAT_INT_MASK, 
            PHY_N_DEF_MSK); */
        /* no interrupts possible from National ??? */
        break;
    }
    XM_OUT16(IoC, Port, XM_MMU_CMD, Reg | XM_MMU_ENA_RX | XM_MMU_ENA_TX);
                      
    return (0);
}    /* SkXmRxTxEnable*/

#ifndef SK_DIAG

/******************************************************************************
 *
 *    SkXmIrq() - Interrupt service routine
 *
 * Description:
 *    Services an Interrupt of the XMAC II
 *
 * Note:
 *    The XMACs interrupt source register is NOT read here.
 *    With an external PHY, some interrupt bits are not meaningfull
 *    any more:
 *    - LinkAsyncEvent (bit #14)              XM_IS_LNK_AE
 *    - LinkPartnerReqConfig (bit #10)    XM_IS_LIPA_RC
 *    - Page Received (bit #9)        XM_IS_RX_PAGE
 *    - NextPageLoadedForXmt (bit #8)        XM_IS_TX_PAGE
 *    - AutoNegDone (bit #7)            XM_IS_AND
 *    Also probably not valid any more is the GP0 input bit:
 *    - GPRegisterBit0set            XM_IS_INP_ASS
 *
 * Returns:
 *    nothing
 */
void SkXmIrq(
SK_AC    *pAC,        /* adapter context */
SK_IOC    IoC,        /* IO context */
int        Port,        /* Port Index (MAC_1 + n) */
SK_U16    IStatus)    /* Interrupt status read from the XMAC */
{
    SK_GEPORT    *pPrt;
    SK_EVPARA    Para;
    SK_U16        IStatus2;

    pPrt = &pAC->GIni.GP[Port];
    
    if (pPrt->PhyType != SK_PHY_XMAC) {
        /* mask bits that are not used with ext. PHY */
        IStatus &= ~(XM_IS_LNK_AE | XM_IS_LIPA_RC |
            XM_IS_RX_PAGE | XM_IS_TX_PAGE |
            XM_IS_AND | XM_IS_INP_ASS);
    }
    
    /*
     * LinkPartner Autonegable?
     */
    if (pPrt->PhyType == SK_PHY_XMAC) {
        SkXmAutoNegLipaXmac(pAC, IoC, Port, IStatus);
    }

    SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
        ("XmacIrq Port %d Isr %x\n", Port, IStatus));

    if (!pPrt->PHWLinkUp) {
        /* Spurious XMAC interrupt */
        SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
            ("SkXmIrq: spurious interrupt on port %d\n", Port));
        return;
    }

    if (IStatus & XM_IS_INP_ASS) {
        /* Reread ISR Register if link is not in sync */
        XM_IN16(IoC, Port, XM_ISRC, &IStatus2);

        SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
            ("SkXmIrq: Link async. Double check port %d %x %x\n",
             Port, IStatus, IStatus2));
        IStatus &= ~XM_IS_INP_ASS;
        IStatus |= IStatus2;

    }

    if (IStatus & XM_IS_LNK_AE) {
        /* not used GP0 is used instead */
    }

    if (IStatus & XM_IS_TX_ABORT) {
        /* not used */
    }

    if (IStatus & XM_IS_FRC_INT) {
        /* not used. use ASIC IRQ instead if needed */
    }

    if (IStatus & (XM_IS_INP_ASS | XM_IS_LIPA_RC | XM_IS_RX_PAGE)) {
        SkHWLinkDown(pAC, IoC, Port);

        /* Signal to RLMT */
        Para.Para32[0] = (SK_U32) Port;
        SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);

        /* Start workaround Errata #2 timer */
        SkTimerStart(pAC, IoC, &pAC->GIni.GP[Port].PWaTimer,
            SK_WA_INA_TIME, SKGE_HWAC, SK_HWEV_WATIM, Para);
    }

    if (IStatus & XM_IS_RX_PAGE) {
        /* not used */
    }

    if (IStatus & XM_IS_TX_PAGE) {
        /* not used */
    }

    if (IStatus & XM_IS_AND) {
        SK_DBG_MSG(pAC,SK_DBGMOD_HWM,SK_DBGCAT_IRQ,
            ("SkXmIrq: AND on link that is up port %d\n", Port));
    }

    if (IStatus & XM_IS_TSC_OV) {
        /* not used */
    }

    if (IStatus & XM_IS_RXC_OV) {
        Para.Para32[0] = (SK_U32) Port;
        Para.Para32[1] = (SK_U32) IStatus;
        SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_SIRQ_OVERFLOW, Para);
    }

    if (IStatus & XM_IS_TXC_OV) {
        Para.Para32[0] = (SK_U32) Port;
        Para.Para32[1] = (SK_U32) IStatus;
        SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_SIRQ_OVERFLOW, Para);
    }

    if (IStatus & XM_IS_RXF_OV) {
        /* normal situation -> no effect */
    }

    if (IStatus & XM_IS_TXF_UR) {
        /* may NOT happen -> error log */
        SK_ERR_LOG(pAC, SK_ERRCL_HW , SKERR_SIRQ_E020,
            SKERR_SIRQ_E020MSG);
    }

    if (IStatus & XM_IS_TX_COMP) {
        /* not served here */
    }

    if (IStatus & XM_IS_RX_COMP) {
        /* not served here */
    }

}    /* SkXmIrq*/

#endif /* !SK_DIAG */

/* End of file */

:: Command execute ::

Enter:
 
Select:
 

:: Search ::
  - regexp 

:: Upload ::
 
[ Read-Only ]

:: Make Dir ::
 
[ Read-Only ]
:: Make File ::
 
[ Read-Only ]

:: Go Dir ::
 
:: Go File ::
 

--[ c99shell v. 1.0 pre-release build #13 powered by Captain Crunch Security Team | http://ccteam.ru | Generation time: 0.0264 ]--