patch-2.4.21 linux-2.4.21/drivers/net/sk98lin/skxmac2.c

Next file: linux-2.4.21/drivers/net/sk_g16.c
Previous file: linux-2.4.21/drivers/net/sk98lin/skvpd.c
Back to the patch index
Back to the overall index

diff -urN linux-2.4.20/drivers/net/sk98lin/skxmac2.c linux-2.4.21/drivers/net/sk98lin/skxmac2.c
@@ -2,15 +2,15 @@
  *
  * 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
+ * Version:	$Revision: 1.87 $
+ * Date:	$Date: 2002/12/10 14:39:05 $
+ * Purpose:	Contains functions to initialize the MACs and PHYs
  *
  ******************************************************************************/
 
 /******************************************************************************
  *
- *	(C)Copyright 1998-2001 SysKonnect GmbH.
+ *	(C)Copyright 1998-2002 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
@@ -26,6 +26,152 @@
  * History:
  *
  *	$Log: skxmac2.c,v $
+ *	Revision 1.87  2002/12/10 14:39:05  rschmidt
+ *	Improved initialization of GPHY in SkGmInitPhyMarv().
+ *	Editorial changes.
+ *	
+ *	Revision 1.86  2002/12/09 15:01:12  rschmidt
+ *	Added setup of Ext. PHY Specific Ctrl Reg (downshift feature).
+ *	
+ *	Revision 1.85  2002/12/05 14:09:16  rschmidt
+ *	Improved avoiding endless loop in SkGmPhyWrite(), SkGmPhyWrite().
+ *	Added additional advertising for 10Base-T when 100Base-T is selected.
+ *	Added case SK_PHY_MARV_FIBER for YUKON Fiber adapter.
+ *	Editorial changes.
+ *	
+ *	Revision 1.84  2002/11/15 12:50:09  rschmidt
+ *	Changed SkGmCableDiagStatus() when getting results.
+ *	
+ *	Revision 1.83  2002/11/13 10:28:29  rschmidt
+ *	Added some typecasts to avoid compiler warnings.
+ *	
+ *	Revision 1.82  2002/11/13 09:20:46  rschmidt
+ *	Replaced for(..) with do {} while (...) in SkXmUpdateStats().
+ *	Replaced 2 macros GM_IN16() with 1 GM_IN32() in SkGmMacStatistic().
+ *	Added SkGmCableDiagStatus() for Virtual Cable Test (VCT).
+ *	Editorial changes.
+ *	
+ *	Revision 1.81  2002/10/28 14:28:08  rschmidt
+ *	Changed MAC address setup for GMAC in SkGmInitMac().
+ *	Optimized handling of counter overflow IRQ in SkGmOverflowStatus().
+ *	Editorial changes.
+ *	
+ *	Revision 1.80  2002/10/14 15:29:44  rschmidt
+ *	Corrected disabling of all PHY IRQs.
+ *	Added WA for deviation #16 (address used for pause packets).
+ *	Set Pause Mode in SkMacRxTxEnable() only for Genesis.
+ *	Added IRQ and counter for Receive FIFO Overflow in DEBUG-mode.
+ *	SkXmTimeStamp() replaced by SkMacTimeStamp().
+ *	Added clearing of GMAC Tx FIFO Underrun IRQ in SkGmIrq().
+ *	Editorial changes.
+ *	
+ *	Revision 1.79  2002/10/10 15:55:36  mkarl
+ *	changes for PLinkSpeedUsed
+ *	
+ *	Revision 1.78  2002/09/12 09:39:51  rwahl
+ *	Removed deactivate code for SIRQ overflow event separate for TX/RX.
+ *	
+ *	Revision 1.77  2002/09/09 12:26:37  mkarl
+ *	added handling for Yukon to SkXmTimeStamp
+ *	
+ *	Revision 1.76  2002/08/21 16:41:16  rschmidt
+ *	Added bit GPC_ENA_XC (Enable MDI crossover) in HWCFG_MODE.
+ *	Added forced speed settings in SkGmInitPhyMarv().
+ *	Added settings of full/half duplex capabilities for YUKON Fiber.
+ *	Editorial changes.
+ *	
+ *	Revision 1.75  2002/08/16 15:12:01  rschmidt
+ *	Replaced all if(GIChipId == CHIP_ID_GENESIS) with new entry GIGenesis.
+ *	Added function SkMacHashing() for ADDR-Module.
+ *	Removed functions SkXmClrSrcCheck(), SkXmClrHashAddr() (calls replaced
+ *	with macros).
+ *	Removed functions SkGmGetMuxConfig().
+ *	Added HWCFG_MODE init for YUKON Fiber.
+ *	Changed initialization of GPHY in SkGmInitPhyMarv().
+ *	Changed check of parameter in SkXmMacStatistic().
+ *	Editorial changes.
+ *	
+ *	Revision 1.74  2002/08/12 14:00:17  rschmidt
+ *	Replaced usage of Broadcom PHY Ids with defines.
+ *	Corrected error messages in SkGmMacStatistic().
+ *	Made SkMacPromiscMode() public for ADDR-Modul.
+ *	Editorial changes.
+ *	
+ *	Revision 1.73  2002/08/08 16:26:24  rschmidt
+ *	Improved reset sequence for YUKON in SkGmHardRst() and SkGmInitMac().
+ *	Replaced XMAC Rx High Watermark init value with SK_XM_RX_HI_WM.
+ *	Editorial changes.
+ *	
+ *	Revision 1.72  2002/07/24 15:11:19  rschmidt
+ *	Fixed wrong placement of parenthesis.
+ *	Editorial changes.
+ *	
+ *	Revision 1.71  2002/07/23 16:05:18  rschmidt
+ *	Added global functions for PHY: SkGePhyRead(), SkGePhyWrite().
+ *	Fixed Tx Counter Overflow IRQ (Bug ID #10730).
+ *	Editorial changes.
+ *	
+ *	Revision 1.70  2002/07/18 14:27:27  rwahl
+ *	Fixed syntax error.
+ *	
+ *	Revision 1.69  2002/07/17 17:08:47  rwahl
+ *	Fixed check in SkXmMacStatistic().
+ *	
+ *	Revision 1.68  2002/07/16 07:35:24  rwahl
+ *	Removed check for cleared mib counter in SkGmResetCounter().
+ *	
+ *	Revision 1.67  2002/07/15 18:35:56  rwahl
+ *	Added SkXmUpdateStats(), SkGmUpdateStats(), SkXmMacStatistic(),
+ *	  SkGmMacStatistic(), SkXmResetCounter(), SkGmResetCounter(),
+ *	  SkXmOverflowStatus(), SkGmOverflowStatus().
+ *	Changes to SkXmIrq() & SkGmIrq(): Combined SIRQ Overflow for both
+ *	  RX & TX.
+ *	Changes to SkGmInitMac(): call to SkGmResetCounter().
+ *	Editorial changes.
+ *	
+ *	Revision 1.66  2002/07/15 15:59:30  rschmidt
+ *	Added PHY Address in SkXmPhyRead(), SkXmPhyWrite().
+ *	Added MIB Clear Counter in SkGmInitMac().
+ *	Added Duplex and Flow-Control settings.
+ *	Reset all Multicast filtering Hash reg. in SkGmInitMac().
+ *	Added new function: SkGmGetMuxConfig().
+ *	Editorial changes.
+ *	
+ *	Revision 1.65  2002/06/10 09:35:39  rschmidt
+ *	Replaced C++ comments (//).
+ *	Added #define VCPU around VCPUwaitTime.
+ *	Editorial changes.
+ *	
+ *	Revision 1.64  2002/06/05 08:41:10  rschmidt
+ *	Added function for XMAC2: SkXmTimeStamp().
+ *	Added function for YUKON: SkGmSetRxCmd().
+ *	Changed SkGmInitMac() resp. SkGmHardRst().
+ *	Fixed wrong variable in SkXmAutoNegLipaXmac() (debug mode).
+ *	SkXmRxTxEnable() replaced by SkMacRxTxEnable().
+ *	Editorial changes.
+ *	
+ *	Revision 1.63  2002/04/25 13:04:44  rschmidt
+ *	Changes for handling YUKON.
+ *	Use of #ifdef OTHER_PHY to eliminate code for unused Phy types.
+ *	Macros for XMAC PHY access PHY_READ(), PHY_WRITE() replaced
+ *	by functions SkXmPhyRead(), SkXmPhyWrite();
+ *	Removed use of PRxCmd to setup XMAC.
+ *	Added define PHY_B_AS_PAUSE_MSK for BCom Pause Res.
+ *	Added setting of XM_RX_DIS_CEXT in SkXmInitMac().
+ *	Removed status parameter from MAC IRQ handler SkMacIrq(),
+ *	SkXmIrq() and SkGmIrq().
+ *	SkXmAutoNegLipa...() for ext. Phy replaced by SkMacAutoNegLipaPhy().
+ *	Added SkMac...() functions to handle both XMAC and GMAC.
+ *	Added functions for YUKON: SkGmHardRst(), SkGmSoftRst(),
+ *	SkGmSetRxTxEn(), SkGmIrq(), SkGmInitMac(), SkGmInitPhyMarv(),
+ *	SkGmAutoNegDoneMarv(), SkGmPhyRead(), SkGmPhyWrite().
+ *	Changes for V-CPU support.
+ *	Editorial changes.
+ *	
+ *	Revision 1.62  2001/08/06 09:50:14  rschmidt
+ *	Workaround BCOM Errata #1 for the C5 type.
+ *	Editorial changes.
+ *	
  *	Revision 1.61  2001/02/09 15:40:59  rassmann
  *	Editorial changes.
  *	
@@ -194,7 +340,7 @@
  *
  *	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
+ *	SKERR_HWI_Exx and SKERR_HWI_E0xxMSG to be independent
  *	from the Sirq module.
  *
  *	Revision 1.11  1998/10/14 13:59:01  gklug
@@ -203,17 +349,16 @@
  *	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.
+ *	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
+ *	add: auto-negotiation done function
  *
  *	Revision 1.7  1998/10/09 06:55:20  malthoff
  *	The configuration of the XMACs Tx Request Threshold
@@ -246,17 +391,9 @@
  ******************************************************************************/
 
 #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 {
@@ -264,6 +401,10 @@
 	SK_U16	PhyVal;		/* Value to write */
 } BCOM_HACK;
 
+/* local variables ************************************************************/
+static const char SysKonnectFileId[] =
+	"@(#)$Id: skxmac2.c,v 1.87 2002/12/10 14:39:05 rschmidt Exp $ (C) SK ";
+
 BCOM_HACK BcomRegA1Hack[] = {
  { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1104 }, { 0x17, 0x0013 },
  { 0x15, 0x0404 }, { 0x17, 0x8006 }, { 0x15, 0x0132 }, { 0x17, 0x8006 },
@@ -279,308 +420,797 @@
 /* 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 void	SkGmInitPhyMarv(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	SkGmAutoNegDoneMarv(SK_AC*, SK_IOC, int);
+#ifdef OTHER_PHY
+static void	SkXmInitPhyLone(SK_AC*, SK_IOC, int, SK_BOOL);
+static void	SkXmInitPhyNat (SK_AC*, SK_IOC, int, SK_BOOL);
 static int	SkXmAutoNegDoneLone(SK_AC*, SK_IOC, int);
 static int	SkXmAutoNegDoneNat (SK_AC*, SK_IOC, int);
+#endif /* OTHER_PHY */
+
+
 
 /******************************************************************************
  *
- *	SkXmSetRxCmd() - Modify the value of the XMACs Rx Command Register
+ *	SkXmPhyRead() - Read from XMAC PHY 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.
+ * Description:	reads a 16-bit word from XMAC PHY or ext. PHY
  *
  * 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 */
+void SkXmPhyRead(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port,		/* Port Index (MAC_1 + n) */
+int		PhyReg,		/* Register Address (Offset) */
+SK_U16	*pVal)		/* Pointer to Value */
 {
+	SK_U16		Mmu;
 	SK_GEPORT	*pPrt;
-	SK_U16		OldRxMode;
 
 	pPrt = &pAC->GIni.GP[Port];
-	OldRxMode = pPrt->PRxCmd;
+	
+	/* write the PHY register's address */
+	XM_OUT16(IoC, Port, XM_PHY_ADDR, PhyReg | pPrt->PhyAddr);
+	
+	/* get the PHY register's value */
+	XM_IN16(IoC, Port, XM_PHY_DATA, pVal);
+	
+	if (pPrt->PhyType != SK_PHY_XMAC) {
+		do {
+			XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu);
+			/* wait until 'Ready' is set */
+		} while ((Mmu & XM_MMU_PHY_RDY) == 0);
 
-	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;
+		/* get the PHY register's value */
+		XM_IN16(IoC, Port, XM_PHY_DATA, pVal);
 	}
+}	/* SkXmPhyRead */
 
-	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;
-	}
+/******************************************************************************
+ *
+ *	SkXmPhyWrite() - Write to XMAC PHY register
+ *
+ * Description:	writes a 16-bit word to XMAC PHY or ext. PHY
+ *
+ * Returns:
+ *	nothing
+ */
+void SkXmPhyWrite(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port,		/* Port Index (MAC_1 + n) */
+int		PhyReg,		/* Register Address (Offset) */
+SK_U16	Val)		/* Value */
+{
+	SK_U16		Mmu;
+	SK_GEPORT	*pPrt;
 
-	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;
+	pPrt = &pAC->GIni.GP[Port];
+	
+	if (pPrt->PhyType != SK_PHY_XMAC) {
+		do {
+			XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu);
+			/* wait until 'Busy' is cleared */
+		} while ((Mmu & XM_MMU_PHY_BUSY) != 0);
 	}
-
-	/* Write the new mode to the receive command register if required */
-	if (OldRxMode != pPrt->PRxCmd) {
-		XM_OUT16(IoC, Port, XM_RX_CMD, pPrt->PRxCmd);
+	
+	/* write the PHY register's address */
+	XM_OUT16(IoC, Port, XM_PHY_ADDR, PhyReg | pPrt->PhyAddr);
+	
+	/* write the PHY register's value */
+	XM_OUT16(IoC, Port, XM_PHY_DATA, Val);
+	
+	if (pPrt->PhyType != SK_PHY_XMAC) {
+		do {
+			XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu);
+			/* wait until 'Busy' is cleared */
+		} while ((Mmu & XM_MMU_PHY_BUSY) != 0);
 	}
-}	/* SkXmSetRxCmd*/
+}	/* SkXmPhyWrite */
 
 
 /******************************************************************************
  *
- *	SkXmClrExactAddr() - Clear Exact Match Address Registers
+ *	SkGmPhyRead() - Read from GPHY register
  *
- * 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'.
+ * Description:	reads a 16-bit word from GPHY through MDIO
  *
  * 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) */
