skxmac2.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:60k
- /******************************************************************************
- *
- * 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 %dn", 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 %dn", 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 %dn", 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 %dn", 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 = %xn", 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 = %xn", 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 = %xn", 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 %dn", 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 %dn", 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 = %xn", 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 = %xn", 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 = %xn", 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 %xn", 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 %xn", 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 %xn", 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 %xn", 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 %dn",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 %dn", 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 %dn", 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 %dn", 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 %dn", 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 %dn", 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 %dn", 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 %dn",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 %dn", 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 %dn", 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 %xn", Port, IStatus));
- if (!pPrt->PHWLinkUp) {
- /* Spurious XMAC interrupt */
- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
- ("SkXmIrq: spurious interrupt on port %dn", 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 %xn",
- 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 %dn", 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 */