+void SkGmPhyRead(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port,		/* Port Index (MAC_1 + n) */
+int		PhyReg,		/* Register Address (Offset) */
+SK_U16	*pVal)		/* Pointer to Value */
 {
-	int		i;
-	SK_U16	ZeroAddr[3] = {0x0000, 0x0000, 0x0000};
+	SK_U16	Ctrl;
+	SK_GEPORT	*pPrt;
+#ifdef VCPU
+	u_long SimCyle;
+	u_long SimLowTime;
+	
+	VCPUgetTime(&SimCyle, &SimLowTime);
+	VCPUprintf(0, "SkGmPhyRead(%u), SimCyle=%u, SimLowTime=%u\n",
+		PhyReg, SimCyle, SimLowTime);
+#endif /* VCPU */
+	
+	pPrt = &pAC->GIni.GP[Port];
+	
+	/* set PHY-Register offset and 'Read' OpCode (= 1) */
+	*pVal = GM_SMI_CT_PHY_AD(pPrt->PhyAddr) | GM_SMI_CT_REG_AD(PhyReg) |
+		GM_SMI_CT_OP_RD;
 
-	if ((unsigned)StartNum > 15 || (unsigned)StopNum > 15 ||
-		StartNum > StopNum) {
+	GM_OUT16(IoC, Port, GM_SMI_CTRL, *pVal);
 
-		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E001, SKERR_HWI_E001MSG);
+	GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
+	
+	/* additional check for MDC/MDIO activity */
+	if ((Ctrl & GM_SMI_CT_BUSY) == 0) {
+		*pVal = 0;
 		return;
 	}
 
-	for (i = StartNum; i <= StopNum; i++) {
-		XM_OUTADDR(IoC, Port, XM_EXM(i), &ZeroAddr[0]);
+	*pVal |= GM_SMI_CT_BUSY;
+	
+	do {
+#ifdef VCPU
+		VCPUwaitTime(1000);
+#endif /* VCPU */
+
+		GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
+
+	/* wait until 'ReadValid' is set */
+	} while (Ctrl == *pVal);
+	
+	/* get the PHY register's value */
+	GM_IN16(IoC, Port, GM_SMI_DATA, pVal);
+
+#ifdef VCPU
+	VCPUgetTime(&SimCyle, &SimLowTime);
+	VCPUprintf(0, "VCPUgetTime(), SimCyle=%u, SimLowTime=%u\n",
+		SimCyle, SimLowTime);
+#endif /* VCPU */
+}	/* SkGmPhyRead */
+
+
+/******************************************************************************
+ *
+ *	SkGmPhyWrite() - Write to GPHY register
+ *
+ * Description:	writes a 16-bit word to GPHY through MDIO
+ *
+ * Returns:
+ *	nothing
+ */
+void SkGmPhyWrite(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port,		/* Port Index (MAC_1 + n) */
+int		PhyReg,		/* Register Address (Offset) */
+SK_U16	Val)		/* Value */
+{
+	SK_U16	Ctrl;
+	SK_GEPORT	*pPrt;
+#ifdef VCPU
+	SK_U32	DWord;
+	u_long	SimCyle;
+	u_long	SimLowTime;
+	
+	VCPUgetTime(&SimCyle, &SimLowTime);
+	VCPUprintf(0, "SkGmPhyWrite(Reg=%u, Val=0x%04x), SimCyle=%u, SimLowTime=%u\n",
+		PhyReg, Val, SimCyle, SimLowTime);
+#endif /* VCPU */
+	
+	pPrt = &pAC->GIni.GP[Port];
+	
+	/* write the PHY register's value */
+	GM_OUT16(IoC, Port, GM_SMI_DATA, Val);
+	
+	/* set PHY-Register offset and 'Write' OpCode (= 0) */
+	Val = GM_SMI_CT_PHY_AD(pPrt->PhyAddr) | GM_SMI_CT_REG_AD(PhyReg);
+
+	GM_OUT16(IoC, Port, GM_SMI_CTRL, Val);
+
+	GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
+	
+	/* additional check for MDC/MDIO activity */
+	if ((Ctrl & GM_SMI_CT_BUSY) == 0) {
+		return;
 	}
-}	/* SkXmClrExactAddr */
+	
+	Val |= GM_SMI_CT_BUSY;
+
+	do {
+#ifdef VCPU
+		/* read Timer value */
+		SK_IN32(IoC, B2_TI_VAL, &DWord);
+
+		VCPUwaitTime(1000);
+#endif /* VCPU */
+
+		GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
+
+	/* wait until 'Busy' is cleared */
+	} while (Ctrl == Val);
+	
+#ifdef VCPU
+	VCPUgetTime(&SimCyle, &SimLowTime);
+	VCPUprintf(0, "VCPUgetTime(), SimCyle=%u, SimLowTime=%u\n",
+		SimCyle, SimLowTime);
+#endif /* VCPU */
+}	/* SkGmPhyWrite */
 
 
 /******************************************************************************
  *
- *	SkXmClrSrcCheck() - Clear Source Check Address Register
+ *	SkGePhyRead() - Read from PHY register
  *
- * Description:
- *	The Source Check Address Register of the XMAC 'Port' number
- *	will be cleared.
+ * Description:	calls a read PHY routine dep. on board type
  *
  * 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) */
+void SkGePhyRead(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port,		/* Port Index (MAC_1 + n) */
+int		PhyReg,		/* Register Address (Offset) */
+SK_U16	*pVal)		/* Pointer to Value */
 {
-	SK_U16	ZeroAddr[3] = {0x0000, 0x0000, 0x0000};
+	void (*r_func)(SK_AC *pAC, SK_IOC IoC, int Port, int Reg, SK_U16 *pVal);
 
-	XM_OUTHASH(IoC, Port, XM_SRC_CHK, &ZeroAddr);
-}	/* SkXmClrSrcCheck */
+	if (pAC->GIni.GIGenesis) {
+		r_func = SkXmPhyRead;
+	}
+	else {
+		r_func = SkGmPhyRead;
+	}
+	
+	r_func(pAC, IoC, Port, PhyReg, pVal);
+}	/* SkGePhyRead */
 
 
 /******************************************************************************
  *
- *	SkXmClrHashAddr() - Clear Hash Address Registers
+ *	SkGePhyWrite() - Write to PHY register
  *
- * Description:
- *	The Hash Address Register of the XMAC 'Port' will be cleared.
+ * Description:	calls a write PHY routine dep. on board type
  *
  * 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) */
+void SkGePhyWrite(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* I/O Context */
+int		Port,		/* Port Index (MAC_1 + n) */
+int		PhyReg,		/* Register Address (Offset) */
+SK_U16	Val)		/* Value */
 {
-	SK_U16	ZeroAddr[4] = {0x0000, 0x0000, 0x0000, 0x0000};
+	void (*w_func)(SK_AC *pAC, SK_IOC IoC, int Port, int Reg, SK_U16 Val);
 
-	XM_OUTHASH(IoC, Port, XM_HSM, &ZeroAddr);
-}	/* SkXmClrHashAddr*/
+	if (pAC->GIni.GIGenesis) {
+		w_func = SkXmPhyWrite;
+	}
+	else {
+		w_func = SkGmPhyWrite;
+	}
+	
+	w_func(pAC, IoC, Port, PhyReg, Val);
+}	/* SkGePhyWrite */
 
 
 /******************************************************************************
  *
- *	SkXmFlushTxFifo() - Flush the XMACs transmit FIFO
+ *	SkMacPromiscMode() - Enable / Disable Promiscuous Mode
  *
  * Description:
- *	Flush the transmit FIFO of the XMAC specified by the index 'Port'
+ *   enables / disables promiscuous mode by setting Mode Register (XMAC) or
+ *   Receive Control Register (GMAC) dep. on board type   	
  *
  * Returns:
  *	nothing
  */
-void SkXmFlushTxFifo(
+void SkMacPromiscMode(
 SK_AC	*pAC,	/* adapter context */
 SK_IOC	IoC,	/* IO context */
-int		Port)	/* The XMAC to handle with belongs to this Port (MAC_1 + n) */
+int		Port,	/* Port Index (MAC_1 + n) */
+SK_BOOL	Enable)	/* Enable / Disable */
 {
+	SK_U16	RcReg;
 	SK_U32	MdReg;
 
-	XM_IN32(IoC, Port, XM_MODE, &MdReg);
-	MdReg |= XM_MD_FTF;
-	XM_OUT32(IoC, Port, XM_MODE, MdReg);
-}	/* SkXmFlushTxFifo */
+	if (pAC->GIni.GIGenesis) {
+		
+		XM_IN32(IoC, Port, XM_MODE, &MdReg);
+		/* enable or disable promiscuous mode */
+		if (Enable) {
+			MdReg |= XM_MD_ENA_PROM;
+		}
+		else {
+			MdReg &= ~XM_MD_ENA_PROM;
+		}
+		/* setup Mode Register */
+		XM_OUT32(IoC, Port, XM_MODE, MdReg);
+	}
+	else {
+		
+		GM_IN16(IoC, Port, GM_RX_CTRL, &RcReg);
+		
+		/* enable or disable unicast and multicast filtering */
+		if (Enable) {
+			RcReg &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
+		}
+		else {
+			RcReg |= (GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
+		}
+		/* setup Receive Control Register */
+		GM_OUT16(IoC, Port, GM_RX_CTRL, RcReg);
+	}
+}	/* SkMacPromiscMode*/
 
 
 /******************************************************************************
  *
- *	SkXmFlushRxFifo() - Flush the XMACs receive FIFO
+ *	SkMacHashing() - Enable / Disable Hashing
  *
  * Description:
- *	Flush the receive FIFO of the XMAC specified by the index 'Port'
+ *   enables / disables hashing by setting Mode Register (XMAC) or
+ *   Receive Control Register (GMAC) dep. on board type		
  *
  * Returns:
  *	nothing
  */
-void SkXmFlushRxFifo(
+void SkMacHashing(
 SK_AC	*pAC,	/* adapter context */
 SK_IOC	IoC,	/* IO context */
-int		Port)	/* The XMAC to handle with belongs to this Port (MAC_1 + n) */
+int		Port,	/* Port Index (MAC_1 + n) */
+SK_BOOL	Enable)	/* Enable / Disable */
 {
+	SK_U16	RcReg;
 	SK_U32	MdReg;
 
-	XM_IN32(IoC, Port, XM_MODE, &MdReg);
-	MdReg |= XM_MD_FRF;
-	XM_OUT32(IoC, Port, XM_MODE, MdReg);
-}	/* SkXmFlushRxFifo*/
+	if (pAC->GIni.GIGenesis) {
+		
+		XM_IN32(IoC, Port, XM_MODE, &MdReg);
+		/* enable or disable hashing */
+		if (Enable) {
+			MdReg |= XM_MD_ENA_HASH;
+		}
+		else {
+			MdReg &= ~XM_MD_ENA_HASH;
+		}
+		/* setup Mode Register */
+		XM_OUT32(IoC, Port, XM_MODE, MdReg);
+	}
+	else {
+		
+		GM_IN16(IoC, Port, GM_RX_CTRL, &RcReg);
+		
+		/* enable or disable multicast filtering */
+		if (Enable) {
+			RcReg |= GM_RXCR_MCF_ENA;
+		}
+		else {
+			RcReg &= ~GM_RXCR_MCF_ENA;
+		}
+		/* setup Receive Control Register */
+		GM_OUT16(IoC, Port, GM_RX_CTRL, RcReg);
+	}
+}	/* SkMacHashing*/
 
 
+#ifdef SK_DIAG
 /******************************************************************************
  *
- *	SkXmSoftRst() - Do a XMAC software reset
+ *	SkXmSetRxCmd() - Modify the value of the XMAC's Rx Command Register
  *
  * 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.
+ *	The features
+ *	 - FCS stripping,					SK_STRIP_FCS_ON/OFF
+ *	 - pad byte stripping,				SK_STRIP_PAD_ON/OFF
+ *	 - don't set XMR_FS_ERR in status	SK_LENERR_OK_ON/OFF
+ *	   for inrange length error frames
+ *	 - don't set XMR_FS_ERR in status	SK_BIG_PK_OK_ON/OFF
+ *	   for frames > 1514 bytes
+ *   - enable Rx of own packets         SK_SELF_RX_ON/OFF
  *
- *	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.
+ *	for incoming 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 written to the Rx Command register immediately.
  *
  * Returns:
  *	nothing
  */
-void SkXmSoftRst(
-SK_AC	*pAC,	/* adapter context */
-SK_IOC	IoC,	/* IO context */
-int		Port)	/* port to stop (MAC_1 + n) */
+static void SkXmSetRxCmd(
+SK_AC	*pAC,		/* adapter context */
+SK_IOC	IoC,		/* IO context */
+int		Port,		/* Port Index (MAC_1 + n) */
+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		Word;
+	SK_U16	OldRxCmd;
+	SK_U16	RxCmd;
 
-	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);
+	XM_IN16(IoC, Port, XM_RX_CMD, &OldRxCmd);
 
-	/*
-	 * 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 */
+	RxCmd = OldRxCmd;
+	
+	switch (Mode & (SK_STRIP_FCS_ON | SK_STRIP_FCS_OFF)) {
+	case SK_STRIP_FCS_ON:
+		RxCmd |= XM_RX_STRIP_FCS;
+		break;
+	case SK_STRIP_FCS_OFF:
+		RxCmd &= ~XM_RX_STRIP_FCS;
+		break;
+	}
+
+	switch (Mode & (SK_STRIP_PAD_ON | SK_STRIP_PAD_OFF)) {
+	case SK_STRIP_PAD_ON:
+		RxCmd |= XM_RX_STRIP_PAD;
+		break;
+	case SK_STRIP_PAD_OFF:
+		RxCmd &= ~XM_RX_STRIP_PAD;
+		break;
+	}
+
+	switch (Mode & (SK_LENERR_OK_ON | SK_LENERR_OK_OFF)) {
+	case SK_LENERR_OK_ON:
+		RxCmd |= XM_RX_LENERR_OK;
+		break;
+	case SK_LENERR_OK_OFF:
+		RxCmd &= ~XM_RX_LENERR_OK;
+		break;
+	}
+
+	switch (Mode & (SK_BIG_PK_OK_ON | SK_BIG_PK_OK_OFF)) {
+	case SK_BIG_PK_OK_ON:
+		RxCmd |= XM_RX_BIG_PK_OK;
+		break;
+	case SK_BIG_PK_OK_OFF:
+		RxCmd &= ~XM_RX_BIG_PK_OK;
+		break;
+	}
+
+	switch (Mode & (SK_SELF_RX_ON | SK_SELF_RX_OFF)) {
+	case SK_SELF_RX_ON:
+		RxCmd |= XM_RX_SELF_RX;
+		break;
+	case SK_SELF_RX_OFF:
+		RxCmd &= ~XM_RX_SELF_RX;
+		break;
+	}
+
+	/* Write the new mode to the Rx command register if required */
+	if (OldRxCmd != RxCmd) {
+		XM_OUT16(IoC, Port, XM_RX_CMD, RxCmd);
+	}
+}	/* SkXmSetRxCmd */
+
+
+/******************************************************************************
+ *
+ *	SkGmSetRxCmd() - Modify the value of the GMAC's Rx Control Register
+ *
+ * Description:
+ *	The features
+ *	 - FCS (CRC) stripping,				SK_STRIP_FCS_ON/OFF
+ *	 - don't set XMR_FS_ERR in status	SK_BIG_PK_OK_ON/OFF
+ *	   for frames > 1514 bytes
+ *   - enable Rx of own packets         SK_SELF_RX_ON/OFF
+ *
+ *	for incoming 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 written to the Rx Command register immediately.
+ *
+ * Returns:
+ *	nothing
+ */
+static void SkGmSetRxCmd(
+SK_AC	*pAC,		/* adapter context */
+SK_IOC	IoC,		/* IO context */
+int		Port,		/* Port Index (MAC_1 + n) */
+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_U16	OldRxCmd;
+	SK_U16	RxCmd;
+
+	if ((Mode & (SK_STRIP_FCS_ON | SK_STRIP_FCS_OFF)) != 0) {
+		
+		GM_IN16(IoC, Port, GM_RX_CTRL, &OldRxCmd);
+
+		RxCmd = OldRxCmd;
+
+		if ((Mode & SK_STRIP_FCS_ON) != 0) {
+			RxCmd |= GM_RXCR_CRC_DIS;
+		}
+		else {
+			RxCmd &= ~GM_RXCR_CRC_DIS;
+		}
+		/* Write the new mode to the Rx control register if required */
+		if (OldRxCmd != RxCmd) {
+			GM_OUT16(IoC, Port, GM_RX_CTRL, RxCmd);
+		}
+	}
+
+	if ((Mode & (SK_BIG_PK_OK_ON | SK_BIG_PK_OK_OFF)) != 0) {
+		
+		GM_IN16(IoC, Port, GM_SERIAL_MODE, &OldRxCmd);
+
+		RxCmd = OldRxCmd;
+
+		if ((Mode & SK_BIG_PK_OK_ON) != 0) {
+			RxCmd |= GM_SMOD_JUMBO_ENA;
+		}
+		else {
+			RxCmd &= ~GM_SMOD_JUMBO_ENA;
+		}
+		/* Write the new mode to the Rx control register if required */
+		if (OldRxCmd != RxCmd) {
+			GM_OUT16(IoC, Port, GM_SERIAL_MODE, RxCmd);
+		}
+	}
+}	/* SkGmSetRxCmd */
+
+
+/******************************************************************************
+ *
+ *	SkMacSetRxCmd() - Modify the value of the MAC's Rx Control Register
+ *
+ * Description:	modifies the MAC's Rx Control reg. dep. on board type
+ *
+ * Returns:
+ *	nothing
+ */
+void SkMacSetRxCmd(
+SK_AC	*pAC,		/* adapter context */
+SK_IOC	IoC,		/* IO context */
+int		Port,		/* Port Index (MAC_1 + n) */
+int		Mode)		/* Rx Mode */
+{
+	if (pAC->GIni.GIGenesis) {
+		
+		SkXmSetRxCmd(pAC, IoC, Port, Mode);
+	}
+	else {
+		
+		SkGmSetRxCmd(pAC, IoC, Port, Mode);
+	}
+}	/* SkMacSetRxCmd */
+
+
+/******************************************************************************
+ *
+ *	SkMacCrcGener() - Enable / Disable CRC Generation
+ *
+ * Description:	enables / disables CRC generation dep. on board type
+ *
+ * Returns:
+ *	nothing
+ */
+void SkMacCrcGener(
+SK_AC	*pAC,	/* adapter context */
+SK_IOC	IoC,	/* IO context */
+int		Port,	/* Port Index (MAC_1 + n) */
+SK_BOOL	Enable)	/* Enable / Disable */
+{
+	SK_U16	Word;
+
+	if (pAC->GIni.GIGenesis) {
+		
+		XM_IN16(IoC, Port, XM_TX_CMD, &Word);
+
+		if (Enable) {
+			Word &= ~XM_TX_NO_CRC;
+		}
+		else {
+			Word |= XM_TX_NO_CRC;
+		}
+		/* setup Tx Command Register */
+		XM_OUT16(pAC, Port, XM_TX_CMD, Word);
+	}
+	else {
+		
+		GM_IN16(IoC, Port, GM_TX_CTRL, &Word);
+		
+		if (Enable) {
+			Word &= ~GM_TXCR_CRC_DIS;
+		}
+		else {
+			Word |= GM_TXCR_CRC_DIS;
+		}
+		/* setup Tx Control Register */
+		GM_OUT16(IoC, Port, GM_TX_CTRL, Word);
+	}
+}	/* SkMacCrcGener*/
+
+#endif /* SK_DIAG */
+
+
+/******************************************************************************
+ *
+ *	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,		/* Port Index (MAC_1 + n) */
+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 */
+
+
+/******************************************************************************
+ *
+ *	SkMacFlushTxFifo() - Flush the MAC's transmit FIFO
+ *
+ * Description:
+ *	Flush the transmit FIFO of the MAC specified by the index 'Port'
+ *
+ * Returns:
+ *	nothing
+ */
+void SkMacFlushTxFifo(
+SK_AC	*pAC,	/* adapter context */
+SK_IOC	IoC,	/* IO context */
+int		Port)	/* Port Index (MAC_1 + n) */
+{
+	SK_U32	MdReg;
+
+	if (pAC->GIni.GIGenesis) {
+		
+		XM_IN32(IoC, Port, XM_MODE, &MdReg);
+
+		XM_OUT32(IoC, Port, XM_MODE, MdReg | XM_MD_FTF);
+	}
+	else {
+		/* no way to flush the FIFO we have to issue a reset */
+		/* TBD */
+	}
+}	/* SkMacFlushTxFifo */
+
+
+/******************************************************************************
+ *
+ *	SkMacFlushRxFifo() - Flush the MAC's receive FIFO
+ *
+ * Description:
+ *	Flush the receive FIFO of the MAC specified by the index 'Port'
+ *
+ * Returns:
+ *	nothing
+ */
+void SkMacFlushRxFifo(
+SK_AC	*pAC,	/* adapter context */
+SK_IOC	IoC,	/* IO context */
+int		Port)	/* Port Index (MAC_1 + n) */
+{
+	SK_U32	MdReg;
+
+	if (pAC->GIni.GIGenesis) {
+
+		XM_IN32(IoC, Port, XM_MODE, &MdReg);
+
+		XM_OUT32(IoC, Port, XM_MODE, MdReg | XM_MD_FRF);
+	}
+	else {
+		/* no way to flush the FIFO we have to issue a reset */
+		/* TBD */
+	}
+}	/* SkMacFlushRxFifo */
+
+
+/******************************************************************************
+ *
+ *	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 machine,
+ *		- resetting 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 machine 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
+ */
+static void SkXmSoftRst(
+SK_AC	*pAC,	/* adapter context */
+SK_IOC	IoC,	/* IO context */
+int		Port)	/* Port Index (MAC_1 + n) */
+{
+	SK_U16	ZeroAddr[4] = {0x0000, 0x0000, 0x0000, 0x0000};
+	
+	/* reset the statistics module */
+	XM_OUT32(IoC, Port, XM_GP_PORT, XM_GP_RES_STAT);
+
+	/* disable all XMAC IRQs */
+	XM_OUT16(IoC, Port, XM_IMSK, 0xffff);
+	
+	XM_OUT32(IoC, Port, XM_MODE, 0);		/* clear Mode Reg */
+	
+	XM_OUT16(IoC, Port, XM_TX_CMD, 0);		/* reset TX CMD Reg */
+	XM_OUT16(IoC, Port, XM_RX_CMD, 0);		/* 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);
+			SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, 0xffff);
 			break;
+#ifdef OTHER_PHY
 		case SK_PHY_LONE:
-			PHY_WRITE(IoC, pPrt, Port, PHY_LONE_INT_ENAB, 0x0);
+			SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, 0);
 			break;
 		case SK_PHY_NAT:
 			/* todo: National
-			 PHY_WRITE(IoC, pPrt, Port, PHY_NAT_INT_MASK, 
-				0xffff); */
+			 SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, 0xffff); */
 			break;
+#endif /* OTHER_PHY */
 	}
 
 	/* clear the Hash Register */
-	SkXmClrHashAddr(pAC, IoC, Port);
+	XM_OUTHASH(IoC, Port, XM_HSM, &ZeroAddr);
 
 	/* 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);
+	
+	/* clear the Source Check Address registers */
+	XM_OUTHASH(IoC, Port, XM_SRC_CHK, &ZeroAddr);
 
-	pAC->GIni.GP[Port].PState = SK_PRT_STOP;
-}	/* SkXmSoftRst*/
+}	/* SkXmSoftRst */
 
 
 /******************************************************************************
@@ -589,23 +1219,21 @@
  *
  * 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).
+ *	(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
+ * 	It is absolutely necessary to reset the SW_RST Bit first
  *	before calling this function.
  *
  * Returns:
  *	nothing
  */
-void SkXmHardRst(
+static void SkXmHardRst(
 SK_AC	*pAC,	/* adapter context */
 SK_IOC	IoC,	/* IO context */
-int		Port)	/* port to stop (MAC_1 + n) */
+int		Port)	/* Port Index (MAC_1 + n) */
 {
 	SK_U32	Reg;
 	int		i;
@@ -613,14 +1241,12 @@
 	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);
+		/* TX_MFF_CTRL1 has 32 bits, but only the lowest 16 bits are used */
+		SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_MAC_RST);
 
 		TOut = 0;
 		do {
-			TOut ++;
-			if (TOut > 10000) {
+			if (TOut++ > 10000) {
 				/*
 				 * Adapter seems to be in RESET state.
 				 * Registers cannot be written.
@@ -628,9 +1254,10 @@
 				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);
+			SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_SET_MAC_RST);
+			
+			SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &Word);
+		
 		} while ((Word & MFF_SET_MAC_RST) == 0);
 	}
 
@@ -652,16 +1279,151 @@
 		SK_IN32(IoC, B2_GP_IO, &Reg);
 	}
 
-	pAC->GIni.GP[Port].PState = SK_PRT_RESET;
 }	/* SkXmHardRst */
 
 
 /******************************************************************************
  *
+ *	SkGmSoftRst() - Do a GMAC software reset
+ *
+ * Description:
+ *	The GPHY registers should not be destroyed during this
+ *	kind of software reset.
+ *
+ * Returns:
+ *	nothing
+ */
+static void SkGmSoftRst(
+SK_AC	*pAC,	/* adapter context */
+SK_IOC	IoC,	/* IO context */
+int		Port)	/* Port Index (MAC_1 + n) */
+{
+	SK_U16	EmptyHash[4] = {0x0000, 0x0000, 0x0000, 0x0000};
+	SK_U16  RxCtrl;
+
+	/* reset the statistics module */
+
+	/* disable all GMAC IRQs */
+	SK_OUT8(IoC, GMAC_IRQ_MSK, 0);
+	
+	/* disable all PHY IRQs */
+	SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, 0);
+	
+	/* clear the Hash Register */
+	GM_OUTHASH(IoC, Port, GM_MC_ADDR_H1, &EmptyHash);
+
+	/* Enable Unicast and Multicast filtering */
+	GM_IN16(IoC, Port, GM_RX_CTRL, &RxCtrl);
+	
+	GM_OUT16(IoC, Port, GM_RX_CTRL,
+		RxCtrl | GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
+
+}	/* SkGmSoftRst */
+
+
+/******************************************************************************
+ *
+ *	SkGmHardRst() - Do a GMAC hardware reset
+ *
+ * Description:
+ *
+ * ATTENTION:
+ * 	It is absolutely necessary to reset the SW_RST Bit first
+ *	before calling this function.
+ *
+ * Returns:
+ *	nothing
+ */
+static void SkGmHardRst(
+SK_AC	*pAC,	/* adapter context */
+SK_IOC	IoC,	/* IO context */
+int		Port)	/* Port Index (MAC_1 + n) */
+{
+	/* set GPHY Control reset */
+	SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), GPC_RST_SET);
+
+	/* set GMAC Control reset */
+	SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET);
+
+}	/* SkGmHardRst */
+
+
+/******************************************************************************
+ *
+ *	SkMacSoftRst() - Do a MAC software reset
+ *
+ * Description:	calls a MAC software reset routine dep. on board type
+ *
+ * Returns:
+ *	nothing
+ */
+void SkMacSoftRst(
+SK_AC	*pAC,	/* adapter context */
+SK_IOC	IoC,	/* IO context */
+int		Port)	/* Port Index (MAC_1 + n) */
+{
+	SK_GEPORT	*pPrt;
+
+	pPrt = &pAC->GIni.GP[Port];
+
+	/* disable receiver and transmitter */
+	SkMacRxTxDisable(pAC, IoC, Port);
+
+	if (pAC->GIni.GIGenesis) {
+		
+		SkXmSoftRst(pAC, IoC, Port);
+	}
+	else {
+		
+		SkGmSoftRst(pAC, IoC, Port);
+	}
+
+	/* flush the MAC's Rx and Tx FIFOs */
+	SkMacFlushTxFifo(pAC, IoC, Port);
+	
+	SkMacFlushRxFifo(pAC, IoC, Port);
+
+	pPrt->PState = SK_PRT_STOP;
+
+}	/* SkMacSoftRst */
+
+
+/******************************************************************************
+ *
+ *	SkMacHardRst() - Do a MAC hardware reset
+ *
+ * Description:	calls a MAC hardware reset routine dep. on board type
+ *
+ * Returns:
+ *	nothing
+ */
+void SkMacHardRst(
+SK_AC	*pAC,	/* adapter context */
+SK_IOC	IoC,	/* IO context */
+int		Port)	/* Port Index (MAC_1 + n) */
+{
+	
+	if (pAC->GIni.GIGenesis) {
+		
+		SkXmHardRst(pAC, IoC, Port);
+	}
+	else {
+		
+		SkGmHardRst(pAC, IoC, Port);
+	}
+
+	pAC->GIni.GP[Port].PState = SK_PRT_RESET;
+
+}	/* SkMacHardRst */
+
+
+
+/******************************************************************************
+ *
  *	SkXmInitMac() - Initialize the XMAC II
  *
  * Description:
- *	Initialize all the XMAC of the specified port.
+ *	Initialize the XMAC of the specified port.
  *	The XMAC must be reset or stopped before calling this function.
  *
  * Note:
@@ -679,7 +1441,6 @@
 	SK_U32		Reg;
 	int			i;
 	SK_U16		SWord;
-	SK_U16		PhyId;
 
 	pPrt = &pAC->GIni.GP[Port];
 
@@ -687,10 +1448,11 @@
 		/* 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) {
+
+		if ((SWord & MFF_SET_MAC_RST) != 0) {
 			/* PState does not match HW state */
 			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E006, SKERR_HWI_E006MSG);
-			/* Correct it. */
+			/* Correct it */
 			pPrt->PState = SK_PRT_RESET;
 		}
 	}
@@ -701,115 +1463,84 @@
 		 * 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);
+		SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_MAC_RST);
 
-		/* Ensure that XMAC reset release is done (errata from LReinbold?). */
+		/* 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) {
+		/* Clear PHY reset */
+		if (pPrt->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;
+				Reg |= (GP_DIR_0 | GP_IO_0); /* set to output */
 			}
 			else {
-				Reg |= GP_DIR_2; /* Set to output. */
-				Reg |= GP_IO_2;
+				Reg |= (GP_DIR_2 | GP_IO_2); /* set to output */
 			}
 			SK_OUT32(IoC, B2_GP_IO, Reg);
 
-			/* Enable GMII interface. */
+			/* 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 */
+			/* read Id from external PHY (all have the same address) */
+			SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_ID1, &pPrt->PhyId1);
 
 			/*
 			 * 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. */
+			if (pPrt->PhyId1 == PHY_BCOM_ID1_C0) {
+				/*
+				 * 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,
+					SkXmPhyWrite(pAC, IoC, 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. */
+			else if (pPrt->PhyId1 == PHY_BCOM_ID1_A1) {
+				/*
+				 * 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,
+					SkXmPhyWrite(pAC, IoC, 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);
+			/*
+			 * Workaround BCOM Errata (#10523) for all BCom PHYs.
+			 * Disable Power Management after reset.
+			 */
+			SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &SWord);
+			
+			SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
+				(SK_U16)(SWord | PHY_B_AC_DIS_PM));
 
-			/* PHY LED initialization is done in SkGeXmitLED(), not here. */
+			/* PHY LED initialization is done in SkGeXmitLED() */
 		}
 
 		/* 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
+		 * The auto-negotiation process starts immediately after
+		 * clearing the reset. The auto-negotiation process should be
 		 * started by the SIRQ, therefore stop it here immediately.
 		 */
-		SkXmInitPhy(pAC, IoC, Port, SK_FALSE);
+		SkMacInitPhy(pAC, IoC, Port, SK_FALSE);
 
 #if 0
 		/* temp. code: enable signal detect */
@@ -820,15 +1551,16 @@
 
 	/*
 	 * 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
+	 * B2_MAC_2 = xx xx xx xx xx x1 is programmed to XMAC A
+	 * B2_MAC_3 = xx xx xx xx xx x2 is programmed to XMAC B
 	 */
 	for (i = 0; i < 3; i++) {
 		/*
 		 * The following 2 statements are together endianess
-		 * independant. Remember this when changing.
+		 * independent. Remember this when changing.
 		 */
 		SK_IN16(IoC, (B2_MAC_2 + Port * 8 + i * 2), &SWord);
+		
 		XM_OUT16(IoC, Port, (XM_SA + i * 2), SWord);
 	}
 
@@ -840,49 +1572,54 @@
 	/* 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);
+	XM_OUT16(IoC, Port, XM_RX_HI_WM, SK_XM_RX_HI_WM);
+
+	/* Configure Tx Request Threshold */
+	SWord = SK_XM_THR_SL;				/* for single port */
 
 	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);
+			SWord = SK_XM_THR_REDL;		/* redundant link */
 			break;
 		case SK_MUL_LINK:
-			/* Configure Tx Request Threshold for load bal. */
-			XM_OUT16(IoC, Port, XM_TX_THR, SK_XM_THR_MULL);
+			SWord = SK_XM_THR_MULL;		/* load balancing */
 			break;
 		case SK_JUMBO_LINK:
-			/* Configure Tx Request Threshold for jumbo frames */
-			XM_OUT16(IoC, Port, XM_TX_THR, SK_XM_THR_JUMBO);
+			SWord = SK_XM_THR_JUMBO;	/* jumbo frames */
 			break;
 		default:
-			SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E014,
-				SKERR_HWI_E014MSG);
+			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);
-	}
+	XM_OUT16(IoC, Port, XM_TX_THR, SWord);
 
-	/*
-	 * setup register defaults for the Rx Command Register
-	 *	- Enable Automatic Frame Padding on Tx side
-	 */
+	/* setup register defaults for the Tx Command Register */
 	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 Rx Command Register */
+	SWord = XM_RX_STRIP_FCS | XM_RX_LENERR_OK;
+
+	if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
+		SWord |= XM_RX_BIG_PK_OK;
+	}
+
+	if (pPrt->PLinkModeConf == SK_LMODE_HALF) {
+		/*
+		 * If in manual half duplex mode the other side might be in
+		 * full duplex mode, so ignore if a carrier extension is not seen
+		 * on frames received
+		 */
+		SWord |= XM_RX_DIS_CEXT;
+	}
+	
+	XM_OUT16(IoC, Port, XM_RX_CMD, SWord);
 
 	/*
 	 * setup register defaults for the Mode Register
 	 *	- Don't strip error frames to avoid Store & Forward
-	 *	  on the rx side.
+	 *	  on the Rx side.
 	 *	- Enable 'Check Station Address' bit
 	 *	- Enable 'Check Address Array' bit
 	 */
@@ -906,15 +1643,226 @@
 	 * 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
+	 * The last action is to enable the Rx and Tx state machine.
+	 * This should be done after the auto-negotiation process
 	 * has been completed successfully.
 	 */
-}	/* SkXmInitMac*/
+}	/* SkXmInitMac */
+
+/******************************************************************************
+ *
+ *	SkGmInitMac() - Initialize the GMAC
+ *
+ * Description:
+ *	Initialize the GMAC of the specified port.
+ *	The GMAC must be reset or stopped before calling this function.
+ *
+ * Note:
+ *	The GMAC's Rx and Tx state machine is still disabled when returning.
+ *
+ * Returns:
+ *	nothing
+ */
+void SkGmInitMac(
+SK_AC	*pAC,		/* adapter context */
+SK_IOC	IoC,		/* IO context */
+int		Port)		/* Port Index (MAC_1 + n) */
+{
+	SK_GEPORT	*pPrt;
+	int			i;
+	SK_U16		SWord;
+	SK_U32		DWord;
+
+	pPrt = &pAC->GIni.GP[Port];
+
+	if (pPrt->PState == SK_PRT_STOP) {
+		/* Port State: SK_PRT_STOP */
+		/* Verify that the reset bit is cleared */
+		SK_IN32(IoC, MR_ADDR(Port, GMAC_CTRL), &DWord);
+		
+		if ((DWord & GMC_RST_SET) != 0) {
+			/* 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) {
+		/* set GPHY Control reset */
+		SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), GPC_RST_SET);
+
+		/* set GMAC Control reset */
+		SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET);
+
+		/* clear GMAC Control reset */
+		SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_CLR);
+
+		/* set GMAC Control reset */
+		SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET);
+
+		/* set HWCFG_MODE */
+		DWord = GPC_INT_POL_HI | GPC_DIS_FC | GPC_DIS_SLEEP |
+			GPC_ENA_XC | GPC_ANEG_ADV_ALL_M | GPC_ENA_PAUSE |
+			(pAC->GIni.GICopperType ? GPC_HWCFG_GMII_COP :
+			GPC_HWCFG_GMII_FIB);
+
+		/* set GPHY Control reset */
+		SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_SET);
+
+		/* release GPHY Control reset */
+		SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_CLR);
+
+		/* clear GMAC Control reset */
+		SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_PAUSE_ON | GMC_RST_CLR);
+
+		/* Dummy read the Interrupt source register */
+		SK_IN16(IoC, GMAC_IRQ_SRC, &SWord);
+		
+#ifndef VCPU
+		/* read Id from PHY */
+		SkGmPhyRead(pAC, IoC, Port, PHY_MARV_ID1, &pPrt->PhyId1);
+		
+		SkGmInitPhyMarv(pAC, IoC, Port, SK_FALSE);
+#endif /* VCPU */
+	}
+
+	(void)SkGmResetCounter(pAC, IoC, Port);
+
+	SWord =  0;
+
+	/* speed settings */
+	switch (pPrt->PLinkSpeed) {
+	case SK_LSPEED_AUTO:
+		/* auto update for speed is already set */
+		break;
+	case SK_LSPEED_1000MBPS:
+		SWord |= GM_GPCR_SPEED_1000;
+		break;
+	case SK_LSPEED_100MBPS:
+		SWord |= GM_GPCR_SPEED_100;
+		break;
+	case SK_LSPEED_10MBPS:
+		break;
+	}
+	
+	/* duplex settings */
+	if (pPrt->PLinkModeConf == SK_LMODE_FULL ||
+		pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE) {
+		
+		SWord |= GM_GPCR_DUP_FULL;
+	}
+
+	/* flow control settings */
+	switch (pPrt->PFlowCtrlMode) {
+	case SK_FLOW_MODE_NONE:
+		/* disable auto-neg of flow control */
+		SWord |= GM_GPCR_FC_TX_DIS | GM_GPCR_FC_RX_DIS;
+		break;
+	case SK_FLOW_MODE_LOC_SEND:
+		SWord |= GM_GPCR_FC_RX_DIS;
+		break;
+	case SK_FLOW_MODE_SYMMETRIC:
+		/* TBD */
+	case SK_FLOW_MODE_SYM_OR_REM:
+		/* do nothing means to enable autoneg for flowcontrol and */
+		/* enable rx and tx of pause frames */
+		break;
+	}
+
+	/* setup General Purpose Control Register */
+	GM_OUT16(IoC, Port, GM_GP_CTRL, SWord);
+
+	/* setup Transmit Control Register */
+	GM_OUT16(IoC, Port, GM_TX_CTRL, GM_TXCR_COL_THR);
+
+	/* setup Receive Control Register */
+	GM_OUT16(IoC, Port, GM_RX_CTRL, GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA |
+		GM_RXCR_CRC_DIS);
+
+	/* setup Transmit Flow Control Register */
+	GM_OUT16(IoC, Port, GM_TX_FLOW_CTRL, 0xffff);
+
+	/* setup Transmit Parameter Register */
+#ifdef VCPU
+	GM_IN16(IoC, Port, GM_TX_PARAM, &SWord);
+#endif /* VCPU */
+
+	SWord = JAM_LEN_VAL(3) | JAM_IPG_VAL(11) | IPG_JAM_DATA(26);
+	
+	GM_OUT16(IoC, Port, GM_TX_PARAM, SWord);
+
+	/* configure the Serial Mode Register */
+#ifdef VCPU
+	GM_IN16(IoC, Port, GM_SERIAL_MODE, &SWord);
+#endif /* VCPU */
+	
+	SWord = GM_SMOD_VLAN_ENA | IPG_VAL_FAST_ETH;
+
+	if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
+		/* enable jumbo mode (Max. Frame Length = 9018) */
+		SWord |= GM_SMOD_JUMBO_ENA;
+	}
+	
+	GM_OUT16(IoC, Port, GM_SERIAL_MODE, SWord);
+	
+	/*
+	 * configure the GMACs Station Addresses
+	 * in PROM you can find our addresses at:
+	 * B2_MAC_1 = xx xx xx xx xx x0 virtual address
+	 * B2_MAC_2 = xx xx xx xx xx x1 is programmed to GMAC A
+	 * B2_MAC_3 = xx xx xx xx xx x2 is reserved for DualPort
+	 */
+
+	for (i = 0; i < 3; i++) {
+		/*
+		 * The following 2 statements are together endianess
+		 * independent. Remember this when changing.
+		 */
+		/* physical address: will be used for pause frames */
+		SK_IN16(IoC, (B2_MAC_2 + Port * 8 + i * 2), &SWord);
+
+#ifdef WA_DEV_16
+		/* WA for deviation #16 */
+		if (pAC->GIni.GIChipRev == 0) {
+			/* swap the address bytes */
+			SWord = ((SWord & 0xff00) >> 8)	| ((SWord & 0x00ff) << 8);
+
+			/* write to register in reversed order */
+			GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + (2 - i) * 4), SWord);
+		}
+		else {
+			GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + i * 4), SWord);
+		}
+#else		
+		GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + i * 4), SWord);
+#endif /* WA_DEV_16 */
+		
+		/* virtual address: will be used for data */
+		SK_IN16(IoC, (B2_MAC_1 + Port * 8 + i * 2), &SWord);
+
+		GM_OUT16(IoC, Port, (GM_SRC_ADDR_2L + i * 4), SWord);
+	}
+
+	/* reset all Multicast filtering Hash registers */
+	GM_OUT16(IoC, Port, GM_MC_ADDR_H1, 0);
+	GM_OUT16(IoC, Port, GM_MC_ADDR_H2, 0);
+	GM_OUT16(IoC, Port, GM_MC_ADDR_H3, 0);
+	GM_OUT16(IoC, Port, GM_MC_ADDR_H4, 0);
+
+	/* enable interrupt mask for counter overflows */
+	GM_OUT16(IoC, Port, GM_TX_IRQ_MSK, 0);
+	GM_OUT16(IoC, Port, GM_RX_IRQ_MSK, 0);
+	GM_OUT16(IoC, Port, GM_TR_IRQ_MSK, 0);
+
+#ifdef VCPU
+	/* read General Purpose Status */
+	GM_IN16(IoC, Port, GM_GP_STAT, &SWord);
+#endif /* VCPU */
+}	/* SkGmInitMac */
 
 
 /******************************************************************************
@@ -922,9 +1870,9 @@
  *	SkXmInitDupMd() - Initialize the XMACs Duplex Mode
  *
  * Description:
- *	This function initilaizes the XMACs Duplex Mode.
+ *	This function initializes the XMACs Duplex Mode.
  *	It should be called after successfully finishing
- *	the Autonegotiation Process
+ *	the Auto-negotiation Process
  *
  * Returns:
  *	nothing
@@ -939,9 +1887,9 @@
 	case SK_LMODE_STAT_HALF:
 		/* Configuration Actions for Half Duplex Mode */
 		/*
-		 * XM_BURST = default value. We are propable not quick
+		 * XM_BURST = default value. We are probable not quick
 		 * 	enough at the 'XMAC' bus to burst 8kB.
-		 *	The XMAC stopps bursting if no transmit frames
+		 *	The XMAC stops bursting if no transmit frames
 		 *	are available or the burst limit is exceeded.
 		 */
 		/* XM_TX_RT_LIM = default value (15) */
@@ -969,10 +1917,10 @@
  *	SkXmInitPauseMd() - initialize the Pause Mode to be used for this port
  *
  * Description:
- *	This function initilaizes the Pause Mode which should
+ *	This function initializes the Pause Mode which should
  *	be used for this port.
  *	It should be called after successfully finishing
- *	the Autonegotiation Process
+ *	the Auto-negotiation Process
  *
  * Returns:
  *	nothing
@@ -988,22 +1936,26 @@
 
 	pPrt = &pAC->GIni.GP[Port];
 
+	XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
+	
 	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);
+		Word |= XM_MMU_IGN_PF;
 	}
 	else {
 		/*
-		 * enabling pause frame reception is required for 1000BT 
+		 * 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);
+		Word &= ~XM_MMU_IGN_PF;
 	}	
+	
+	XM_OUT16(IoC, Port, XM_MMU_CMD, Word);
+
+	XM_IN32(IoC, Port, XM_MODE, &DWord);
 
 	if (pPrt->PFlowCtrlStatus == SK_FLOW_STAT_SYMMETRIC ||
 		pPrt->PFlowCtrlStatus == SK_FLOW_STAT_LOC_SEND) {
@@ -1011,11 +1963,10 @@
 		/*
 		 * 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.
+		 * Sending pause frames is edge triggered.
+		 * Send a Pause frame with the maximum pause time if
+		 * internal oder external FIFO full condition occurs.
+		 * Send a zero pause time frame to re-start transmission.
 		 */
 
 		/* XM_PAUSE_DA = '010000C28001' (default) */
@@ -1025,71 +1976,32 @@
 		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);
+		DWord |= XM_PAUSE_MODE;
 
 		/* Set Pause Mode in MAC Rx FIFO */
-		SK_OUT16(IoC, MR_ADDR(Port,RX_MFF_CTRL1), MFF_ENA_PAUSE);
+		SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_ENA_PAUSE);
 	}
 	else {
 		/*
-		 * disable pause frame generation is required for 1000BT 
+		 * 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);
+		DWord &= ~XM_PAUSE_MODE;
 
 		/* Disable Pause Mode in MAC Rx FIFO */
-		SK_OUT16(IoC, MR_ADDR(Port,RX_MFF_CTRL1), MFF_DIS_PAUSE);
+		SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_DIS_PAUSE);
 	}
+	
+	XM_OUT32(IoC, Port, XM_MODE, DWord);
 }	/* 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
+ *	SkXmInitPhyXmac() - Initialize the XMAC Phy registers
  *
- * Description:
- *	Initialize all the XMACs Phy registers
+ * Description:	initializes all the XMACs Phy registers
  *
  * Note:
  *
@@ -1100,32 +2012,32 @@
 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_BOOL	DoLoop)		/* Should a Phy LoopBack 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 */
+	Ctrl = 0;
+	
+	/* Auto-negotiation ? */
+	if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+			("InitPhyXmac: no auto-negotiation Port %d\n", Port));
 		/* Set DuplexMode in Config register */
-		Ctrl = (pPrt->PLinkMode == SK_LMODE_FULL ? PHY_CT_DUP_MD : 0);
+		if (pPrt->PLinkMode == SK_LMODE_FULL) {
+			Ctrl |= PHY_CT_DUP_MD;
+		}
 
 		/*
-		 * Do NOT enable Autonegotiation here. This would hold
-		 * the link down because no IDLES are transmitted
+		 * Do NOT enable Auto-negotiation 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;
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+			("InitPhyXmac: with auto-negotiation Port %d\n", Port));
+		/* Set Auto-negotiation advertisement */
 
 		/* Set Full/half duplex capabilities */
 		switch (pPrt->PLinkMode) {
@@ -1139,8 +2051,8 @@
 			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);
+			SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
+				SKERR_HWI_E015MSG);
 		}
 
 		switch (pPrt->PFlowCtrlMode) {
@@ -1157,14 +2069,14 @@
 			Ctrl |= PHY_X_P_BOTH_MD;
 			break;
 		default:
-			SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT,
-				SKERR_HWI_E016, SKERR_HWI_E016MSG);
+			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);
+		SkXmPhyWrite(pAC, IoC, Port, PHY_XMAC_AUNE_ADV, Ctrl);
 
-		/* Restart Autonegotiation */
+		/* Restart Auto-negotiation */
 		Ctrl = PHY_CT_ANE | PHY_CT_RE_CFG;
 	}
 
@@ -1174,16 +2086,15 @@
 	}
 
 	/* Write to the Phy control register */
-	PHY_WRITE(IoC, pPrt, Port, PHY_XMAC_CTRL, Ctrl);
-}	/* SkXmInitPhyXmac*/
+	SkXmPhyWrite(pAC, IoC, Port, PHY_XMAC_CTRL, Ctrl);
+}	/* SkXmInitPhyXmac */
 
 
 /******************************************************************************
  *
  *	SkXmInitPhyBcom() - Initialize the Broadcom Phy registers
  *
- * Description:
- *	Initialize all the Broadcom Phy registers
+ * Description:	initializes all the Broadcom Phy registers
  *
  * Note:
  *
@@ -1194,7 +2105,7 @@
 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_BOOL	DoLoop)		/* Should a Phy LoopBack be set-up? */
 {
 	SK_GEPORT	*pPrt;
 	SK_U16		Ctrl1;
@@ -1203,7 +2114,7 @@
 	SK_U16		Ctrl4;
 	SK_U16		Ctrl5;
 
-	Ctrl1 = PHY_B_CT_SP1000;
+	Ctrl1 = PHY_CT_SP1000;
 	Ctrl2 = 0;
 	Ctrl3 = PHY_SEL_TYPE;
 	Ctrl4 = PHY_B_PEC_EN_LTR;
@@ -1213,120 +2124,452 @@
 
 	/* manually Master/Slave ? */
 	if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
-		Ctrl2 |= PHY_B_1000C_MSE;
+		Ctrl2 |= PHY_B_1000C_MSE;
+		
+		if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
+			Ctrl2 |= PHY_B_1000C_MSC;
+		}
+	}
+	/* Auto-negotiation ? */
+	if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+			("InitPhyBcom: no auto-negotiation Port %d\n", Port));
+		/* 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 Auto-negotiation 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 auto-negotiation Port %d\n", Port));
+		/* Set Auto-negotiation advertisement */
+
+		/*
+		 * Workaround BCOM Errata #1 for the C5 type.
+		 * 1000Base-T Link Acquisition Failure in Slave Mode
+		 * Set Repeater/DTE bit 10 of the 1000Base-T Control Register
+		 */
+		Ctrl2 |= PHY_B_1000C_RD;
+		
+		 /* 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 Auto-negotiation */
+		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 */
+	SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, Ctrl2);
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("1000B-T Ctrl Reg=0x%04X\n", Ctrl2));
+	
+	/* Write AutoNeg Advertisement Register */
+	SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, Ctrl3);
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("Auto-Neg. Adv. Reg=0x%04X\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 transmission of ext. packets */
+		Ctrl4 |= PHY_B_PEC_HIGH_LA;
+
+		/* configure reception of extended packets */
+		Ctrl5 |= PHY_B_AC_LONG_PACK;
+
+		SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, Ctrl5);
+	}
+
+	/* Configure LED Traffic Mode and Jumbo Frame usage if specified */
+	SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, Ctrl4);
+	
+	/* Write to the Phy control register */
+	SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL, Ctrl1);
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("PHY Control Reg=0x%04X\n", Ctrl1));
+}	/* SkXmInitPhyBcom */
+
+
+/******************************************************************************
+ *
+ *	SkGmInitPhyMarv() - Initialize the Marvell Phy registers
+ *
+ * Description:	initializes all the Marvell Phy registers
+ *
+ * Note:
+ *
+ * Returns:
+ *	nothing
+ */
+static void SkGmInitPhyMarv(
+SK_AC	*pAC,		/* adapter context */
+SK_IOC	IoC,		/* IO context */
+int		Port,		/* Port Index (MAC_1 + n) */
+SK_BOOL	DoLoop)		/* Should a Phy LoopBack be set-up? */
+{
+	SK_GEPORT	*pPrt;
+	SK_U16		PhyCtrl;
+	SK_U16		PhyStat;
+	SK_U16		PhyStat1;
+	SK_U16		PhySpec;
+	SK_U16		C1000BaseT;
+	SK_U16		AutoNegAdv;
+	SK_U16		ExtPhyCtrl;
+
+#ifdef VCPU
+	VCPUprintf(0, "SkGmInitPhyMarv(), Port=%u, DoLoop=%u\n",
+		Port, DoLoop);
+#else /* VCPU */
+	
+	if (!DoLoop) {
+		/* Read Ext. PHY Specific Control */
+		SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL, &ExtPhyCtrl);
+		
+		ExtPhyCtrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK |
+			PHY_M_EC_MAC_S_MSK);
+		
+		ExtPhyCtrl |= PHY_M_EC_M_DSC(1) | PHY_M_EC_S_DSC(1) |
+			PHY_M_EC_MAC_S(MAC_TX_CLK_25_MHZ);
+	
+		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_CTRL, ExtPhyCtrl);
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+			("Ext.PHYCtrl=0x%04X\n", ExtPhyCtrl));
+		
+		/* Read PHY Control */
+		SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &PhyCtrl);
+		
+		/* Assert software reset */
+		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PhyCtrl | PHY_CT_RESET);
+	}
+#endif /* VCPU */
+
+	pPrt = &pAC->GIni.GP[Port];
+
+	PhyCtrl = PHY_CT_COL_TST;
+	C1000BaseT = 0;
+	AutoNegAdv = PHY_SEL_TYPE;
+
+	/* manually Master/Slave ? */
+	if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
+		/* enable Manual Master/Slave */
+		C1000BaseT |= PHY_M_1000C_MSE;
+		
 		if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
-			Ctrl2 |= PHY_B_1000C_MSC;
+			C1000BaseT |= PHY_M_1000C_MSC;	/* set it to Master */
 		}
 	}
-	/* 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);
+	
+	/* Auto-negotiation ? */
+	if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+			("InitPhyMarv: no auto-negotiation Port %d\n", Port));
+		
+		if (pPrt->PLinkMode == SK_LMODE_FULL) {
+			/* Set Full Duplex Mode */
+			PhyCtrl |= PHY_CT_DUP_MD;
+		}
 
-		/* Determine Master/Slave manually if not already done. */
+		/* Set Master/Slave manually if not already done */
 		if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
-			Ctrl2 |= PHY_B_1000C_MSE;	/* set it to Slave */
+			C1000BaseT |= PHY_M_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;
+		/* Set Speed */
+		switch (pPrt->PLinkSpeed) {
+		case SK_LSPEED_AUTO:
+		case SK_LSPEED_1000MBPS:
+			PhyCtrl |= PHY_CT_SP1000;
 			break;
-		case SK_LMODE_AUTOFULL:
-			Ctrl2 |= PHY_B_1000C_AFD;
+		case SK_LSPEED_100MBPS:
+			PhyCtrl |= PHY_CT_SP100;
 			break;
-		case SK_LMODE_AUTOBOTH:
-			Ctrl2 |= PHY_B_1000C_AFD | PHY_B_1000C_AHD;
+		case SK_LSPEED_10MBPS:
 			break;
 		default:
-			SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT,
-				SKERR_HWI_E015, SKERR_HWI_E015MSG);
+			SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E019,
+				SKERR_HWI_E019MSG);
 		}
 
-		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);
+		if (!DoLoop) {
+			PhyCtrl |= PHY_CT_RESET;
 		}
+		/*
+		 * Do NOT enable Auto-negotiation here. This would hold
+		 * the link down because no IDLES are transmitted
+		 */
+	}
+	else {
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+			("InitPhyMarv: with auto-negotiation Port %d\n", Port));
+		
+		PhyCtrl |= PHY_CT_ANE;
+		
+		if (pAC->GIni.GICopperType) {
+			/* Set Speed capabilities */
+			switch (pPrt->PLinkSpeed) {
+			case SK_LSPEED_AUTO:
+				C1000BaseT |= PHY_M_1000C_AHD | PHY_M_1000C_AFD;
+				AutoNegAdv |= PHY_M_AN_100_FD | PHY_M_AN_100_HD |
+					PHY_M_AN_10_FD | PHY_M_AN_10_HD;
+				break;
+			case SK_LSPEED_1000MBPS:
+				C1000BaseT |= PHY_M_1000C_AHD | PHY_M_1000C_AFD;
+				break;
+			case SK_LSPEED_100MBPS:
+				AutoNegAdv |= PHY_M_AN_100_FD | PHY_M_AN_100_HD |
+					PHY_M_AN_10_FD | PHY_M_AN_10_HD;
+				break;
+			case SK_LSPEED_10MBPS:
+				AutoNegAdv |= PHY_M_AN_10_FD | PHY_M_AN_10_HD;
+				break;
+			default:
+				SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E019,
+					SKERR_HWI_E019MSG);
+			}
 
-		/* Restart Autonegotiation */
-		Ctrl1 |= PHY_CT_ANE | PHY_CT_RE_CFG;
+			/* Set Full/half duplex capabilities */
+			switch (pPrt->PLinkMode) {
+			case SK_LMODE_AUTOHALF:
+				C1000BaseT &= ~PHY_M_1000C_AFD;
+				AutoNegAdv &= ~(PHY_M_AN_100_FD | PHY_M_AN_10_FD);
+				break;
+			case SK_LMODE_AUTOFULL:
+				C1000BaseT &= ~PHY_M_1000C_AHD;
+				AutoNegAdv &= ~(PHY_M_AN_100_HD | PHY_M_AN_10_HD);
+				break;
+			case SK_LMODE_AUTOBOTH:
+				break;
+			default:
+				SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
+					SKERR_HWI_E015MSG);
+			}
+			
+			/* Set Auto-negotiation advertisement */
+			switch (pPrt->PFlowCtrlMode) {
+			case SK_FLOW_MODE_NONE:
+				AutoNegAdv |= PHY_B_P_NO_PAUSE;
+				break;
+			case SK_FLOW_MODE_LOC_SEND:
+				AutoNegAdv |= PHY_B_P_ASYM_MD;
+				break;
+			case SK_FLOW_MODE_SYMMETRIC:
+				AutoNegAdv |= PHY_B_P_SYM_MD;
+				break;
+			case SK_FLOW_MODE_SYM_OR_REM:
+				AutoNegAdv |= PHY_B_P_BOTH_MD;
+				break;
+			default:
+				SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
+					SKERR_HWI_E016MSG);
+			}
+		}
+		else {	/* special defines for FIBER (88E1011S only) */
+			
+			/* Set Full/half duplex capabilities */
+			switch (pPrt->PLinkMode) {
+			case SK_LMODE_AUTOHALF:
+				AutoNegAdv |= PHY_M_AN_1000X_AHD;
+				break;
+			case SK_LMODE_AUTOFULL:
+				AutoNegAdv |= PHY_M_AN_1000X_AFD;
+				break;
+			case SK_LMODE_AUTOBOTH:
+				AutoNegAdv |= PHY_M_AN_1000X_AHD | PHY_M_AN_1000X_AFD;
+				break;
+			default:
+				SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
+					SKERR_HWI_E015MSG);
+			}
+			
+			/* Set Auto-negotiation advertisement */
+			switch (pPrt->PFlowCtrlMode) {
+			case SK_FLOW_MODE_NONE:
+				AutoNegAdv |= PHY_M_P_NO_PAUSE_X;
+				break;
+			case SK_FLOW_MODE_LOC_SEND:
+				AutoNegAdv |= PHY_M_P_ASYM_MD_X;
+				break;
+			case SK_FLOW_MODE_SYMMETRIC:
+				AutoNegAdv |= PHY_M_P_SYM_MD_X;
+				break;
+			case SK_FLOW_MODE_SYM_OR_REM:
+				AutoNegAdv |= PHY_M_P_BOTH_MD_X;
+				break;
+			default:
+				SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
+					SKERR_HWI_E016MSG);
+			}
+		}
 
+		if (!DoLoop) {
+			/* Restart Auto-negotiation */
+			PhyCtrl |= 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) */
+#ifdef VCPU
+	/*
+	 * E-mail from Gu Lin (08-03-2002):
+	 */
+	
+	/* Program PHY register 30 as 16'h0708 for simulation speed up */
+	SkGmPhyWrite(pAC, IoC, Port, 30, 0x0708);
+	
+#if 0
+	/* Program PHY register 20 as 16'h2070 */
+	SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_CTRL, 0x2070);
+#endif /* 0 */
+	
+	VCpuWait(2000);
+
+#else /* VCPU */
 	
 	/* 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));
+	SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_1000T_CTRL, C1000BaseT);
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("1000B-T Ctrl=0x%04X\n", C1000BaseT));
 	
 	/* 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));
+	SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_AUNE_ADV, AutoNegAdv);
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("Auto-Neg.Ad.=0x%04X\n", AutoNegAdv));
+#endif /* VCPU */
 	
-
 	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;
+		/* Set the PHY Loopback bit */
+		PhyCtrl |= PHY_CT_LOOP;
 
-		/* configure reception of extended packets */
-		Ctrl5 |= PHY_B_AC_LONG_PACK;
+		/* Program PHY register 16 as 16'h0400 to force link good */
+		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, PHY_M_PC_FL_GOOD);
 
-		PHY_WRITE(IoC, pPrt, Port, PHY_BCOM_AUX_CTRL, Ctrl5);
+#if 0
+		if (pPrt->PLinkSpeed != SK_LSPEED_AUTO) {
+			/* Write Ext. PHY Specific Control */
+			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_CTRL,
+				(SK_U16)((pPrt->PLinkSpeed + 2) << 4));
+		}
+	}
+	else if (pPrt->PLinkSpeed == SK_LSPEED_10MBPS) {
+			/* Write PHY Specific Control */
+			SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, PHY_M_PC_EN_DET_MSK);
+		}
+#endif /* 0 */
 	}
 
-	/* 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 */
+	SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PhyCtrl);
+
+#ifdef VCPU
+	VCpuWait(2000);
+#endif /* VCPU */
+
+#ifdef SK_DIAG
+	c_print("PHY Ctrl Val=0x%04X\n", PhyCtrl);
+	c_print("1000 B-T Val=0x%04X\n", C1000BaseT);
+	c_print("Auto-Neg Val=0x%04X\n", AutoNegAdv);
+	c_print("Ext Ctrl Val=0x%04X\n", ExtPhyCtrl);
+#endif /* SK_DIAG */
+
+#ifndef VCPU
+	/* Read PHY Control */
+	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &PhyCtrl);
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("PHY Ctrl Reg.=0x%04X\n", PhyCtrl));
 	
-	/* 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 */
+	/* Read 1000Base-T Control Register */
+	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_CTRL, &C1000BaseT);
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("1000B-T Ctrl =0x%04X\n", C1000BaseT));
+	
+	/* Read AutoNeg Advertisement Register */
+	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_ADV, &AutoNegAdv);
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("Auto-Neg. Ad.=0x%04X\n", AutoNegAdv));
+	
+	/* Read Ext. PHY Specific Control */
+	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL, &ExtPhyCtrl);
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("Ext PHY Ctrl=0x%04X\n", ExtPhyCtrl));
+	
+	/* Read PHY Status */
+	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat);
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("PHY Stat Reg.=0x%04X\n", PhyStat));
+	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat1);
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("PHY Stat Reg.=0x%04X\n", PhyStat1));
+	
+	/* Read PHY Specific Status */
+	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &PhySpec);
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("PHY Spec Stat=0x%04X\n", PhySpec));
+#endif /* VCPU */
+
+#ifdef SK_DIAG
+	c_print("PHY Ctrl Reg=0x%04X\n", PhyCtrl);
+	c_print("PHY 1000 Reg=0x%04X\n", C1000BaseT);
+	c_print("PHY AnAd Reg=0x%04X\n", AutoNegAdv);
+	c_print("Ext Ctrl Reg=0x%04X\n", ExtPhyCtrl);
+	c_print("PHY Stat Reg=0x%04X\n", PhyStat);
+	c_print("PHY Stat Reg=0x%04X\n", PhyStat1);
+	c_print("PHY Spec Reg=0x%04X\n", PhySpec);
+#endif /* SK_DIAG */
+
+}	/* SkGmInitPhyMarv */
 
 
+#ifdef OTHER_PHY
 /******************************************************************************
  *
  *	SkXmInitPhyLone() - Initialize the Level One Phy registers
  *
- * Description:
- *	Initialize all the Level One Phy registers
+ * Description:	initializes all the Level One Phy registers
  *
  * Note:
  *
@@ -1337,14 +2580,14 @@
 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_BOOL	DoLoop)		/* Should a Phy LoopBack be set-up? */
 {
 	SK_GEPORT	*pPrt;
 	SK_U16		Ctrl1;
 	SK_U16		Ctrl2;
 	SK_U16		Ctrl3;
 
-	Ctrl1 = PHY_L_CT_SP1000;
+	Ctrl1 = PHY_CT_SP1000;
 	Ctrl2 = 0;
 	Ctrl3 = PHY_SEL_TYPE;
 
@@ -1353,39 +2596,36 @@
 	/* 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) {
+	/* Auto-negotiation ? */
+	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 */
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+			("InitPhyLone: no auto-negotiation Port %d\n", Port));
 		/* Set DuplexMode in Config register */
 		Ctrl1 = (pPrt->PLinkMode == SK_LMODE_FULL ? PHY_CT_DUP_MD : 0);
 
-		/* Determine Master/Slave manually if not already done. */
+		/* 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
+		 * Do NOT enable Auto-negotiation 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 */
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+			("InitPhyLone: with auto-negotiation Port %d\n", Port));
+		/* Set Auto-negotiation advertisement */
 
 		/* Set Full/half duplex capabilities */
 		switch (pPrt->PLinkMode) {
@@ -1399,8 +2639,8 @@
 			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);
+			SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
+				SKERR_HWI_E015MSG);
 		}
 
 		switch (pPrt->PFlowCtrlMode) {
@@ -1417,11 +2657,11 @@
 			Ctrl3 |= PHY_L_P_BOTH_MD;
 			break;
 		default:
-			SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT,
-				SKERR_HWI_E016, SKERR_HWI_E016MSG);
+			SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
+				SKERR_HWI_E016MSG);
 		}
 
-		/* Restart Autonegotiation */
+		/* Restart Auto-negotiation */
 		Ctrl1 = PHY_CT_ANE | PHY_CT_RE_CFG;
 
 	}
@@ -1431,14 +2671,14 @@
 	   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));
+	SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_1000T_CTRL, Ctrl2);
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("1000B-T Ctrl Reg=0x%04X\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));
+	SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_AUNE_ADV, Ctrl3);
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("Auto-Neg. Adv. Reg=0x%04X\n", Ctrl3));
 	
 
 	if (DoLoop) {
@@ -1446,26 +2686,18 @@
 		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*/
+	SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_CTRL, Ctrl1);
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("PHY Control Reg=0x%04X\n", Ctrl1));
+}	/* SkXmInitPhyLone */
 
 
 /******************************************************************************
  *
  *	SkXmInitPhyNat() - Initialize the National Phy registers
  *
- * Description:
- *	Initialize all the National Phy registers
+ * Description:	initializes all the National Phy registers
  *
  * Note:
  *
@@ -1476,103 +2708,96 @@
 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_BOOL	DoLoop)		/* Should a Phy LoopBack be set-up? */
 {
 /* todo: National */
-}	/* SkXmInitPhyNat*/
+}	/* SkXmInitPhyNat */
+#endif /* OTHER_PHY */
 
 
 /******************************************************************************
  *
- *	SkXmAutoNegLipaXmac() - Decides whether Link Partner could do autoneg
+ *	SkMacInitPhy() - Initialize the PHY registers
  *
- *	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*/
-
-
-/******************************************************************************
+ * Description:	calls the Init PHY routines dep. on board type
  *
- *	SkXmAutoNegLipaBcom() - Decides whether Link Partner could do autoneg
+ * Note:
  *
- *	This function analyses the PHY status word. If any of the
- *	Autonegotiating bits are set, The PLipaAutoNeg variable
- *	is set true.
+ * Returns:
+ *	nothing
  */
-void	SkXmAutoNegLipaBcom(
+void SkMacInitPhy(
 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_BOOL	DoLoop)		/* Should a Phy LoopBack be set-up? */
 {
 	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;
+	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_MARV_COPPER:
+	case SK_PHY_MARV_FIBER:
+		SkGmInitPhyMarv(pAC, IoC, Port, DoLoop);
+		break;
+#ifdef OTHER_PHY
+	case SK_PHY_LONE:
+		SkXmInitPhyLone(pAC, IoC, Port, DoLoop);
+		break;
+	case SK_PHY_NAT:
+		SkXmInitPhyNat(pAC, IoC, Port, DoLoop);
+		break;
+#endif /* OTHER_PHY */
 	}
-}	/* SkXmAutoNegLipaBcom*/
+}	/* SkMacInitPhy */
 
 
+#ifndef SK_DIAG
 /******************************************************************************
  *
- *	SkXmAutoNegLipaLone() - Decides whether Link Partner could do autoneg
+ *	SkXmAutoNegLipaXmac() - Decides whether Link Partner could do auto-neg
  *
- *	This function analyses the PHY status word. If any of the
- *	Autonegotiating bits are set, The PLipaAutoNeg variable
+ *	This function analyses the Interrupt status word. If any of the
+ *	Auto-negotiating interrupt bits are set, the PLipaAutoNeg variable
  *	is set true.
  */
-void	SkXmAutoNegLipaLone(
+void SkXmAutoNegLipaXmac(
 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 */
+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 &&
-		(PhyStat & (PHY_ST_AN_OVER))) {
+		(IStatus & (XM_IS_LIPA_RC | XM_IS_RX_PAGE | XM_IS_AND)) != 0) {
 
-		SK_DBG_MSG(pAC,SK_DBGMOD_HWM,SK_DBGCAT_CTRL,
-			("AutoNegLipa: AutoNeg detected on port %d %x\n", Port, PhyStat));
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+			("AutoNegLipa: AutoNeg detected on Port %d, IStatus=0x%04x\n",
+			Port, IStatus));
 		pPrt->PLipaAutoNeg = SK_LIPA_AUTO;
 	}
-}	/* SkXmAutoNegLipaLone*/
+}	/* SkXmAutoNegLipaXmac */
 
 
 /******************************************************************************
  *
- *	SkXmAutoNegLipaNat() - Decides whether Link Partner could do autoneg
+ *	SkMacAutoNegLipaPhy() - Decides whether Link Partner could do auto-neg
  *
- *	This function analyses the PHY status word. If any of the
- *	Autonegotiating bits are set, The PLipaAutoNeg variable
+ *	This function analyses the PHY status word.
+ *  If any of the Auto-negotiating bits are set, the PLipaAutoNeg variable
  *	is set true.
  */
-void	SkXmAutoNegLipaNat(
+void SkMacAutoNegLipaPhy(
 SK_AC	*pAC,		/* adapter context */
 SK_IOC	IoC,		/* IO context */
 int		Port,		/* Port Index (MAC_1 + n) */
@@ -1583,67 +2808,30 @@
 	pPrt = &pAC->GIni.GP[Port];
 
 	if (pPrt->PLipaAutoNeg != SK_LIPA_AUTO &&
-		(PhyStat & (PHY_ST_AN_OVER))) {
+		(PhyStat & PHY_ST_AN_OVER) != 0) {
 
-		SK_DBG_MSG(pAC,SK_DBGMOD_HWM,SK_DBGCAT_CTRL,
-			("AutoNegLipa: AutoNeg detected on port %d %x\n", Port, PhyStat));
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+			("AutoNegLipa: AutoNeg detected on Port %d, PhyStat=0x%04x\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*/
+}	/* SkMacAutoNegLipaPhy */
+#endif /* SK_DIAG */
 
 
 /******************************************************************************
  *
- *	SkXmAutoNegDoneXmac() - Auto negotiation handling
+ *	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.
+ *	This function handles the auto-negotiation if the Done bit is set.
  *
  * Returns:
  *	SK_AND_OK	o.k.
  *	SK_AND_DUP_CAP 	Duplex capability error happened
  *	SK_AND_OTHER 	Other error happened
  */
-static int	SkXmAutoNegDoneXmac(
+static int SkXmAutoNegDoneXmac(
 SK_AC	*pAC,		/* adapter context */
 SK_IOC	IoC,		/* IO context */
 int		Port)		/* Port Index (MAC_1 + n) */
@@ -1652,22 +2840,22 @@
 	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));
+	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);
+	SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_LP, &LPAb);
+	SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_RES_ABI, &ResAb);
 
-	if (LPAb & PHY_X_AN_RFB) {
+	if ((LPAb & PHY_X_AN_RFB) != 0) {
 		/* At least one of the remote fault bit is set */
 		/* Error */
-		SK_DBG_MSG(pAC,SK_DBGMOD_HWM,SK_DBGCAT_CTRL,
+		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);
+		return(SK_AND_OTHER);
 	}
 
 	/* Check Duplex mismatch */
@@ -1679,10 +2867,10 @@
 	}
 	else {
 		/* Error */
-		SK_DBG_MSG(pAC,SK_DBGMOD_HWM,SK_DBGCAT_CTRL,
-			("AutoNegFail: Duplex mode mismatch port %d\n", Port));
+		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);
+		return(SK_AND_DUP_CAP);
 	}
 
 	/* Check PAUSE mismatch */
@@ -1690,7 +2878,7 @@
 	/* 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)) {
+	    (LPAb & PHY_X_P_SYM_MD) != 0) {
 		/* Symmetric PAUSE */
 		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
 	}
@@ -1708,31 +2896,25 @@
 		/* PAUSE mismatch -> no PAUSE */
 		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
 	}
+	pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_1000MBPS;
 
-	/* We checked everything and may now enable the link */
-	pPrt->PAutoNegFail = SK_FALSE;
-
-	SkXmRxTxEnable(pAC, IoC, Port);
-	return (SK_AND_OK);
-}	/* SkXmAutoNegDoneXmac*/
+	return(SK_AND_OK);
+}	/* SkXmAutoNegDoneXmac */
 
 
 /******************************************************************************
  *
- *	SkXmAutoNegDoneBcom() - Auto negotiation handling
+ *	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.
+ *	This function handles the auto-negotiation if the Done bit is set.
  *
  * Returns:
  *	SK_AND_OK	o.k.
  *	SK_AND_DUP_CAP 	Duplex capability error happened
  *	SK_AND_OTHER 	Other error happened
  */
-static int	SkXmAutoNegDoneBcom(
+static int SkXmAutoNegDoneBcom(
 SK_AC	*pAC,		/* adapter context */
 SK_IOC	IoC,		/* IO context */
 int		Port)		/* Port Index (MAC_1 + n) */
@@ -1746,105 +2928,199 @@
 	SK_U16		ResAb;		/* Resolved Ability */
 #endif	/* 0 */
 
-	SK_DBG_MSG(pAC,SK_DBGMOD_HWM,SK_DBGCAT_CTRL,
+	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);
+	/* Get PHY parameters */
+	SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &LPAb);
 #if 0
 01-Sep-2000 RA;:;:
-	PHY_READ(IoC, pPrt, Port, PHY_BCOM_1000T_STAT, &ResAb);
+	SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb);
 #endif	/* 0 */
-	PHY_READ(IoC, pPrt, Port, PHY_BCOM_AUX_STAT, &AuxStat);
+	
+	SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &AuxStat);
 
-	if (LPAb & PHY_B_AN_RF) {
-		/* Remote fault bit is set: Error. */
+	if ((LPAb & PHY_B_AN_RF) != 0) {
+		/* 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);
+		return(SK_AND_OTHER);
 	}
 
-	/* Check Duplex mismatch. */
-	if ((AuxStat & PHY_B_AS_AN_RES) == PHY_B_RES_1000FD) {
+	/* Check Duplex mismatch */
+	if ((AuxStat & PHY_B_AS_AN_RES_MSK) == PHY_B_RES_1000FD) {
 		pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOFULL;
 	}
-	else if ((AuxStat & PHY_B_AS_AN_RES) == PHY_B_RES_1000HD) {
+	else if ((AuxStat & PHY_B_AS_AN_RES_MSK) == 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));
+		/* 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);
+		return(SK_AND_DUP_CAP);
 	}
 	
 #if 0
 01-Sep-2000 RA;:;:
-	/* Check Master/Slave resolution. */
-	if (ResAb & PHY_B_1000S_MSF) {
-		/* Error. */
+	/* Check Master/Slave resolution */
+	if ((ResAb & PHY_B_1000S_MSF) != 0) {
 		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
-			("Master/Slave Fault port %d\n", Port));
+			("Master/Slave Fault Port %d\n", Port));
 		pPrt->PAutoNegFail = SK_TRUE;
 		pPrt->PMSStatus = SK_MS_STAT_FAULT;
-		return (SK_AND_OTHER);
+		return(SK_AND_OTHER);
 	}
-	else if (ResAb & PHY_B_1000S_MSR) {
-		pPrt->PMSStatus = SK_MS_STAT_MASTER;
+	
+	pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
+		SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE;
+#endif	/* 0 */
+
+	/* Check PAUSE mismatch */
+	/* We are using IEEE 802.3z/D5.0 Table 37-4 */
+	if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PAUSE_MSK) {
+		/* Symmetric PAUSE */
+		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
+	}
+	else if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PRR) {
+		/* Enable PAUSE receive, disable PAUSE transmit */
+		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
+	}
+	else if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PRT) {
+		/* Disable PAUSE receive, enable PAUSE transmit */
+		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
 	}
 	else {
-		pPrt->PMSStatus = SK_MS_STAT_SLAVE;
+		/* PAUSE mismatch -> no PAUSE */
+		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
+	}
+	pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_1000MBPS;
+
+	return(SK_AND_OK);
+}	/* SkXmAutoNegDoneBcom */
+
+
+/******************************************************************************
+ *
+ *	SkGmAutoNegDoneMarv() - Auto-negotiation handling
+ *
+ * Description:
+ *	This function handles the auto-negotiation if the Done bit is set.
+ *
+ * Returns:
+ *	SK_AND_OK	o.k.
+ *	SK_AND_DUP_CAP 	Duplex capability error happened
+ *	SK_AND_OTHER 	Other error happened
+ */
+static int SkGmAutoNegDoneMarv(
+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		ResAb;		/* Resolved Ability */
+	SK_U16		AuxStat;	/* Auxiliary Status */
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("AutoNegDoneMarv, Port %d\n", Port));
+	pPrt = &pAC->GIni.GP[Port];
+
+	/* Get PHY parameters */
+	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_LP, &LPAb);
+	
+	if ((LPAb & PHY_B_AN_RF) != 0) {
+		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);
+	}
+
+	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_STAT, &ResAb);
+	
+	/* Check Master/Slave resolution */
+	if ((ResAb & PHY_B_1000S_MSF) != 0) {
+		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);
+	}
+	
+	pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
+		(SK_U8)SK_MS_STAT_MASTER : (SK_U8)SK_MS_STAT_SLAVE;
+	
+	/* Read PHY Specific Status */
+	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &AuxStat);
+	
+	/* Check Speed & Duplex resolved */
+	if ((AuxStat & PHY_M_PS_SPDUP_RES) == 0) {
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+			("AutoNegFail: Speed & Duplex not resolved Port %d\n", Port));
+		pPrt->PAutoNegFail = SK_TRUE;
+		pPrt->PLinkModeStatus = SK_LMODE_STAT_UNKNOWN;
+		return(SK_AND_DUP_CAP);
+	}
+	
+	if ((AuxStat & PHY_M_PS_FULL_DUP) != 0) {
+		pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOFULL;
+	}
+	else {
+		pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOHALF;
 	}
-#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. */
+	
+	/* Check PAUSE mismatch */
+	/* We are using IEEE 802.3z/D5.0 Table 37-4 */
+	if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_PAUSE_MSK) {
+		/* 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. */
+	else if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_RX_P_EN) {
+		/* 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. */
+	else if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_TX_P_EN) {
+		/* Disable PAUSE receive, enable PAUSE transmit */
 		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
 	}
 	else {
-		/* PAUSE mismatch -> no PAUSE. */
+		/* PAUSE mismatch -> no PAUSE */
 		pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
 	}
+	
+	/* set used link speed */
+	switch ((unsigned)(AuxStat & PHY_M_PS_SPEED_MSK)) {
+	case (unsigned)PHY_M_PS_SPEED_1000:
+		pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_1000MBPS;
+		break;
+	case PHY_M_PS_SPEED_100:
+		pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_100MBPS;
+		break;
+	default:
+		pPrt->PLinkSpeedUsed = SK_LSPEED_STAT_10MBPS;
+	}
 
-	/* We checked everything and may now enable the link. */
-	pPrt->PAutoNegFail = SK_FALSE;
-
-	SkXmRxTxEnable(pAC, IoC, Port);
-	return (SK_AND_OK);
-}	/* SkXmAutoNegDoneBcom*/
+	return(SK_AND_OK);
+}	/* SkGmAutoNegDoneMarv */
 
 
+#ifdef OTHER_PHY
 /******************************************************************************
  *
- *	SkXmAutoNegDoneLone() - Auto negotiation handling
+ *	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.
+ *	This function handles the auto-negotiation if the Done bit is set.
  *
  * Returns:
  *	SK_AND_OK	o.k.
  *	SK_AND_DUP_CAP 	Duplex capability error happened
  *	SK_AND_OTHER 	Other error happened
  */
-static int	SkXmAutoNegDoneLone(
+static int SkXmAutoNegDoneLone(
 SK_AC	*pAC,		/* adapter context */
 SK_IOC	IoC,		/* IO context */
 int		Port)		/* Port Index (MAC_1 + n) */
@@ -1854,26 +3130,26 @@
 	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));
+	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);
+	SkXmPhyRead(pAC, IoC, Port, PHY_LONE_AUNE_LP, &LPAb);
+	SkXmPhyRead(pAC, IoC, Port, PHY_LONE_1000T_STAT, &ResAb);
+	SkXmPhyRead(pAC, IoC, Port, PHY_LONE_Q_STAT, &QuickStat);
 
-	if (LPAb & PHY_L_AN_RF) {
+	if ((LPAb & PHY_L_AN_RF) != 0) {
 		/* Remote fault bit is set */
 		/* Error */
-		SK_DBG_MSG(pAC,SK_DBGMOD_HWM,SK_DBGCAT_CTRL,
+		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);
+		return(SK_AND_OTHER);
 	}
 
 	/* Check Duplex mismatch */
-	if (QuickStat & PHY_L_QS_DUP_MOD) {
+	if ((QuickStat & PHY_L_QS_DUP_MOD) != 0) {
 		pPrt->PLinkModeStatus = SK_LMODE_STAT_AUTOFULL;
 	}
 	else {
@@ -1881,13 +3157,13 @@
 	}
 	
 	/* Check Master/Slave resolution */
-	if (ResAb & (PHY_L_1000S_MSF)) {
+	if ((ResAb & PHY_L_1000S_MSF) != 0) {
 		/* Error */
-		SK_DBG_MSG(pAC,SK_DBGMOD_HWM,SK_DBGCAT_CTRL,
-			("Master/Slave Fault port %d\n", Port));
+		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);
+		return(SK_AND_OTHER);
 	}
 	else if (ResAb & PHY_L_1000S_MSR) {
 		pPrt->PMSStatus = SK_MS_STAT_MASTER;
@@ -1897,7 +3173,6 @@
 	}
 
 	/* 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;
@@ -1913,7 +3188,7 @@
 		}
 		break;
 	case SK_FLOW_MODE_SYMMETRIC:
-		if ((QuickStat & PHY_L_QS_PAUSE) == PHY_L_QS_PAUSE) {
+		if ((QuickStat & PHY_L_QS_PAUSE) != 0) {
 			/* Symmetric PAUSE */
 			pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
 		}
@@ -1924,154 +3199,545 @@
 			/* Enable PAUSE receive, disable PAUSE transmit */
 			pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
 		}
-		else if ((QuickStat & PHY_L_QS_PAUSE) == PHY_L_QS_PAUSE) {
+		else if ((QuickStat & PHY_L_QS_PAUSE) != 0) {
 			/* 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);
+		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);
+	
+	return(SK_AND_OK);
 }	/* SkXmAutoNegDoneLone */
 
 
 /******************************************************************************
  *
- *	SkXmAutoNegDoneNat() - Auto negotiation handling
+ *	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.
+ *	This function handles the auto-negotiation if the Done bit is set.
  *
  * Returns:
  *	SK_AND_OK	o.k.
  *	SK_AND_DUP_CAP 	Duplex capability error happened
  *	SK_AND_OTHER 	Other error happened
  */
-static int	SkXmAutoNegDoneNat(
+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*/
+	return(SK_AND_OK);
+}	/* SkXmAutoNegDoneNat */
+#endif /* OTHER_PHY */
+
+
+/******************************************************************************
+ *
+ *	SkMacAutoNegDone() - Auto-negotiation handling
+ *
+ * Description:	calls the auto-negotiation done routines dep. on board type
+ *
+ * Returns:
+ *	SK_AND_OK	o.k.
+ *	SK_AND_DUP_CAP 	Duplex capability error happened
+ *	SK_AND_OTHER 	Other error happened
+ */
+int	SkMacAutoNegDone(
+SK_AC	*pAC,		/* adapter context */
+SK_IOC	IoC,		/* IO context */
+int		Port)		/* Port Index (MAC_1 + n) */
+{
+	SK_GEPORT	*pPrt;
+	int	Rtv;
+
+	pPrt = &pAC->GIni.GP[Port];
+
+	switch (pPrt->PhyType) {
+	case SK_PHY_XMAC:
+		Rtv = SkXmAutoNegDoneXmac(pAC, IoC, Port);
+		break;
+	case SK_PHY_BCOM:
+		Rtv = SkXmAutoNegDoneBcom(pAC, IoC, Port);
+		break;
+	case SK_PHY_MARV_COPPER:
+	case SK_PHY_MARV_FIBER:
+		Rtv = SkGmAutoNegDoneMarv(pAC, IoC, Port);
+		break;
+#ifdef OTHER_PHY
+	case SK_PHY_LONE:
+		Rtv = SkXmAutoNegDoneLone(pAC, IoC, Port);
+		break;
+	case SK_PHY_NAT:
+		Rtv = SkXmAutoNegDoneNat(pAC, IoC, Port);
+		break;
+#endif /* OTHER_PHY */
+	default:
+		return(SK_AND_OTHER);
+	}
+	
+	if (Rtv != SK_AND_OK) {
+		return(Rtv);
+	}
+
+	/* We checked everything and may now enable the link */
+	pPrt->PAutoNegFail = SK_FALSE;
+
+	SkMacRxTxEnable(pAC, IoC, Port);
+	
+	return(SK_AND_OK);
+}	/* SkMacAutoNegDone */
 
 
 /******************************************************************************
  *
- *	SkXmRxTxEnable() - Enable RxTx activity if port is up
+ *	SkXmSetRxTxEn() - Special Set Rx/Tx Enable and some features in XMAC
  *
  * Description:
+ *  sets MAC or PHY LoopBack and Duplex Mode in the MMU Command Reg.
+ *  enables Rx/Tx
  *
- * Note:
- *	o The XMACs interrupt source register is NOT read here.
+ * Returns: N/A
+ */
+static void SkXmSetRxTxEn(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* IO context */
+int		Port,		/* Port Index (MAC_1 + n) */
+int		Para)		/* Parameter to set: MAC or PHY LoopBack, Duplex Mode */
+{
+	SK_U16	Word;
+
+	XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
+
+	switch (Para & (SK_MAC_LOOPB_ON | SK_MAC_LOOPB_OFF)) {
+	case SK_MAC_LOOPB_ON:
+		Word |= XM_MMU_MAC_LB;
+		break;
+	case SK_MAC_LOOPB_OFF:
+		Word &= ~XM_MMU_MAC_LB;
+		break;
+	}
+
+	switch (Para & (SK_PHY_LOOPB_ON | SK_PHY_LOOPB_OFF)) {
+	case SK_PHY_LOOPB_ON:
+		Word |= XM_MMU_GMII_LOOP;
+		break;
+	case SK_PHY_LOOPB_OFF:
+		Word &= ~XM_MMU_GMII_LOOP;
+		break;
+	}
+	
+	switch (Para & (SK_PHY_FULLD_ON | SK_PHY_FULLD_OFF)) {
+	case SK_PHY_FULLD_ON:
+		Word |= XM_MMU_GMII_FD;
+		break;
+	case SK_PHY_FULLD_OFF:
+		Word &= ~XM_MMU_GMII_FD;
+		break;
+	}
+	
+	XM_OUT16(IoC, Port, XM_MMU_CMD, Word | XM_MMU_ENA_RX | XM_MMU_ENA_TX);
+
+	/* dummy read to ensure writing */
+	XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
+
+}	/* SkXmSetRxTxEn */
+
+
+/******************************************************************************
+ *
+ *	SkGmSetRxTxEn() - Special Set Rx/Tx Enable and some features in GMAC
+ *
+ * Description:
+ *  sets MAC LoopBack and Duplex Mode in the General Purpose Control Reg.
+ *  enables Rx/Tx
+ *
+ * Returns: N/A
+ */
+static void SkGmSetRxTxEn(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* IO context */
+int		Port,		/* Port Index (MAC_1 + n) */
+int		Para)		/* Parameter to set: MAC LoopBack, Duplex Mode */
+{
+	SK_U16	Ctrl;
+	
+	GM_IN16(IoC, Port, GM_GP_CTRL, &Ctrl);
+
+	switch (Para & (SK_MAC_LOOPB_ON | SK_MAC_LOOPB_OFF)) {
+	case SK_MAC_LOOPB_ON:
+		Ctrl |= GM_GPCR_LOOP_ENA;
+		break;
+	case SK_MAC_LOOPB_OFF:
+		Ctrl &= ~GM_GPCR_LOOP_ENA;
+		break;
+	}
+
+	switch (Para & (SK_PHY_FULLD_ON | SK_PHY_FULLD_OFF)) {
+	case SK_PHY_FULLD_ON:
+		Ctrl |= GM_GPCR_DUP_FULL;
+		break;
+	case SK_PHY_FULLD_OFF:
+		Ctrl &= ~GM_GPCR_DUP_FULL;
+		break;
+	}
+	
+	GM_OUT16(IoC, Port, GM_GP_CTRL, Ctrl | GM_GPCR_RX_ENA | GM_GPCR_TX_ENA);
+
+	/* dummy read to ensure writing */
+	GM_IN16(IoC, Port, GM_GP_CTRL, &Ctrl);
+
+}	/* SkGmSetRxTxEn */
+
+
+/******************************************************************************
+ *
+ *	SkMacSetRxTxEn() - Special Set Rx/Tx Enable and parameters
+ *
+ * Description:	calls the Special Set Rx/Tx Enable routines dep. on board type
+ *
+ * Returns: N/A
+ */
+void SkMacSetRxTxEn(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* IO context */
+int		Port,		/* Port Index (MAC_1 + n) */
+int		Para)
+{
+	if (pAC->GIni.GIGenesis) {
+		
+		SkXmSetRxTxEn(pAC, IoC, Port, Para);
+	}
+	else {
+		
+		SkGmSetRxTxEn(pAC, IoC, Port, Para);
+	}
+
+}	/* SkMacSetRxTxEn */
+
+
+/******************************************************************************
+ *
+ *	SkMacRxTxEnable() - Enable Rx/Tx activity if port is up
+ *
+ * Description:	enables Rx/Tx dep. on board type
  *
  * Returns:
  *	0	o.k.
  *	!= 0	Error happened
  */
-int SkXmRxTxEnable(
+int SkMacRxTxEnable(
 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		Reg;		/* 16-bit register value */
+	SK_U16		IntMask;	/* MAC interrupt mask */
 	SK_U16		SWord;
 
 	pPrt = &pAC->GIni.GP[Port];
 
 	if (!pPrt->PHWLinkUp) {
 		/* The Hardware link is NOT up */
-		return (0);
+		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);
+		/* Auto-negotiation 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) {
+	if (pAC->GIni.GIGenesis) {
+		/* set Duplex 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
+		 */
 		IntMask = XM_DEF_MSK;
+
+#ifdef DEBUG
+		/* add IRQ for Receive FIFO Overflow */
+		IntMask &= ~XM_IS_RXF_OV;
+#endif /* DEBUG */
+		
+		if (pPrt->PhyType != SK_PHY_XMAC) {
+			/* disable GP0 interrupt bit */
+			IntMask |= XM_IS_INP_ASS;
+		}
+		XM_OUT16(IoC, Port, XM_IMSK, IntMask);
+	
+		/* get MMU Command Reg. */
+		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)) {
+			/* set to Full Duplex */
+			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
+			 */
+			SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &SWord);
+			SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
+				(SK_U16)(SWord & ~PHY_B_AC_DIS_PM));
+			SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, PHY_B_DEF_MSK);
+			break;
+#ifdef OTHER_PHY
+		case SK_PHY_LONE:
+			SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, PHY_L_DEF_MSK);
+			break;
+		case SK_PHY_NAT:
+			/* todo National:
+			SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, PHY_N_DEF_MSK); */
+			/* no interrupts possible from National ??? */
+			break;
+#endif /* OTHER_PHY */
+		}
+		
+		/* enable Rx/Tx */
+		XM_OUT16(IoC, Port, XM_MMU_CMD, Reg | XM_MMU_ENA_RX | XM_MMU_ENA_TX);
 	}
 	else {
-		/* disable GP0 interrupt bit */
-		IntMask = XM_DEF_MSK | XM_IS_INP_ASS;
+		/*
+		 * Initialize the Interrupt Mask Register. Default IRQs are...
+		 *	- Rx Counter Event Overflow
+		 *	- Tx Counter Event Overflow
+		 *	- Transmit FIFO Underrun
+		 */
+		IntMask = GMAC_DEF_MSK;
+
+#ifdef DEBUG
+		/* add IRQ for Receive FIFO Overrun */
+		IntMask |= GM_IS_RX_FF_OR;
+#endif /* DEBUG */
+		
+		SK_OUT8(IoC, GMAC_IRQ_MSK, (SK_U8)IntMask);
+		
+		/* get General Purpose Control */
+		GM_IN16(IoC, Port, GM_GP_CTRL, &Reg);
+		
+		if (pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL ||
+			pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL) {
+			/* set to Full Duplex */
+			Reg |= GM_GPCR_DUP_FULL;
+		}
+		
+		/* enable Rx/Tx */
+		GM_OUT16(IoC, Port, GM_GP_CTRL, Reg | GM_GPCR_RX_ENA | GM_GPCR_TX_ENA);
+
+#ifndef VCPU
+		/* Enable all PHY interrupts */
+		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK);
+#endif /* VCPU */
 	}
-	XM_OUT16(IoC, Port, XM_IMSK, IntMask);
+					
+	return(0);
+
+}	/* SkMacRxTxEnable */
+
+
+/******************************************************************************
+ *
+ *	SkMacRxTxDisable() - Disable Receiver and Transmitter
+ *
+ * Description:	disables Rx/Tx dep. on board type
+ *
+ * Returns: N/A
+ */
+void SkMacRxTxDisable(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* IO context */
+int		Port)		/* Port Index (MAC_1 + n) */
+{
+	SK_U16	Word;
 
-	/* 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;
+	if (pAC->GIni.GIGenesis) {
+		
+		XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
+		
+		XM_OUT16(IoC, Port, XM_MMU_CMD, Word & ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX));
+	
+		/* dummy read to ensure writing */
+		XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
 	}
-	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;
+	else {
+		
+		GM_IN16(IoC, Port, GM_GP_CTRL, &Word);
+
+		GM_OUT16(IoC, Port, GM_GP_CTRL, Word & ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA));
+
+		/* dummy read to ensure writing */
+		GM_IN16(IoC, Port, GM_GP_CTRL, &Word);
+	}
+}	/* SkMacRxTxDisable */
+
+
+/******************************************************************************
+ *
+ *	SkMacIrqDisable() - Disable IRQ from MAC
+ *
+ * Description:	sets the IRQ-mask to disable IRQ dep. on board type
+ *
+ * Returns: N/A
+ */
+void SkMacIrqDisable(
+SK_AC	*pAC,		/* Adapter Context */
+SK_IOC	IoC,		/* IO context */
+int		Port)		/* Port Index (MAC_1 + n) */
+{
+	SK_GEPORT	*pPrt;
+	SK_U16		Word;
+
+	pPrt = &pAC->GIni.GP[Port];
+
+	if (pAC->GIni.GIGenesis) {
+		
+		/* disable all XMAC IRQs */
+		XM_OUT16(IoC, Port, XM_IMSK, 0xffff);	
+		
+		/* Disable all PHY interrupts */
+		switch (pPrt->PhyType) {
+			case SK_PHY_BCOM:
+				/* Make sure that PHY is initialized */
+				if (pPrt->PState != SK_PRT_RESET) {
+					/* NOT allowed if BCOM is in RESET state */
+					/* Workaround BCOM Errata (#10523) all BCom */
+					/* Disable Power Management if link is down */
+					SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Word);
+					SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL,
+						(SK_U16)(Word | PHY_B_AC_DIS_PM));
+					SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, 0xffff);
+				}
+				break;
+#ifdef OTHER_PHY
+			case SK_PHY_LONE:
+				SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, 0);
+				break;
+			case SK_PHY_NAT:
+				/* todo: National
+				SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, 0xffff); */
+				break;
+#endif /* OTHER_PHY */
+		}
+	}
+	else {
+		/* disable all GMAC IRQs */
+		SK_OUT8(IoC, GMAC_IRQ_MSK, 0);
+		
+#ifndef VCPU
+		/* Disable all PHY interrupts */
+		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, 0);
+#endif /* VCPU */
+	}
+}	/* SkMacIrqDisable */
+
+
+#ifdef SK_DIAG
+/******************************************************************************
+ *
+ *	SkXmSendCont() - Enable / Disable Send Continuous Mode
+ *
+ * Description:	enable / disable Send Continuous Mode on XMAC
+ *
+ * Returns:
+ *	nothing
+ */
+void SkXmSendCont(
+SK_AC	*pAC,	/* adapter context */
+SK_IOC	IoC,	/* IO context */
+int		Port,	/* Port Index (MAC_1 + n) */
+SK_BOOL	Enable)	/* Enable / Disable */
+{
+	SK_U32	MdReg;
+
+	XM_IN32(IoC, Port, XM_MODE, &MdReg);
+
+	if (Enable) {
+		MdReg |= XM_MD_TX_CONT;
+	}
+	else {
+		MdReg &= ~XM_MD_TX_CONT;
+	}
+	/* setup Mode Register */
+	XM_OUT32(IoC, Port, XM_MODE, MdReg);
+
+}	/* SkXmSendCont*/
+
+/******************************************************************************
+ *
+ *	SkMacTimeStamp() - Enable / Disable Time Stamp
+ *
+ * Description:	enable / disable Time Stamp generation for Rx packets
+ *
+ * Returns:
+ *	nothing
+ */
+void SkMacTimeStamp(
+SK_AC	*pAC,	/* adapter context */
+SK_IOC	IoC,	/* IO context */
+int		Port,	/* Port Index (MAC_1 + n) */
+SK_BOOL	Enable)	/* Enable / Disable */
+{
+	SK_U32	MdReg;
+	SK_U8	TimeCtrl;
+
+	if (pAC->GIni.GIGenesis) {
+
+		XM_IN32(IoC, Port, XM_MODE, &MdReg);
+
+		if (Enable) {
+			MdReg |= XM_MD_ATS;
+		}
+		else {
+			MdReg &= ~XM_MD_ATS;
+		}
+		/* setup Mode Register */
+		XM_OUT32(IoC, Port, XM_MODE, MdReg);
+	}
+	else {
+		if (Enable) {
+			TimeCtrl = GMT_ST_START | GMT_ST_CLR_IRQ;
+		}
+		else {
+			TimeCtrl = GMT_ST_STOP | GMT_ST_CLR_IRQ;
+		}
+		/* Start/Stop Time Stamp Timer */
+		SK_OUT8(pAC, GMAC_TI_ST_CTRL, TimeCtrl);
 	}
-	XM_OUT16(IoC, Port, XM_MMU_CMD, Reg | XM_MMU_ENA_RX | XM_MMU_ENA_TX);
-				      
-	return (0);
-}	/* SkXmRxTxEnable*/
+}	/* SkMacTimeStamp*/
 
-#ifndef SK_DIAG
+#else /* SK_DIAG */
 
 /******************************************************************************
  *
- *	SkXmIrq() - Interrupt service routine
+ *	SkXmIrq() - Interrupt Service Routine
  *
- * Description:
- *	Services an Interrupt of the XMAC II
+ * Description:	services an Interrupt Request of the XMAC
  *
  * Note:
- *	The XMACs interrupt source register is NOT read here.
- *	With an external PHY, some interrupt bits are not meaningfull
- *	any more:
+ *	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
@@ -2086,124 +3752,589 @@
 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 */
+int		Port)		/* Port Index (MAC_1 + n) */
 {
 	SK_GEPORT	*pPrt;
 	SK_EVPARA	Para;
+	SK_U16		IStatus;	/* Interrupt status read from the XMAC */
 	SK_U16		IStatus2;
 
 	pPrt = &pAC->GIni.GP[Port];
 	
-	if (pPrt->PhyType != SK_PHY_XMAC) {
+	XM_IN16(IoC, Port, XM_ISRC, &IStatus);
+	
+	/* LinkPartner Auto-negable? */
+	if (pPrt->PhyType == SK_PHY_XMAC) {
+		SkXmAutoNegLipaXmac(pAC, IoC, Port, IStatus);
+	}
+	else {
 		/* 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));
+		("XmacIrq Port %d Isr 0x%04x\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));
+			("SkXmIrq: spurious interrupt on Port %d\n", Port));
 		return;
 	}
 
-	if (IStatus & XM_IS_INP_ASS) {
+	if ((IStatus & XM_IS_INP_ASS) != 0) {
 		/* 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",
+			("SkXmIrq: Link async. Double check Port %d 0x%04x 0x%04x\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_LNK_AE) != 0) {
+		/* not used, GP0 is used instead */
 	}
 
-	if (IStatus & XM_IS_TX_ABORT) {
+	if ((IStatus & XM_IS_TX_ABORT) != 0) {
 		/* not used */
 	}
 
-	if (IStatus & XM_IS_FRC_INT) {
-		/* not used. use ASIC IRQ instead if needed */
+	if ((IStatus & XM_IS_FRC_INT) != 0) {
+		/* not used, use ASIC IRQ instead if needed */
 	}
 
-	if (IStatus & (XM_IS_INP_ASS | XM_IS_LIPA_RC | XM_IS_RX_PAGE)) {
+	if ((IStatus & (XM_IS_INP_ASS | XM_IS_LIPA_RC | XM_IS_RX_PAGE)) != 0) {
 		SkHWLinkDown(pAC, IoC, Port);
 
 		/* Signal to RLMT */
-		Para.Para32[0] = (SK_U32) Port;
+		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);
+		SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME,
+			SKGE_HWAC, SK_HWEV_WATIM, Para);
 	}
 
-	if (IStatus & XM_IS_RX_PAGE) {
+	if ((IStatus & XM_IS_RX_PAGE) != 0) {
 		/* not used */
 	}
 
-	if (IStatus & XM_IS_TX_PAGE) {
+	if ((IStatus & XM_IS_TX_PAGE) != 0) {
 		/* 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_AND) != 0) {
+		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) {
+	if ((IStatus & XM_IS_TSC_OV) != 0) {
 		/* not used */
 	}
 
-	if (IStatus & XM_IS_RXC_OV) {
-		Para.Para32[0] = (SK_U32) Port;
-		Para.Para32[1] = (SK_U32) IStatus;
+	/* Combined Tx & Rx Counter Overflow SIRQ Event */
+	if ((IStatus & (XM_IS_RXC_OV | XM_IS_TXC_OV)) != 0) {
+		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;
+	if ((IStatus & XM_IS_RXF_OV) != 0) {
+		/* normal situation -> no effect */
+		pPrt->PRxOverCnt++;
+	}
+
+	if ((IStatus & XM_IS_TXF_UR) != 0) {
+		/* may NOT happen -> error log */
+		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E020, SKERR_SIRQ_E020MSG);
+	}
+
+	if ((IStatus & XM_IS_TX_COMP) != 0) {
+		/* not served here */
+	}
+
+	if ((IStatus & XM_IS_RX_COMP) != 0) {
+		/* not served here */
+	}
+}	/* SkXmIrq */
+
+
+/******************************************************************************
+ *
+ *	SkGmIrq() - Interrupt Service Routine
+ *
+ * Description:	services an Interrupt Request of the GMAC
+ *
+ * Note:
+ *
+ * Returns:
+ *	nothing
+ */
+void SkGmIrq(
+SK_AC	*pAC,		/* adapter context */
+SK_IOC	IoC,		/* IO context */
+int		Port)		/* Port Index (MAC_1 + n) */
+{
+	SK_GEPORT	*pPrt;
+	SK_EVPARA	Para;
+	SK_U8		IStatus;	/* Interrupt status */
+
+	pPrt = &pAC->GIni.GP[Port];
+	
+	SK_IN8(IoC, GMAC_IRQ_SRC, &IStatus);
+	
+	/* LinkPartner Auto-negable? */
+	SkMacAutoNegLipaPhy(pAC, IoC, Port, IStatus);
+	
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+		("GmacIrq Port %d Isr 0x%04x\n", Port, IStatus));
+
+	/* Combined Tx & Rx Counter Overflow SIRQ Event */
+	if (IStatus & (GM_IS_RX_CO_OV | GM_IS_TX_CO_OV)) {
+		/* these IRQs will be cleared by reading GMACs register */
+		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 & GM_IS_RX_FF_OR) {
+		/* clear GMAC Rx FIFO Overrun IRQ */
+		SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_CLI_RX_FO);
+
+		pPrt->PRxOverCnt++;
 	}
 
-	if (IStatus & XM_IS_TXF_UR) {
+	if (IStatus & GM_IS_TX_FF_UR) {
+		/* clear GMAC Tx FIFO Underrun IRQ */
+		SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_CLI_TX_FU);
 		/* may NOT happen -> error log */
-		SK_ERR_LOG(pAC, SK_ERRCL_HW , SKERR_SIRQ_E020,
-			SKERR_SIRQ_E020MSG);
+		SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E020, SKERR_SIRQ_E020MSG);
 	}
 
-	if (IStatus & XM_IS_TX_COMP) {
+	if (IStatus & GM_IS_TX_COMPL) {
 		/* not served here */
 	}
 
-	if (IStatus & XM_IS_RX_COMP) {
+	if (IStatus & GM_IS_RX_COMPL) {
 		/* not served here */
 	}
+}	/* SkGmIrq */
+
+/******************************************************************************
+ *
+ *	SkMacIrq() - Interrupt Service Routine for MAC
+ *
+ * Description:	calls the Interrupt Service Routine dep. on board type
+ *
+ * Returns:
+ *	nothing
+ */
+void SkMacIrq(
+SK_AC	*pAC,		/* adapter context */
+SK_IOC	IoC,		/* IO context */
+int		Port)		/* Port Index (MAC_1 + n) */
+{
 
-}	/* SkXmIrq*/
+	if (pAC->GIni.GIGenesis) {
+		/* IRQ from XMAC */
+		SkXmIrq(pAC, IoC, Port);
+	}
+	else {
+		/* IRQ from GMAC */
+		SkGmIrq(pAC, IoC, Port);
+	}
+}	/* SkMacIrq */
 
 #endif /* !SK_DIAG */
 
+/******************************************************************************
+ *
+ *	SkXmUpdateStats() - Force the XMAC to output the current statistic
+ *
+ * Description:
+ *	The XMAC holds its statistic internally. To obtain the current
+ *	values a command must be sent so that the statistic data will
+ *	be written to a predefined memory area on the adapter.
+ *
+ * Returns:
+ *	0:  success
+ *	1:  something went wrong
+ */
+int SkXmUpdateStats(
+SK_AC	*pAC,		/* adapter context */
+SK_IOC	IoC,		/* IO context */
+unsigned int Port)	/* Port Index (MAC_1 + n) */
+{
+	SK_GEPORT	*pPrt;
+	SK_U16		StatReg;
+	int			WaitIndex;
+
+	pPrt = &pAC->GIni.GP[Port];
+	WaitIndex = 0;
+
+	/* Send an update command to XMAC specified */
+	XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_SNP_TXC | XM_SC_SNP_RXC);
+
+	/*
+	 * It is an auto-clearing register. If the command bits
+	 * went to zero again, the statistics are transferred.
+	 * Normally the command should be executed immediately.
+	 * But just to be sure we execute a loop.
+	 */
+	do {
+
+		XM_IN16(IoC, Port, XM_STAT_CMD, &StatReg);
+		
+		if (++WaitIndex > 10) {
+
+			SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E021, SKERR_HWI_E021MSG);
+
+			return(1);
+		}
+	} while ((StatReg & (XM_SC_SNP_TXC | XM_SC_SNP_RXC)) != 0);
+	
+	return(0);
+}	/* SkXmUpdateStats */
+
+/******************************************************************************
+ *
+ *	SkGmUpdateStats() - Force the GMAC to output the current statistic
+ *
+ * Description:
+ *	Empty function for GMAC. Statistic data is accessible in direct way.
+ *
+ * Returns:
+ *	0:  success
+ *	1:  something went wrong
+ */
+int SkGmUpdateStats(
+SK_AC	*pAC,		/* adapter context */
+SK_IOC	IoC,		/* IO context */
+unsigned int Port)	/* Port Index (MAC_1 + n) */
+{
+	return(0);
+}
+
+/******************************************************************************
+ *
+ *	SkXmMacStatistic() - Get XMAC counter value
+ *
+ * Description:
+ *	Gets the 32bit counter value. Except for the octet counters
+ *	the lower 32bit are counted in hardware and the upper 32bit
+ *	must be counted in software by monitoring counter overflow interrupts.
+ *
+ * Returns:
+ *	0:  success
+ *	1:  something went wrong
+ */
+int SkXmMacStatistic(
+SK_AC	*pAC,		/* adapter context */
+SK_IOC	IoC,		/* IO context */
+unsigned int Port,	/* Port Index (MAC_1 + n) */
+SK_U16	StatAddr,	/* MIB counter base address */
+SK_U32	*pVal)		/* ptr to return statistic value */
+{
+	if ((StatAddr < XM_TXF_OK) || (StatAddr > XM_RXF_MAX_SZ)) {
+		
+		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E022, SKERR_HWI_E022MSG);
+		
+		return(1);
+	}
+	
+	XM_IN32(IoC, Port, StatAddr, pVal);
+
+	return(0);
+}	/* SkXmMacStatistic */
+
+/******************************************************************************
+ *
+ *	SkGmMacStatistic() - Get GMAC counter value
+ *
+ * Description:
+ *	Gets the 32bit counter value. Except for the octet counters
+ *	the lower 32bit are counted in hardware and the upper 32bit
+ *	must be counted in software by monitoring counter overflow interrupts.
+ *
+ * Returns:
+ *	0:  success
+ *	1:  something went wrong
+ */
+int SkGmMacStatistic(
+SK_AC	*pAC,		/* adapter context */
+SK_IOC	IoC,		/* IO context */
+unsigned int Port,	/* Port Index (MAC_1 + n) */
+SK_U16	StatAddr,	/* MIB counter base address */
+SK_U32	*pVal)		/* ptr to return statistic value */
+{
+
+	if ((StatAddr < GM_RXF_UC_OK) || (StatAddr > GM_TXE_FIFO_UR)) {
+		
+		SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E022, SKERR_HWI_E022MSG);
+		
+		SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+			("SkGmMacStat: wrong MIB counter 0x%04X\n", StatAddr));
+		return(1);
+	}
+		
+	GM_IN32(IoC, Port, StatAddr, pVal);
+
+	return(0);
+}	/* SkGmMacStatistic */
+
+/******************************************************************************
+ *
+ *	SkXmResetCounter() - Clear MAC statistic counter
+ *
+ * Description:
+ *	Force the XMAC to clear its statistic counter.
+ *
+ * Returns:
+ *	0:  success
+ *	1:  something went wrong
+ */
+int SkXmResetCounter(
+SK_AC	*pAC,		/* adapter context */
+SK_IOC	IoC,		/* IO context */
+unsigned int Port)	/* Port Index (MAC_1 + n) */
+{
+	XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_CLR_RXC | XM_SC_CLR_TXC);
+	/* Clear two times according to Errata #3 */
+	XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_CLR_RXC | XM_SC_CLR_TXC);
+
+	return(0);
+}	/* SkXmResetCounter */
+
+/******************************************************************************
+ *
+ *	SkGmResetCounter() - Clear MAC statistic counter
+ *
+ * Description:
+ *	Force GMAC to clear its statistic counter.
+ *
+ * Returns:
+ *	0:  success
+ *	1:  something went wrong
+ */
+int SkGmResetCounter(
+SK_AC	*pAC,		/* adapter context */
+SK_IOC	IoC,		/* IO context */
+unsigned int Port)	/* Port Index (MAC_1 + n) */
+{
+	SK_U16	Reg;	/* Phy Address Register */
+	SK_U16	Word;
+	int		i;
+
+	GM_IN16(IoC, Port, GM_PHY_ADDR, &Reg);
+
+#ifndef VCPU
+	/* set MIB Clear Counter Mode */
+	GM_OUT16(IoC, Port, GM_PHY_ADDR, Reg | GM_PAR_MIB_CLR);
+	
+	/* read all MIB Counters with Clear Mode set */
+	for (i = 0; i < GM_MIB_CNT_SIZE; i++) {
+		/* the reset is performed only when the lower 16 bits are read */
+		GM_IN16(IoC, Port, GM_MIB_CNT_BASE + 8*i, &Word);
+	}
+	
+	/* clear MIB Clear Counter Mode */
+	GM_OUT16(IoC, Port, GM_PHY_ADDR, Reg);
+#endif /* !VCPU */
+	
+	return(0);
+}	/* SkGmResetCounter */
+
+/******************************************************************************
+ *
+ *	SkXmOverflowStatus() - Gets the status of counter overflow interrupt
+ *
+ * Description:
+ *	Checks the source causing an counter overflow interrupt. On success the
+ *	resulting counter overflow status is written to <pStatus>, whereas the
+ *	upper dword stores the XMAC ReceiveCounterEvent register and the lower
+ *	dword the XMAC TransmitCounterEvent register.
+ *
+ * Note:
+ *	For XMAC the interrupt source is a self-clearing register, so the source
+ *	must be checked only once. SIRQ module does another check to be sure
+ *	that no interrupt get lost during process time.
+ *
+ * Returns:
+ *	0:  success
+ *	1:  something went wrong
+ */
+int SkXmOverflowStatus(
+SK_AC	*pAC,		/* adapter context */
+SK_IOC	IoC,		/* IO context */
+unsigned int Port,	/* Port Index (MAC_1 + n) */
+SK_U16  IStatus,	/* Interupt Status from MAC */
+SK_U64	*pStatus)	/* ptr for return overflow status value */
+{
+	SK_U64	Status;	/* Overflow status */
+	SK_U32	RegVal;
+
+	Status = 0;
+
+	if ((IStatus & XM_IS_RXC_OV) != 0) {
+
+		XM_IN32(IoC, Port, XM_RX_CNT_EV, &RegVal);
+		Status |= (SK_U64)RegVal << 32;
+	}
+	
+	if ((IStatus & XM_IS_TXC_OV) != 0) {
+
+		XM_IN32(IoC, Port, XM_TX_CNT_EV, &RegVal);
+		Status |= (SK_U64)RegVal;
+	}
+
+	*pStatus = Status;
+
+	return(0);
+}	/* SkXmOverflowStatus */
+
+
+/******************************************************************************
+ *
+ *	SkGmOverflowStatus() - Gets the status of counter overflow interrupt
+ *
+ * Description:
+ *	Checks the source causing an counter overflow interrupt. On success the
+ *	resulting counter overflow status is written to <pStatus>, whereas the
+ *	the following bit coding is used:
+ *	63:56 - unused
+ *	55:48 - TxRx interrupt register bit7:0
+ *	32:47 - Rx interrupt register
+ *	31:24 - unused
+ *	23:16 - TxRx interrupt register bit15:8
+ *	15:0  - Tx interrupt register
+ *
+ * Returns:
+ *	0:  success
+ *	1:  something went wrong
+ */
+int SkGmOverflowStatus(
+SK_AC	*pAC,		/* adapter context */
+SK_IOC	IoC,		/* IO context */
+unsigned int Port,	/* Port Index (MAC_1 + n) */
+SK_U16  IStatus,	/* Interupt Status from MAC */
+SK_U64	*pStatus)	/* ptr for return overflow status value */
+{
+	SK_U64	Status;		/* Overflow status */
+	SK_U16	RegVal;
+
+	Status = 0;
+
+	if ((IStatus & GM_IS_RX_CO_OV) != 0) {
+		/* this register is self-clearing after read */
+		GM_IN16(IoC, Port, GM_RX_IRQ_SRC, &RegVal);
+		Status |= (SK_U64)RegVal << 32;
+	}
+	
+	if ((IStatus & GM_IS_TX_CO_OV) != 0) {
+		/* this register is self-clearing after read */
+		GM_IN16(IoC, Port, GM_TX_IRQ_SRC, &RegVal);
+		Status |= (SK_U64)RegVal;
+	}
+	
+	/* this register is self-clearing after read */
+	GM_IN16(IoC, Port, GM_TR_IRQ_SRC, &RegVal);
+	/* Rx overflow interrupt register bits (LoByte)*/
+	Status |= (SK_U64)((SK_U8)RegVal) << 48;
+	/* Tx overflow interrupt register bits (HiByte)*/
+	Status |= (SK_U64)(RegVal >> 8) << 16;
+
+	*pStatus = Status;
+
+	return(0);
+}	/* SkGmOverflowStatus */
+
+/******************************************************************************
+ *
+ *	SkGmCableDiagStatus() - Starts / Gets status of cable diagnostic test
+ *
+ * Description:
+ *  starts the cable diagnostic test if 'StartTest' is true
+ *  gets the results if 'StartTest' is true
+ *
+ * NOTE:	this test is meaningful only when link is down
+ *	
+ * Returns:
+ *	0:  success
+ *	1:	no YUKON copper
+ *	2:	test in progress
+ */
+int SkGmCableDiagStatus(
+SK_AC	*pAC,		/* adapter context */
+SK_IOC	IoC,   		/* IO context */
+int		Port,		/* Port Index (MAC_1 + n) */
+SK_BOOL	StartTest)	/* flag for start / get result */
+{
+	int		i;
+	SK_U16	RegVal;
+	SK_GEPORT	*pPrt;
+
+	pPrt = &pAC->GIni.GP[Port];
+
+	if (pPrt->PhyType != SK_PHY_MARV_COPPER) {
+		
+		return(1);
+	}
+
+	if (StartTest) {
+		/* only start the cable test */
+		if ((pPrt->PhyId1 & PHY_I1_REV_MSK) < 4) {
+			/* apply TDR workaround from Marvell */
+			SkGmPhyWrite(pAC, IoC, Port, 29, 0x001e);
+			
+			SkGmPhyWrite(pAC, IoC, Port, 30, 0xcc00);
+			SkGmPhyWrite(pAC, IoC, Port, 30, 0xc800);
+			SkGmPhyWrite(pAC, IoC, Port, 30, 0xc400);
+			SkGmPhyWrite(pAC, IoC, Port, 30, 0xc000);
+			SkGmPhyWrite(pAC, IoC, Port, 30, 0xc100);
+		}
+
+		/* set address to 0 for MDI[0] */
+		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 0);
+
+		/* Read Cable Diagnostic Reg */
+		SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal);
+
+		/* start Cable Diagnostic Test */
+		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CABLE_DIAG,
+			RegVal | PHY_M_CABD_ENA_TEST);
+	
+		return(0);
+	}
+	
+	/* Read Cable Diagnostic Reg */
+	SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal);
+
+	SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+		("PHY Cable Diag.=0x%04X\n", RegVal));
+
+	if ((RegVal & PHY_M_CABD_ENA_TEST) != 0) {
+		/* test is running */
+		return(2);
+	}
+
+	/* get the test results */
+	for (i = 0; i < 4; i++)  {
+		/* set address to i for MDI[i] */
+		SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, (SK_U16)i);
+
+		/* get Cable Diagnostic values */
+		SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal);
+
+		pPrt->PMdiPairLen[i] = (SK_U8)(RegVal & PHY_M_CABD_DIST_MSK);
+
+		pPrt->PMdiPairSts[i] = (SK_U8)((RegVal & PHY_M_CABD_STAT_MSK) >> 13);
+	}
+
+	return(0);
+}	/* SkGmCableDiagStatus */
+
 /* End of file */

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)