summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'openvz-sources/022.072-r1/5107_linux-2.6.8.1-sk98lin-8.24.1.3.patch')
-rw-r--r--openvz-sources/022.072-r1/5107_linux-2.6.8.1-sk98lin-8.24.1.3.patch41326
1 files changed, 41326 insertions, 0 deletions
diff --git a/openvz-sources/022.072-r1/5107_linux-2.6.8.1-sk98lin-8.24.1.3.patch b/openvz-sources/022.072-r1/5107_linux-2.6.8.1-sk98lin-8.24.1.3.patch
new file mode 100644
index 0000000..626b947
--- /dev/null
+++ b/openvz-sources/022.072-r1/5107_linux-2.6.8.1-sk98lin-8.24.1.3.patch
@@ -0,0 +1,41326 @@
+diff -ruN linux/drivers/net/sk98lin/h/lm80.h linux-new/drivers/net/sk98lin/h/lm80.h
+--- linux/drivers/net/sk98lin/h/lm80.h 2005-09-26 13:32:48.000000000 +0400
++++ linux-new/drivers/net/sk98lin/h/lm80.h 2005-08-09 17:15:51.000000000 +0400
+@@ -2,8 +2,8 @@
+ *
+ * Name: lm80.h
+ * Project: Gigabit Ethernet Adapters, Common Modules
+- * Version: $Revision: 1.6 $
+- * Date: $Date: 2003/05/13 17:26:52 $
++ * Version: $Revision: 2.1 $
++ * Date: $Date: 2003/10/27 14:16:08 $
+ * Purpose: Contains all defines for the LM80 Chip
+ * (National Semiconductor).
+ *
+diff -ruN linux/drivers/net/sk98lin/h/skaddr.h linux-new/drivers/net/sk98lin/h/skaddr.h
+--- linux/drivers/net/sk98lin/h/skaddr.h 2005-09-26 13:32:47.000000000 +0400
++++ linux-new/drivers/net/sk98lin/h/skaddr.h 2005-08-09 17:15:51.000000000 +0400
+@@ -2,8 +2,8 @@
+ *
+ * Name: skaddr.h
+ * Project: Gigabit Ethernet Adapters, ADDR-Modul
+- * Version: $Revision: 1.29 $
+- * Date: $Date: 2003/05/13 16:57:24 $
++ * Version: $Revision: 2.1 $
++ * Date: $Date: 2003/10/27 14:16:07 $
+ * Purpose: Header file for Address Management (MC, UC, Prom).
+ *
+ ******************************************************************************/
+diff -ruN linux/drivers/net/sk98lin/h/skcsum.h linux-new/drivers/net/sk98lin/h/skcsum.h
+--- linux/drivers/net/sk98lin/h/skcsum.h 2005-09-26 13:32:47.000000000 +0400
++++ linux-new/drivers/net/sk98lin/h/skcsum.h 2005-08-09 17:15:51.000000000 +0400
+@@ -2,8 +2,8 @@
+ *
+ * Name: skcsum.h
+ * Project: GEnesis - SysKonnect SK-NET Gigabit Ethernet (SK-98xx)
+- * Version: $Revision: 1.10 $
+- * Date: $Date: 2003/08/20 13:59:57 $
++ * Version: $Revision: 2.2 $
++ * Date: $Date: 2003/12/29 15:37:26 $
+ * Purpose: Store/verify Internet checksum in send/receive packets.
+ *
+ ******************************************************************************/
+@@ -157,9 +157,7 @@
+ typedef struct s_Csum {
+ /* Enabled receive SK_PROTO_XXX bit flags. */
+ unsigned ReceiveFlags[SK_MAX_NETS];
+-#ifdef TX_CSUM
+ unsigned TransmitFlags[SK_MAX_NETS];
+-#endif /* TX_CSUM */
+
+ /* The protocol statistics structure; one per supported protocol. */
+ SKCS_PROTO_STATS ProtoStats[SK_MAX_NETS][SKCS_NUM_PROTOCOLS];
+diff -ruN linux/drivers/net/sk98lin/h/skdebug.h linux-new/drivers/net/sk98lin/h/skdebug.h
+--- linux/drivers/net/sk98lin/h/skdebug.h 2005-09-26 13:32:47.000000000 +0400
++++ linux-new/drivers/net/sk98lin/h/skdebug.h 2005-08-09 17:15:51.000000000 +0400
+@@ -2,8 +2,8 @@
+ *
+ * Name: skdebug.h
+ * Project: Gigabit Ethernet Adapters, Common Modules
+- * Version: $Revision: 1.14 $
+- * Date: $Date: 2003/05/13 17:26:00 $
++ * Version: $Revision: 2.3 $
++ * Date: $Date: 2005/01/25 16:44:28 $
+ * Purpose: SK specific DEBUG support
+ *
+ ******************************************************************************/
+@@ -11,13 +11,12 @@
+ /******************************************************************************
+ *
+ * (C)Copyright 1998-2002 SysKonnect.
+- * (C)Copyright 2002-2003 Marvell.
++ * (C)Copyright 2002-2005 Marvell.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+- *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+@@ -28,9 +27,9 @@
+ #ifdef DEBUG
+ #ifndef SK_DBG_MSG
+ #define SK_DBG_MSG(pAC,comp,cat,arg) \
+- if ( ((comp) & SK_DBG_CHKMOD(pAC)) && \
+- ((cat) & SK_DBG_CHKCAT(pAC)) ) { \
+- SK_DBG_PRINTF arg ; \
++ if ( ((comp) & SK_DBG_CHKMOD(pAC)) && \
++ ((cat) & SK_DBG_CHKCAT(pAC)) ) { \
++ SK_DBG_PRINTF arg; \
+ }
+ #endif
+ #else
+@@ -58,6 +57,13 @@
+ #define SK_DBGMOD_ADDR 0x00000080L /* ADDR module */
+ #define SK_DBGMOD_PECP 0x00000100L /* PECP module */
+ #define SK_DBGMOD_POWM 0x00000200L /* Power Management module */
++#ifdef SK_ASF
++#define SK_DBGMOD_ASF 0x00000400L /* ASF module */
++#endif
++#ifdef SK_LBFO
++#define SK_DBGMOD_LACP 0x00000800L /* link aggregation control protocol */
++#define SK_DBGMOD_FD 0x00001000L /* frame distributor (link aggregation) */
++#endif /* SK_LBFO */
+
+ /* Debug events */
+
+diff -ruN linux/drivers/net/sk98lin/h/skdrv1st.h linux-new/drivers/net/sk98lin/h/skdrv1st.h
+--- linux/drivers/net/sk98lin/h/skdrv1st.h 2005-09-26 13:32:47.000000000 +0400
++++ linux-new/drivers/net/sk98lin/h/skdrv1st.h 2005-08-09 17:15:51.000000000 +0400
+@@ -2,8 +2,8 @@
+ *
+ * Name: skdrv1st.h
+ * Project: GEnesis, PCI Gigabit Ethernet Adapter
+- * Version: $Revision: 1.4 $
+- * Date: $Date: 2003/11/12 14:28:14 $
++ * Version: $Revision: 1.5.2.6 $
++ * Date: $Date: 2005/08/09 07:14:29 $
+ * Purpose: First header file for driver and all other modules
+ *
+ ******************************************************************************/
+@@ -11,7 +11,7 @@
+ /******************************************************************************
+ *
+ * (C)Copyright 1998-2002 SysKonnect GmbH.
+- * (C)Copyright 2002-2003 Marvell.
++ * (C)Copyright 2002-2005 Marvell.
+ *
+ * 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
+@@ -22,20 +22,6 @@
+ *
+ ******************************************************************************/
+
+-/******************************************************************************
+- *
+- * Description:
+- *
+- * This is the first include file of the driver, which includes all
+- * neccessary system header files and some of the GEnesis header files.
+- * It also defines some basic items.
+- *
+- * Include File Hierarchy:
+- *
+- * see skge.c
+- *
+- ******************************************************************************/
+-
+ #ifndef __INC_SKDRV1ST_H
+ #define __INC_SKDRV1ST_H
+
+@@ -58,6 +44,9 @@
+
+ #define SK_ADDR_EQUAL(a1,a2) (!memcmp(a1,a2,6))
+
++#define SK_STRNCMP(s1,s2,len) strncmp(s1,s2,len)
++#define SK_STRCPY(dest,src) strcpy(dest,src)
++
+ #include <linux/types.h>
+ #include <linux/kernel.h>
+ #include <linux/string.h>
+@@ -78,11 +67,7 @@
+ #include <net/checksum.h>
+
+ #define SK_CS_CALCULATE_CHECKSUM
+-#ifndef CONFIG_X86_64
+-#define SkCsCalculateChecksum(p,l) ((~ip_compute_csum(p, l)) & 0xffff)
+-#else
+-#define SkCsCalculateChecksum(p,l) ((~ip_fast_csum(p, l)) & 0xffff)
+-#endif
++#define SkCsCalculateChecksum(p,l) (~csum_fold(csum_partial(p, l, 0)))
+
+ #include "h/sktypes.h"
+ #include "h/skerror.h"
+@@ -90,10 +75,15 @@
+ #include "h/lm80.h"
+ #include "h/xmac_ii.h"
+
++#ifndef SK_BMU_RX_WM_PEX
++#define SK_BMU_RX_WM_PEX 0x80
++#endif
++
+ #ifdef __LITTLE_ENDIAN
+ #define SK_LITTLE_ENDIAN
+ #else
+ #define SK_BIG_ENDIAN
++#define SK_USE_REV_DESC
+ #endif
+
+ #define SK_NET_DEVICE net_device
+@@ -188,3 +178,8 @@
+
+ #endif
+
++/*******************************************************************************
++ *
++ * End of file
++ *
++ ******************************************************************************/
+diff -ruN linux/drivers/net/sk98lin/h/skdrv2nd.h linux-new/drivers/net/sk98lin/h/skdrv2nd.h
+--- linux/drivers/net/sk98lin/h/skdrv2nd.h 2005-09-26 13:32:48.000000000 +0400
++++ linux-new/drivers/net/sk98lin/h/skdrv2nd.h 2005-08-09 17:15:51.000000000 +0400
+@@ -1,17 +1,17 @@
+ /******************************************************************************
+ *
+- * Name: skdrv2nd.h
+- * Project: GEnesis, PCI Gigabit Ethernet Adapter
+- * Version: $Revision: 1.10 $
+- * Date: $Date: 2003/12/11 16:04:45 $
+- * Purpose: Second header file for driver and all other modules
++ * Name: skdrv2nd.h
++ * Project: GEnesis, PCI Gigabit Ethernet Adapter
++ * Version: $Revision: 1.29.2.24 $
++ * Date: $Date: 2005/08/09 10:41:04 $
++ * Purpose: Second header file for driver and all other modules
+ *
+ ******************************************************************************/
+
+ /******************************************************************************
+ *
+ * (C)Copyright 1998-2002 SysKonnect GmbH.
+- * (C)Copyright 2002-2003 Marvell.
++ * (C)Copyright 2002-2005 Marvell.
+ *
+ * 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
+@@ -42,10 +42,11 @@
+ #include "h/skqueue.h"
+ #include "h/skgehwt.h"
+ #include "h/sktimer.h"
+-#include "h/ski2c.h"
++#include "h/sktwsi.h"
+ #include "h/skgepnmi.h"
+ #include "h/skvpd.h"
+ #include "h/skgehw.h"
++#include "h/sky2le.h"
+ #include "h/skgeinit.h"
+ #include "h/skaddr.h"
+ #include "h/skgesirq.h"
+@@ -53,158 +54,187 @@
+ #include "h/skrlmt.h"
+ #include "h/skgedrv.h"
+
+-#define SK_PCI_ISCOMPLIANT(result, pdev) { \
+- result = SK_FALSE; /* default */ \
+- /* 3Com (0x10b7) */ \
+- if (pdev->vendor == 0x10b7) { \
+- /* Gigabit Ethernet Adapter (0x1700) */ \
+- if ((pdev->device == 0x1700) || \
+- (pdev->device == 0x80eb)) { \
+- result = SK_TRUE; \
+- } \
+- /* SysKonnect (0x1148) */ \
+- } else if (pdev->vendor == 0x1148) { \
+- /* SK-98xx Gigabit Ethernet Server Adapter (0x4300) */ \
+- /* SK-98xx V2.0 Gigabit Ethernet Adapter (0x4320) */ \
+- if ((pdev->device == 0x4300) || \
+- (pdev->device == 0x4320)) { \
+- result = SK_TRUE; \
+- } \
+- /* D-Link (0x1186) */ \
+- } else if (pdev->vendor == 0x1186) { \
+- /* Gigabit Ethernet Adapter (0x4c00) */ \
+- if ((pdev->device == 0x4c00)) { \
+- result = SK_TRUE; \
+- } \
+- /* Marvell (0x11ab) */ \
+- } else if (pdev->vendor == 0x11ab) { \
+- /* Gigabit Ethernet Adapter (0x4320) */ \
+- /* Gigabit Ethernet Adapter (0x4360) */ \
+- /* Gigabit Ethernet Adapter (0x4361) */ \
+- /* Belkin (0x5005) */ \
+- if ((pdev->device == 0x4320) || \
+- (pdev->device == 0x4360) || \
+- (pdev->device == 0x4361) || \
+- (pdev->device == 0x5005)) { \
+- result = SK_TRUE; \
+- } \
+- /* CNet (0x1371) */ \
+- } else if (pdev->vendor == 0x1371) { \
+- /* GigaCard Network Adapter (0x434e) */ \
+- if ((pdev->device == 0x434e)) { \
+- result = SK_TRUE; \
+- } \
+- /* Linksys (0x1737) */ \
+- } else if (pdev->vendor == 0x1737) { \
+- /* Gigabit Network Adapter (0x1032) */ \
+- /* Gigabit Network Adapter (0x1064) */ \
+- if ((pdev->device == 0x1032) || \
+- (pdev->device == 0x1064)) { \
+- result = SK_TRUE; \
+- } \
+- } else { \
+- result = SK_FALSE; \
+- } \
+-}
++/* Defines for the poll cotroller */
++#ifdef HAVE_POLL_CONTROLLER
++#define SK_POLL_CONTROLLER
++#define CONFIG_SK98LIN_NAPI
++#elif CONFIG_NET_POLL_CONTROLLER
++#define SK_POLL_CONTROLLER
++#define CONFIG_SK98LIN_NAPI
++#endif
+
+
+-extern SK_MBUF *SkDrvAllocRlmtMbuf(SK_AC*, SK_IOC, unsigned);
+-extern void SkDrvFreeRlmtMbuf(SK_AC*, SK_IOC, SK_MBUF*);
+-extern SK_U64 SkOsGetTime(SK_AC*);
+-extern int SkPciReadCfgDWord(SK_AC*, int, SK_U32*);
+-extern int SkPciReadCfgWord(SK_AC*, int, SK_U16*);
+-extern int SkPciReadCfgByte(SK_AC*, int, SK_U8*);
+-extern int SkPciWriteCfgDWord(SK_AC*, int, SK_U32);
+-extern int SkPciWriteCfgWord(SK_AC*, int, SK_U16);
+-extern int SkPciWriteCfgByte(SK_AC*, int, SK_U8);
+-extern int SkDrvEvent(SK_AC*, SK_IOC IoC, SK_U32, SK_EVPARA);
+-
+-#ifdef SK_DIAG_SUPPORT
+-extern int SkDrvEnterDiagMode(SK_AC *pAc);
+-extern int SkDrvLeaveDiagMode(SK_AC *pAc);
++/******************************************************************************
++ *
++ * Generic driver defines
++ *
++ ******************************************************************************/
++
++#define USE_TIST_FOR_RESET /* Use timestamp for reset */
++#define Y2_RECOVERY /* use specific recovery yukon2 functions */
++#define Y2_LE_CHECK /* activate check for LE order */
++#define Y2_SYNC_CHECK /* activate check for receiver in sync */
++#define SK_YUKON2 /* Enable Yukon2 dual net support */
++#define USE_SK_TX_CHECKSUM /* use the tx hw checksum driver functionality */
++#define USE_SK_RX_CHECKSUM /* use the rx hw checksum driver functionality */
++#define USE_SK_TSO_FEATURE /* use TCP segmentation offload if possible */
++#define SK_COPY_THRESHOLD 50 /* threshold for copying small RX frames;
++ * 0 avoids copying, 9001 copies all */
++#define SK_MAX_CARD_PARAM 16 /* number of adapters that can be configured via
++ * command line params */
++//#define USE_TX_COMPLETE /* use of a transmit complete interrupt */
++#define Y2_RX_CHECK /* RX Check timestamp */
++
++/*
++ * use those defines for a compile-in version of the driver instead
++ * of command line parameters
++ */
++// #define LINK_SPEED_A {"Auto",}
++// #define LINK_SPEED_B {"Auto",}
++// #define AUTO_NEG_A {"Sense",}
++// #define AUTO_NEG_B {"Sense"}
++// #define DUP_CAP_A {"Both",}
++// #define DUP_CAP_B {"Both",}
++// #define FLOW_CTRL_A {"SymOrRem",}
++// #define FLOW_CTRL_B {"SymOrRem",}
++// #define ROLE_A {"Auto",}
++// #define ROLE_B {"Auto",}
++// #define PREF_PORT {"A",}
++// #define CON_TYPE {"Auto",}
++// #define RLMT_MODE {"CheckLinkState",}
++
++#ifdef Y2_RECOVERY
++#define CHECK_TRANSMIT_TIMEOUT
++#define Y2_RESYNC_WATERMARK 1000000L
+ #endif
+
++
++/******************************************************************************
++ *
++ * Generic ISR defines
++ *
++ ******************************************************************************/
++
++#define SkIsrRetVar irqreturn_t
++#define SkIsrRetNone IRQ_NONE
++#define SkIsrRetHandled IRQ_HANDLED
++
++#define DEV_KFREE_SKB(skb) dev_kfree_skb(skb)
++#define DEV_KFREE_SKB_IRQ(skb) dev_kfree_skb_irq(skb)
++#define DEV_KFREE_SKB_ANY(skb) dev_kfree_skb_any(skb)
++
++/******************************************************************************
++ *
++ * Global function prototypes
++ *
++ ******************************************************************************/
++
++extern SK_MBUF *SkDrvAllocRlmtMbuf(SK_AC*, SK_IOC, unsigned);
++extern void SkDrvFreeRlmtMbuf(SK_AC*, SK_IOC, SK_MBUF*);
++extern SK_U64 SkOsGetTime(SK_AC*);
++extern int SkPciReadCfgDWord(SK_AC*, int, SK_U32*);
++extern int SkPciReadCfgWord(SK_AC*, int, SK_U16*);
++extern int SkPciReadCfgByte(SK_AC*, int, SK_U8*);
++extern int SkPciWriteCfgDWord(SK_AC*, int, SK_U32);
++extern int SkPciWriteCfgWord(SK_AC*, int, SK_U16);
++extern int SkPciWriteCfgByte(SK_AC*, int, SK_U8);
++extern int SkDrvEvent(SK_AC*, SK_IOC IoC, SK_U32, SK_EVPARA);
++extern int SkDrvEnterDiagMode(SK_AC *pAc);
++extern int SkDrvLeaveDiagMode(SK_AC *pAc);
++
++/******************************************************************************
++ *
++ * Linux specific RLMT buffer structure (SK_MBUF typedef in skdrv1st)!
++ *
++ ******************************************************************************/
++
+ struct s_DrvRlmtMbuf {
+- SK_MBUF *pNext; /* Pointer to next RLMT Mbuf. */
+- SK_U8 *pData; /* Data buffer (virtually contig.). */
+- unsigned Size; /* Data buffer size. */
+- unsigned Length; /* Length of packet (<= Size). */
+- SK_U32 PortIdx; /* Receiving/transmitting port. */
++ SK_MBUF *pNext; /* Pointer to next RLMT Mbuf. */
++ SK_U8 *pData; /* Data buffer (virtually contig.). */
++ unsigned Size; /* Data buffer size. */
++ unsigned Length; /* Length of packet (<= Size). */
++ SK_U32 PortIdx; /* Receiving/transmitting port. */
+ #ifdef SK_RLMT_MBUF_PRIVATE
+- SK_RLMT_MBUF Rlmt; /* Private part for RLMT. */
+-#endif /* SK_RLMT_MBUF_PRIVATE */
+- struct sk_buff *pOs; /* Pointer to message block */
++ SK_RLMT_MBUF Rlmt; /* Private part for RLMT. */
++#endif
++ struct sk_buff *pOs; /* Pointer to message block */
+ };
+
++/******************************************************************************
++ *
++ * Linux specific TIME defines
++ *
++ ******************************************************************************/
+
+-/*
+- * Time macros
+- */
+ #if SK_TICKS_PER_SEC == 100
+ #define SK_PNMI_HUNDREDS_SEC(t) (t)
+ #else
+-#define SK_PNMI_HUNDREDS_SEC(t) ((((unsigned long)t) * 100) / \
+- (SK_TICKS_PER_SEC))
++#define SK_PNMI_HUNDREDS_SEC(t) ((((unsigned long)t)*100)/(SK_TICKS_PER_SEC))
+ #endif
+
+-/*
+- * New SkOsGetTime
+- */
+ #define SkOsGetTimeCurrent(pAC, pUsec) {\
++ static struct timeval prev_t; \
+ struct timeval t;\
+ do_gettimeofday(&t);\
+- *pUsec = ((((t.tv_sec) * 1000000L)+t.tv_usec)/10000);\
++ if (prev_t.tv_sec == t.tv_sec) { \
++ if (prev_t.tv_usec > t.tv_usec) { \
++ t.tv_usec = prev_t.tv_usec; \
++ } else { \
++ prev_t.tv_usec = t.tv_usec; \
++ } \
++ } else { \
++ prev_t = t; \
++ } \
++ *pUsec = ((t.tv_sec*100L)+(t.tv_usec/10000));\
+ }
+
++/******************************************************************************
++ *
++ * Linux specific IOCTL defines and typedefs
++ *
++ ******************************************************************************/
+
+-/*
+- * ioctl definitions
+- */
+-#define SK_IOCTL_BASE (SIOCDEVPRIVATE)
+-#define SK_IOCTL_GETMIB (SK_IOCTL_BASE + 0)
+-#define SK_IOCTL_SETMIB (SK_IOCTL_BASE + 1)
+-#define SK_IOCTL_PRESETMIB (SK_IOCTL_BASE + 2)
+-#define SK_IOCTL_GEN (SK_IOCTL_BASE + 3)
+-#define SK_IOCTL_DIAG (SK_IOCTL_BASE + 4)
+-
+-typedef struct s_IOCTL SK_GE_IOCTL;
++#define SK_IOCTL_BASE (SIOCDEVPRIVATE)
++#define SK_IOCTL_GETMIB (SK_IOCTL_BASE + 0)
++#define SK_IOCTL_SETMIB (SK_IOCTL_BASE + 1)
++#define SK_IOCTL_PRESETMIB (SK_IOCTL_BASE + 2)
++#define SK_IOCTL_GEN (SK_IOCTL_BASE + 3)
++#define SK_IOCTL_DIAG (SK_IOCTL_BASE + 4)
+
++typedef struct s_IOCTL SK_GE_IOCTL;
+ struct s_IOCTL {
+ char __user * pData;
+ unsigned int Len;
+ };
+
++/******************************************************************************
++ *
++ * Generic sizes and length definitions
++ *
++ ******************************************************************************/
+
+-/*
+- * define sizes of descriptor rings in bytes
+- */
+-
+-#define TX_RING_SIZE (8*1024)
+-#define RX_RING_SIZE (24*1024)
+-
+-/*
+- * Buffer size for ethernet packets
+- */
+-#define ETH_BUF_SIZE 1540
+-#define ETH_MAX_MTU 1514
+-#define ETH_MIN_MTU 60
+-#define ETH_MULTICAST_BIT 0x01
+-#define SK_JUMBO_MTU 9000
+-
+-/*
+- * transmit priority selects the queue: LOW=asynchron, HIGH=synchron
+- */
+-#define TX_PRIO_LOW 0
+-#define TX_PRIO_HIGH 1
++#define TX_RING_SIZE (24*1024) /* GEnesis/Yukon */
++#define RX_RING_SIZE (24*1024) /* GEnesis/Yukon */
++#define RX_MAX_NBR_BUFFERS 128 /* Yukon-EC/-II */
++#define TX_MAX_NBR_BUFFERS 128 /* Yukon-EC/-II */
++#define MAXIMUM_LOW_ADDRESS 0xFFFFFFFF /* Max. low address */
++
++#define ETH_BUF_SIZE 1560 /* multiples of 8 bytes */
++#define ETH_MAX_MTU 1514
++#define ETH_MIN_MTU 60
++#define ETH_MULTICAST_BIT 0x01
++#define SK_JUMBO_MTU 9000
++
++#define TX_PRIO_LOW 0 /* asynchronous queue */
++#define TX_PRIO_HIGH 1 /* synchronous queue */
++#define DESCR_ALIGN 64 /* alignment of Rx/Tx descriptors */
+
+-/*
+- * alignment of rx/tx descriptors
+- */
+-#define DESCR_ALIGN 64
++/******************************************************************************
++ *
++ * PNMI related definitions
++ *
++ ******************************************************************************/
+
+-/*
+- * definitions for pnmi. TODO
+- */
+ #define SK_DRIVER_RESET(pAC, IoC) 0
+ #define SK_DRIVER_SENDEVENT(pAC, IoC) 0
+ #define SK_DRIVER_SELFTEST(pAC, IoC) 0
+@@ -213,20 +243,16 @@
+ #define SK_DRIVER_SET_MTU(pAc,IoC,i,v) 0
+ #define SK_DRIVER_PRESET_MTU(pAc,IoC,i,v) 0
+
+-/*
+-** Interim definition of SK_DRV_TIMER placed in this file until
+-** common modules have boon finallized
+-*/
+-#define SK_DRV_TIMER 11
+-#define SK_DRV_MODERATION_TIMER 1
+-#define SK_DRV_MODERATION_TIMER_LENGTH 1000000 /* 1 second */
+-#define SK_DRV_RX_CLEANUP_TIMER 2
+-#define SK_DRV_RX_CLEANUP_TIMER_LENGTH 1000000 /* 100 millisecs */
+
+-/*
+-** Definitions regarding transmitting frames
+-** any calculating any checksum.
+-*/
++/******************************************************************************
++ *
++ * Various offsets and sizes
++ *
++ ******************************************************************************/
++
++#define SK_DRV_MODERATION_TIMER 1 /* id */
++#define SK_DRV_MODERATION_TIMER_LENGTH 1 /* 1 second */
++
+ #define C_LEN_ETHERMAC_HEADER_DEST_ADDR 6
+ #define C_LEN_ETHERMAC_HEADER_SRC_ADDR 6
+ #define C_LEN_ETHERMAC_HEADER_LENTYPE 2
+@@ -252,114 +278,445 @@
+ #define C_PROTO_ID_UDP 17 /* refer to RFC 790 or Stevens' */
+ #define C_PROTO_ID_TCP 6 /* TCP/IP illustrated for details */
+
+-/* TX and RX descriptors *****************************************************/
++/******************************************************************************
++ *
++ * Tx and Rx descriptor definitions
++ *
++ ******************************************************************************/
+
+ typedef struct s_RxD RXD; /* the receive descriptor */
+-
+ struct s_RxD {
+- volatile SK_U32 RBControl; /* Receive Buffer Control */
+- SK_U32 VNextRxd; /* Next receive descriptor,low dword */
+- SK_U32 VDataLow; /* Receive buffer Addr, low dword */
+- SK_U32 VDataHigh; /* Receive buffer Addr, high dword */
+- SK_U32 FrameStat; /* Receive Frame Status word */
+- SK_U32 TimeStamp; /* Time stamp from XMAC */
+- SK_U32 TcpSums; /* TCP Sum 2 / TCP Sum 1 */
+- SK_U32 TcpSumStarts; /* TCP Sum Start 2 / TCP Sum Start 1 */
+- RXD *pNextRxd; /* Pointer to next Rxd */
+- struct sk_buff *pMBuf; /* Pointer to Linux' socket buffer */
++ volatile SK_U32 RBControl; /* Receive Buffer Control */
++ SK_U32 VNextRxd; /* Next receive descriptor,low dword */
++ SK_U32 VDataLow; /* Receive buffer Addr, low dword */
++ SK_U32 VDataHigh; /* Receive buffer Addr, high dword */
++ SK_U32 FrameStat; /* Receive Frame Status word */
++ SK_U32 TimeStamp; /* Time stamp from XMAC */
++ SK_U32 TcpSums; /* TCP Sum 2 / TCP Sum 1 */
++ SK_U32 TcpSumStarts; /* TCP Sum Start 2 / TCP Sum Start 1 */
++ RXD *pNextRxd; /* Pointer to next Rxd */
++ struct sk_buff *pMBuf; /* Pointer to Linux' socket buffer */
+ };
+
+ typedef struct s_TxD TXD; /* the transmit descriptor */
+-
+ struct s_TxD {
+- volatile SK_U32 TBControl; /* Transmit Buffer Control */
+- SK_U32 VNextTxd; /* Next transmit descriptor,low dword */
+- SK_U32 VDataLow; /* Transmit Buffer Addr, low dword */
+- SK_U32 VDataHigh; /* Transmit Buffer Addr, high dword */
+- SK_U32 FrameStat; /* Transmit Frame Status Word */
+- SK_U32 TcpSumOfs; /* Reserved / TCP Sum Offset */
+- SK_U16 TcpSumSt; /* TCP Sum Start */
+- SK_U16 TcpSumWr; /* TCP Sum Write */
+- SK_U32 TcpReserved; /* not used */
+- TXD *pNextTxd; /* Pointer to next Txd */
+- struct sk_buff *pMBuf; /* Pointer to Linux' socket buffer */
++ volatile SK_U32 TBControl; /* Transmit Buffer Control */
++ SK_U32 VNextTxd; /* Next transmit descriptor,low dword */
++ SK_U32 VDataLow; /* Transmit Buffer Addr, low dword */
++ SK_U32 VDataHigh; /* Transmit Buffer Addr, high dword */
++ SK_U32 FrameStat; /* Transmit Frame Status Word */
++ SK_U32 TcpSumOfs; /* Reserved / TCP Sum Offset */
++ SK_U16 TcpSumSt; /* TCP Sum Start */
++ SK_U16 TcpSumWr; /* TCP Sum Write */
++ SK_U32 TcpReserved; /* not used */
++ TXD *pNextTxd; /* Pointer to next Txd */
++ struct sk_buff *pMBuf; /* Pointer to Linux' socket buffer */
++};
++
++/******************************************************************************
++ *
++ * Generic Yukon-II defines
++ *
++ ******************************************************************************/
++
++#define LE_SIZE sizeof(SK_HWLE)
++#define MAX_NUM_FRAGS (MAX_SKB_FRAGS + 1)
++#define MIN_LEN_OF_LE_TAB 128
++#define MAX_LEN_OF_LE_TAB 4096
++#define MAX_UNUSED_RX_LE_WORKING 8
++#ifdef MAX_FRAG_OVERHEAD
++#undef MAX_FRAG_OVERHEAD
++#define MAX_FRAG_OVERHEAD 4
++#endif
++// as we have a maximum of 16 physical fragments,
++// maximum 1 ADDR64 per physical fragment
++// maximum 4 LEs for VLAN, Csum, LargeSend, Packet
++#define MIN_LE_FREE_REQUIRED ((16*2) + 4)
++#define IS_GMAC(pAc) (!pAc->GIni.GIGenesis)
++#ifdef USE_SYNC_TX_QUEUE
++#define TXS_MAX_LE 256
++#else /* !USE_SYNC_TX_QUEUE */
++#define TXS_MAX_LE 0
++#endif
++
++#define ETHER_MAC_HDR_LEN (6+6+2) // MAC SRC ADDR, MAC DST ADDR, TYPE
++#define IP_HDR_LEN 20
++#define TCP_CSUM_OFFS 0x10
++#define UDP_CSUM_OFFS 0x06
++#define TXA_MAX_LE 256
++#define RX_MAX_LE 256
++#define ST_MAX_LE (SK_MAX_MACS)*((3*RX_MAX_LE)+(TXA_MAX_LE)+(TXS_MAX_LE))
++
++#if (defined (Y2_RECOVERY) || defined (Y2_LE_CHECK))
++/* event for recovery from tx hang or rx out of sync */
++#define SK_DRV_RECOVER 17
++#endif
++/******************************************************************************
++ *
++ * Structures specific for Yukon-II
++ *
++ ******************************************************************************/
++
++typedef struct s_frag SK_FRAG;
++struct s_frag {
++ SK_FRAG *pNext;
++ char *pVirt;
++ SK_U64 pPhys;
++ unsigned int FragLen;
++};
++
++typedef struct s_packet SK_PACKET;
++struct s_packet {
++ /* Common infos: */
++ SK_PACKET *pNext; /* pointer for packet queues */
++ unsigned int PacketLen; /* length of packet */
++ unsigned int NumFrags; /* nbr of fragments (for Rx always 1) */
++ SK_FRAG *pFrag; /* fragment list */
++ SK_FRAG FragArray[MAX_NUM_FRAGS]; /* TX fragment array */
++ unsigned int NextLE; /* next LE to use for the next packet */
++
++ /* Private infos: */
++ struct sk_buff *pMBuf; /* Pointer to Linux' socket buffer */
+ };
+
+-/* Used interrupt bits in the interrupts source register *********************/
++typedef struct s_queue SK_PKT_QUEUE;
++struct s_queue {
++ SK_PACKET *pHead;
++ SK_PACKET *pTail;
++ spinlock_t QueueLock; /* serialize packet accesses */
++};
+
+-#define DRIVER_IRQS ((IS_IRQ_SW) | \
+- (IS_R1_F) |(IS_R2_F) | \
+- (IS_XS1_F) |(IS_XA1_F) | \
+- (IS_XS2_F) |(IS_XA2_F))
+-
+-#define SPECIAL_IRQS ((IS_HW_ERR) |(IS_I2C_READY) | \
+- (IS_EXT_REG) |(IS_TIMINT) | \
+- (IS_PA_TO_RX1) |(IS_PA_TO_RX2) | \
+- (IS_PA_TO_TX1) |(IS_PA_TO_TX2) | \
+- (IS_MAC1) |(IS_LNK_SYNC_M1)| \
+- (IS_MAC2) |(IS_LNK_SYNC_M2)| \
+- (IS_R1_C) |(IS_R2_C) | \
+- (IS_XS1_C) |(IS_XA1_C) | \
+- (IS_XS2_C) |(IS_XA2_C))
+-
+-#define IRQ_MASK ((IS_IRQ_SW) | \
+- (IS_R1_B) |(IS_R1_F) |(IS_R2_B) |(IS_R2_F) | \
+- (IS_XS1_B) |(IS_XS1_F) |(IS_XA1_B)|(IS_XA1_F)| \
+- (IS_XS2_B) |(IS_XS2_F) |(IS_XA2_B)|(IS_XA2_F)| \
+- (IS_HW_ERR) |(IS_I2C_READY)| \
+- (IS_EXT_REG) |(IS_TIMINT) | \
+- (IS_PA_TO_RX1) |(IS_PA_TO_RX2)| \
+- (IS_PA_TO_TX1) |(IS_PA_TO_TX2)| \
+- (IS_MAC1) |(IS_MAC2) | \
+- (IS_R1_C) |(IS_R2_C) | \
+- (IS_XS1_C) |(IS_XA1_C) | \
+- (IS_XS2_C) |(IS_XA2_C))
++/*******************************************************************************
++ *
++ * Macros specific for Yukon-II queues
++ *
++ ******************************************************************************/
+
+-#define IRQ_HWE_MASK (IS_ERR_MSK) /* enable all HW irqs */
++#define IS_Q_EMPTY(pQueue) ((pQueue)->pHead != NULL) ? SK_FALSE : SK_TRUE
++#define IS_Q_LOCKED(pQueue) spin_is_locked(&((pQueue)->QueueLock))
++
++#define PLAIN_POP_FIRST_PKT_FROM_QUEUE(pQueue, pPacket) { \
++ if ((pQueue)->pHead != NULL) { \
++ (pPacket) = (pQueue)->pHead; \
++ (pQueue)->pHead = (pPacket)->pNext; \
++ if ((pQueue)->pHead == NULL) { \
++ (pQueue)->pTail = NULL; \
++ } \
++ (pPacket)->pNext = NULL; \
++ } else { \
++ (pPacket) = NULL; \
++ } \
++}
++
++#define PLAIN_PUSH_PKT_AS_FIRST_IN_QUEUE(pQueue, pPacket) { \
++ if ((pQueue)->pHead != NULL) { \
++ (pPacket)->pNext = (pQueue)->pHead; \
++ } else { \
++ (pPacket)->pNext = NULL; \
++ (pQueue)->pTail = (pPacket); \
++ } \
++ (pQueue)->pHead = (pPacket); \
++}
++
++#define PLAIN_PUSH_PKT_AS_LAST_IN_QUEUE(pQueue, pPacket) { \
++ (pPacket)->pNext = NULL; \
++ if ((pQueue)->pTail != NULL) { \
++ (pQueue)->pTail->pNext = (pPacket); \
++ } else { \
++ (pQueue)->pHead = (pPacket); \
++ } \
++ (pQueue)->pTail = (pPacket); \
++}
++
++#define PLAIN_PUSH_MULTIPLE_PKT_AS_LAST_IN_QUEUE(pQueue,pPktGrpStart,pPktGrpEnd) { \
++ if ((pPktGrpStart) != NULL) { \
++ if ((pQueue)->pTail != NULL) { \
++ (pQueue)->pTail->pNext = (pPktGrpStart); \
++ } else { \
++ (pQueue)->pHead = (pPktGrpStart); \
++ } \
++ (pQueue)->pTail = (pPktGrpEnd); \
++ } \
++}
++
++/* Required: 'Flags' */
++#define POP_FIRST_PKT_FROM_QUEUE(pQueue, pPacket) { \
++ spin_lock_irqsave(&((pQueue)->QueueLock), Flags); \
++ if ((pQueue)->pHead != NULL) { \
++ (pPacket) = (pQueue)->pHead; \
++ (pQueue)->pHead = (pPacket)->pNext; \
++ if ((pQueue)->pHead == NULL) { \
++ (pQueue)->pTail = NULL; \
++ } \
++ (pPacket)->pNext = NULL; \
++ } else { \
++ (pPacket) = NULL; \
++ } \
++ spin_unlock_irqrestore(&((pQueue)->QueueLock), Flags); \
++}
++
++/* Required: 'Flags' */
++#define PUSH_PKT_AS_FIRST_IN_QUEUE(pQueue, pPacket) { \
++ spin_lock_irqsave(&(pQueue)->QueueLock, Flags); \
++ if ((pQueue)->pHead != NULL) { \
++ (pPacket)->pNext = (pQueue)->pHead; \
++ } else { \
++ (pPacket)->pNext = NULL; \
++ (pQueue)->pTail = (pPacket); \
++ } \
++ (pQueue)->pHead = (pPacket); \
++ spin_unlock_irqrestore(&(pQueue)->QueueLock, Flags); \
++}
++
++/* Required: 'Flags' */
++#define PUSH_PKT_AS_LAST_IN_QUEUE(pQueue, pPacket) { \
++ (pPacket)->pNext = NULL; \
++ spin_lock_irqsave(&(pQueue)->QueueLock, Flags); \
++ if ((pQueue)->pTail != NULL) { \
++ (pQueue)->pTail->pNext = (pPacket); \
++ } else { \
++ (pQueue)->pHead = (pPacket); \
++ } \
++ (pQueue)->pTail = (pPacket); \
++ spin_unlock_irqrestore(&(pQueue)->QueueLock, Flags); \
++}
++
++/* Required: 'Flags' */
++#define PUSH_MULTIPLE_PKT_AS_LAST_IN_QUEUE(pQueue,pPktGrpStart,pPktGrpEnd) { \
++ if ((pPktGrpStart) != NULL) { \
++ spin_lock_irqsave(&(pQueue)->QueueLock, Flags); \
++ if ((pQueue)->pTail != NULL) { \
++ (pQueue)->pTail->pNext = (pPktGrpStart); \
++ } else { \
++ (pQueue)->pHead = (pPktGrpStart); \
++ } \
++ (pQueue)->pTail = (pPktGrpEnd); \
++ spin_unlock_irqrestore(&(pQueue)->QueueLock, Flags); \
++ } \
++}
++
++/*
++ *Check if the low address (32 bit) is near the 4G limit or over it.
++ * Set the high address to a wrong value.
++ * Doing so we force to write the ADDR64 LE.
++ */
++#define CHECK_LOW_ADDRESS( _HighAddress, _LowAddress , _Length) { \
++ if ((~0-_LowAddress) <_Length) { \
++ _HighAddress= MAXIMUM_LOW_ADDRESS; \
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, \
++ ("High Address must be set for HW. LowAddr = %d Length = %d\n", \
++ _LowAddress, _Length)); \
++ } \
++}
++
++/*******************************************************************************
++ *
++ * Macros specific for Yukon-II queues (tist)
++ *
++ ******************************************************************************/
++
++#ifdef USE_TIST_FOR_RESET
++/* port is fully operational */
++#define SK_PSTATE_NOT_WAITING_FOR_TIST 0
++/* port in reset until any tist LE */
++#define SK_PSTATE_WAITING_FOR_ANY_TIST BIT_0
++/* port in reset until timer reaches pAC->MinTistLo */
++#define SK_PSTATE_WAITING_FOR_SPECIFIC_TIST BIT_1
++#define SK_PSTATE_PORT_SHIFT 4
++#define SK_PSTATE_PORT_MASK ((1 << SK_PSTATE_PORT_SHIFT) - 1)
++
++/* use this + Port to build OP_MOD_TXINDEX_NO_PORT_A|B */
++#define OP_MOD_TXINDEX 0x71
++/* opcode for a TX_INDEX LE in which Port A has to be ignored */
++#define OP_MOD_TXINDEX_NO_PORT_A 0x71
++/* opcode for a TX_INDEX LE in which Port B has to be ignored */
++#define OP_MOD_TXINDEX_NO_PORT_B 0x72
++/* opcode for LE to be ignored because port is still in reset */
++#define OP_MOD_LE 0x7F
++
++/* set tist wait mode Bit for port */
++#define SK_SET_WAIT_BIT_FOR_PORT(pAC, Bit, Port) \
++ { \
++ (pAC)->AdapterResetState |= ((Bit) << (SK_PSTATE_PORT_SHIFT * Port)); \
++ }
++
++/* reset tist waiting for specified port */
++#define SK_CLR_STATE_FOR_PORT(pAC, Port) \
++ { \
++ (pAC)->AdapterResetState &= \
++ ~(SK_PSTATE_PORT_MASK << (SK_PSTATE_PORT_SHIFT * Port)); \
++ }
++
++/* return SK_TRUE when port is in reset waiting for tist */
++#define SK_PORT_WAITING_FOR_TIST(pAC, Port) \
++ ((((pAC)->AdapterResetState >> (SK_PSTATE_PORT_SHIFT * Port)) & \
++ SK_PSTATE_PORT_MASK) != SK_PSTATE_NOT_WAITING_FOR_TIST)
++
++/* return SK_TRUE when port is in reset waiting for any tist */
++#define SK_PORT_WAITING_FOR_ANY_TIST(pAC, Port) \
++ ((((pAC)->AdapterResetState >> (SK_PSTATE_PORT_SHIFT * Port)) & \
++ SK_PSTATE_WAITING_FOR_ANY_TIST) == SK_PSTATE_WAITING_FOR_ANY_TIST)
++
++/* return SK_TRUE when port is in reset waiting for a specific tist */
++#define SK_PORT_WAITING_FOR_SPECIFIC_TIST(pAC, Port) \
++ ((((pAC)->AdapterResetState >> (SK_PSTATE_PORT_SHIFT * Port)) & \
++ SK_PSTATE_WAITING_FOR_SPECIFIC_TIST) == \
++ SK_PSTATE_WAITING_FOR_SPECIFIC_TIST)
++
++/* return whether adapter is expecting a tist LE */
++#define SK_ADAPTER_WAITING_FOR_TIST(pAC) ((pAC)->AdapterResetState != 0)
++
++/* enable timestamp timer and force creation of tist LEs */
++#define Y2_ENABLE_TIST(IoC) \
++ SK_OUT8(IoC, GMAC_TI_ST_CTRL, (SK_U8) GMT_ST_START)
++
++/* disable timestamp timer and stop creation of tist LEs */
++#define Y2_DISABLE_TIST(IoC) \
++ SK_OUT8(IoC, GMAC_TI_ST_CTRL, (SK_U8) GMT_ST_STOP)
++
++/* get current value of timestamp timer */
++#define Y2_GET_TIST_LOW_VAL(IoC, pVal) \
++ SK_IN32(IoC, GMAC_TI_ST_VAL, pVal)
++
++#endif
++
++
++/*******************************************************************************
++ *
++ * Used interrupt bits in the interrupts source register
++ *
++ ******************************************************************************/
++
++#define DRIVER_IRQS ((IS_IRQ_SW) | \
++ (IS_R1_F) | (IS_R2_F) | \
++ (IS_XS1_F) | (IS_XA1_F) | \
++ (IS_XS2_F) | (IS_XA2_F))
++
++#define TX_COMPL_IRQS ((IS_XS1_B) | (IS_XS1_F) | \
++ (IS_XA1_B) | (IS_XA1_F) | \
++ (IS_XS2_B) | (IS_XS2_F) | \
++ (IS_XA2_B) | (IS_XA2_F))
++
++#define NAPI_DRV_IRQS ((IS_R1_F) | (IS_R2_F) | \
++ (IS_XS1_F) | (IS_XA1_F)| \
++ (IS_XS2_F) | (IS_XA2_F))
++
++#define Y2_DRIVER_IRQS ((Y2_IS_STAT_BMU) | (Y2_IS_IRQ_SW) | (Y2_IS_POLL_CHK))
++
++#define SPECIAL_IRQS ((IS_HW_ERR) |(IS_I2C_READY) | \
++ (IS_EXT_REG) |(IS_TIMINT) | \
++ (IS_PA_TO_RX1) |(IS_PA_TO_RX2) | \
++ (IS_PA_TO_TX1) |(IS_PA_TO_TX2) | \
++ (IS_MAC1) |(IS_LNK_SYNC_M1)| \
++ (IS_MAC2) |(IS_LNK_SYNC_M2)| \
++ (IS_R1_C) |(IS_R2_C) | \
++ (IS_XS1_C) |(IS_XA1_C) | \
++ (IS_XS2_C) |(IS_XA2_C))
++
++#define Y2_SPECIAL_IRQS ((Y2_IS_HW_ERR) |(Y2_IS_ASF) | \
++ (Y2_IS_TWSI_RDY) |(Y2_IS_TIMINT) | \
++ (Y2_IS_IRQ_PHY2) |(Y2_IS_IRQ_MAC2) | \
++ (Y2_IS_CHK_RX2) |(Y2_IS_CHK_TXS2) | \
++ (Y2_IS_CHK_TXA2) |(Y2_IS_IRQ_PHY1) | \
++ (Y2_IS_IRQ_MAC1) |(Y2_IS_CHK_RX1) | \
++ (Y2_IS_CHK_TXS1) |(Y2_IS_CHK_TXA1))
++
++#define IRQ_MASK ((IS_IRQ_SW) | \
++ (IS_R1_F) |(IS_R2_F) | \
++ (IS_XS1_F) |(IS_XA1_F) | \
++ (IS_XS2_F) |(IS_XA2_F) | \
++ (IS_HW_ERR) |(IS_I2C_READY)| \
++ (IS_EXT_REG) |(IS_TIMINT) | \
++ (IS_PA_TO_RX1) |(IS_PA_TO_RX2)| \
++ (IS_PA_TO_TX1) |(IS_PA_TO_TX2)| \
++ (IS_MAC1) |(IS_MAC2) | \
++ (IS_R1_C) |(IS_R2_C) | \
++ (IS_XS1_C) |(IS_XA1_C) | \
++ (IS_XS2_C) |(IS_XA2_C))
++
++#define Y2_IRQ_MASK ((Y2_DRIVER_IRQS) | (Y2_SPECIAL_IRQS))
++
++#define IRQ_HWE_MASK (IS_ERR_MSK) /* enable all HW irqs */
++#define Y2_IRQ_HWE_MASK (Y2_HWE_ALL_MSK) /* enable all HW irqs */
+
+ typedef struct s_DevNet DEV_NET;
+
+ struct s_DevNet {
+- struct proc_dir_entry *proc;
+- int PortNr;
+- int NetNr;
+- int Mtu;
+- int Up;
+- SK_AC *pAC;
++ struct proc_dir_entry *proc;
++ int PortNr;
++ int NetNr;
++ char InitialDevName[20];
++ SK_BOOL NetConsoleMode;
++#ifdef Y2_RECOVERY
++ struct timer_list KernelTimer; /* Kernel timer struct */
++ int TransmitTimeoutTimer; /* Transmit timer */
++ SK_BOOL TimerExpired; /* Transmit timer */
++ SK_BOOL InRecover; /* Recover flag */
++#ifdef Y2_RX_CHECK
++ SK_U32 PreviousMACFifoRP; /* Backup of the FRP */
++ SK_U32 PreviousMACFifoRLev; /* Backup of the FRL */
++ SK_U32 PreviousRXFifoRP; /* Backup of the RX FRP */
++ SK_U8 PreviousRXFifoRLev; /* Backup of the RX FRL */
++ SK_U32 LastJiffies; /* Backup of the jiffies*/
++#endif
++#endif
++ SK_AC *pAC;
+ };
+
+-typedef struct s_TxPort TX_PORT;
++/*******************************************************************************
++ *
++ * Rx/Tx Port structures
++ *
++ ******************************************************************************/
+
+-struct s_TxPort {
+- /* the transmit descriptor rings */
+- caddr_t pTxDescrRing; /* descriptor area memory */
+- SK_U64 VTxDescrRing; /* descr. area bus virt. addr. */
+- TXD *pTxdRingHead; /* Head of Tx rings */
+- TXD *pTxdRingTail; /* Tail of Tx rings */
+- TXD *pTxdRingPrev; /* descriptor sent previously */
+- int TxdRingFree; /* # of free entrys */
+- spinlock_t TxDesRingLock; /* serialize descriptor accesses */
+- caddr_t HwAddr; /* bmu registers address */
+- int PortIndex; /* index number of port (0 or 1) */
++typedef struct s_TxPort TX_PORT;
++struct s_TxPort { /* the transmit descriptor rings */
++ caddr_t pTxDescrRing; /* descriptor area memory */
++ SK_U64 VTxDescrRing; /* descr. area bus virt. addr. */
++ TXD *pTxdRingHead; /* Head of Tx rings */
++ TXD *pTxdRingTail; /* Tail of Tx rings */
++ TXD *pTxdRingPrev; /* descriptor sent previously */
++ int TxdRingPrevFree;/* previously # of free entrys */
++ int TxdRingFree; /* # of free entrys */
++ spinlock_t TxDesRingLock; /* serialize descriptor accesses */
++ caddr_t HwAddr; /* bmu registers address */
++ int PortIndex; /* index number of port (0 or 1) */
++ SK_PACKET *TransmitPacketTable;
++ SK_LE_TABLE TxALET; /* tx (async) list element table */
++ SK_LE_TABLE TxSLET; /* tx (sync) list element table */
++ SK_PKT_QUEUE TxQ_free;
++ SK_PKT_QUEUE TxAQ_waiting;
++ SK_PKT_QUEUE TxSQ_waiting;
++ SK_PKT_QUEUE TxAQ_working;
++ SK_PKT_QUEUE TxSQ_working;
++ unsigned LastDone;
+ };
+
+-typedef struct s_RxPort RX_PORT;
+-
+-struct s_RxPort {
+- /* the receive descriptor rings */
+- caddr_t pRxDescrRing; /* descriptor area memory */
+- SK_U64 VRxDescrRing; /* descr. area bus virt. addr. */
+- RXD *pRxdRingHead; /* Head of Rx rings */
+- RXD *pRxdRingTail; /* Tail of Rx rings */
+- RXD *pRxdRingPrev; /* descriptor given to BMU previously */
+- int RxdRingFree; /* # of free entrys */
+- spinlock_t RxDesRingLock; /* serialize descriptor accesses */
+- int RxFillLimit; /* limit for buffers in ring */
+- caddr_t HwAddr; /* bmu registers address */
+- int PortIndex; /* index number of port (0 or 1) */
++typedef struct s_RxPort RX_PORT;
++struct s_RxPort { /* the receive descriptor rings */
++ caddr_t pRxDescrRing; /* descriptor area memory */
++ SK_U64 VRxDescrRing; /* descr. area bus virt. addr. */
++ RXD *pRxdRingHead; /* Head of Rx rings */
++ RXD *pRxdRingTail; /* Tail of Rx rings */
++ RXD *pRxdRingPrev; /* descr given to BMU previously */
++ int RxdRingFree; /* # of free entrys */
++ spinlock_t RxDesRingLock; /* serialize descriptor accesses */
++ int RxFillLimit; /* limit for buffers in ring */
++ caddr_t HwAddr; /* bmu registers address */
++ int PortIndex; /* index number of port (0 or 1) */
++ SK_BOOL UseRxCsum; /* use Rx checksumming (yes/no) */
++ SK_PACKET *ReceivePacketTable;
++ SK_LE_TABLE RxLET; /* rx list element table */
++ SK_PKT_QUEUE RxQ_working;
++ SK_PKT_QUEUE RxQ_waiting;
++ int RxBufSize;
+ };
+
+-/* Definitions needed for interrupt moderation *******************************/
++/*******************************************************************************
++ *
++ * Interrupt masks used in combination with interrupt moderation
++ *
++ ******************************************************************************/
+
+ #define IRQ_EOF_AS_TX ((IS_XA1_F) | (IS_XA2_F))
+ #define IRQ_EOF_SY_TX ((IS_XS1_F) | (IS_XS2_F))
+@@ -371,139 +728,150 @@
+ #define IRQ_MASK_SP_TX ((SPECIAL_IRQS) | (IRQ_MASK_TX_ONLY))
+ #define IRQ_MASK_RX_TX_SP ((SPECIAL_IRQS) | (IRQ_MASK_TX_RX))
+
+-#define C_INT_MOD_NONE 1
+-#define C_INT_MOD_STATIC 2
+-#define C_INT_MOD_DYNAMIC 4
+-
+-#define C_CLK_FREQ_GENESIS 53215000 /* shorter: 53.125 MHz */
+-#define C_CLK_FREQ_YUKON 78215000 /* shorter: 78.125 MHz */
+-
+-#define C_INTS_PER_SEC_DEFAULT 2000
+-#define C_INT_MOD_ENABLE_PERCENTAGE 50 /* if higher 50% enable */
+-#define C_INT_MOD_DISABLE_PERCENTAGE 50 /* if lower 50% disable */
+-#define C_INT_MOD_IPS_LOWER_RANGE 30
+-#define C_INT_MOD_IPS_UPPER_RANGE 40000
+-
+-
+-typedef struct s_DynIrqModInfo DIM_INFO;
+-struct s_DynIrqModInfo {
+- unsigned long PrevTimeVal;
+- unsigned int PrevSysLoad;
+- unsigned int PrevUsedTime;
+- unsigned int PrevTotalTime;
+- int PrevUsedDescrRatio;
+- int NbrProcessedDescr;
+- SK_U64 PrevPort0RxIntrCts;
+- SK_U64 PrevPort1RxIntrCts;
+- SK_U64 PrevPort0TxIntrCts;
+- SK_U64 PrevPort1TxIntrCts;
+- SK_BOOL ModJustEnabled; /* Moderation just enabled yes/no */
+-
+- int MaxModIntsPerSec; /* Moderation Threshold */
+- int MaxModIntsPerSecUpperLimit; /* Upper limit for DIM */
+- int MaxModIntsPerSecLowerLimit; /* Lower limit for DIM */
+-
+- long MaskIrqModeration; /* ModIrqType (eg. 'TxRx') */
+- SK_BOOL DisplayStats; /* Stats yes/no */
+- SK_BOOL AutoSizing; /* Resize DIM-timer on/off */
+- int IntModTypeSelect; /* EnableIntMod (eg. 'dynamic') */
++#define IRQ_MASK_Y2_TX_ONLY (Y2_IS_STAT_BMU)
++#define IRQ_MASK_Y2_RX_ONLY (Y2_IS_STAT_BMU)
++#define IRQ_MASK_Y2_SP_ONLY (SPECIAL_IRQS)
++#define IRQ_MASK_Y2_TX_RX ((IRQ_MASK_TX_ONLY)| (IRQ_MASK_RX_ONLY))
++#define IRQ_MASK_Y2_SP_RX ((SPECIAL_IRQS) | (IRQ_MASK_RX_ONLY))
++#define IRQ_MASK_Y2_SP_TX ((SPECIAL_IRQS) | (IRQ_MASK_TX_ONLY))
++#define IRQ_MASK_Y2_RX_TX_SP ((SPECIAL_IRQS) | (IRQ_MASK_TX_RX))
+
+- SK_TIMER ModTimer; /* just some timer */
+-};
++/*******************************************************************************
++ *
++ * Defines and typedefs regarding interrupt moderation
++ *
++ ******************************************************************************/
+
+-typedef struct s_PerStrm PER_STRM;
++#define C_INT_MOD_NONE 1
++#define C_INT_MOD_STATIC 2
++#define C_INT_MOD_DYNAMIC 4
++
++#define C_CLK_FREQ_GENESIS 53215000 /* or: 53.125 MHz */
++#define C_CLK_FREQ_YUKON 78215000 /* or: 78.125 MHz */
++#define C_CLK_FREQ_YUKON_EC 125000000 /* or: 125.000 MHz */
++
++#define C_Y2_INTS_PER_SEC_DEFAULT 5000
++#define C_INTS_PER_SEC_DEFAULT 2000
++#define C_INT_MOD_IPS_LOWER_RANGE 30 /* in IRQs/second */
++#define C_INT_MOD_IPS_UPPER_RANGE 40000 /* in IRQs/second */
++
++typedef struct s_DynIrqModInfo {
++ SK_U64 PrevPort0RxIntrCts;
++ SK_U64 PrevPort1RxIntrCts;
++ SK_U64 PrevPort0TxIntrCts;
++ SK_U64 PrevPort1TxIntrCts;
++ SK_U64 PrevPort0StatusLeIntrCts;
++ SK_U64 PrevPort1StatusLeIntrCts;
++ int MaxModIntsPerSec; /* Moderation Threshold */
++ int MaxModIntsPerSecUpperLimit; /* Upper limit for DIM */
++ int MaxModIntsPerSecLowerLimit; /* Lower limit for DIM */
++ long MaskIrqModeration; /* IRQ Mask (eg. 'TxRx') */
++ int IntModTypeSelect; /* Type (eg. 'dynamic') */
++ int DynIrqModSampleInterval; /* expressed in seconds! */
++ SK_TIMER ModTimer; /* Timer for dynamic mod. */
++} DIM_INFO;
+
+-#define SK_ALLOC_IRQ 0x00000001
++/*******************************************************************************
++ *
++ * Defines and typedefs regarding wake-on-lan
++ *
++ ******************************************************************************/
++
++typedef struct s_WakeOnLanInfo {
++ SK_U32 SupportedWolOptions; /* e.g. WAKE_PHY... */
++ SK_U32 ConfiguredWolOptions; /* e.g. WAKE_PHY... */
++} WOL_INFO;
+
+-#ifdef SK_DIAG_SUPPORT
++#define SK_ALLOC_IRQ 0x00000001
+ #define DIAG_ACTIVE 1
+ #define DIAG_NOTACTIVE 0
+-#endif
+
+ /****************************************************************************
++ *
+ * Per board structure / Adapter Context structure:
+- * Allocated within attach(9e) and freed within detach(9e).
+- * Contains all 'per device' necessary handles, flags, locks etc.:
+- */
++ * Contains all 'per device' necessary handles, flags, locks etc.:
++ *
++ ******************************************************************************/
++
+ struct s_AC {
+- SK_GEINIT GIni; /* GE init struct */
+- SK_PNMI Pnmi; /* PNMI data struct */
+- SK_VPD vpd; /* vpd data struct */
+- SK_QUEUE Event; /* Event queue */
+- SK_HWT Hwt; /* Hardware Timer control struct */
+- SK_TIMCTRL Tim; /* Software Timer control struct */
+- SK_I2C I2c; /* I2C relevant data structure */
+- SK_ADDR Addr; /* for Address module */
+- SK_CSUM Csum; /* for checksum module */
+- SK_RLMT Rlmt; /* for rlmt module */
+- spinlock_t SlowPathLock; /* Normal IRQ lock */
+- SK_PNMI_STRUCT_DATA PnmiStruct; /* structure to get all Pnmi-Data */
+- int RlmtMode; /* link check mode to set */
+- int RlmtNets; /* Number of nets */
+-
+- SK_IOC IoBase; /* register set of adapter */
+- int BoardLevel; /* level of active hw init (0-2) */
+- char DeviceStr[80]; /* adapter string from vpd */
+- SK_U32 AllocFlag; /* flag allocation of resources */
+- struct pci_dev *PciDev; /* for access to pci config space */
+- SK_U32 PciDevId; /* pci device id */
+- struct SK_NET_DEVICE *dev[2]; /* pointer to device struct */
+- char Name[30]; /* driver name */
+- struct SK_NET_DEVICE *Next; /* link all devices (for clearing) */
+- int RxBufSize; /* length of receive buffers */
+- struct net_device_stats stats; /* linux 'netstat -i' statistics */
+- int Index; /* internal board index number */
+-
+- /* adapter RAM sizes for queues of active port */
+- int RxQueueSize; /* memory used for receive queue */
+- int TxSQueueSize; /* memory used for sync. tx queue */
+- int TxAQueueSize; /* memory used for async. tx queue */
+-
+- int PromiscCount; /* promiscuous mode counter */
+- int AllMultiCount; /* allmulticast mode counter */
+- int MulticCount; /* number of different MC */
+- /* addresses for this board */
+- /* (may be more than HW can)*/
+-
+- int HWRevision; /* Hardware revision */
+- int ActivePort; /* the active XMAC port */
+- int MaxPorts; /* number of activated ports */
+- int TxDescrPerRing; /* # of descriptors per tx ring */
+- int RxDescrPerRing; /* # of descriptors per rx ring */
+-
+- caddr_t pDescrMem; /* Pointer to the descriptor area */
+- dma_addr_t pDescrMemDMA; /* PCI DMA address of area */
+-
+- /* the port structures with descriptor rings */
+- TX_PORT TxPort[SK_MAX_MACS][2];
+- RX_PORT RxPort[SK_MAX_MACS];
+-
+- unsigned int CsOfs1; /* for checksum calculation */
+- unsigned int CsOfs2; /* for checksum calculation */
+- SK_U32 CsOfs; /* for checksum calculation */
+-
+- SK_BOOL CheckQueue; /* check event queue soon */
+- SK_TIMER DrvCleanupTimer;/* to check for pending descriptors */
+- DIM_INFO DynIrqModInfo; /* all data related to DIM */
+-
+- /* Only for tests */
+- int PortUp;
+- int PortDown;
+- int ChipsetType; /* Chipset family type
+- * 0 == Genesis family support
+- * 1 == Yukon family support
+- */
+-#ifdef SK_DIAG_SUPPORT
+- SK_U32 DiagModeActive; /* is diag active? */
+- SK_BOOL DiagFlowCtrl; /* for control purposes */
+- SK_PNMI_STRUCT_DATA PnmiBackup; /* backup structure for all Pnmi-Data */
+- SK_BOOL WasIfUp[SK_MAX_MACS]; /* for OpenClose while
+- * DIAG is busy with NIC
+- */
++ SK_GEINIT GIni; /* GE init struct */
++ SK_PNMI Pnmi; /* PNMI data struct */
++ SK_VPD vpd; /* vpd data struct */
++ SK_QUEUE Event; /* Event queue */
++ SK_HWT Hwt; /* Hardware Timer ctrl struct */
++ SK_TIMCTRL Tim; /* Software Timer ctrl struct */
++ SK_I2C I2c; /* I2C relevant data structure*/
++ SK_ADDR Addr; /* for Address module */
++ SK_CSUM Csum; /* for checksum module */
++ SK_RLMT Rlmt; /* for rlmt module */
++ spinlock_t SlowPathLock; /* Normal IRQ lock */
++ spinlock_t TxQueueLock; /* TX Queue lock */
++ SK_PNMI_STRUCT_DATA PnmiStruct; /* struct for all Pnmi-Data */
++ int RlmtMode; /* link check mode to set */
++ int RlmtNets; /* Number of nets */
++ SK_IOC IoBase; /* register set of adapter */
++ int BoardLevel; /* level of hw init (0-2) */
++ char DeviceStr[80]; /* adapter string from vpd */
++ SK_U32 AllocFlag; /* alloc flag of resources */
++ struct pci_dev *PciDev; /* for access to pci cfg space*/
++ SK_U32 PciDevId; /* pci device id */
++ struct SK_NET_DEVICE *dev[2]; /* pointer to device struct */
++ char Name[30]; /* driver name */
++ struct SK_NET_DEVICE *Next; /* link all devs for cleanup */
++ struct net_device_stats stats; /* linux 'netstat -i' stats */
++ int Index; /* internal board idx number */
++ int RxQueueSize; /* memory used for RX queue */
++ int TxSQueueSize; /* memory used for TXS queue */
++ int TxAQueueSize; /* memory used for TXA queue */
++ int PromiscCount; /* promiscuous mode counter */
++ int AllMultiCount; /* allmulticast mode counter */
++ int MulticCount; /* number of MC addresses used*/
++ int HWRevision; /* Hardware revision */
++ int ActivePort; /* the active XMAC port */
++ int MaxPorts; /* number of activated ports */
++ int TxDescrPerRing;/* # of descriptors TX ring */
++ int RxDescrPerRing;/* # of descriptors RX ring */
++ caddr_t pDescrMem; /* Ptr to the descriptor area */
++ dma_addr_t pDescrMemDMA; /* PCI DMA address of area */
++ SK_U32 PciState[16]; /* PCI state */
++ TX_PORT TxPort[SK_MAX_MACS][2];
++ RX_PORT RxPort[SK_MAX_MACS];
++ SK_LE_TABLE StatusLETable;
++ unsigned SizeOfAlignedLETables;
++ spinlock_t SetPutIndexLock;
++ int MaxUnusedRxLeWorking;
++ unsigned int CsOfs1; /* for checksum calculation */
++ unsigned int CsOfs2; /* for checksum calculation */
++ SK_U32 CsOfs; /* for checksum calculation */
++ SK_BOOL CheckQueue; /* check event queue soon */
++ DIM_INFO DynIrqModInfo; /* all data related to IntMod */
++ WOL_INFO WolInfo; /* all info regarding WOL */
++ int ChipsetType; /* 0=GENESIS; 1=Yukon */
++ SK_BOOL LowLatency; /* LowLatency optimization on?*/
++ SK_U32 DiagModeActive;/* is diag active? */
++ SK_BOOL DiagFlowCtrl; /* for control purposes */
++ SK_PNMI_STRUCT_DATA PnmiBackup; /* backup structure for PNMI */
++ SK_BOOL WasIfUp[SK_MAX_MACS];
++#ifdef USE_TIST_FOR_RESET
++ int AdapterResetState;
++ SK_U32 MinTistLo;
++ SK_U32 MinTistHi;
++#endif
++#ifdef Y2_RECOVERY
++ int LastPort; /* port for curr. handled rx */
++ int LastOpc; /* last rx LEs opcode */
++#endif
++#ifdef Y2_SYNC_CHECK
++ unsigned long FramesWithoutSyncCheck; /* since last check */
+ #endif
+-
+ };
+
+
+-#endif /* __INC_SKDRV2ND_H */
+
++#endif
++
++/*******************************************************************************
++ *
++ * End of file
++ *
++ ******************************************************************************/
+diff -ruN linux/drivers/net/sk98lin/h/skerror.h linux-new/drivers/net/sk98lin/h/skerror.h
+--- linux/drivers/net/sk98lin/h/skerror.h 2005-09-26 13:32:47.000000000 +0400
++++ linux-new/drivers/net/sk98lin/h/skerror.h 2005-08-09 17:15:51.000000000 +0400
+@@ -2,8 +2,8 @@
+ *
+ * Name: skerror.h
+ * Project: Gigabit Ethernet Adapters, Common Modules
+- * Version: $Revision: 1.7 $
+- * Date: $Date: 2003/05/13 17:25:13 $
++ * Version: $Revision: 2.2 $
++ * Date: $Date: 2004/05/24 15:27:19 $
+ * Purpose: SK specific Error log support
+ *
+ ******************************************************************************/
+@@ -11,13 +11,12 @@
+ /******************************************************************************
+ *
+ * (C)Copyright 1998-2002 SysKonnect.
+- * (C)Copyright 2002-2003 Marvell.
++ * (C)Copyright 2002-2004 Marvell.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+- *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+@@ -36,7 +35,6 @@
+ #define SK_ERRCL_HW (1L<<4) /* Hardware Failure */
+ #define SK_ERRCL_COMM (1L<<5) /* Communication error */
+
+-
+ /*
+ * Define Error Code Bases
+ */
+@@ -49,7 +47,9 @@
+ #define SK_ERRBASE_I2C 700 /* Base Error number for I2C module */
+ #define SK_ERRBASE_QUEUE 800 /* Base Error number for Scheduler */
+ #define SK_ERRBASE_ADDR 900 /* Base Error number for Address module */
+-#define SK_ERRBASE_PECP 1000 /* Base Error number for PECP */
++#define SK_ERRBASE_PECP 1000 /* Base Error number for PECP */
+ #define SK_ERRBASE_DRV 1100 /* Base Error number for Driver */
++#define SK_ERRBASE_ASF 1200 /* Base Error number for ASF */
+
+ #endif /* _INC_SKERROR_H_ */
++
+diff -ruN linux/drivers/net/sk98lin/h/skgedrv.h linux-new/drivers/net/sk98lin/h/skgedrv.h
+--- linux/drivers/net/sk98lin/h/skgedrv.h 2005-09-26 13:32:47.000000000 +0400
++++ linux-new/drivers/net/sk98lin/h/skgedrv.h 2005-08-09 17:15:51.000000000 +0400
+@@ -2,8 +2,8 @@
+ *
+ * Name: skgedrv.h
+ * Project: Gigabit Ethernet Adapters, Common Modules
+- * Version: $Revision: 1.10 $
+- * Date: $Date: 2003/07/04 12:25:01 $
++ * Version: $Revision: 2.2 $
++ * Date: $Date: 2005/07/14 10:16:00 $
+ * Purpose: Interface with the driver
+ *
+ ******************************************************************************/
+@@ -11,13 +11,12 @@
+ /******************************************************************************
+ *
+ * (C)Copyright 1998-2002 SysKonnect.
+- * (C)Copyright 2002-2003 Marvell.
++ * (C)Copyright 2002-2005 Marvell.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+- *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+@@ -33,7 +32,7 @@
+ * In case of the driver we put the definition of the events here.
+ */
+ #define SK_DRV_PORT_RESET 1 /* The port needs to be reset */
+-#define SK_DRV_NET_UP 2 /* The net is operational */
++#define SK_DRV_NET_UP 2 /* The net is operational */
+ #define SK_DRV_NET_DOWN 3 /* The net is down */
+ #define SK_DRV_SWITCH_SOFT 4 /* Ports switch with both links connected */
+ #define SK_DRV_SWITCH_HARD 5 /* Port switch due to link failure */
+@@ -44,8 +43,9 @@
+ #define SK_DRV_POWER_DOWN 10 /* Power down mode */
+ #define SK_DRV_TIMER 11 /* Timer for free use */
+ #ifdef SK_NO_RLMT
+-#define SK_DRV_LINK_UP 12 /* Link Up event for driver */
++#define SK_DRV_LINK_UP 12 /* Link Up event for driver */
+ #define SK_DRV_LINK_DOWN 13 /* Link Down event for driver */
+ #endif
+ #define SK_DRV_DOWNSHIFT_DET 14 /* Downshift 4-Pair / 2-Pair (YUKON only) */
++#define SK_DRV_RX_OVERFLOW 15 /* Receive Overflow */
+ #endif /* __INC_SKGEDRV_H_ */
+diff -ruN linux/drivers/net/sk98lin/h/skgehw.h linux-new/drivers/net/sk98lin/h/skgehw.h
+--- linux/drivers/net/sk98lin/h/skgehw.h 2005-09-26 13:32:48.000000000 +0400
++++ linux-new/drivers/net/sk98lin/h/skgehw.h 2005-08-09 17:15:51.000000000 +0400
+@@ -2,8 +2,8 @@
+ *
+ * Name: skgehw.h
+ * Project: Gigabit Ethernet Adapters, Common Modules
+- * Version: $Revision: 1.56 $
+- * Date: $Date: 2003/09/23 09:01:00 $
++ * Version: $Revision: 2.50 $
++ * Date: $Date: 2005/07/14 12:49:03 $
+ * Purpose: Defines and Macros for the Gigabit Ethernet Adapter Product Family
+ *
+ ******************************************************************************/
+@@ -11,13 +11,12 @@
+ /******************************************************************************
+ *
+ * (C)Copyright 1998-2002 SysKonnect.
+- * (C)Copyright 2002-2003 Marvell.
++ * (C)Copyright 2002-2005 Marvell.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+- *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+@@ -114,6 +113,16 @@
+ #define SHIFT1(x) ((x) << 1)
+ #define SHIFT0(x) ((x) << 0)
+
++/* Macro for arbitrary alignment of a given pointer */
++#define ALIGN_ADDR( ADDRESS, GRANULARITY ) { \
++ SK_UPTR addr = (SK_UPTR)(ADDRESS); \
++ if (addr & ((GRANULARITY)-1)) { \
++ addr += (GRANULARITY); \
++ addr &= ~(SK_UPTR)((GRANULARITY)-1); \
++ ADDRESS = (void *)addr; \
++ }\
++}
++
+ /*
+ * Configuration Space header
+ * Since this module is used for different OS', those may be
+@@ -132,34 +141,74 @@
+ #define PCI_BIST 0x0f /* 8 bit Built-in selftest */
+ #define PCI_BASE_1ST 0x10 /* 32 bit 1st Base address */
+ #define PCI_BASE_2ND 0x14 /* 32 bit 2nd Base address */
+- /* Byte 0x18..0x2b: reserved */
++ /* Bytes 0x18..0x2b: reserved */
+ #define PCI_SUB_VID 0x2c /* 16 bit Subsystem Vendor ID */
+ #define PCI_SUB_ID 0x2e /* 16 bit Subsystem ID */
+ #define PCI_BASE_ROM 0x30 /* 32 bit Expansion ROM Base Address */
+-#define PCI_CAP_PTR 0x34 /* 8 bit Capabilities Ptr */
+- /* Byte 0x35..0x3b: reserved */
++#define PCI_CAP_PTR 0x34 /* 8 bit Capabilities Pointer */
++ /* Bytes 0x35..0x3b: reserved */
+ #define PCI_IRQ_LINE 0x3c /* 8 bit Interrupt Line */
+ #define PCI_IRQ_PIN 0x3d /* 8 bit Interrupt Pin */
+ #define PCI_MIN_GNT 0x3e /* 8 bit Min_Gnt */
+ #define PCI_MAX_LAT 0x3f /* 8 bit Max_Lat */
+ /* Device Dependent Region */
+-#define PCI_OUR_REG_1 0x40 /* 32 bit Our Register 1 */
+-#define PCI_OUR_REG_2 0x44 /* 32 bit Our Register 2 */
++#define PCI_OUR_REG_1 0x40 /* 32 bit Our Register 1 */
++#define PCI_OUR_REG_2 0x44 /* 32 bit Our Register 2 */
+ /* Power Management Region */
+-#define PCI_PM_CAP_ID 0x48 /* 8 bit Power Management Cap. ID */
+-#define PCI_PM_NITEM 0x49 /* 8 bit Next Item Ptr */
+-#define PCI_PM_CAP_REG 0x4a /* 16 bit Power Management Capabilities */
+-#define PCI_PM_CTL_STS 0x4c /* 16 bit Power Manag. Control/Status */
++#define PCI_PM_CAP_ID 0x48 /* 8 bit Power Management Cap. ID */
++#define PCI_PM_NITEM 0x49 /* 8 bit PM Next Item Pointer */
++#define PCI_PM_CAP_REG 0x4a /* 16 bit Power Management Capabilities */
++#define PCI_PM_CTL_STS 0x4c /* 16 bit Power Manag. Control/Status */
+ /* Byte 0x4e: reserved */
+-#define PCI_PM_DAT_REG 0x4f /* 8 bit Power Manag. Data Register */
++#define PCI_PM_DAT_REG 0x4f /* 8 bit Power Manag. Data Register */
+ /* VPD Region */
+-#define PCI_VPD_CAP_ID 0x50 /* 8 bit VPD Cap. ID */
+-#define PCI_VPD_NITEM 0x51 /* 8 bit Next Item Ptr */
+-#define PCI_VPD_ADR_REG 0x52 /* 16 bit VPD Address Register */
+-#define PCI_VPD_DAT_REG 0x54 /* 32 bit VPD Data Register */
+- /* Byte 0x58..0x59: reserved */
+-#define PCI_SER_LD_CTRL 0x5a /* 16 bit SEEPROM Loader Ctrl (YUKON only) */
+- /* Byte 0x5c..0xff: reserved */
++#define PCI_VPD_CAP_ID 0x50 /* 8 bit VPD Cap. ID */
++#define PCI_VPD_NITEM 0x51 /* 8 bit VPD Next Item Pointer */
++#define PCI_VPD_ADR_REG 0x52 /* 16 bit VPD Address Register */
++#define PCI_VPD_DAT_REG 0x54 /* 32 bit VPD Data Register */
++ /* Bytes 0x58..0x59: reserved */
++#define PCI_SER_LD_CTRL 0x5a /* 16 bit SEEPROM Loader Ctrl (YUKON only) */
++ /* Bytes 0x5c..0xfc: used by Yukon-2 */
++#define PCI_MSI_CAP_ID 0x5c /* 8 bit MSI Capability ID Register */
++#define PCI_MSI_NITEM 0x5d /* 8 bit MSI Next Item Pointer */
++#define PCI_MSI_CTRL 0x5e /* 16 bit MSI Message Control */
++#define PCI_MSI_ADR_LO 0x60 /* 32 bit MSI Message Address (Lower) */
++#define PCI_MSI_ADR_HI 0x64 /* 32 bit MSI Message Address (Upper) */
++#define PCI_MSI_DATA 0x68 /* 16 bit MSI Message Data */
++ /* Bytes 0x6a..0x6b: reserved */
++#define PCI_X_CAP_ID 0x6c /* 8 bit PCI-X Capability ID Register */
++#define PCI_X_NITEM 0x6d /* 8 bit PCI-X Next Item Pointer */
++#define PCI_X_COMMAND 0x6e /* 16 bit PCI-X Command */
++#define PCI_X_PE_STAT 0x70 /* 32 bit PCI-X / PE Status */
++#define PCI_CAL_CTRL 0x74 /* 16 bit PCI Calibration Control Register */
++#define PCI_CAL_STAT 0x76 /* 16 bit PCI Calibration Status Register */
++#define PCI_DISC_CNT 0x78 /* 16 bit PCI Discard Counter */
++#define PCI_RETRY_CNT 0x7a /* 8 bit PCI Retry Counter */
++ /* Byte 0x7b: reserved */
++#define PCI_OUR_STATUS 0x7c /* 32 bit Adapter Status Register */
++ /* Bytes 0x80..0xdf: reserved */
++
++/* PCI Express Capability */
++#define PEX_CAP_ID 0xe0 /* 8 bit PEX Capability ID */
++#define PEX_NITEM 0xe1 /* 8 bit PEX Next Item Pointer */
++#define PEX_CAP_REG 0xe2 /* 16 bit PEX Capability Register */
++#define PEX_DEV_CAP 0xe4 /* 32 bit PEX Device Capabilities */
++#define PEX_DEV_CTRL 0xe8 /* 16 bit PEX Device Control */
++#define PEX_DEV_STAT 0xea /* 16 bit PEX Device Status */
++#define PEX_LNK_CAP 0xec /* 32 bit PEX Link Capabilities */
++#define PEX_LNK_CTRL 0xf0 /* 16 bit PEX Link Control */
++#define PEX_LNK_STAT 0xf2 /* 16 bit PEX Link Status */
++ /* Bytes 0xf4..0xff: reserved */
++
++/* PCI Express Extended Capabilities */
++#define PEX_ADV_ERR_REP 0x100 /* 32 bit PEX Advanced Error Reporting */
++#define PEX_UNC_ERR_STAT 0x104 /* 32 bit PEX Uncorr. Errors Status */
++#define PEX_UNC_ERR_MASK 0x108 /* 32 bit PEX Uncorr. Errors Mask */
++#define PEX_UNC_ERR_SEV 0x10c /* 32 bit PEX Uncorr. Errors Severity */
++#define PEX_COR_ERR_STAT 0x110 /* 32 bit PEX Correc. Errors Status */
++#define PEX_COR_ERR_MASK 0x114 /* 32 bit PEX Correc. Errors Mask */
++#define PEX_ADV_ERR_CAP_C 0x118 /* 32 bit PEX Advanced Error Cap./Ctrl */
++#define PEX_HEADER_LOG 0x11c /* 4x32 bit PEX Header Log Register */
+
+ /*
+ * I2C Address (PCI Config)
+@@ -180,13 +229,13 @@
+ #define PCI_ADSTEP BIT_7S /* Address Stepping */
+ #define PCI_PERREN BIT_6S /* Parity Report Response enable */
+ #define PCI_VGA_SNOOP BIT_5S /* VGA palette snoop */
+-#define PCI_MWIEN BIT_4S /* Memory write an inv cycl ena */
++#define PCI_MWIEN BIT_4S /* Memory write an inv cycl enable */
+ #define PCI_SCYCEN BIT_3S /* Special Cycle enable */
+ #define PCI_BMEN BIT_2S /* Bus Master enable */
+ #define PCI_MEMEN BIT_1S /* Memory Space Access enable */
+ #define PCI_IOEN BIT_0S /* I/O Space Access enable */
+
+-#define PCI_COMMAND_VAL (PCI_FBTEN | PCI_SERREN | PCI_PERREN | PCI_MWIEN |\
++#define PCI_COMMAND_VAL (PCI_INT_DIS | PCI_SERREN | PCI_PERREN | \
+ PCI_BMEN | PCI_MEMEN | PCI_IOEN)
+
+ /* PCI_STATUS 16 bit Status */
+@@ -220,7 +269,7 @@
+
+ /* PCI_HEADER_T 8 bit Header Type */
+ #define PCI_HD_MF_DEV BIT_7S /* 0= single, 1= multi-func dev */
+-#define PCI_HD_TYPE 0x7f /* Bit 6..0: Header Layout 0= normal */
++#define PCI_HD_TYPE 0x7f /* Bit 6..0: Header Layout (0=normal) */
+
+ /* PCI_BIST 8 bit Built-in selftest */
+ /* Built-in Self test not supported (optional) */
+@@ -229,33 +278,42 @@
+ #define PCI_MEMSIZE 0x4000L /* use 16 kB Memory Base */
+ #define PCI_MEMBASE_MSK 0xffffc000L /* Bit 31..14: Memory Base Address */
+ #define PCI_MEMSIZE_MSK 0x00003ff0L /* Bit 13.. 4: Memory Size Req. */
+-#define PCI_PREFEN BIT_3 /* Prefetchable */
+-#define PCI_MEM_TYP (3L<<2) /* Bit 2.. 1: Memory Type */
++#define PCI_PREFEN BIT_3 /* Prefetch enable */
++#define PCI_MEM_TYP_MSK (3L<<1) /* Bit 2.. 1: Memory Type Mask */
++#define PCI_MEMSPACE BIT_0 /* Memory Space Indicator */
++
+ #define PCI_MEM32BIT (0L<<1) /* Base addr anywhere in 32 Bit range */
+ #define PCI_MEM1M (1L<<1) /* Base addr below 1 MegaByte */
+ #define PCI_MEM64BIT (2L<<1) /* Base addr anywhere in 64 Bit range */
+-#define PCI_MEMSPACE BIT_0 /* Memory Space Indicator */
+
+ /* PCI_BASE_2ND 32 bit 2nd Base address */
+ #define PCI_IOBASE 0xffffff00L /* Bit 31.. 8: I/O Base address */
+ #define PCI_IOSIZE 0x000000fcL /* Bit 7.. 2: I/O Size Requirements */
+- /* Bit 1: reserved */
++ /* Bit 1: reserved */
+ #define PCI_IOSPACE BIT_0 /* I/O Space Indicator */
+
+ /* PCI_BASE_ROM 32 bit Expansion ROM Base Address */
+ #define PCI_ROMBASE_MSK 0xfffe0000L /* Bit 31..17: ROM Base address */
+ #define PCI_ROMBASE_SIZ (0x1cL<<14) /* Bit 16..14: Treat as Base or Size */
+ #define PCI_ROMSIZE (0x38L<<11) /* Bit 13..11: ROM Size Requirements */
+- /* Bit 10.. 1: reserved */
++ /* Bit 10.. 1: reserved */
+ #define PCI_ROMEN BIT_0 /* Address Decode enable */
+
+ /* Device Dependent Region */
+ /* PCI_OUR_REG_1 32 bit Our Register 1 */
+- /* Bit 31..29: reserved */
++ /* Bit 31..29: reserved */
+ #define PCI_PHY_COMA BIT_28 /* Set PHY to Coma Mode (YUKON only) */
+ #define PCI_TEST_CAL BIT_27 /* Test PCI buffer calib. (YUKON only) */
+ #define PCI_EN_CAL BIT_26 /* Enable PCI buffer calib. (YUKON only) */
+ #define PCI_VIO BIT_25 /* PCI I/O Voltage, 0 = 3.3V, 1 = 5V */
++/* Yukon-2 */
++#define PCI_Y2_PIG_ENA BIT_31 /* Enable Plug-in-Go (YUKON-2) */
++#define PCI_Y2_DLL_DIS BIT_30 /* Disable PCI DLL (YUKON-2) */
++#define PCI_Y2_PHY2_COMA BIT_29 /* Set PHY 2 to Coma Mode (YUKON-2) */
++#define PCI_Y2_PHY1_COMA BIT_28 /* Set PHY 1 to Coma Mode (YUKON-2) */
++#define PCI_Y2_PHY2_POWD BIT_27 /* Set PHY 2 to Power Down (YUKON-2) */
++#define PCI_Y2_PHY1_POWD BIT_26 /* Set PHY 1 to Power Down (YUKON-2) */
++ /* Bit 25: reserved */
+ #define PCI_DIS_BOOT BIT_24 /* Disable BOOT via ROM */
+ #define PCI_EN_IO BIT_23 /* Mapping to I/O space */
+ #define PCI_EN_FPROM BIT_22 /* Enable FLASH mapping to memory */
+@@ -266,9 +324,10 @@
+ #define PCI_PAGE_32K (1L<<20) /* 32 k pages */
+ #define PCI_PAGE_64K (2L<<20) /* 64 k pages */
+ #define PCI_PAGE_128K (3L<<20) /* 128 k pages */
+- /* Bit 19: reserved */
++ /* Bit 19: reserved */
+ #define PCI_PAGEREG (7L<<16) /* Bit 18..16: Page Register */
+ #define PCI_NOTAR BIT_15 /* No turnaround cycle */
++#define PCI_PEX_LEGNAT BIT_15 /* PEX PM legacy/native mode (YUKON-2) */
+ #define PCI_FORCE_BE BIT_14 /* Assert all BEs on MR */
+ #define PCI_DIS_MRL BIT_13 /* Disable Mem Read Line */
+ #define PCI_DIS_MRM BIT_12 /* Disable Mem Read Multiple */
+@@ -278,13 +337,13 @@
+ #define PCI_DIS_PCI_CLK BIT_8 /* Disable PCI clock driving */
+ #define PCI_SKEW_DAS (0xfL<<4) /* Bit 7.. 4: Skew Ctrl, DAS Ext */
+ #define PCI_SKEW_BASE 0xfL /* Bit 3.. 0: Skew Ctrl, Base */
+-
++#define PCI_CLS_OPT BIT_3 /* Cache Line Size opt. PCI-X (YUKON-2) */
+
+ /* PCI_OUR_REG_2 32 bit Our Register 2 */
+ #define PCI_VPD_WR_THR (0xffL<<24) /* Bit 31..24: VPD Write Threshold */
+ #define PCI_DEV_SEL (0x7fL<<17) /* Bit 23..17: EEPROM Device Select */
+ #define PCI_VPD_ROM_SZ (7L<<14) /* Bit 16..14: VPD ROM Size */
+- /* Bit 13..12: reserved */
++ /* Bit 13..12: reserved */
+ #define PCI_PATCH_DIR (0xfL<<8) /* Bit 11.. 8: Ext Patches dir 3..0 */
+ #define PCI_PATCH_DIR_3 BIT_11
+ #define PCI_PATCH_DIR_2 BIT_10
+@@ -297,21 +356,20 @@
+ #define PCI_EXT_PATCH_0 BIT_4
+ #define PCI_EN_DUMMY_RD BIT_3 /* Enable Dummy Read */
+ #define PCI_REV_DESC BIT_2 /* Reverse Desc. Bytes */
+- /* Bit 1: reserved */
++ /* Bit 1: reserved */
+ #define PCI_USEDATA64 BIT_0 /* Use 64Bit Data bus ext */
+
+-
+ /* Power Management Region */
+ /* PCI_PM_CAP_REG 16 bit Power Management Capabilities */
+ #define PCI_PME_SUP_MSK (0x1f<<11) /* Bit 15..11: PM Event Support Mask */
+-#define PCI_PME_D3C_SUP BIT_15S /* PME from D3cold Support (if Vaux) */
++#define PCI_PME_D3C_SUP BIT_15S /* PME from D3cold Support (if VAUX) */
+ #define PCI_PME_D3H_SUP BIT_14S /* PME from D3hot Support */
+ #define PCI_PME_D2_SUP BIT_13S /* PME from D2 Support */
+ #define PCI_PME_D1_SUP BIT_12S /* PME from D1 Support */
+ #define PCI_PME_D0_SUP BIT_11S /* PME from D0 Support */
+ #define PCI_PM_D2_SUP BIT_10S /* D2 Support in 33 MHz mode */
+ #define PCI_PM_D1_SUP BIT_9S /* D1 Support */
+- /* Bit 8.. 6: reserved */
++ /* Bit 8.. 6: reserved */
+ #define PCI_PM_DSI BIT_5S /* Device Specific Initialization */
+ #define PCI_PM_APS BIT_4S /* Auxialiary Power Source */
+ #define PCI_PME_CLOCK BIT_3S /* PM Event Clock */
+@@ -322,7 +380,7 @@
+ #define PCI_PM_DAT_SCL (3<<13) /* Bit 14..13: Data Reg. scaling factor */
+ #define PCI_PM_DAT_SEL (0xf<<9) /* Bit 12.. 9: PM data selector field */
+ #define PCI_PME_EN BIT_8S /* Enable PME# generation (YUKON only) */
+- /* Bit 7.. 2: reserved */
++ /* Bit 7.. 2: reserved */
+ #define PCI_PM_STATE_MSK 3 /* Bit 1.. 0: Power Management State */
+
+ #define PCI_PM_STATE_D0 0 /* D0: Operational (default) */
+@@ -333,7 +391,67 @@
+ /* VPD Region */
+ /* PCI_VPD_ADR_REG 16 bit VPD Address Register */
+ #define PCI_VPD_FLAG BIT_15S /* starts VPD rd/wr cycle */
+-#define PCI_VPD_ADR_MSK 0x7fffL /* Bit 14.. 0: VPD address mask */
++#define PCI_VPD_ADR_MSK 0x7fffL /* Bit 14.. 0: VPD Address Mask */
++
++/* PCI_OUR_STATUS 32 bit Adapter Status Register (Yukon-2) */
++#define PCI_OS_PCI64B BIT_31 /* Conventional PCI 64 bits Bus */
++#define PCI_OS_PCIX BIT_30 /* PCI-X Bus */
++#define PCI_OS_MODE_MSK (3L<<28) /* Bit 29..28: PCI-X Bus Mode Mask */
++#define PCI_OS_PCI66M BIT_27 /* PCI 66 MHz Bus */
++#define PCI_OS_PCI_X BIT_26 /* PCI/PCI-X Bus (0 = PEX) */
++#define PCI_OS_DLLE_MSK (3L<<24) /* Bit 25..24: DLL Status Indication */
++#define PCI_OS_DLLR_MSK (0xfL<<20) /* Bit 23..20: DLL Row Counters Values */
++#define PCI_OS_DLLC_MSK (0xfL<<16) /* Bit 19..16: DLL Col. Counters Values */
++ /* Bit 15.. 8: reserved */
++
++#define PCI_OS_SPEED(val) ((val & PCI_OS_MODE_MSK) >> 28) /* PCI-X Speed */
++/* possible values for the speed field of the register */
++#define PCI_OS_SPD_PCI 0 /* PCI Conventional Bus */
++#define PCI_OS_SPD_X66 1 /* PCI-X 66MHz Bus */
++#define PCI_OS_SPD_X100 2 /* PCI-X 100MHz Bus */
++#define PCI_OS_SPD_X133 3 /* PCI-X 133MHz Bus */
++
++/* PEX_DEV_CTRL 16 bit PEX Device Control (Yukon-2) */
++ /* Bit 15 reserved */
++#define PEX_DC_MAX_RRS_MSK (7<<12) /* Bit 14..12: Max. Read Request Size */
++#define PEX_DC_EN_NO_SNOOP BIT_11S /* Enable No Snoop */
++#define PEX_DC_EN_AUX_POW BIT_10S /* Enable AUX Power */
++#define PEX_DC_EN_PHANTOM BIT_9S /* Enable Phantom Functions */
++#define PEX_DC_EN_EXT_TAG BIT_8S /* Enable Extended Tag Field */
++#define PEX_DC_MAX_PLS_MSK (7<<5) /* Bit 7.. 5: Max. Payload Size Mask */
++#define PEX_DC_EN_REL_ORD BIT_4S /* Enable Relaxed Ordering */
++#define PEX_DC_EN_UNS_RQ_RP BIT_3S /* Enable Unsupported Request Reporting */
++#define PEX_DC_EN_FAT_ER_RP BIT_2S /* Enable Fatal Error Reporting */
++#define PEX_DC_EN_NFA_ER_RP BIT_1S /* Enable Non-Fatal Error Reporting */
++#define PEX_DC_EN_COR_ER_RP BIT_0S /* Enable Correctable Error Reporting */
++
++#define PEX_DC_MAX_RD_RQ_SIZE(x) (SHIFT12(x) & PEX_DC_MAX_RRS_MSK)
++
++/* PEX_LNK_STAT 16 bit PEX Link Status (Yukon-2) */
++ /* Bit 15..13 reserved */
++#define PEX_LS_SLOT_CLK_CFG BIT_12S /* Slot Clock Config */
++#define PEX_LS_LINK_TRAIN BIT_11S /* Link Training */
++#define PEX_LS_TRAIN_ERROR BIT_10S /* Training Error */
++#define PEX_LS_LINK_WI_MSK (0x3f<<4) /* Bit 9.. 4: Neg. Link Width Mask */
++#define PEX_LS_LINK_SP_MSK 0x0f /* Bit 3.. 0: Link Speed Mask */
++
++/* PEX_UNC_ERR_STAT PEX Uncorrectable Errors Status Register (Yukon-2) */
++ /* Bit 31..21 reserved */
++#define PEX_UNSUP_REQ BIT_20 /* Unsupported Request Error */
++ /* ECRC Error (not supported) */
++#define PEX_MALFOR_TLP BIT_18 /* Malformed TLP */
++ /* Receiver Overflow (not supported) */
++#define PEX_UNEXP_COMP BIT_16 /* Unexpected Completion */
++ /* Completer Abort (not supported) */
++#define PEX_COMP_TO BIT_14 /* Completion Timeout */
++#define PEX_FLOW_CTRL_P BIT_13 /* Flow Control Protocol Error */
++#define PEX_POIS_TLP BIT_12 /* Poisoned TLP */
++ /* Bit 11.. 5: reserved */
++#define PEX_DATA_LINK_P BIT_4 /* Data Link Protocol Error */
++ /* Bit 3.. 1: reserved */
++ /* Training Error (not supported) */
++
++#define PEX_FATAL_ERRORS (PEX_MALFOR_TLP | PEX_FLOW_CTRL_P | PEX_DATA_LINK_P)
+
+ /* Control Register File (Address Map) */
+
+@@ -349,8 +467,14 @@
+ #define B0_IMSK 0x000c /* 32 bit Interrupt Mask Register */
+ #define B0_HWE_ISRC 0x0010 /* 32 bit HW Error Interrupt Src Reg */
+ #define B0_HWE_IMSK 0x0014 /* 32 bit HW Error Interrupt Mask Reg */
+-#define B0_SP_ISRC 0x0018 /* 32 bit Special Interrupt Source Reg */
+- /* 0x001c: reserved */
++#define B0_SP_ISRC 0x0018 /* 32 bit Special Interrupt Source Reg 1 */
++
++/* Special ISR registers (Yukon-2 only) */
++#define B0_Y2_SP_ISRC2 0x001c /* 32 bit Special Interrupt Source Reg 2 */
++#define B0_Y2_SP_ISRC3 0x0020 /* 32 bit Special Interrupt Source Reg 3 */
++#define B0_Y2_SP_EISR 0x0024 /* 32 bit Enter ISR Reg */
++#define B0_Y2_SP_LISR 0x0028 /* 32 bit Leave ISR Reg */
++#define B0_Y2_SP_ICR 0x002c /* 32 bit Interrupt Control Reg */
+
+ /* B0 XMAC 1 registers (GENESIS only) */
+ #define B0_XM1_IMSK 0x0020 /* 16 bit r/w XMAC 1 Interrupt Mask Register*/
+@@ -372,7 +496,7 @@
+ #define B0_XM2_PHY_DATA 0x0054 /* 16 bit r/w XMAC 2 PHY Data Register */
+ /* 0x0056 - 0x005f: reserved */
+
+-/* BMU Control Status Registers */
++/* BMU Control Status Registers (Yukon and Genesis) */
+ #define B0_R1_CSR 0x0060 /* 32 bit BMU Ctrl/Stat Rx Queue 1 */
+ #define B0_R2_CSR 0x0064 /* 32 bit BMU Ctrl/Stat Rx Queue 2 */
+ #define B0_XS1_CSR 0x0068 /* 32 bit BMU Ctrl/Stat Sync Tx Queue 1 */
+@@ -390,7 +514,7 @@
+ /*
+ * Bank 2
+ */
+-/* NA reg = 48 bit Network Address Register, 3x16 or 8x8 bit readable */
++/* NA reg = 48 bit Network Address Register, 3x16 or 6x8 bit readable */
+ #define B2_MAC_1 0x0100 /* NA reg MAC Address 1 */
+ /* 0x0106 - 0x0107: reserved */
+ #define B2_MAC_2 0x0108 /* NA reg MAC Address 2 */
+@@ -400,14 +524,23 @@
+ #define B2_CONN_TYP 0x0118 /* 8 bit Connector type */
+ #define B2_PMD_TYP 0x0119 /* 8 bit PMD type */
+ #define B2_MAC_CFG 0x011a /* 8 bit MAC Configuration / Chip Revision */
+-#define B2_CHIP_ID 0x011b /* 8 bit Chip Identification Number */
+- /* Eprom registers are currently of no use */
++#define B2_CHIP_ID 0x011b /* 8 bit Chip Identification Number */
++ /* Eprom registers */
+ #define B2_E_0 0x011c /* 8 bit EPROM Byte 0 (ext. SRAM size */
++/* Yukon and Genesis */
+ #define B2_E_1 0x011d /* 8 bit EPROM Byte 1 (PHY type) */
+ #define B2_E_2 0x011e /* 8 bit EPROM Byte 2 */
++/* Yukon-2 */
++#define B2_Y2_CLK_GATE 0x011d /* 8 bit Clock Gating (Yukon-2) */
++#define B2_Y2_HW_RES 0x011e /* 8 bit HW Resources (Yukon-2) */
++
+ #define B2_E_3 0x011f /* 8 bit EPROM Byte 3 */
++
++/* Yukon and Genesis */
+ #define B2_FAR 0x0120 /* 32 bit Flash-Prom Addr Reg/Cnt */
+ #define B2_FDP 0x0124 /* 8 bit Flash-Prom Data Port */
++/* Yukon-2 */
++#define B2_Y2_CLK_CTRL 0x0120 /* 32 bit Core Clock Frequency Control */
+ /* 0x0125 - 0x0127: reserved */
+ #define B2_LD_CTRL 0x0128 /* 8 bit EPROM loader control register */
+ #define B2_LD_TEST 0x0129 /* 8 bit EPROM loader test register */
+@@ -439,6 +572,10 @@
+ #define B2_BSC_CTRL 0x0178 /* 8 bit Blink Source Counter Control */
+ #define B2_BSC_STAT 0x0179 /* 8 bit Blink Source Counter Status */
+ #define B2_BSC_TST 0x017a /* 16 bit Blink Source Counter Test Reg */
++
++/* Yukon-2 */
++#define Y2_PEX_PHY_DATA 0x0170 /* 16 bit PEX PHY Data Register */
++#define Y2_PEX_PHY_ADDR 0x0172 /* 16 bit PEX PHY Address Register */
+ /* 0x017c - 0x017f: reserved */
+
+ /*
+@@ -448,9 +585,13 @@
+ #define B3_RAM_ADDR 0x0180 /* 32 bit RAM Address, to read or write */
+ #define B3_RAM_DATA_LO 0x0184 /* 32 bit RAM Data Word (low dWord) */
+ #define B3_RAM_DATA_HI 0x0188 /* 32 bit RAM Data Word (high dWord) */
++
++#define SELECT_RAM_BUFFER(rb, addr) (addr | (rb << 6)) /* Yukon-2 only */
++
+ /* 0x018c - 0x018f: reserved */
+
+ /* RAM Interface Registers */
++/* Yukon-2: use SELECT_RAM_BUFFER() to access the RAM buffer */
+ /*
+ * The HW-Spec. calls this registers Timeout Value 0..11. But this names are
+ * not usable in SW. Please notice these are NOT real timeouts, these are
+@@ -517,8 +658,8 @@
+ /* 0x01ea - 0x01eb: reserved */
+ #define B3_PA_TOVAL_TX2 0x01ec /* 16 bit Timeout Val Tx Path MAC 2 */
+ /* 0x01ee - 0x01ef: reserved */
+-#define B3_PA_CTRL 0x01f0 /* 16 bit Packet Arbiter Ctrl Register */
+-#define B3_PA_TEST 0x01f2 /* 16 bit Packet Arbiter Test Register */
++#define B3_PA_CTRL 0x01f0 /* 16 bit Packet Arbiter Ctrl Register */
++#define B3_PA_TEST 0x01f2 /* 16 bit Packet Arbiter Test Register */
+ /* 0x01f4 - 0x01ff: reserved */
+
+ /*
+@@ -532,7 +673,16 @@
+ #define TXA_CTRL 0x0210 /* 8 bit Tx Arbiter Control Register */
+ #define TXA_TEST 0x0211 /* 8 bit Tx Arbiter Test Register */
+ #define TXA_STAT 0x0212 /* 8 bit Tx Arbiter Status Register */
+- /* 0x0213 - 0x027f: reserved */
++ /* 0x0213 - 0x021f: reserved */
++
++ /* RSS key registers for Yukon-2 Family */
++#define B4_RSS_KEY 0x0220 /* 4x32 bit RSS Key register (Yukon-2) */
++ /* RSS key register offsets */
++#define KEY_IDX_0 0 /* offset for location of KEY 0 */
++#define KEY_IDX_1 4 /* offset for location of KEY 1 */
++#define KEY_IDX_2 8 /* offset for location of KEY 2 */
++#define KEY_IDX_3 12 /* offset for location of KEY 3 */
++
+ /* 0x0280 - 0x0292: MAC 2 */
+ /* 0x0213 - 0x027f: reserved */
+
+@@ -570,8 +720,37 @@
+ #define Q_T1_SV 0x3f /* 8 bit Test Register 1 Supervisor SM */
+ #define Q_T2 0x40 /* 32 bit Test Register 2 */
+ #define Q_T3 0x44 /* 32 bit Test Register 3 */
++
++/* Yukon-2 */
++#define Q_DONE 0x24 /* 16 bit Done Index (Yukon-2 only) */
++#define Q_WM 0x40 /* 16 bit FIFO Watermark */
++#define Q_AL 0x42 /* 8 bit FIFO Alignment */
++#define Q_RSP 0x44 /* 16 bit FIFO Read Shadow Pointer */
++#define Q_RSL 0x46 /* 8 bit FIFO Read Shadow Level */
++#define Q_RP 0x48 /* 8 bit FIFO Read Pointer */
++#define Q_RL 0x4a /* 8 bit FIFO Read Level */
++#define Q_WP 0x4c /* 8 bit FIFO Write Pointer */
++#define Q_WSP 0x4d /* 8 bit FIFO Write Shadow Pointer */
++#define Q_WL 0x4e /* 8 bit FIFO Write Level */
++#define Q_WSL 0x4f /* 8 bit FIFO Write Shadow Level */
+ /* 0x48 - 0x7f: reserved */
+
++/* Queue Prefetch Unit Offsets, use Y2_PREF_Q_ADDR() to address (Yukon-2 only)*/
++#define Y2_B8_PREF_REGS 0x0450
++
++#define PREF_UNIT_CTRL_REG 0x00 /* 32 bit Prefetch Control register */
++#define PREF_UNIT_LAST_IDX_REG 0x04 /* 16 bit Last Index */
++#define PREF_UNIT_ADDR_LOW_REG 0x08 /* 32 bit List start addr, low part */
++#define PREF_UNIT_ADDR_HI_REG 0x0c /* 32 bit List start addr, high part*/
++#define PREF_UNIT_GET_IDX_REG 0x10 /* 16 bit Get Index */
++#define PREF_UNIT_PUT_IDX_REG 0x14 /* 16 bit Put Index */
++#define PREF_UNIT_FIFO_WP_REG 0x20 /* 8 bit FIFO write pointer */
++#define PREF_UNIT_FIFO_RP_REG 0x24 /* 8 bit FIFO read pointer */
++#define PREF_UNIT_FIFO_WM_REG 0x28 /* 8 bit FIFO watermark */
++#define PREF_UNIT_FIFO_LEV_REG 0x2c /* 8 bit FIFO level */
++
++#define PREF_UNIT_MASK_IDX 0x0fff
++
+ /*
+ * Bank 16 - 23
+ */
+@@ -583,17 +762,17 @@
+ #define RB_END 0x04 /* 32 bit RAM Buffer End Address */
+ #define RB_WP 0x08 /* 32 bit RAM Buffer Write Pointer */
+ #define RB_RP 0x0c /* 32 bit RAM Buffer Read Pointer */
+-#define RB_RX_UTPP 0x10 /* 32 bit Rx Upper Threshold, Pause Pack */
+-#define RB_RX_LTPP 0x14 /* 32 bit Rx Lower Threshold, Pause Pack */
++#define RB_RX_UTPP 0x10 /* 32 bit Rx Upper Threshold, Pause Packet */
++#define RB_RX_LTPP 0x14 /* 32 bit Rx Lower Threshold, Pause Packet */
+ #define RB_RX_UTHP 0x18 /* 32 bit Rx Upper Threshold, High Prio */
+ #define RB_RX_LTHP 0x1c /* 32 bit Rx Lower Threshold, High Prio */
+ /* 0x10 - 0x1f: reserved at Tx RAM Buffer Registers */
+ #define RB_PC 0x20 /* 32 bit RAM Buffer Packet Counter */
+ #define RB_LEV 0x24 /* 32 bit RAM Buffer Level Register */
+-#define RB_CTRL 0x28 /* 8 bit RAM Buffer Control Register */
++#define RB_CTRL 0x28 /* 32 bit RAM Buffer Control Register */
+ #define RB_TST1 0x29 /* 8 bit RAM Buffer Test Register 1 */
+-#define RB_TST2 0x2A /* 8 bit RAM Buffer Test Register 2 */
+- /* 0x2c - 0x7f: reserved */
++#define RB_TST2 0x2a /* 8 bit RAM Buffer Test Register 2 */
++ /* 0x2b - 0x7f: reserved */
+
+ /*
+ * Bank 24
+@@ -603,7 +782,7 @@
+ * use MR_ADDR() to access
+ */
+ #define RX_MFF_EA 0x0c00 /* 32 bit Receive MAC FIFO End Address */
+-#define RX_MFF_WP 0x0c04 /* 32 bit Receive MAC FIFO Write Pointer */
++#define RX_MFF_WP 0x0c04 /* 32 bit Receive MAC FIFO Write Pointer */
+ /* 0x0c08 - 0x0c0b: reserved */
+ #define RX_MFF_RP 0x0c0c /* 32 bit Receive MAC FIFO Read Pointer */
+ #define RX_MFF_PC 0x0c10 /* 32 bit Receive MAC FIFO Packet Cnt */
+@@ -628,20 +807,22 @@
+ #define LNK_LED_REG 0x0c3c /* 8 bit Link LED Register */
+ /* 0x0c3d - 0x0c3f: reserved */
+
+-/* Receive GMAC FIFO (YUKON only), use MR_ADDR() to access */
++/* Receive GMAC FIFO (YUKON and Yukon-2), use MR_ADDR() to access */
+ #define RX_GMF_EA 0x0c40 /* 32 bit Rx GMAC FIFO End Address */
+ #define RX_GMF_AF_THR 0x0c44 /* 32 bit Rx GMAC FIFO Almost Full Thresh. */
+ #define RX_GMF_CTRL_T 0x0c48 /* 32 bit Rx GMAC FIFO Control/Test */
+ #define RX_GMF_FL_MSK 0x0c4c /* 32 bit Rx GMAC FIFO Flush Mask */
+ #define RX_GMF_FL_THR 0x0c50 /* 32 bit Rx GMAC FIFO Flush Threshold */
+- /* 0x0c54 - 0x0c5f: reserved */
+-#define RX_GMF_WP 0x0c60 /* 32 bit Rx GMAC FIFO Write Pointer */
++#define RX_GMF_TR_THR 0x0c54 /* 32 bit Rx Truncation Threshold (Yukon-2) */
++ /* 0x0c58 - 0x0c5b: reserved */
++#define RX_GMF_VLAN 0x0c5c /* 32 bit Rx VLAN Type Register (Yukon-2) */
++#define RX_GMF_WP 0x0c60 /* 32 bit Rx GMAC FIFO Write Pointer */
+ /* 0x0c64 - 0x0c67: reserved */
+-#define RX_GMF_WLEV 0x0c68 /* 32 bit Rx GMAC FIFO Write Level */
++#define RX_GMF_WLEV 0x0c68 /* 32 bit Rx GMAC FIFO Write Level */
+ /* 0x0c6c - 0x0c6f: reserved */
+-#define RX_GMF_RP 0x0c70 /* 32 bit Rx GMAC FIFO Read Pointer */
++#define RX_GMF_RP 0x0c70 /* 32 bit Rx GMAC FIFO Read Pointer */
+ /* 0x0c74 - 0x0c77: reserved */
+-#define RX_GMF_RLEV 0x0c78 /* 32 bit Rx GMAC FIFO Read Level */
++#define RX_GMF_RLEV 0x0c78 /* 32 bit Rx GMAC FIFO Read Level */
+ /* 0x0c7c - 0x0c7f: reserved */
+
+ /*
+@@ -658,7 +839,7 @@
+ * use MR_ADDR() to access
+ */
+ #define TX_MFF_EA 0x0d00 /* 32 bit Transmit MAC FIFO End Address */
+-#define TX_MFF_WP 0x0d04 /* 32 bit Transmit MAC FIFO WR Pointer */
++#define TX_MFF_WP 0x0d04 /* 32 bit Transmit MAC FIFO WR Pointer */
+ #define TX_MFF_WSP 0x0d08 /* 32 bit Transmit MAC FIFO WR Shadow Ptr */
+ #define TX_MFF_RP 0x0d0c /* 32 bit Transmit MAC FIFO RD Pointer */
+ #define TX_MFF_PC 0x0d10 /* 32 bit Transmit MAC FIFO Packet Cnt */
+@@ -676,18 +857,19 @@
+ #define TX_LED_TST 0x0d29 /* 8 bit Transmit LED Cnt Test Reg */
+ /* 0x0d2a - 0x0d3f: reserved */
+
+-/* Transmit GMAC FIFO (YUKON only), use MR_ADDR() to access */
++/* Transmit GMAC FIFO (YUKON and Yukon-2), use MR_ADDR() to access */
+ #define TX_GMF_EA 0x0d40 /* 32 bit Tx GMAC FIFO End Address */
+ #define TX_GMF_AE_THR 0x0d44 /* 32 bit Tx GMAC FIFO Almost Empty Thresh.*/
+ #define TX_GMF_CTRL_T 0x0d48 /* 32 bit Tx GMAC FIFO Control/Test */
+- /* 0x0d4c - 0x0d5f: reserved */
+-#define TX_GMF_WP 0x0d60 /* 32 bit Tx GMAC FIFO Write Pointer */
+-#define TX_GMF_WSP 0x0d64 /* 32 bit Tx GMAC FIFO Write Shadow Ptr. */
+-#define TX_GMF_WLEV 0x0d68 /* 32 bit Tx GMAC FIFO Write Level */
++ /* 0x0d4c - 0x0d5b: reserved */
++#define TX_GMF_VLAN 0x0d5c /* 32 bit Tx VLAN Type Register (Yukon-2) */
++#define TX_GMF_WP 0x0d60 /* 32 bit Tx GMAC FIFO Write Pointer */
++#define TX_GMF_WSP 0x0d64 /* 32 bit Tx GMAC FIFO Write Shadow Pointer */
++#define TX_GMF_WLEV 0x0d68 /* 32 bit Tx GMAC FIFO Write Level */
+ /* 0x0d6c - 0x0d6f: reserved */
+-#define TX_GMF_RP 0x0d70 /* 32 bit Tx GMAC FIFO Read Pointer */
+-#define TX_GMF_RSTP 0x0d74 /* 32 bit Tx GMAC FIFO Restart Pointer */
+-#define TX_GMF_RLEV 0x0d78 /* 32 bit Tx GMAC FIFO Read Level */
++#define TX_GMF_RP 0x0d70 /* 32 bit Tx GMAC FIFO Read Pointer */
++#define TX_GMF_RSTP 0x0d74 /* 32 bit Tx GMAC FIFO Restart Pointer */
++#define TX_GMF_RLEV 0x0d78 /* 32 bit Tx GMAC FIFO Read Level */
+ /* 0x0d7c - 0x0d7f: reserved */
+
+ /*
+@@ -713,12 +895,84 @@
+ #define GMAC_TI_ST_CTRL 0x0e18 /* 8 bit Time Stamp Timer Ctrl Reg */
+ /* 0x0e19: reserved */
+ #define GMAC_TI_ST_TST 0x0e1a /* 8 bit Time Stamp Timer Test Reg */
+- /* 0x0e1b - 0x0e7f: reserved */
++ /* 0x0e1b - 0x0e1f: reserved */
++
++/* Polling Unit Registers (Yukon-2 only) */
++#define POLL_CTRL 0x0e20 /* 32 bit Polling Unit Control Reg */
++#define POLL_LAST_IDX 0x0e24 /* 16 bit Polling Unit List Last Index */
++ /* 0x0e26 - 0x0e27: reserved */
++#define POLL_LIST_ADDR_LO 0x0e28 /* 32 bit Poll. List Start Addr (low) */
++#define POLL_LIST_ADDR_HI 0x0e2c /* 32 bit Poll. List Start Addr (high) */
++ /* 0x0e30 - 0x0e3f: reserved */
++
++/* ASF Subsystem Registers (Yukon-2 only) */
++#define B28_Y2_SMB_CONFIG 0x0e40 /* 32 bit ASF SMBus Config Register */
++#define B28_Y2_SMB_CSD_REG 0x0e44 /* 32 bit ASF SMB Control/Status/Data */
++ /* 0x0e48 - 0x0e5f: reserved */
++#define B28_Y2_ASF_IRQ_V_BASE 0x0e60 /* 32 bit ASF IRQ Vector Base */
++ /* 0x0e64 - 0x0e67: reserved */
++#define B28_Y2_ASF_STAT_CMD 0x0e68 /* 32 bit ASF Status and Command Reg */
++#define B28_Y2_ASF_HOST_COM 0x0e6c /* 32 bit ASF Host Communication Reg */
++#define B28_Y2_DATA_REG_1 0x0e70 /* 32 bit ASF/Host Data Register 1 */
++#define B28_Y2_DATA_REG_2 0x0e74 /* 32 bit ASF/Host Data Register 2 */
++#define B28_Y2_DATA_REG_3 0x0e78 /* 32 bit ASF/Host Data Register 3 */
++#define B28_Y2_DATA_REG_4 0x0e7c /* 32 bit ASF/Host Data Register 4 */
+
+ /*
+ * Bank 29
+ */
+- /* 0x0e80 - 0x0efc: reserved */
++
++/* Status BMU Registers (Yukon-2 only)*/
++#define STAT_CTRL 0x0e80 /* 32 bit Status BMU Control Reg */
++#define STAT_LAST_IDX 0x0e84 /* 16 bit Status BMU Last Index */
++ /* 0x0e85 - 0x0e86: reserved */
++#define STAT_LIST_ADDR_LO 0x0e88 /* 32 bit Status List Start Addr (low) */
++#define STAT_LIST_ADDR_HI 0x0e8c /* 32 bit Status List Start Addr (high) */
++#define STAT_TXA1_RIDX 0x0e90 /* 16 bit Status TxA1 Report Index Reg */
++#define STAT_TXS1_RIDX 0x0e92 /* 16 bit Status TxS1 Report Index Reg */
++#define STAT_TXA2_RIDX 0x0e94 /* 16 bit Status TxA2 Report Index Reg */
++#define STAT_TXS2_RIDX 0x0e96 /* 16 bit Status TxS2 Report Index Reg */
++#define STAT_TX_IDX_TH 0x0e98 /* 16 bit Status Tx Index Threshold Reg */
++ /* 0x0e9a - 0x0e9b: reserved */
++#define STAT_PUT_IDX 0x0e9c /* 16 bit Status Put Index Reg */
++ /* 0x0e9e - 0x0e9f: reserved */
++
++/* FIFO Control/Status Registers (Yukon-2 only)*/
++#define STAT_FIFO_WP 0x0ea0 /* 8 bit Status FIFO Write Pointer Reg */
++ /* 0x0ea1 - 0x0ea3: reserved */
++#define STAT_FIFO_RP 0x0ea4 /* 8 bit Status FIFO Read Pointer Reg */
++ /* 0x0ea5: reserved */
++#define STAT_FIFO_RSP 0x0ea6 /* 8 bit Status FIFO Read Shadow Ptr */
++ /* 0x0ea7: reserved */
++#define STAT_FIFO_LEVEL 0x0ea8 /* 8 bit Status FIFO Level Reg */
++ /* 0x0ea9: reserved */
++#define STAT_FIFO_SHLVL 0x0eaa /* 8 bit Status FIFO Shadow Level Reg */
++ /* 0x0eab: reserved */
++#define STAT_FIFO_WM 0x0eac /* 8 bit Status FIFO Watermark Reg */
++#define STAT_FIFO_ISR_WM 0x0ead /* 8 bit Status FIFO ISR Watermark Reg */
++ /* 0x0eae - 0x0eaf: reserved */
++
++/* Level and ISR Timer Registers (Yukon-2 only)*/
++#define STAT_LEV_TIMER_INI 0x0eb0 /* 32 bit Level Timer Init. Value Reg */
++#define STAT_LEV_TIMER_CNT 0x0eb4 /* 32 bit Level Timer Counter Reg */
++#define STAT_LEV_TIMER_CTRL 0x0eb8 /* 8 bit Level Timer Control Reg */
++#define STAT_LEV_TIMER_TEST 0x0eb9 /* 8 bit Level Timer Test Reg */
++ /* 0x0eba - 0x0ebf: reserved */
++#define STAT_TX_TIMER_INI 0x0ec0 /* 32 bit Tx Timer Init. Value Reg */
++#define STAT_TX_TIMER_CNT 0x0ec4 /* 32 bit Tx Timer Counter Reg */
++#define STAT_TX_TIMER_CTRL 0x0ec8 /* 8 bit Tx Timer Control Reg */
++#define STAT_TX_TIMER_TEST 0x0ec9 /* 8 bit Tx Timer Test Reg */
++ /* 0x0eca - 0x0ecf: reserved */
++#define STAT_ISR_TIMER_INI 0x0ed0 /* 32 bit ISR Timer Init. Value Reg */
++#define STAT_ISR_TIMER_CNT 0x0ed4 /* 32 bit ISR Timer Counter Reg */
++#define STAT_ISR_TIMER_CTRL 0x0ed8 /* 8 bit ISR Timer Control Reg */
++#define STAT_ISR_TIMER_TEST 0x0ed9 /* 8 bit ISR Timer Test Reg */
++ /* 0x0eda - 0x0eff: reserved */
++
++#define ST_LAST_IDX_MASK 0x007f /* Last Index Mask */
++#define ST_TXRP_IDX_MASK 0x0fff /* Tx Report Index Mask */
++#define ST_TXTH_IDX_MASK 0x0fff /* Tx Threshold Index Mask */
++#define ST_WM_IDX_MASK 0x3f /* FIFO Watermark Index Mask */
+
+ /*
+ * Bank 30
+@@ -742,11 +996,9 @@
+ #define WOL_MATCH_RES 0x0f23 /* 8 bit WOL Match Result Reg */
+ #define WOL_MAC_ADDR_LO 0x0f24 /* 32 bit WOL MAC Address Low */
+ #define WOL_MAC_ADDR_HI 0x0f28 /* 16 bit WOL MAC Address High */
+-#define WOL_PATT_RPTR 0x0f2c /* 8 bit WOL Pattern Read Ptr */
+-
+-/* use this macro to access above registers */
+-#define WOL_REG(Reg) ((Reg) + (pAC->GIni.GIWolOffs))
+-
++#define WOL_PATT_PME 0x0f2a /* 8 bit WOL PME Match Enable (Yukon-2) */
++#define WOL_PATT_ASFM 0x0f2b /* 8 bit WOL ASF Match Enable (Yukon-2) */
++#define WOL_PATT_RPTR 0x0f2c /* 8 bit WOL Pattern Read Pointer */
+
+ /* WOL Pattern Length Registers (YUKON only) */
+
+@@ -764,11 +1016,22 @@
+ */
+ /* 0x0f80 - 0x0fff: reserved */
+
++/* WOL registers link 2 */
++
++/* use this macro to access WOL registers */
++#define WOL_REG(Port, Reg) ((Reg) + ((Port)*0x80) + (pAC->GIni.GIWolOffs))
++
+ /*
+ * Bank 32 - 33
+ */
+ #define WOL_PATT_RAM_1 0x1000 /* WOL Pattern RAM Link 1 */
++#define WOL_PATT_RAM_2 0x1400 /* WOL Pattern RAM Link 2 */
+
++/* use this macro to retrieve the pattern ram base address */
++#define WOL_PATT_RAM_BASE(Port) (WOL_PATT_RAM_1 + (Port)*0x400)
++
++/* offset to configuration space on Yukon-2 */
++#define Y2_CFG_SPC 0x1c00
+ /*
+ * Bank 0x22 - 0x3f
+ */
+@@ -800,13 +1063,26 @@
+ */
+ /* B0_RAP 8 bit Register Address Port */
+ /* Bit 7: reserved */
+-#define RAP_RAP 0x3f /* Bit 6..0: 0 = block 0,..,6f = block 6f */
++#define RAP_MSK 0x7f /* Bit 6..0: 0 = block 0,..,6f = block 6f */
++
++/* B0_CTST 24 bit Control/Status register */
++ /* Bit 23..18: reserved */
++#define Y2_VMAIN_AVAIL BIT_17 /* VMAIN available (YUKON-2 only) */
++#define Y2_VAUX_AVAIL BIT_16 /* VAUX available (YUKON-2 only) */
++ /* Bit 15..14: reserved */
++#define Y2_ASF_ENABLE BIT_13S /* ASF Unit Enable (YUKON-2 only) */
++#define Y2_ASF_DISABLE BIT_12S /* ASF Unit Disable (YUKON-2 only) */
++#define Y2_CLK_RUN_ENA BIT_11S /* CLK_RUN Enable (YUKON-2 only) */
++#define Y2_CLK_RUN_DIS BIT_10S /* CLK_RUN Disable (YUKON-2 only) */
++#define Y2_LED_STAT_ON BIT_9S /* Status LED On (YUKON-2 only) */
++#define Y2_LED_STAT_OFF BIT_8S /* Status LED Off (YUKON-2 only) */
++ /* Bit 7.. 0: same as below */
+
+ /* B0_CTST 16 bit Control/Status register */
+ /* Bit 15..14: reserved */
+-#define CS_CLK_RUN_HOT BIT_13S /* CLK_RUN hot m. (YUKON-Lite only) */
+-#define CS_CLK_RUN_RST BIT_12S /* CLK_RUN reset (YUKON-Lite only) */
+-#define CS_CLK_RUN_ENA BIT_11S /* CLK_RUN enable (YUKON-Lite only) */
++#define CS_CLK_RUN_HOT BIT_13S /* CLK_RUN Hot m. (YUKON-Lite only) */
++#define CS_CLK_RUN_RST BIT_12S /* CLK_RUN Reset (YUKON-Lite only) */
++#define CS_CLK_RUN_ENA BIT_11S /* CLK_RUN Enable (YUKON-Lite only) */
+ #define CS_VAUX_AVAIL BIT_10S /* VAUX available (YUKON only) */
+ #define CS_BUS_CLOCK BIT_9S /* Bus Clock 0/1 = 33/66 MHz */
+ #define CS_BUS_SLOT_SZ BIT_8S /* Slot Size 0/1 = 32/64 bit slot */
+@@ -814,26 +1090,27 @@
+ #define CS_CL_SW_IRQ BIT_6S /* Clear IRQ SW Request */
+ #define CS_STOP_DONE BIT_5S /* Stop Master is finished */
+ #define CS_STOP_MAST BIT_4S /* Command Bit to stop the master */
+-#define CS_MRST_CLR BIT_3S /* Clear Master reset */
+-#define CS_MRST_SET BIT_2S /* Set Master reset */
+-#define CS_RST_CLR BIT_1S /* Clear Software reset */
+-#define CS_RST_SET BIT_0S /* Set Software reset */
++#define CS_MRST_CLR BIT_3S /* Clear Master Reset */
++#define CS_MRST_SET BIT_2S /* Set Master Reset */
++#define CS_RST_CLR BIT_1S /* Clear Software Reset */
++#define CS_RST_SET BIT_0S /* Set Software Reset */
+
+-/* B0_LED 8 Bit LED register */
++/* B0_LED 8 Bit LED register (GENESIS only)*/
+ /* Bit 7.. 2: reserved */
+-#define LED_STAT_ON BIT_1S /* Status LED on */
+-#define LED_STAT_OFF BIT_0S /* Status LED off */
++#define LED_STAT_ON BIT_1S /* Status LED On */
++#define LED_STAT_OFF BIT_0S /* Status LED Off */
+
+ /* B0_POWER_CTRL 8 Bit Power Control reg (YUKON only) */
+ #define PC_VAUX_ENA BIT_7 /* Switch VAUX Enable */
+-#define PC_VAUX_DIS BIT_6 /* Switch VAUX Disable */
+-#define PC_VCC_ENA BIT_5 /* Switch VCC Enable */
+-#define PC_VCC_DIS BIT_4 /* Switch VCC Disable */
+-#define PC_VAUX_ON BIT_3 /* Switch VAUX On */
+-#define PC_VAUX_OFF BIT_2 /* Switch VAUX Off */
+-#define PC_VCC_ON BIT_1 /* Switch VCC On */
+-#define PC_VCC_OFF BIT_0 /* Switch VCC Off */
++#define PC_VAUX_DIS BIT_6 /* Switch VAUX Disable */
++#define PC_VCC_ENA BIT_5 /* Switch VCC Enable */
++#define PC_VCC_DIS BIT_4 /* Switch VCC Disable */
++#define PC_VAUX_ON BIT_3 /* Switch VAUX On */
++#define PC_VAUX_OFF BIT_2 /* Switch VAUX Off */
++#define PC_VCC_ON BIT_1 /* Switch VCC On */
++#define PC_VCC_OFF BIT_0 /* Switch VCC Off */
+
++/* Yukon and Genesis */
+ /* B0_ISRC 32 bit Interrupt Source Register */
+ /* B0_IMSK 32 bit Interrupt Mask Register */
+ /* B0_SP_ISRC 32 bit Special Interrupt Source Reg */
+@@ -879,12 +1156,51 @@
+ #define IS_XA2_F BIT_1 /* Q_XA2 End of Frame */
+ #define IS_XA2_C BIT_0 /* Q_XA2 Encoding Error */
+
++/* Yukon-2 */
++/* B0_ISRC 32 bit Interrupt Source Register */
++/* B0_IMSK 32 bit Interrupt Mask Register */
++/* B0_SP_ISRC 32 bit Special Interrupt Source Reg */
++/* B2_IRQM_MSK 32 bit IRQ Moderation Mask */
++/* B0_Y2_SP_ISRC2 32 bit Special Interrupt Source Reg 2 */
++/* B0_Y2_SP_ISRC3 32 bit Special Interrupt Source Reg 3 */
++/* B0_Y2_SP_EISR 32 bit Enter ISR Reg */
++/* B0_Y2_SP_LISR 32 bit Leave ISR Reg */
++#define Y2_IS_PORT_MASK(Port, Mask) ((Mask) << (Port*8))
++#define Y2_IS_HW_ERR BIT_31 /* Interrupt HW Error */
++#define Y2_IS_STAT_BMU BIT_30 /* Status BMU Interrupt */
++#define Y2_IS_ASF BIT_29 /* ASF subsystem Interrupt */
++ /* Bit 28: reserved */
++#define Y2_IS_POLL_CHK BIT_27 /* Check IRQ from polling unit */
++#define Y2_IS_TWSI_RDY BIT_26 /* IRQ on end of TWSI Tx */
++#define Y2_IS_IRQ_SW BIT_25 /* SW forced IRQ */
++#define Y2_IS_TIMINT BIT_24 /* IRQ from Timer */
++ /* Bit 23..16 reserved */
++ /* Link 2 Interrupts */
++#define Y2_IS_IRQ_PHY2 BIT_12 /* Interrupt from PHY 2 */
++#define Y2_IS_IRQ_MAC2 BIT_11 /* Interrupt from MAC 2 */
++#define Y2_IS_CHK_RX2 BIT_10 /* Descriptor error Rx 2 */
++#define Y2_IS_CHK_TXS2 BIT_9 /* Descriptor error TXS 2 */
++#define Y2_IS_CHK_TXA2 BIT_8 /* Descriptor error TXA 2 */
++ /* Bit 7.. 5 reserved */
++ /* Link 1 interrupts */
++#define Y2_IS_IRQ_PHY1 BIT_4 /* Interrupt from PHY 1 */
++#define Y2_IS_IRQ_MAC1 BIT_3 /* Interrupt from MAC 1 */
++#define Y2_IS_CHK_RX1 BIT_2 /* Descriptor error Rx 1 */
++#define Y2_IS_CHK_TXS1 BIT_1 /* Descriptor error TXS 1 */
++#define Y2_IS_CHK_TXA1 BIT_0 /* Descriptor error TXA 1 */
++
++#define Y2_IS_L1_MASK 0x0000001fUL /* IRQ Mask for port 1 */
+
++#define Y2_IS_L2_MASK 0x00001f00UL /* IRQ Mask for port 2 */
++
++#define Y2_IS_ALL_MSK 0xef001f1fUL /* All Interrupt bits */
++
++/* Yukon and Genesis */
+ /* B0_HWE_ISRC 32 bit HW Error Interrupt Src Reg */
+ /* B0_HWE_IMSK 32 bit HW Error Interrupt Mask Reg */
+ /* B2_IRQM_HWE_MSK 32 bit IRQ Moderation HW Error Mask */
+ #define IS_ERR_MSK 0x00000fffL /* All Error bits */
+- /* Bit 31..14: reserved */
++ /* Bit 31..14: reserved */
+ #define IS_IRQ_TIST_OV BIT_13 /* Time Stamp Timer Overflow (YUKON only) */
+ #define IS_IRQ_SENSOR BIT_12 /* IRQ from Sensor (YUKON only) */
+ #define IS_IRQ_MST_ERR BIT_11 /* IRQ master error detected */
+@@ -900,6 +1216,43 @@
+ #define IS_R1_PAR_ERR BIT_1 /* Queue R1 Parity Error */
+ #define IS_R2_PAR_ERR BIT_0 /* Queue R2 Parity Error */
+
++/* Yukon-2 */
++/* B0_HWE_ISRC 32 bit HW Error Interrupt Src Reg */
++/* B0_HWE_IMSK 32 bit HW Error Interrupt Mask Reg */
++/* B2_IRQM_HWE_MSK 32 bit IRQ Moderation HW Error Mask */
++ /* Bit: 31..30 reserved */
++#define Y2_IS_TIST_OV BIT_29 /* Time Stamp Timer overflow interrupt */
++#define Y2_IS_SENSOR BIT_28 /* Sensor interrupt */
++#define Y2_IS_MST_ERR BIT_27 /* Master error interrupt */
++#define Y2_IS_IRQ_STAT BIT_26 /* Status exception interrupt */
++#define Y2_IS_PCI_EXP BIT_25 /* PCI-Express interrupt */
++#define Y2_IS_PCI_NEXP BIT_24 /* Bus Abort detected */
++ /* Bit: 23..14 reserved */
++ /* Link 2 */
++#define Y2_IS_PAR_RD2 BIT_13 /* Read RAM parity error interrupt */
++#define Y2_IS_PAR_WR2 BIT_12 /* Write RAM parity error interrupt */
++#define Y2_IS_PAR_MAC2 BIT_11 /* MAC hardware fault interrupt */
++#define Y2_IS_PAR_RX2 BIT_10 /* Parity Error Rx Queue 2 */
++#define Y2_IS_TCP_TXS2 BIT_9 /* TCP length mismatch sync Tx queue IRQ */
++#define Y2_IS_TCP_TXA2 BIT_8 /* TCP length mismatch async Tx queue IRQ */
++ /* Bit: 9.. 6 reserved */
++ /* Link 1 */
++#define Y2_IS_PAR_RD1 BIT_5 /* Read RAM parity error interrupt */
++#define Y2_IS_PAR_WR1 BIT_4 /* Write RAM parity error interrupt */
++#define Y2_IS_PAR_MAC1 BIT_3 /* MAC hardware fault interrupt */
++#define Y2_IS_PAR_RX1 BIT_2 /* Parity Error Rx Queue 1 */
++#define Y2_IS_TCP_TXS1 BIT_1 /* TCP length mismatch sync Tx queue IRQ */
++#define Y2_IS_TCP_TXA1 BIT_0 /* TCP length mismatch async Tx queue IRQ */
++
++#define Y2_HWE_L1_MASK (Y2_IS_PAR_RD1 | Y2_IS_PAR_WR1 | Y2_IS_PAR_MAC1 |\
++ Y2_IS_PAR_RX1 | Y2_IS_TCP_TXS1| Y2_IS_TCP_TXA1)
++#define Y2_HWE_L2_MASK (Y2_IS_PAR_RD2 | Y2_IS_PAR_WR2 | Y2_IS_PAR_MAC2 |\
++ Y2_IS_PAR_RX2 | Y2_IS_TCP_TXS2| Y2_IS_TCP_TXA2)
++
++#define Y2_HWE_ALL_MSK (Y2_IS_TIST_OV | /* Y2_IS_SENSOR | */ Y2_IS_MST_ERR |\
++ Y2_IS_IRQ_STAT | Y2_IS_PCI_EXP |\
++ Y2_HWE_L1_MASK | Y2_HWE_L2_MASK)
++
+ /* B2_CONN_TYP 8 bit Connector type */
+ /* B2_PMD_TYP 8 bit PMD type */
+ /* Values of connector and PMD type comply to SysKonnect internal std */
+@@ -908,19 +1261,66 @@
+ #define CFG_CHIP_R_MSK (0xf<<4) /* Bit 7.. 4: Chip Revision */
+ /* Bit 3.. 2: reserved */
+ #define CFG_DIS_M2_CLK BIT_1S /* Disable Clock for 2nd MAC */
+-#define CFG_SNG_MAC BIT_0S /* MAC Config: 0=2 MACs / 1=1 MAC*/
++#define CFG_SNG_MAC BIT_0S /* MAC Config: 0 = 2 MACs; 1 = 1 MAC */
+
+-/* B2_CHIP_ID 8 bit Chip Identification Number */
++/* B2_CHIP_ID 8 bit Chip Identification Number */
+ #define CHIP_ID_GENESIS 0x0a /* Chip ID for GENESIS */
+ #define CHIP_ID_YUKON 0xb0 /* Chip ID for YUKON */
+ #define CHIP_ID_YUKON_LITE 0xb1 /* Chip ID for YUKON-Lite (Rev. A1-A3) */
+ #define CHIP_ID_YUKON_LP 0xb2 /* Chip ID for YUKON-LP */
++#define CHIP_ID_YUKON_XL 0xb3 /* Chip ID for YUKON-2 XL */
++#define CHIP_ID_YUKON_EC_U 0xb4 /* Chip ID for YUKON-2 EC Ultra */
++#define CHIP_ID_YUKON_EC 0xb6 /* Chip ID for YUKON-2 EC */
++#define CHIP_ID_YUKON_FE 0xb7 /* Chip ID for YUKON-2 FE */
+
+ #define CHIP_REV_YU_LITE_A1 3 /* Chip Rev. for YUKON-Lite A1,A2 */
+ #define CHIP_REV_YU_LITE_A3 7 /* Chip Rev. for YUKON-Lite A3 */
+
++#define CHIP_REV_YU_EC_A1 0 /* Chip Rev. for Yukon-EC A1/A0 */
++#define CHIP_REV_YU_EC_A2 1 /* Chip Rev. for Yukon-EC A2 */
++#define CHIP_REV_YU_EC_A3 2 /* Chip Rev. for Yukon-EC A3 */
++
++/* B2_Y2_CLK_GATE 8 bit Clock Gating (Yukon-2 only) */
++#define Y2_STATUS_LNK2_INAC BIT_7S /* Status Link 2 inactiv (0 = activ) */
++#define Y2_CLK_GAT_LNK2_DIS BIT_6S /* Disable PHY clock for Link 2 */
++#define Y2_COR_CLK_LNK2_DIS BIT_5S /* Disable Core clock Link 2 */
++#define Y2_PCI_CLK_LNK2_DIS BIT_4S /* Disable PCI clock Link 2 */
++#define Y2_STATUS_LNK1_INAC BIT_3S /* Status Link 1 inactiv (0 = activ) */
++#define Y2_CLK_GAT_LNK1_DIS BIT_2S /* Disable PHY clock for Link 1 */
++#define Y2_COR_CLK_LNK1_DIS BIT_1S /* Disable Core clock Link 1 */
++#define Y2_PCI_CLK_LNK1_DIS BIT_0S /* Disable PCI clock Link 1 */
++
++/* B2_Y2_HW_RES 8 bit HW Resources (Yukon-2 only) */
++ /* Bit 7.. 5: reserved */
++#define CFG_LED_MODE_MSK (7<<2) /* Bit 4.. 2: LED Mode Mask */
++#define CFG_LINK_2_AVAIL BIT_1S /* Link 2 available */
++#define CFG_LINK_1_AVAIL BIT_0S /* Link 1 available */
++
++#define CFG_LED_MODE(x) (((x) & CFG_LED_MODE_MSK) >> 2)
++#define CFG_DUAL_MAC_MSK (CFG_LINK_2_AVAIL | CFG_LINK_1_AVAIL)
++
++#define CFG_LED_SING_ACT_LNK 0 /* Single LED ACT/LNK mode */
++#define CFG_LED_DUAL_ACT_LNK 1 /* Dual LED ACT/LNK mode */
++
++/* B2_E_3 8 bit lower 4 bits used for HW self test result */
++#define B2_E3_RES_MASK 0x0f
++
+ /* B2_FAR 32 bit Flash-Prom Addr Reg/Cnt */
+-#define FAR_ADDR 0x1ffffL /* Bit 16.. 0: FPROM Address mask */
++#define FAR_ADDR 0x1ffffL /* Bit 16.. 0: FPROM Address Mask */
++
++/* B2_Y2_CLK_CTRL 32 bit Core Clock Frequency Control Register (Yukon-2/EC) */
++ /* Bit 31..24: reserved */
++/* Yukon-EC/FE */
++#define Y2_CLK_DIV_VAL_MSK (0xffL<<16) /* Bit 23..16: Clock Divisor Value */
++#define Y2_CLK_DIV_VAL(x) (SHIFT16(x) & Y2_CLK_DIV_VAL_MSK)
++/* Yukon-2 */
++#define Y2_CLK_DIV_VAL2_MSK (7L<<21) /* Bit 23..21: Clock Divisor Value */
++#define Y2_CLK_SELECT2_MSK (0x1fL<<16) /* Bit 20..16: Clock Select */
++#define Y2_CLK_DIV_VAL_2(x) (SHIFT21(x) & Y2_CLK_DIV_VAL2_MSK)
++#define Y2_CLK_SEL_VAL_2(x) (SHIFT16(x) & Y2_CLK_SELECT2_MSK)
++ /* Bit 15.. 2: reserved */
++#define Y2_CLK_DIV_ENA BIT_1S /* Enable Core Clock Division */
++#define Y2_CLK_DIV_DIS BIT_0S /* Disable Core Clock Division */
+
+ /* B2_LD_CTRL 8 bit EPROM loader control register */
+ /* Bits are currently reserved */
+@@ -960,9 +1360,6 @@
+ #define DPT_START BIT_1S /* Start Descriptor Poll Timer */
+ #define DPT_STOP BIT_0S /* Stop Descriptor Poll Timer */
+
+-/* B2_E_3 8 bit lower 4 bits used for HW self test result */
+-#define B2_E3_RES_MASK 0x0f
+-
+ /* B2_TST_CTRL1 8 bit Test Control Register 1 */
+ #define TST_FRC_DPERR_MR BIT_7S /* force DATAPERR on MST RD */
+ #define TST_FRC_DPERR_MW BIT_6S /* force DATAPERR on MST WR */
+@@ -975,14 +1372,14 @@
+
+ /* B2_TST_CTRL2 8 bit Test Control Register 2 */
+ /* Bit 7.. 4: reserved */
+- /* force the following error on the next master read/write */
++ /* force the following error on the next master read/write */
+ #define TST_FRC_DPERR_MR64 BIT_3S /* DataPERR RD 64 */
+ #define TST_FRC_DPERR_MW64 BIT_2S /* DataPERR WR 64 */
+ #define TST_FRC_APERR_1M64 BIT_1S /* AddrPERR on 1. phase */
+ #define TST_FRC_APERR_2M64 BIT_0S /* AddrPERR on 2. phase */
+
+ /* B2_GP_IO 32 bit General Purpose I/O Register */
+- /* Bit 31..26: reserved */
++ /* Bit 31..26: reserved */
+ #define GP_DIR_9 BIT_25 /* IO_9 direct, 0=In/1=Out */
+ #define GP_DIR_8 BIT_24 /* IO_8 direct, 0=In/1=Out */
+ #define GP_DIR_7 BIT_23 /* IO_7 direct, 0=In/1=Out */
+@@ -1026,16 +1423,14 @@
+ /* Bit 31.. 1 reserved */
+ #define I2C_CLR_IRQ BIT_0 /* Clear I2C IRQ */
+
+-/* B2_I2C_SW 32 bit (8 bit access) I2C HW SW Port Register */
++/* B2_I2C_SW 32 bit (8 bit access) I2C SW Port Register */
+ /* Bit 7.. 3: reserved */
+ #define I2C_DATA_DIR BIT_2S /* direction of I2C_DATA */
+ #define I2C_DATA BIT_1S /* I2C Data Port */
+ #define I2C_CLK BIT_0S /* I2C Clock Port */
+
+-/*
+- * I2C Address
+- */
+-#define I2C_SENS_ADDR LM80_ADDR /* I2C Sensor Address, (Volt and Temp)*/
++/* I2C Address */
++#define I2C_SENS_ADDR LM80_ADDR /* I2C Sensor Address (Volt and Temp) */
+
+
+ /* B2_BSC_CTRL 8 bit Blink Source Counter Control */
+@@ -1052,16 +1447,20 @@
+ #define BSC_T_OFF BIT_1S /* Test mode off */
+ #define BSC_T_STEP BIT_0S /* Test step */
+
++/* Y2_PEX_PHY_ADDR/DATA PEX PHY address and data reg (Yukon-2 only) */
++#define PEX_RD_ACCESS BIT_31 /* Access Mode Read = 1, Write = 0 */
++#define PEX_DB_ACCESS BIT_30 /* Access to debug register */
++
+
+ /* B3_RAM_ADDR 32 bit RAM Address, to read or write */
+ /* Bit 31..19: reserved */
+ #define RAM_ADR_RAN 0x0007ffffL /* Bit 18.. 0: RAM Address Range */
+
+ /* RAM Interface Registers */
+-/* B3_RI_CTRL 16 bit RAM Iface Control Register */
++/* B3_RI_CTRL 16 bit RAM Interface Control Register */
+ /* Bit 15..10: reserved */
+-#define RI_CLR_RD_PERR BIT_9S /* Clear IRQ RAM Read Parity Err */
+-#define RI_CLR_WR_PERR BIT_8S /* Clear IRQ RAM Write Parity Err*/
++#define RI_CLR_RD_PERR BIT_9S /* Clear IRQ RAM Read Parity Err */
++#define RI_CLR_WR_PERR BIT_8S /* Clear IRQ RAM Write Parity Err */
+ /* Bit 7.. 2: reserved */
+ #define RI_RST_CLR BIT_1S /* Clear RAM Interface Reset */
+ #define RI_RST_SET BIT_0S /* Set RAM Interface Reset */
+@@ -1171,7 +1570,7 @@
+ /* Bit 31..16: reserved */
+ #define BC_MAX 0xffff /* Bit 15.. 0: Byte counter */
+
+-/* BMU Control Status Registers */
++/* BMU Control / Status Registers (Yukon and Genesis) */
+ /* B0_R1_CSR 32 bit BMU Ctrl/Stat Rx Queue 1 */
+ /* B0_R2_CSR 32 bit BMU Ctrl/Stat Rx Queue 2 */
+ /* B0_XA1_CSR 32 bit BMU Ctrl/Stat Sync Tx Queue 1 */
+@@ -1212,6 +1611,41 @@
+ CSR_SV_RUN | CSR_DREAD_RUN | CSR_DWRITE_RUN |\
+ CSR_TRANS_RUN)
+
++/* Rx BMU Control / Status Registers (Yukon-2) */
++#define BMU_IDLE BIT_31 /* BMU Idle State */
++#define BMU_RX_TCP_PKT BIT_30 /* Rx TCP Packet (when RSS Hash enabled) */
++#define BMU_RX_IP_PKT BIT_29 /* Rx IP Packet (when RSS Hash enabled) */
++ /* Bit 28..16: reserved */
++#define BMU_ENA_RX_RSS_HASH BIT_15 /* Enable Rx RSS Hash */
++#define BMU_DIS_RX_RSS_HASH BIT_14 /* Disable Rx RSS Hash */
++#define BMU_ENA_RX_CHKSUM BIT_13 /* Enable Rx TCP/IP Checksum Check */
++#define BMU_DIS_RX_CHKSUM BIT_12 /* Disable Rx TCP/IP Checksum Check */
++#define BMU_CLR_IRQ_PAR BIT_11 /* Clear IRQ on Parity errors (Rx) */
++#define BMU_CLR_IRQ_TCP BIT_11 /* Clear IRQ on TCP segmen. error (Tx) */
++#define BMU_CLR_IRQ_CHK BIT_10 /* Clear IRQ Check */
++#define BMU_STOP BIT_9 /* Stop Rx/Tx Queue */
++#define BMU_START BIT_8 /* Start Rx/Tx Queue */
++#define BMU_FIFO_OP_ON BIT_7 /* FIFO Operational On */
++#define BMU_FIFO_OP_OFF BIT_6 /* FIFO Operational Off */
++#define BMU_FIFO_ENA BIT_5 /* Enable FIFO */
++#define BMU_FIFO_RST BIT_4 /* Reset FIFO */
++#define BMU_OP_ON BIT_3 /* BMU Operational On */
++#define BMU_OP_OFF BIT_2 /* BMU Operational Off */
++#define BMU_RST_CLR BIT_1 /* Clear BMU Reset (Enable) */
++#define BMU_RST_SET BIT_0 /* Set BMU Reset */
++
++#define BMU_CLR_RESET (BMU_FIFO_RST | BMU_OP_OFF | BMU_RST_CLR)
++#define BMU_OPER_INIT (BMU_CLR_IRQ_PAR | BMU_CLR_IRQ_CHK | BMU_START | \
++ BMU_FIFO_ENA | BMU_OP_ON)
++
++/* Tx BMU Control / Status Registers (Yukon-2) */
++ /* Bit 31: same as for Rx */
++ /* Bit 30..14: reserved */
++#define BMU_TX_IPIDINCR_ON BIT_13 /* Enable IP ID Increment */
++#define BMU_TX_IPIDINCR_OFF BIT_12 /* Disable IP ID Increment */
++#define BMU_TX_CLR_IRQ_TCP BIT_11 /* Clear IRQ on TCP segm. length mism. */
++ /* Bit 10..0: same as for Rx */
++
+ /* Q_F 32 bit Flag Register */
+ /* Bit 31..28: reserved */
+ #define F_ALM_FULL BIT_27 /* Rx FIFO: almost full */
+@@ -1260,6 +1694,13 @@
+ /* Bit 3: reserved */
+ #define T3_VRAM_MSK 7 /* Bit 2.. 0: Virtual RAM Buffer Address */
+
++/* Queue Prefetch Unit Offsets, use Y2_PREF_Q_ADDR() to address (Yukon-2 only)*/
++/* PREF_UNIT_CTRL_REG 32 bit Prefetch Control register */
++#define PREF_UNIT_OP_ON BIT_3 /* prefetch unit operational */
++#define PREF_UNIT_OP_OFF BIT_2 /* prefetch unit not operational */
++#define PREF_UNIT_RST_CLR BIT_1 /* Clear Prefetch Unit Reset */
++#define PREF_UNIT_RST_SET BIT_0 /* Set Prefetch Unit Reset */
++
+ /* RAM Buffer Register Offsets, use RB_ADDR(Queue, Offs) to access */
+ /* RB_START 32 bit RAM Buffer Start Address */
+ /* RB_END 32 bit RAM Buffer End Address */
+@@ -1275,24 +1716,24 @@
+ #define RB_MSK 0x0007ffff /* Bit 18.. 0: RAM Buffer Pointer Bits */
+
+ /* RB_TST2 8 bit RAM Buffer Test Register 2 */
+- /* Bit 7.. 4: reserved */
+-#define RB_PC_DEC BIT_3S /* Packet Counter Decrem */
++ /* Bit 7.. 4: reserved */
++#define RB_PC_DEC BIT_3S /* Packet Counter Decrement */
+ #define RB_PC_T_ON BIT_2S /* Packet Counter Test On */
+-#define RB_PC_T_OFF BIT_1S /* Packet Counter Tst Off */
+-#define RB_PC_INC BIT_0S /* Packet Counter Increm */
++#define RB_PC_T_OFF BIT_1S /* Packet Counter Test Off */
++#define RB_PC_INC BIT_0S /* Packet Counter Increment */
+
+ /* RB_TST1 8 bit RAM Buffer Test Register 1 */
+ /* Bit 7: reserved */
+ #define RB_WP_T_ON BIT_6S /* Write Pointer Test On */
+ #define RB_WP_T_OFF BIT_5S /* Write Pointer Test Off */
+-#define RB_WP_INC BIT_4S /* Write Pointer Increm */
++#define RB_WP_INC BIT_4S /* Write Pointer Increment */
+ /* Bit 3: reserved */
+ #define RB_RP_T_ON BIT_2S /* Read Pointer Test On */
+ #define RB_RP_T_OFF BIT_1S /* Read Pointer Test Off */
+-#define RB_RP_DEC BIT_0S /* Read Pointer Decrement */
++#define RB_RP_INC BIT_0S /* Read Pointer Increment */
+
+ /* RB_CTRL 8 bit RAM Buffer Control Register */
+- /* Bit 7.. 6: reserved */
++ /* Bit 7.. 6: reserved */
+ #define RB_ENA_STFWD BIT_5S /* Enable Store & Forward */
+ #define RB_DIS_STFWD BIT_4S /* Disable Store & Forward */
+ #define RB_ENA_OP_MD BIT_3S /* Enable Operation Mode */
+@@ -1300,16 +1741,31 @@
+ #define RB_RST_CLR BIT_1S /* Clear RAM Buf STM Reset */
+ #define RB_RST_SET BIT_0S /* Set RAM Buf STM Reset */
+
++/* Yukon-2 */
++ /* Bit 31..20: reserved */
++#define RB_CNT_DOWN BIT_19 /* Packet Counter Decrement */
++#define RB_CNT_TST_ON BIT_18 /* Packet Counter Test On */
++#define RB_CNT_TST_OFF BIT_17 /* Packet Counter Test Off */
++#define RB_CNT_UP BIT_16 /* Packet Counter Increment */
++ /* Bit 15: reserved */
++#define RB_WP_TST_ON BIT_14 /* Write Pointer Test On */
++#define RB_WP_TST_OFF BIT_13 /* Write Pointer Test Off */
++#define RB_WP_UP BIT_12 /* Write Pointer Increment */
++ /* Bit 11: reserved */
++#define RB_RP_TST_ON BIT_10 /* Read Pointer Test On */
++#define RB_RP_TST_OFF BIT_9 /* Read Pointer Test Off */
++#define RB_RP_UP BIT_8 /* Read Pointer Increment */
++
+
+ /* Receive and Transmit MAC FIFO Registers (GENESIS only) */
+
+ /* RX_MFF_EA 32 bit Receive MAC FIFO End Address */
+-/* RX_MFF_WP 32 bit Receive MAC FIFO Write Pointer */
++/* RX_MFF_WP 32 bit Receive MAC FIFO Write Pointer */
+ /* RX_MFF_RP 32 bit Receive MAC FIFO Read Pointer */
+ /* RX_MFF_PC 32 bit Receive MAC FIFO Packet Counter */
+ /* RX_MFF_LEV 32 bit Receive MAC FIFO Level */
+ /* TX_MFF_EA 32 bit Transmit MAC FIFO End Address */
+-/* TX_MFF_WP 32 bit Transmit MAC FIFO Write Pointer */
++/* TX_MFF_WP 32 bit Transmit MAC FIFO Write Pointer */
+ /* TX_MFF_WSP 32 bit Transmit MAC FIFO WR Shadow Pointer */
+ /* TX_MFF_RP 32 bit Transmit MAC FIFO Read Pointer */
+ /* TX_MFF_PC 32 bit Transmit MAC FIFO Packet Cnt */
+@@ -1359,9 +1815,9 @@
+ /* RX_MFF_TST2 8 bit Receive MAC FIFO Test Register 2 */
+ /* TX_MFF_TST2 8 bit Transmit MAC FIFO Test Register 2 */
+ /* Bit 7: reserved */
+-#define MFF_WSP_T_ON BIT_6S /* Tx: Write Shadow Ptr TestOn */
+-#define MFF_WSP_T_OFF BIT_5S /* Tx: Write Shadow Ptr TstOff */
+-#define MFF_WSP_INC BIT_4S /* Tx: Write Shadow Ptr Increment */
++#define MFF_WSP_T_ON BIT_6S /* Tx: Write Shadow Pointer Test On */
++#define MFF_WSP_T_OFF BIT_5S /* Tx: Write Shadow Pointer Test Off */
++#define MFF_WSP_INC BIT_4S /* Tx: Write Shadow Pointer Increment */
+ #define MFF_PC_DEC BIT_3S /* Packet Counter Decrement */
+ #define MFF_PC_T_ON BIT_2S /* Packet Counter Test On */
+ #define MFF_PC_T_OFF BIT_1S /* Packet Counter Test Off */
+@@ -1372,7 +1828,7 @@
+ /* Bit 7: reserved */
+ #define MFF_WP_T_ON BIT_6S /* Write Pointer Test On */
+ #define MFF_WP_T_OFF BIT_5S /* Write Pointer Test Off */
+-#define MFF_WP_INC BIT_4S /* Write Pointer Increm */
++#define MFF_WP_INC BIT_4S /* Write Pointer Increment */
+ /* Bit 3: reserved */
+ #define MFF_RP_T_ON BIT_2S /* Read Pointer Test On */
+ #define MFF_RP_T_OFF BIT_1S /* Read Pointer Test Off */
+@@ -1391,12 +1847,16 @@
+
+ /* RX_LED_CTRL 8 bit Receive LED Cnt Control Reg */
+ /* TX_LED_CTRL 8 bit Transmit LED Cnt Control Reg */
++ /* Bit 7.. 3: reserved */
++#define LED_START BIT_2S /* Start Counter */
++#define LED_STOP BIT_1S /* Stop Counter */
++#define LED_STATE BIT_0S /* Rx/Tx: LED State, 1=LED On */
++
+ /* LNK_SYNC_CTRL 8 bit Link Sync Cnt Control Register */
+ /* Bit 7.. 3: reserved */
+-#define LED_START BIT_2S /* Start Timer */
+-#define LED_STOP BIT_1S /* Stop Timer */
+-#define LED_STATE BIT_0S /* Rx/Tx: LED State, 1=LED on */
+-#define LED_CLR_IRQ BIT_0S /* Lnk: Clear Link IRQ */
++#define LNK_START BIT_2S /* Start Counter */
++#define LNK_STOP BIT_1S /* Stop Counter */
++#define LNK_CLR_IRQ BIT_0S /* Clear Link IRQ */
+
+ /* RX_LED_TST 8 bit Receive LED Cnt Test Register */
+ /* TX_LED_TST 8 bit Transmit LED Cnt Test Register */
+@@ -1407,86 +1867,138 @@
+ #define LED_T_STEP BIT_0S /* LED Counter Step */
+
+ /* LNK_LED_REG 8 bit Link LED Register */
+- /* Bit 7.. 6: reserved */
++ /* Bit 7.. 6: reserved */
+ #define LED_BLK_ON BIT_5S /* Link LED Blinking On */
+ #define LED_BLK_OFF BIT_4S /* Link LED Blinking Off */
+ #define LED_SYNC_ON BIT_3S /* Use Sync Wire to switch LED */
+ #define LED_SYNC_OFF BIT_2S /* Disable Sync Wire Input */
+-#define LED_ON BIT_1S /* switch LED on */
+-#define LED_OFF BIT_0S /* switch LED off */
++#define LED_ON BIT_1S /* Switch LED On */
++#define LED_OFF BIT_0S /* Switch LED Off */
+
+ /* Receive and Transmit GMAC FIFO Registers (YUKON only) */
+
+ /* RX_GMF_EA 32 bit Rx GMAC FIFO End Address */
+ /* RX_GMF_AF_THR 32 bit Rx GMAC FIFO Almost Full Thresh. */
+-/* RX_GMF_WP 32 bit Rx GMAC FIFO Write Pointer */
+-/* RX_GMF_WLEV 32 bit Rx GMAC FIFO Write Level */
+-/* RX_GMF_RP 32 bit Rx GMAC FIFO Read Pointer */
+-/* RX_GMF_RLEV 32 bit Rx GMAC FIFO Read Level */
++/* RX_GMF_WP 32 bit Rx GMAC FIFO Write Pointer */
++/* RX_GMF_WLEV 32 bit Rx GMAC FIFO Write Level */
++/* RX_GMF_RP 32 bit Rx GMAC FIFO Read Pointer */
++/* RX_GMF_RLEV 32 bit Rx GMAC FIFO Read Level */
+ /* TX_GMF_EA 32 bit Tx GMAC FIFO End Address */
+ /* TX_GMF_AE_THR 32 bit Tx GMAC FIFO Almost Empty Thresh.*/
+-/* TX_GMF_WP 32 bit Tx GMAC FIFO Write Pointer */
+-/* TX_GMF_WSP 32 bit Tx GMAC FIFO Write Shadow Ptr. */
+-/* TX_GMF_WLEV 32 bit Tx GMAC FIFO Write Level */
+-/* TX_GMF_RP 32 bit Tx GMAC FIFO Read Pointer */
+-/* TX_GMF_RSTP 32 bit Tx GMAC FIFO Restart Pointer */
+-/* TX_GMF_RLEV 32 bit Tx GMAC FIFO Read Level */
++/* TX_GMF_WP 32 bit Tx GMAC FIFO Write Pointer */
++/* TX_GMF_WSP 32 bit Tx GMAC FIFO Write Shadow Pointer */
++/* TX_GMF_WLEV 32 bit Tx GMAC FIFO Write Level */
++/* TX_GMF_RP 32 bit Tx GMAC FIFO Read Pointer */
++/* TX_GMF_RSTP 32 bit Tx GMAC FIFO Restart Pointer */
++/* TX_GMF_RLEV 32 bit Tx GMAC FIFO Read Level */
+
+ /* RX_GMF_CTRL_T 32 bit Rx GMAC FIFO Control/Test */
+- /* Bits 31..15: reserved */
+-#define GMF_WP_TST_ON BIT_14 /* Write Pointer Test On */
+-#define GMF_WP_TST_OFF BIT_13 /* Write Pointer Test Off */
+-#define GMF_WP_STEP BIT_12 /* Write Pointer Step/Increment */
++ /* Bit 31..28 reserved */
++#define RX_TRUNC_ON BIT_27 /* enable packet truncation */
++#define RX_TRUNC_OFF BIT_26 /* disable packet truncation */
++#define RX_VLAN_STRIP_ON BIT_25 /* enable VLAN stripping */
++#define RX_VLAN_STRIP_OFF BIT_24 /* disable VLAN stripping */
++ /* Bit 23..15 reserved */
++#define GMF_WP_TST_ON BIT_14 /* Write Pointer Test On */
++#define GMF_WP_TST_OFF BIT_13 /* Write Pointer Test Off */
++#define GMF_WP_STEP BIT_12 /* Write Pointer Step/Increment */
+ /* Bit 11: reserved */
+-#define GMF_RP_TST_ON BIT_10 /* Read Pointer Test On */
+-#define GMF_RP_TST_OFF BIT_9 /* Read Pointer Test Off */
+-#define GMF_RP_STEP BIT_8 /* Read Pointer Step/Increment */
+-#define GMF_RX_F_FL_ON BIT_7 /* Rx FIFO Flush Mode On */
+-#define GMF_RX_F_FL_OFF BIT_6 /* Rx FIFO Flush Mode Off */
+-#define GMF_CLI_RX_FO BIT_5 /* Clear IRQ Rx FIFO Overrun */
+-#define GMF_CLI_RX_FC BIT_4 /* Clear IRQ Rx Frame Complete */
+-#define GMF_OPER_ON BIT_3 /* Operational Mode On */
+-#define GMF_OPER_OFF BIT_2 /* Operational Mode Off */
+-#define GMF_RST_CLR BIT_1 /* Clear GMAC FIFO Reset */
+-#define GMF_RST_SET BIT_0 /* Set GMAC FIFO Reset */
+-
+-/* TX_GMF_CTRL_T 32 bit Tx GMAC FIFO Control/Test */
+- /* Bits 31..19: reserved */
+-#define GMF_WSP_TST_ON BIT_18 /* Write Shadow Pointer Test On */
+-#define GMF_WSP_TST_OFF BIT_17 /* Write Shadow Pointer Test Off */
+-#define GMF_WSP_STEP BIT_16 /* Write Shadow Pointer Step/Increment */
+- /* Bits 15..7: same as for RX_GMF_CTRL_T */
+-#define GMF_CLI_TX_FU BIT_6 /* Clear IRQ Tx FIFO Underrun */
+-#define GMF_CLI_TX_FC BIT_5 /* Clear IRQ Tx Frame Complete */
+-#define GMF_CLI_TX_PE BIT_4 /* Clear IRQ Tx Parity Error */
++#define GMF_RP_TST_ON BIT_10 /* Read Pointer Test On */
++#define GMF_RP_TST_OFF BIT_9 /* Read Pointer Test Off */
++#define GMF_RP_STEP BIT_8 /* Read Pointer Step/Increment */
++#define GMF_RX_F_FL_ON BIT_7 /* Rx FIFO Flush Mode On */
++#define GMF_RX_F_FL_OFF BIT_6 /* Rx FIFO Flush Mode Off */
++#define GMF_CLI_RX_FO BIT_5 /* Clear IRQ Rx FIFO Overrun */
++#define GMF_CLI_RX_FC BIT_4 /* Clear IRQ Rx Frame Complete */
++#define GMF_OPER_ON BIT_3 /* Operational Mode On */
++#define GMF_OPER_OFF BIT_2 /* Operational Mode Off */
++#define GMF_RST_CLR BIT_1 /* Clear GMAC FIFO Reset */
++#define GMF_RST_SET BIT_0 /* Set GMAC FIFO Reset */
++
++/* TX_GMF_CTRL_T 32 bit Tx GMAC FIFO Control/Test (YUKON and Yukon-2) */
++ /* Bits 31..26: reserved */
++#define TX_VLAN_TAG_ON BIT_25 /* enable VLAN tagging */
++#define TX_VLAN_TAG_OFF BIT_24 /* disable VLAN tagging */
++ /* Bits 23..19: reserved */
++#define GMF_WSP_TST_ON BIT_18 /* Write Shadow Pointer Test On */
++#define GMF_WSP_TST_OFF BIT_17 /* Write Shadow Pointer Test Off */
++#define GMF_WSP_STEP BIT_16 /* Write Shadow Pointer Step/Increment */
++ /* Bits 15..8: same as for RX_GMF_CTRL_T */
++ /* Bit 7: reserved */
++#define GMF_CLI_TX_FU BIT_6 /* Clear IRQ Tx FIFO Underrun */
++#define GMF_CLI_TX_FC BIT_5 /* Clear IRQ Tx Frame Complete */
++#define GMF_CLI_TX_PE BIT_4 /* Clear IRQ Tx Parity Error */
+ /* Bits 3..0: same as for RX_GMF_CTRL_T */
+
+ #define GMF_RX_CTRL_DEF (GMF_OPER_ON | GMF_RX_F_FL_ON)
+ #define GMF_TX_CTRL_DEF GMF_OPER_ON
+
++#define RX_GMF_AF_THR_MIN 0x0c /* Rx GMAC FIFO Almost Full Thresh. min. */
+ #define RX_GMF_FL_THR_DEF 0x0a /* Rx GMAC FIFO Flush Threshold default */
+
+ /* GMAC_TI_ST_CTRL 8 bit Time Stamp Timer Ctrl Reg (YUKON only) */
+- /* Bit 7.. 3: reserved */
+-#define GMT_ST_START BIT_2S /* Start Time Stamp Timer */
+-#define GMT_ST_STOP BIT_1S /* Stop Time Stamp Timer */
+-#define GMT_ST_CLR_IRQ BIT_0S /* Clear Time Stamp Timer IRQ */
+-
++ /* Bit 7.. 3: reserved */
++#define GMT_ST_START BIT_2S /* Start Time Stamp Timer */
++#define GMT_ST_STOP BIT_1S /* Stop Time Stamp Timer */
++#define GMT_ST_CLR_IRQ BIT_0S /* Clear Time Stamp Timer IRQ */
++
++/* POLL_CTRL 32 bit Polling Unit control register (Yukon-2 only) */
++ /* Bit 31.. 6: reserved */
++#define PC_CLR_IRQ_CHK BIT_5 /* Clear IRQ Check */
++#define PC_POLL_RQ BIT_4 /* Poll Request Start */
++#define PC_POLL_OP_ON BIT_3 /* Operational Mode On */
++#define PC_POLL_OP_OFF BIT_2 /* Operational Mode Off */
++#define PC_POLL_RST_CLR BIT_1 /* Clear Polling Unit Reset (Enable) */
++#define PC_POLL_RST_SET BIT_0 /* Set Polling Unit Reset */
++
++
++/* The bit definition of the following registers is still missing! */
++/* B28_Y2_SMB_CONFIG 32 bit ASF SMBus Config Register */
++/* B28_Y2_SMB_CSD_REG 32 bit ASF SMB Control/Status/Data */
++/* B28_Y2_ASF_IRQ_V_BASE 32 bit ASF IRQ Vector Base */
++
++/* B28_Y2_ASF_STAT_CMD 32 bit ASF Status and Command Reg */
++/* This register is used by the host driver software */
++ /* Bit 31:5 reserved */
++#define Y2_ASF_OS_PRES BIT_4S /* ASF operation system present */
++#define Y2_ASF_RESET BIT_3S /* ASF system in reset state */
++#define Y2_ASF_RUNNING BIT_2S /* ASF system operational */
++#define Y2_ASF_CLR_HSTI BIT_1S /* Clear ASF IRQ */
++#define Y2_ASF_IRQ BIT_0S /* Issue an IRQ to ASF system */
++
++#define Y2_ASF_UC_STATE (3<<2) /* ASF uC State */
++#define Y2_ASF_CLK_HALT 0 /* ASF system clock stopped */
++
++/* B28_Y2_ASF_HOST_COM 32 bit ASF Host Communication Reg */
++/* This register is used by the ASF firmware */
++ /* Bit 31:2 reserved */
++#define Y2_ASF_CLR_ASFI BIT_1 /* Clear host IRQ */
++#define Y2_ASF_HOST_IRQ BIT_0 /* Issue an IRQ to HOST system */
++
++
++/* STAT_CTRL 32 bit Status BMU control register (Yukon-2 only) */
++ /* Bit 7.. 5: reserved */
++#define SC_STAT_CLR_IRQ BIT_4 /* Status Burst IRQ clear */
++#define SC_STAT_OP_ON BIT_3 /* Operational Mode On */
++#define SC_STAT_OP_OFF BIT_2 /* Operational Mode Off */
++#define SC_STAT_RST_CLR BIT_1 /* Clear Status Unit Reset (Enable) */
++#define SC_STAT_RST_SET BIT_0 /* Set Status Unit Reset */
++
+ /* GMAC_CTRL 32 bit GMAC Control Reg (YUKON only) */
+ /* Bits 31.. 8: reserved */
+-#define GMC_H_BURST_ON BIT_7 /* Half Duplex Burst Mode On */
+-#define GMC_H_BURST_OFF BIT_6 /* Half Duplex Burst Mode Off */
+-#define GMC_F_LOOPB_ON BIT_5 /* FIFO Loopback On */
+-#define GMC_F_LOOPB_OFF BIT_4 /* FIFO Loopback Off */
+-#define GMC_PAUSE_ON BIT_3 /* Pause On */
+-#define GMC_PAUSE_OFF BIT_2 /* Pause Off */
+-#define GMC_RST_CLR BIT_1 /* Clear GMAC Reset */
+-#define GMC_RST_SET BIT_0 /* Set GMAC Reset */
++#define GMC_H_BURST_ON BIT_7 /* Half Duplex Burst Mode On */
++#define GMC_H_BURST_OFF BIT_6 /* Half Duplex Burst Mode Off */
++#define GMC_F_LOOPB_ON BIT_5 /* FIFO Loopback On */
++#define GMC_F_LOOPB_OFF BIT_4 /* FIFO Loopback Off */
++#define GMC_PAUSE_ON BIT_3 /* Pause On */
++#define GMC_PAUSE_OFF BIT_2 /* Pause Off */
++#define GMC_RST_CLR BIT_1 /* Clear GMAC Reset */
++#define GMC_RST_SET BIT_0 /* Set GMAC Reset */
+
+ /* GPHY_CTRL 32 bit GPHY Control Reg (YUKON only) */
+ /* Bits 31..29: reserved */
+ #define GPC_SEL_BDT BIT_28 /* Select Bi-Dir. Transfer for MDC/MDIO */
+-#define GPC_INT_POL_HI BIT_27 /* IRQ Polarity is Active HIGH */
++#define GPC_INT_POL BIT_27 /* IRQ Polarity is Active Low */
+ #define GPC_75_OHM BIT_26 /* Use 75 Ohm Termination instead of 50 */
+ #define GPC_DIS_FC BIT_25 /* Disable Automatic Fiber/Copper Detection */
+ #define GPC_DIS_SLEEP BIT_24 /* Disable Energy Detect */
+@@ -1540,14 +2052,14 @@
+
+ /* GMAC_IRQ_SRC 8 bit GMAC Interrupt Source Reg (YUKON only) */
+ /* GMAC_IRQ_MSK 8 bit GMAC Interrupt Mask Reg (YUKON only) */
+-#define GM_IS_TX_CO_OV BIT_5 /* Transmit Counter Overflow IRQ */
+-#define GM_IS_RX_CO_OV BIT_4 /* Receive Counter Overflow IRQ */
+-#define GM_IS_TX_FF_UR BIT_3 /* Transmit FIFO Underrun */
+-#define GM_IS_TX_COMPL BIT_2 /* Frame Transmission Complete */
+-#define GM_IS_RX_FF_OR BIT_1 /* Receive FIFO Overrun */
+-#define GM_IS_RX_COMPL BIT_0 /* Frame Reception Complete */
++#define GM_IS_RX_CO_OV BIT_5S /* Receive Counter Overflow IRQ */
++#define GM_IS_TX_CO_OV BIT_4S /* Transmit Counter Overflow IRQ */
++#define GM_IS_TX_FF_UR BIT_3S /* Transmit FIFO Underrun */
++#define GM_IS_TX_COMPL BIT_2S /* Frame Transmission Complete */
++#define GM_IS_RX_FF_OR BIT_1S /* Receive FIFO Overrun */
++#define GM_IS_RX_COMPL BIT_0S /* Frame Reception Complete */
+
+-#define GMAC_DEF_MSK (GM_IS_TX_CO_OV | GM_IS_RX_CO_OV | \
++#define GMAC_DEF_MSK (GM_IS_RX_CO_OV | GM_IS_TX_CO_OV | \
+ GM_IS_TX_FF_UR)
+
+ /* GMAC_LINK_CTRL 16 bit GMAC Link Control Reg (YUKON only) */
+@@ -1579,15 +2091,19 @@
+
+ #define WOL_CTL_DEFAULT \
+ (WOL_CTL_DIS_PME_ON_LINK_CHG | \
+- WOL_CTL_DIS_PME_ON_PATTERN | \
+- WOL_CTL_DIS_PME_ON_MAGIC_PKT | \
+- WOL_CTL_DIS_LINK_CHG_UNIT | \
+- WOL_CTL_DIS_PATTERN_UNIT | \
+- WOL_CTL_DIS_MAGIC_PKT_UNIT)
++ WOL_CTL_DIS_PME_ON_PATTERN | \
++ WOL_CTL_DIS_PME_ON_MAGIC_PKT | \
++ WOL_CTL_DIS_LINK_CHG_UNIT | \
++ WOL_CTL_DIS_PATTERN_UNIT | \
++ WOL_CTL_DIS_MAGIC_PKT_UNIT)
+
+ /* WOL_MATCH_CTL 8 bit WOL Match Control Reg */
+ #define WOL_CTL_PATT_ENA(x) (BIT_0 << (x))
+
++/* WOL_PATT_PME 8 bit WOL PME Match Enable (Yukon-2) */
++#define WOL_PATT_FORCE_PME BIT_7 /* Generates a PME */
++#define WOL_PATT_MATCH_PME_ALL 0x7f
++
+ #define SK_NUM_WOL_PATTERN 7
+ #define SK_PATTERN_PER_WORD 4
+ #define SK_BITMASK_PATTERN 7
+@@ -1597,6 +2113,8 @@
+ #define WOL_LENGTH_SHIFT 8
+
+
++/* typedefs ******************************************************************/
++
+ /* Receive and Transmit Descriptors ******************************************/
+
+ /* Transmit Descriptor struct */
+@@ -1606,17 +2124,17 @@
+ SK_U32 TxAdrLo; /* Physical Tx Buffer Address lower dword */
+ SK_U32 TxAdrHi; /* Physical Tx Buffer Address upper dword */
+ SK_U32 TxStat; /* Transmit Frame Status Word */
+-#ifndef SK_USE_REV_DESC
++#ifndef SK_USE_REV_DESC
+ SK_U16 TxTcpOffs; /* TCP Checksum Calculation Start Value */
+ SK_U16 TxRes1; /* 16 bit reserved field */
+ SK_U16 TxTcpWp; /* TCP Checksum Write Position */
+ SK_U16 TxTcpSp; /* TCP Checksum Calculation Start Position */
+-#else /* SK_USE_REV_DESC */
++#else /* SK_USE_REV_DESC */
+ SK_U16 TxRes1; /* 16 bit reserved field */
+ SK_U16 TxTcpOffs; /* TCP Checksum Calculation Start Value */
+ SK_U16 TxTcpSp; /* TCP Checksum Calculation Start Position */
+ SK_U16 TxTcpWp; /* TCP Checksum Write Position */
+-#endif /* SK_USE_REV_DESC */
++#endif /* SK_USE_REV_DESC */
+ SK_U32 TxRes2; /* 32 bit reserved field */
+ } SK_HWTXD;
+
+@@ -1628,29 +2146,262 @@
+ SK_U32 RxAdrHi; /* Physical Rx Buffer Address upper dword */
+ SK_U32 RxStat; /* Receive Frame Status Word */
+ SK_U32 RxTiSt; /* Receive Time Stamp (from XMAC on GENESIS) */
+-#ifndef SK_USE_REV_DESC
+- SK_U16 RxTcpSum1; /* TCP Checksum 1 */
+- SK_U16 RxTcpSum2; /* TCP Checksum 2 */
++#ifndef SK_USE_REV_DESC
++ SK_U16 RxTcpSum1; /* Rx TCP Checksum 1 */
++ SK_U16 RxTcpSum2; /* Rx TCP Checksum 2 */
+ SK_U16 RxTcpSp1; /* TCP Checksum Calculation Start Position 1 */
+ SK_U16 RxTcpSp2; /* TCP Checksum Calculation Start Position 2 */
+-#else /* SK_USE_REV_DESC */
+- SK_U16 RxTcpSum2; /* TCP Checksum 2 */
+- SK_U16 RxTcpSum1; /* TCP Checksum 1 */
++#else /* SK_USE_REV_DESC */
++ SK_U16 RxTcpSum2; /* Rx TCP Checksum 2 */
++ SK_U16 RxTcpSum1; /* Rx TCP Checksum 1 */
+ SK_U16 RxTcpSp2; /* TCP Checksum Calculation Start Position 2 */
+ SK_U16 RxTcpSp1; /* TCP Checksum Calculation Start Position 1 */
+-#endif /* SK_USE_REV_DESC */
++#endif /* SK_USE_REV_DESC */
+ } SK_HWRXD;
+
+ /*
+ * Drivers which use the reverse descriptor feature (PCI_OUR_REG_2)
+ * should set the define SK_USE_REV_DESC.
+- * Structures are 'normaly' not endianess dependent. But in
+- * this case the SK_U16 fields are bound to bit positions inside the
+- * descriptor. RxTcpSum1 e.g. must start at bit 0 within the 6.th DWord.
++ * Structures are 'normally' not endianess dependent. But in this case
++ * the SK_U16 fields are bound to bit positions inside the descriptor.
++ * RxTcpSum1 e.g. must start at bit 0 within the 7.th DWord.
+ * The bit positions inside a DWord are of course endianess dependent and
+- * swaps if the DWord is swapped by the hardware.
++ * swap if the DWord is swapped by the hardware.
+ */
+
++/* YUKON-2 descriptors ******************************************************/
++
++typedef struct _TxChksum {
++#ifndef SK_USE_REV_DESC
++ SK_U16 TxTcpWp; /* TCP Checksum Write Position */
++ SK_U16 TxTcpSp; /* TCP Checksum Calculation Start Position */
++#else /* SK_USE_REV_DESC */
++ SK_U16 TxTcpSp; /* TCP Checksum Calculation Start Position */
++ SK_U16 TxTcpWp; /* TCP Checksum Write Position */
++#endif /* SK_USE_REV_DESC */
++} SK_HWTXCS;
++
++typedef struct _LargeSend {
++#ifndef SK_USE_REV_DESC
++ SK_U16 Length; /* Large Send Segment Length */
++ SK_U16 Reserved; /* reserved */
++#else /* SK_USE_REV_DESC */
++ SK_U16 Reserved; /* reserved */
++ SK_U16 Length; /* Large Send Segment Length */
++#endif /* SK_USE_REV_DESC */
++} SK_HWTXLS;
++
++typedef union u_HwTxBuf {
++ SK_U16 BufLen; /* Tx Buffer Length */
++ SK_U16 VlanTag; /* VLAN Tag */
++ SK_U16 InitCsum; /* Init. Checksum */
++} SK_HWTXBUF;
++
++/* Tx List Element structure */
++typedef struct s_HwLeTx {
++ union {
++ SK_U32 BufAddr; /* Tx LE Buffer Address high/low */
++ SK_HWTXCS ChkSum; /* Tx LE TCP Checksum parameters */
++ SK_HWTXLS LargeSend;/* Large Send length */
++ } TxUn;
++#ifndef SK_USE_REV_DESC
++ SK_HWTXBUF Send;
++ SK_U8 ControlFlags; /* Tx LE Control field or Lock Number */
++ SK_U8 Opcode; /* Tx LE Opcode field */
++#else /* SK_USE_REV_DESC */
++ SK_U8 Opcode; /* Tx LE Opcode field */
++ SK_U8 ControlFlags; /* Tx LE Control field or Lock Number */
++ SK_HWTXBUF Send;
++#endif /* SK_USE_REV_DESC */
++} SK_HWLETX;
++
++typedef struct _RxChkSum{
++#ifndef SK_USE_REV_DESC
++ SK_U16 RxTcpSp1; /* TCP Checksum Calculation Start Position 1 */
++ SK_U16 RxTcpSp2; /* TCP Checksum Calculation Start Position 2 */
++#else /* SK_USE_REV_DESC */
++ SK_U16 RxTcpSp2; /* TCP Checksum Calculation Start Position 2 */
++ SK_U16 RxTcpSp1; /* TCP Checksum Calculation Start Position 1 */
++#endif /* SK_USE_REV_DESC */
++} SK_HWRXCS;
++
++/* Rx List Element structure */
++typedef struct s_HwLeRx {
++ union {
++ SK_U32 BufAddr; /* Rx LE Buffer Address high/low */
++ SK_HWRXCS ChkSum; /* Rx LE TCP Checksum parameters */
++ } RxUn;
++#ifndef SK_USE_REV_DESC
++ SK_U16 BufferLength; /* Rx LE Buffer Length field */
++ SK_U8 ControlFlags; /* Rx LE Control field */
++ SK_U8 Opcode; /* Rx LE Opcode field */
++#else /* SK_USE_REV_DESC */
++ SK_U8 Opcode; /* Rx LE Opcode field */
++ SK_U8 ControlFlags; /* Rx LE Control field */
++ SK_U16 BufferLength; /* Rx LE Buffer Length field */
++#endif /* SK_USE_REV_DESC */
++} SK_HWLERX;
++
++typedef struct s_StRxTCPChkSum {
++#ifndef SK_USE_REV_DESC
++ SK_U16 RxTCPSum1; /* Rx TCP Checksum 1 */
++ SK_U16 RxTCPSum2; /* Rx TCP Checksum 2 */
++#else /* SK_USE_REV_DESC */
++ SK_U16 RxTCPSum2; /* Rx TCP Checksum 2 */
++ SK_U16 RxTCPSum1; /* Rx TCP Checksum 1 */
++#endif /* SK_USE_REV_DESC */
++} SK_HWSTCS;
++
++typedef struct s_StRxRssFlags {
++#ifndef SK_USE_REV_DESC
++ SK_U8 FlagField; /* contains TCP and IP flags */
++ SK_U8 reserved; /* reserved */
++#else /* SK_USE_REV_DESC */
++ SK_U8 reserved; /* reserved */
++ SK_U8 FlagField; /* contains TCP and IP flags */
++#endif /* SK_USE_REV_DESC */
++} SK_HWSTRSS;
++
++/* bit definition of RSS LE bit 32/33 (SK_HWSTRSS.FlagField) */
++ /* bit 7..2 reserved */
++#define RSS_TCP_FLAG BIT_1S /* RSS value related to TCP area */
++#define RSS_IP_FLAG BIT_0S /* RSS value related to IP area */
++/* StRxRssValue is valid if at least RSS_IP_FLAG is set */
++/* For protocol errors or other protocols an empty RSS LE is generated */
++
++typedef union u_HwStBuf {
++ SK_U16 BufLen; /* Rx Buffer Length */
++ SK_U16 VlanTag; /* VLAN Tag */
++ SK_U16 StTxStatHi; /* Tx Queue Status (high) */
++ SK_HWSTRSS Rss; /* Flag Field for TCP and IP protocol */
++} SK_HWSTBUF;
++
++/* Status List Element structure */
++typedef struct s_HwLeSt {
++ union {
++ SK_U32 StRxStatWord; /* Rx Status Dword */
++ SK_U32 StRxTimeStamp; /* Rx Timestamp */
++ SK_HWSTCS StRxTCPCSum; /* Rx TCP Checksum */
++ SK_U32 StTxStatLow; /* Tx Queue Status (low) */
++ SK_U32 StRxRssValue; /* Rx RSS value */
++ } StUn;
++#ifndef SK_USE_REV_DESC
++ SK_HWSTBUF Stat;
++ SK_U8 Link; /* Status LE Link field */
++ SK_U8 Opcode; /* Status LE Opcode field */
++#else /* SK_USE_REV_DESC */
++ SK_U8 Opcode; /* Status LE Opcode field */
++ SK_U8 Link; /* Status LE Link field */
++ SK_HWSTBUF Stat;
++#endif /* SK_USE_REV_DESC */
++} SK_HWLEST;
++
++/* Special Action List Element */
++typedef struct s_HwLeSa {
++#ifndef SK_USE_REV_DESC
++ SK_U16 TxAIdxVld; /* Special Action LE TxA Put Index field */
++ SK_U16 TxSIdxVld; /* Special Action LE TxS Put Index field */
++ SK_U16 RxIdxVld; /* Special Action LE Rx Put Index field */
++ SK_U8 Link; /* Special Action LE Link field */
++ SK_U8 Opcode; /* Special Action LE Opcode field */
++#else /* SK_USE_REV_DESC */
++ SK_U16 TxSIdxVld; /* Special Action LE TxS Put Index field */
++ SK_U16 TxAIdxVld; /* Special Action LE TxA Put Index field */
++ SK_U8 Opcode; /* Special Action LE Opcode field */
++ SK_U8 Link; /* Special Action LE Link field */
++ SK_U16 RxIdxVld; /* Special Action LE Rx Put Index field */
++#endif /* SK_USE_REV_DESC */
++} SK_HWLESA;
++
++/* Common List Element union */
++typedef union u_HwLeTxRxSt {
++ /* Transmit List Element Structure */
++ SK_HWLETX Tx;
++ /* Receive List Element Structure */
++ SK_HWLERX Rx;
++ /* Status List Element Structure */
++ SK_HWLEST St;
++ /* Special Action List Element Structure */
++ SK_HWLESA Sa;
++ /* Full List Element */
++ SK_U64 Full;
++} SK_HWLE;
++
++/* mask and shift value to get Tx async queue status for port 1 */
++#define STLE_TXA1_MSKL 0x00000fff
++#define STLE_TXA1_SHIFTL 0
++
++/* mask and shift value to get Tx sync queue status for port 1 */
++#define STLE_TXS1_MSKL 0x00fff000
++#define STLE_TXS1_SHIFTL 12
++
++/* mask and shift value to get Tx async queue status for port 2 */
++#define STLE_TXA2_MSKL 0xff000000
++#define STLE_TXA2_SHIFTL 24
++#define STLE_TXA2_MSKH 0x000f
++/* this one shifts up */
++#define STLE_TXA2_SHIFTH 8
++
++/* mask and shift value to get Tx sync queue status for port 2 */
++#define STLE_TXS2_MSKL 0x00000000
++#define STLE_TXS2_SHIFTL 0
++#define STLE_TXS2_MSKH 0xfff0
++#define STLE_TXS2_SHIFTH 4
++
++/* YUKON-2 bit values */
++#define HW_OWNER BIT_7
++#define SW_OWNER 0
++
++#define PU_PUTIDX_VALID BIT_12
++
++/* YUKON-2 Control flags */
++#define UDPTCP BIT_0S
++#define CALSUM BIT_1S
++#define WR_SUM BIT_2S
++#define INIT_SUM BIT_3S
++#define LOCK_SUM BIT_4S
++#define INS_VLAN BIT_5S
++#define FRC_STAT BIT_6S
++#define EOP BIT_7S
++
++#define TX_LOCK BIT_8S
++#define BUF_SEND BIT_9S
++#define PACKET_SEND BIT_10S
++
++#define NO_WARNING BIT_14S
++#define NO_UPDATE BIT_15S
++
++/* YUKON-2 Rx/Tx opcodes defines */
++#define OP_TCPWRITE 0x11
++#define OP_TCPSTART 0x12
++#define OP_TCPINIT 0x14
++#define OP_TCPLCK 0x18
++#define OP_TCPCHKSUM OP_TCPSTART
++#define OP_TCPIS (OP_TCPINIT | OP_TCPSTART)
++#define OP_TCPLW (OP_TCPLCK | OP_TCPWRITE)
++#define OP_TCPLSW (OP_TCPLCK | OP_TCPSTART | OP_TCPWRITE)
++#define OP_TCPLISW (OP_TCPLCK | OP_TCPINIT | OP_TCPSTART | OP_TCPWRITE)
++#define OP_ADDR64 0x21
++#define OP_VLAN 0x22
++#define OP_ADDR64VLAN (OP_ADDR64 | OP_VLAN)
++#define OP_LRGLEN 0x24
++#define OP_LRGLENVLAN (OP_LRGLEN | OP_VLAN)
++#define OP_BUFFER 0x40
++#define OP_PACKET 0x41
++#define OP_LARGESEND 0x43
++
++/* YUKON-2 STATUS opcodes defines */
++#define OP_RXSTAT 0x60
++#define OP_RXTIMESTAMP 0x61
++#define OP_RXVLAN 0x62
++#define OP_RXCHKS 0x64
++#define OP_RXCHKSVLAN (OP_RXCHKS | OP_RXVLAN)
++#define OP_RXTIMEVLAN (OP_RXTIMESTAMP | OP_RXVLAN)
++#define OP_RSS_HASH 0x65
++#define OP_TXINDEXLE 0x68
++
++/* YUKON-2 SPECIAL opcodes defines */
++#define OP_PUTIDX 0x70
+
+ /* Descriptor Bit Definition */
+ /* TxCtrl Transmit Buffer Control Field */
+@@ -1685,6 +2436,10 @@
+
+ /* macros ********************************************************************/
+
++/* Macro for accessing the key registers */
++#define RSS_KEY_ADDR(Port, KeyIndex) \
++ ((B4_RSS_KEY | ( ((Port) == 0) ? 0 : 0x80)) + (KeyIndex))
++
+ /* Receive and Transmit Queues */
+ #define Q_R1 0x0000 /* Receive Queue 1 */
+ #define Q_R2 0x0080 /* Receive Queue 2 */
+@@ -1693,6 +2448,10 @@
+ #define Q_XS2 0x0300 /* Synchronous Transmit Queue 2 */
+ #define Q_XA2 0x0380 /* Asynchronous Transmit Queue 2 */
+
++#define Q_ASF_R1 0x100 /* ASF Rx Queue 1 */
++#define Q_ASF_R2 0x180 /* ASF Rx Queue 2 */
++#define Q_ASF_T1 0x140 /* ASF Tx Queue 1 */
++#define Q_ASF_T2 0x1c0 /* ASF Tx Queue 2 */
+ /*
+ * Macro Q_ADDR()
+ *
+@@ -1704,11 +2463,27 @@
+ * Offs Queue register offset.
+ * Values: Q_D, Q_DA_L ... Q_T2, Q_T3
+ *
+- * usage SK_IN32(pAC, Q_ADDR(Q_R2, Q_BC), pVal)
++ * usage SK_IN32(IoC, Q_ADDR(Q_R2, Q_BC), pVal)
+ */
+ #define Q_ADDR(Queue, Offs) (B8_Q_REGS + (Queue) + (Offs))
+
+ /*
++ * Macro Y2_PREF_Q_ADDR()
++ *
++ * Use this macro to access the Prefetch Units of the receive and
++ * transmit queues of Yukon-2.
++ *
++ * para:
++ * Queue Queue to access.
++ * Values: Q_R1, Q_R2, Q_XS1, Q_XA1, Q_XS2, Q_XA2,
++ * Offs Queue register offset.
++ * Values: PREF_UNIT_CTRL_REG ... PREF_UNIT_FIFO_LEV_REG
++ *
++ * usage SK_IN16(IoC, Y2_Q_ADDR(Q_R2, PREF_UNIT_GET_IDX_REG), pVal)
++ */
++#define Y2_PREF_Q_ADDR(Queue, Offs) (Y2_B8_PREF_REGS + (Queue) + (Offs))
++
++/*
+ * Macro RB_ADDR()
+ *
+ * Use this macro to access the RAM Buffer Registers.
+@@ -1719,14 +2494,14 @@
+ * Offs Queue register offset.
+ * Values: RB_START, RB_END ... RB_LEV, RB_CTRL
+ *
+- * usage SK_IN32(pAC, RB_ADDR(Q_R2, RB_RP), pVal)
++ * usage SK_IN32(IoC, RB_ADDR(Q_R2, RB_RP), pVal)
+ */
+ #define RB_ADDR(Queue, Offs) (B16_RAM_REGS + (Queue) + (Offs))
+
+
+ /* MAC Related Registers */
+-#define MAC_1 0 /* belongs to the port near the slot */
+-#define MAC_2 1 /* belongs to the port far away from the slot */
++#define MAC_1 0 /* 1st port */
++#define MAC_2 1 /* 2nd port */
+
+ /*
+ * Macro MR_ADDR()
+@@ -1740,19 +2515,10 @@
+ * Values: RX_MFF_EA, RX_MFF_WP ... LNK_LED_REG,
+ * TX_MFF_EA, TX_MFF_WP ... TX_LED_TST
+ *
+- * usage SK_IN32(pAC, MR_ADDR(MAC_1, TX_MFF_EA), pVal)
++ * usage SK_IN32(IoC, MR_ADDR(MAC_1, TX_MFF_EA), pVal)
+ */
+ #define MR_ADDR(Mac, Offs) (((Mac) << 7) + (Offs))
+
+-#ifdef SK_LITTLE_ENDIAN
+-#define XM_WORD_LO 0
+-#define XM_WORD_HI 1
+-#else /* !SK_LITTLE_ENDIAN */
+-#define XM_WORD_LO 1
+-#define XM_WORD_HI 0
+-#endif /* !SK_LITTLE_ENDIAN */
+-
+-
+ /*
+ * macros to access the XMAC (GENESIS only)
+ *
+@@ -1777,22 +2543,31 @@
+ #define XMA(Mac, Reg) \
+ ((BASE_XMAC_1 + (Mac) * (BASE_XMAC_2 - BASE_XMAC_1)) | ((Reg) << 1))
+
+-#define XM_IN16(IoC, Mac, Reg, pVal) \
+- SK_IN16((IoC), XMA((Mac), (Reg)), (pVal))
++#define XM_IN16(IoC, Mac, Reg, pVal) \
++ SK_IN16(IoC, XMA(Mac, Reg), pVal)
+
+-#define XM_OUT16(IoC, Mac, Reg, Val) \
+- SK_OUT16((IoC), XMA((Mac), (Reg)), (Val))
++#define XM_OUT16(IoC, Mac, Reg, Val) \
++ SK_OUT16(IoC, XMA(Mac, Reg), Val)
+
+-#define XM_IN32(IoC, Mac, Reg, pVal) { \
+- SK_IN16((IoC), XMA((Mac), (Reg)), \
+- (SK_U16 SK_FAR*)&((SK_U16 SK_FAR*)(pVal))[XM_WORD_LO]); \
+- SK_IN16((IoC), XMA((Mac), (Reg+2)), \
+- (SK_U16 SK_FAR*)&((SK_U16 SK_FAR*)(pVal))[XM_WORD_HI]); \
++#ifdef SK_LITTLE_ENDIAN
++
++#define XM_IN32(IoC, Mac, Reg, pVal) { \
++ SK_IN16(IoC, XMA(Mac, Reg), (SK_U16 SK_FAR *)(pVal)); \
++ SK_IN16(IoC, XMA(Mac, (Reg) + 2), (SK_U16 SK_FAR *)(pVal) + 1); \
+ }
+
++#else /* !SK_LITTLE_ENDIAN */
++
++#define XM_IN32(IoC, Mac, Reg, pVal) { \
++ SK_IN16(IoC, XMA(Mac, Reg), (SK_U16 SK_FAR *)(pVal) + 1); \
++ SK_IN16(IoC, XMA(Mac, (Reg) + 2), (SK_U16 SK_FAR *)(pVal)); \
++}
++
++#endif /* !SK_LITTLE_ENDIAN */
++
+ #define XM_OUT32(IoC, Mac, Reg, Val) { \
+- SK_OUT16((IoC), XMA((Mac), (Reg)), (SK_U16)((Val) & 0xffffL)); \
+- SK_OUT16((IoC), XMA((Mac), (Reg+2)), (SK_U16)(((Val) >> 16) & 0xffffL));\
++ SK_OUT16(IoC, XMA(Mac, Reg), (SK_U16)((Val) & 0xffffL)); \
++ SK_OUT16(IoC, XMA(Mac, (Reg) + 2), (SK_U16)(((Val) >> 16) & 0xffffL)); \
+ }
+
+ /* Remember: we are always writing to / reading from LITTLE ENDIAN memory */
+@@ -1802,13 +2577,13 @@
+ SK_U8 *pByte; \
+ pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0]; \
+ SK_IN16((IoC), XMA((Mac), (Reg)), &Word); \
+- pByte[0] = (SK_U8)(Word & 0x00ff); \
++ pByte[0] = (SK_U8)(Word & 0x00ff); \
+ pByte[1] = (SK_U8)((Word >> 8) & 0x00ff); \
+- SK_IN16((IoC), XMA((Mac), (Reg+2)), &Word); \
+- pByte[2] = (SK_U8)(Word & 0x00ff); \
++ SK_IN16((IoC), XMA((Mac), (Reg) + 2), &Word); \
++ pByte[2] = (SK_U8)(Word & 0x00ff); \
+ pByte[3] = (SK_U8)((Word >> 8) & 0x00ff); \
+- SK_IN16((IoC), XMA((Mac), (Reg+4)), &Word); \
+- pByte[4] = (SK_U8)(Word & 0x00ff); \
++ SK_IN16((IoC), XMA((Mac), (Reg) + 4), &Word); \
++ pByte[4] = (SK_U8)(Word & 0x00ff); \
+ pByte[5] = (SK_U8)((Word >> 8) & 0x00ff); \
+ }
+
+@@ -1818,10 +2593,10 @@
+ SK_OUT16((IoC), XMA((Mac), (Reg)), (SK_U16) \
+ (((SK_U16)(pByte[0]) & 0x00ff) | \
+ (((SK_U16)(pByte[1]) << 8) & 0xff00))); \
+- SK_OUT16((IoC), XMA((Mac), (Reg+2)), (SK_U16) \
++ SK_OUT16((IoC), XMA((Mac), (Reg) + 2), (SK_U16) \
+ (((SK_U16)(pByte[2]) & 0x00ff) | \
+ (((SK_U16)(pByte[3]) << 8) & 0xff00))); \
+- SK_OUT16((IoC), XMA((Mac), (Reg+4)), (SK_U16) \
++ SK_OUT16((IoC), XMA((Mac), (Reg) + 4), (SK_U16) \
+ (((SK_U16)(pByte[4]) & 0x00ff) | \
+ (((SK_U16)(pByte[5]) << 8) & 0xff00))); \
+ }
+@@ -1831,16 +2606,16 @@
+ SK_U8 SK_FAR *pByte; \
+ pByte = (SK_U8 SK_FAR *)&((SK_U8 SK_FAR *)(pVal))[0]; \
+ SK_IN16((IoC), XMA((Mac), (Reg)), &Word); \
+- pByte[0] = (SK_U8)(Word & 0x00ff); \
++ pByte[0] = (SK_U8)(Word & 0x00ff); \
+ pByte[1] = (SK_U8)((Word >> 8) & 0x00ff); \
+- SK_IN16((IoC), XMA((Mac), (Reg+2)), &Word); \
+- pByte[2] = (SK_U8)(Word & 0x00ff); \
++ SK_IN16((IoC), XMA((Mac), (Reg) + 2), &Word); \
++ pByte[2] = (SK_U8)(Word & 0x00ff); \
+ pByte[3] = (SK_U8)((Word >> 8) & 0x00ff); \
+- SK_IN16((IoC), XMA((Mac), (Reg+4)), &Word); \
+- pByte[4] = (SK_U8)(Word & 0x00ff); \
++ SK_IN16((IoC), XMA((Mac), (Reg) + 4), &Word); \
++ pByte[4] = (SK_U8)(Word & 0x00ff); \
+ pByte[5] = (SK_U8)((Word >> 8) & 0x00ff); \
+- SK_IN16((IoC), XMA((Mac), (Reg+6)), &Word); \
+- pByte[6] = (SK_U8)(Word & 0x00ff); \
++ SK_IN16((IoC), XMA((Mac), (Reg) + 6), &Word); \
++ pByte[6] = (SK_U8)(Word & 0x00ff); \
+ pByte[7] = (SK_U8)((Word >> 8) & 0x00ff); \
+ }
+
+@@ -1850,13 +2625,13 @@
+ SK_OUT16((IoC), XMA((Mac), (Reg)), (SK_U16) \
+ (((SK_U16)(pByte[0]) & 0x00ff)| \
+ (((SK_U16)(pByte[1]) << 8) & 0xff00))); \
+- SK_OUT16((IoC), XMA((Mac), (Reg+2)), (SK_U16) \
++ SK_OUT16((IoC), XMA((Mac), (Reg) + 2), (SK_U16) \
+ (((SK_U16)(pByte[2]) & 0x00ff)| \
+ (((SK_U16)(pByte[3]) << 8) & 0xff00))); \
+- SK_OUT16((IoC), XMA((Mac), (Reg+4)), (SK_U16) \
++ SK_OUT16((IoC), XMA((Mac), (Reg) + 4), (SK_U16) \
+ (((SK_U16)(pByte[4]) & 0x00ff)| \
+ (((SK_U16)(pByte[5]) << 8) & 0xff00))); \
+- SK_OUT16((IoC), XMA((Mac), (Reg+6)), (SK_U16) \
++ SK_OUT16((IoC), XMA((Mac), (Reg) + 6), (SK_U16) \
+ (((SK_U16)(pByte[6]) & 0x00ff)| \
+ (((SK_U16)(pByte[7]) << 8) & 0xff00))); \
+ }
+@@ -1866,7 +2641,7 @@
+ *
+ * GM_IN16(), to read a 16 bit register (e.g. GM_GP_STAT)
+ * GM_OUT16(), to write a 16 bit register (e.g. GM_GP_CTRL)
+- * GM_IN32(), to read a 32 bit register (e.g. GM_)
++ * GM_IN32(), to read a 32 bit register (e.g. GM_RXF_UC_OK)
+ * GM_OUT32(), to write a 32 bit register (e.g. GM_)
+ * GM_INADDR(), to read a network address register (e.g. GM_SRC_ADDR_1L)
+ * GM_OUTADDR(), to write a network address register (e.g. GM_SRC_ADDR_2L)
+@@ -1885,22 +2660,31 @@
+ #define GMA(Mac, Reg) \
+ ((BASE_GMAC_1 + (Mac) * (BASE_GMAC_2 - BASE_GMAC_1)) | (Reg))
+
+-#define GM_IN16(IoC, Mac, Reg, pVal) \
+- SK_IN16((IoC), GMA((Mac), (Reg)), (pVal))
++#define GM_IN16(IoC, Mac, Reg, pVal) \
++ SK_IN16(IoC, GMA(Mac, Reg), pVal)
+
+-#define GM_OUT16(IoC, Mac, Reg, Val) \
+- SK_OUT16((IoC), GMA((Mac), (Reg)), (Val))
++#define GM_OUT16(IoC, Mac, Reg, Val) \
++ SK_OUT16(IoC, GMA(Mac, Reg), Val)
+
+-#define GM_IN32(IoC, Mac, Reg, pVal) { \
+- SK_IN16((IoC), GMA((Mac), (Reg)), \
+- (SK_U16 SK_FAR*)&((SK_U16 SK_FAR*)(pVal))[XM_WORD_LO]); \
+- SK_IN16((IoC), GMA((Mac), (Reg+4)), \
+- (SK_U16 SK_FAR*)&((SK_U16 SK_FAR*)(pVal))[XM_WORD_HI]); \
++#ifdef SK_LITTLE_ENDIAN
++
++#define GM_IN32(IoC, Mac, Reg, pVal) { \
++ SK_IN16(IoC, GMA(Mac, Reg), (SK_U16 SK_FAR *)(pVal)); \
++ SK_IN16((IoC), GMA(Mac, (Reg) + 4), (SK_U16 SK_FAR *)(pVal) + 1); \
+ }
+
++#else /* !SK_LITTLE_ENDIAN */
++
++#define GM_IN32(IoC, Mac, Reg, pVal) { \
++ SK_IN16(IoC, GMA(Mac, Reg), (SK_U16 SK_FAR *)(pVal) + 1); \
++ SK_IN16(IoC, GMA(Mac, (Reg) + 4), (SK_U16 SK_FAR *)(pVal)); \
++}
++
++#endif /* !SK_LITTLE_ENDIAN */
++
+ #define GM_OUT32(IoC, Mac, Reg, Val) { \
+- SK_OUT16((IoC), GMA((Mac), (Reg)), (SK_U16)((Val) & 0xffffL)); \
+- SK_OUT16((IoC), GMA((Mac), (Reg+4)), (SK_U16)(((Val) >> 16) & 0xffffL));\
++ SK_OUT16(IoC, GMA(Mac, Reg), (SK_U16)((Val) & 0xffffL)); \
++ SK_OUT16(IoC, GMA(Mac, (Reg) + 4), (SK_U16)(((Val) >> 16) & 0xffffL)); \
+ }
+
+ #define GM_INADDR(IoC, Mac, Reg, pVal) { \
+@@ -1908,13 +2692,13 @@
+ SK_U8 *pByte; \
+ pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0]; \
+ SK_IN16((IoC), GMA((Mac), (Reg)), &Word); \
+- pByte[0] = (SK_U8)(Word & 0x00ff); \
++ pByte[0] = (SK_U8)(Word & 0x00ff); \
+ pByte[1] = (SK_U8)((Word >> 8) & 0x00ff); \
+- SK_IN16((IoC), GMA((Mac), (Reg+4)), &Word); \
+- pByte[2] = (SK_U8)(Word & 0x00ff); \
++ SK_IN16((IoC), GMA((Mac), (Reg) + 4), &Word); \
++ pByte[2] = (SK_U8)(Word & 0x00ff); \
+ pByte[3] = (SK_U8)((Word >> 8) & 0x00ff); \
+- SK_IN16((IoC), GMA((Mac), (Reg+8)), &Word); \
+- pByte[4] = (SK_U8)(Word & 0x00ff); \
++ SK_IN16((IoC), GMA((Mac), (Reg) + 8), &Word); \
++ pByte[4] = (SK_U8)(Word & 0x00ff); \
+ pByte[5] = (SK_U8)((Word >> 8) & 0x00ff); \
+ }
+
+@@ -1924,10 +2708,10 @@
+ SK_OUT16((IoC), GMA((Mac), (Reg)), (SK_U16) \
+ (((SK_U16)(pByte[0]) & 0x00ff) | \
+ (((SK_U16)(pByte[1]) << 8) & 0xff00))); \
+- SK_OUT16((IoC), GMA((Mac), (Reg+4)), (SK_U16) \
++ SK_OUT16((IoC), GMA((Mac), (Reg) + 4), (SK_U16) \
+ (((SK_U16)(pByte[2]) & 0x00ff) | \
+ (((SK_U16)(pByte[3]) << 8) & 0xff00))); \
+- SK_OUT16((IoC), GMA((Mac), (Reg+8)), (SK_U16) \
++ SK_OUT16((IoC), GMA((Mac), (Reg) + 8), (SK_U16) \
+ (((SK_U16)(pByte[4]) & 0x00ff) | \
+ (((SK_U16)(pByte[5]) << 8) & 0xff00))); \
+ }
+@@ -1937,16 +2721,16 @@
+ SK_U8 *pByte; \
+ pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0]; \
+ SK_IN16((IoC), GMA((Mac), (Reg)), &Word); \
+- pByte[0] = (SK_U8)(Word & 0x00ff); \
++ pByte[0] = (SK_U8)(Word & 0x00ff); \
+ pByte[1] = (SK_U8)((Word >> 8) & 0x00ff); \
+- SK_IN16((IoC), GMA((Mac), (Reg+4)), &Word); \
+- pByte[2] = (SK_U8)(Word & 0x00ff); \
++ SK_IN16((IoC), GMA((Mac), (Reg) + 4), &Word); \
++ pByte[2] = (SK_U8)(Word & 0x00ff); \
+ pByte[3] = (SK_U8)((Word >> 8) & 0x00ff); \
+- SK_IN16((IoC), GMA((Mac), (Reg+8)), &Word); \
+- pByte[4] = (SK_U8)(Word & 0x00ff); \
++ SK_IN16((IoC), GMA((Mac), (Reg) + 8), &Word); \
++ pByte[4] = (SK_U8)(Word & 0x00ff); \
+ pByte[5] = (SK_U8)((Word >> 8) & 0x00ff); \
+- SK_IN16((IoC), GMA((Mac), (Reg+12)), &Word); \
+- pByte[6] = (SK_U8)(Word & 0x00ff); \
++ SK_IN16((IoC), GMA((Mac), (Reg) + 12), &Word); \
++ pByte[6] = (SK_U8)(Word & 0x00ff); \
+ pByte[7] = (SK_U8)((Word >> 8) & 0x00ff); \
+ }
+
+@@ -1956,13 +2740,13 @@
+ SK_OUT16((IoC), GMA((Mac), (Reg)), (SK_U16) \
+ (((SK_U16)(pByte[0]) & 0x00ff)| \
+ (((SK_U16)(pByte[1]) << 8) & 0xff00))); \
+- SK_OUT16((IoC), GMA((Mac), (Reg+4)), (SK_U16) \
++ SK_OUT16((IoC), GMA((Mac), (Reg) + 4), (SK_U16) \
+ (((SK_U16)(pByte[2]) & 0x00ff)| \
+ (((SK_U16)(pByte[3]) << 8) & 0xff00))); \
+- SK_OUT16((IoC), GMA((Mac), (Reg+8)), (SK_U16) \
++ SK_OUT16((IoC), GMA((Mac), (Reg) + 8), (SK_U16) \
+ (((SK_U16)(pByte[4]) & 0x00ff)| \
+ (((SK_U16)(pByte[5]) << 8) & 0xff00))); \
+- SK_OUT16((IoC), GMA((Mac), (Reg+12)), (SK_U16) \
++ SK_OUT16((IoC), GMA((Mac), (Reg) + 12), (SK_U16) \
+ (((SK_U16)(pByte[6]) & 0x00ff)| \
+ (((SK_U16)(pByte[7]) << 8) & 0xff00))); \
+ }
+@@ -2010,30 +2794,30 @@
+ *
+ * usage: PHY_READ(IoC, pPort, MAC_1, PHY_CTRL, Value);
+ * Warning: a PHY_READ on an uninitialized PHY (PHY still in reset) never
+- * comes back. This is checked in DEBUG mode.
++ * comes back. This is checked in DEBUG mode.
+ */
+ #ifndef DEBUG
+ #define PHY_READ(IoC, pPort, Mac, PhyReg, pVal) { \
+- SK_U16 Mmu; \
++ SK_U16 Mmu; \
+ \
+ XM_OUT16((IoC), (Mac), XM_PHY_ADDR, (PhyReg) | (pPort)->PhyAddr); \
+ XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal)); \
+ if ((pPort)->PhyType != SK_PHY_XMAC) { \
+- do { \
++ do { \
+ XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu); \
+ } while ((Mmu & XM_MMU_PHY_RDY) == 0); \
+ XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal)); \
+- } \
++ } \
+ }
+ #else
+ #define PHY_READ(IoC, pPort, Mac, PhyReg, pVal) { \
+- SK_U16 Mmu; \
++ SK_U16 Mmu; \
+ int __i = 0; \
+ \
+ XM_OUT16((IoC), (Mac), XM_PHY_ADDR, (PhyReg) | (pPort)->PhyAddr); \
+ XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal)); \
+ if ((pPort)->PhyType != SK_PHY_XMAC) { \
+- do { \
++ do { \
+ XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu); \
+ __i++; \
+ if (__i > 100000) { \
+@@ -2044,7 +2828,7 @@
+ } \
+ } while ((Mmu & XM_MMU_PHY_RDY) == 0); \
+ XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal)); \
+- } \
++ } \
+ }
+ #endif /* DEBUG */
+
+@@ -2052,17 +2836,17 @@
+ SK_U16 Mmu; \
+ \
+ if ((pPort)->PhyType != SK_PHY_XMAC) { \
+- do { \
++ do { \
+ XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu); \
+ } while ((Mmu & XM_MMU_PHY_BUSY) != 0); \
+- } \
++ } \
+ XM_OUT16((IoC), (Mac), XM_PHY_ADDR, (PhyReg) | (pPort)->PhyAddr); \
+ XM_OUT16((IoC), (Mac), XM_PHY_DATA, (Val)); \
+ if ((pPort)->PhyType != SK_PHY_XMAC) { \
+- do { \
++ do { \
+ XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu); \
+ } while ((Mmu & XM_MMU_PHY_BUSY) != 0); \
+- } \
++ } \
+ }
+
+ /*
+@@ -2071,12 +2855,14 @@
+ * Use this macro to access PCI config register from the I/O space.
+ *
+ * para:
++ * pAC Pointer to adapter context
+ * Addr PCI configuration register to access.
+ * Values: PCI_VENDOR_ID ... PCI_VPD_ADR_REG,
+ *
+- * usage SK_IN16(pAC, PCI_C(PCI_VENDOR_ID), pVal);
++ * usage SK_IN16(IoC, PCI_C(pAC, PCI_VENDOR_ID), pVal);
+ */
+-#define PCI_C(Addr) (B7_CFG_SPC + (Addr)) /* PCI Config Space */
++#define PCI_C(p, Addr) \
++ (((CHIP_ID_YUKON_2(p)) ? Y2_CFG_SPC : B7_CFG_SPC) + (Addr))
+
+ /*
+ * Macro SK_HW_ADDR(Base, Addr)
+@@ -2088,7 +2874,7 @@
+ * Addr Address offset
+ *
+ * usage: May be used in SK_INxx and SK_OUTxx macros
+- * #define SK_IN8(pAC, Addr, pVal) ...\
++ * #define SK_IN8(IoC, Addr, pVal) ...\
+ * *pVal = (SK_U8)inp(SK_HW_ADDR(pAC->Hw.Iop, Addr)))
+ */
+ #ifdef SK_MEM_MAPPED_IO
+@@ -2107,20 +2893,31 @@
+ * para:
+ * pAC Pointer to adapter context struct
+ * IoC I/O context needed for SK I/O macros
+- * Port Port number
++ * Port Port number
+ * Mode Mode to set for this LED
+ */
+ #define SK_HWAC_LINK_LED(pAC, IoC, Port, Mode) \
+ SK_OUT8(IoC, MR_ADDR(Port, LNK_LED_REG), Mode);
+
++#define SK_SET_GP_IO(IoC, Bit) { \
++ SK_U32 DWord; \
++ SK_IN32(IoC, B2_GP_IO, &DWord); \
++ DWord |= ((GP_DIR_0 | GP_IO_0) << (Bit));\
++ SK_OUT32(IoC, B2_GP_IO, DWord); \
++}
+
+-/* typedefs *******************************************************************/
+-
++#define SK_CLR_GP_IO(IoC, Bit) { \
++ SK_U32 DWord; \
++ SK_IN32(IoC, B2_GP_IO, &DWord); \
++ DWord &= ~((GP_DIR_0 | GP_IO_0) << (Bit));\
++ SK_OUT32(IoC, B2_GP_IO, DWord); \
++}
+
+-/* function prototypes ********************************************************/
++#define SK_GE_PCI_FIFO_SIZE 1600 /* PCI FIFO Size */
+
+ #ifdef __cplusplus
+ }
+ #endif /* __cplusplus */
+
+ #endif /* __INC_SKGEHW_H */
++
+diff -ruN linux/drivers/net/sk98lin/h/skgehwt.h linux-new/drivers/net/sk98lin/h/skgehwt.h
+--- linux/drivers/net/sk98lin/h/skgehwt.h 2005-09-26 13:32:47.000000000 +0400
++++ linux-new/drivers/net/sk98lin/h/skgehwt.h 2005-08-09 17:15:51.000000000 +0400
+@@ -2,8 +2,8 @@
+ *
+ * Name: skhwt.h
+ * Project: Gigabit Ethernet Adapters, Event Scheduler Module
+- * Version: $Revision: 1.7 $
+- * Date: $Date: 2003/09/16 12:55:08 $
++ * Version: $Revision: 2.1 $
++ * Date: $Date: 2003/10/27 14:16:09 $
+ * Purpose: Defines for the hardware timer functions
+ *
+ ******************************************************************************/
+diff -ruN linux/drivers/net/sk98lin/h/skgei2c.h linux-new/drivers/net/sk98lin/h/skgei2c.h
+--- linux/drivers/net/sk98lin/h/skgei2c.h 2005-09-26 13:32:48.000000000 +0400
++++ linux-new/drivers/net/sk98lin/h/skgei2c.h 1970-01-01 03:00:00.000000000 +0300
+@@ -1,210 +0,0 @@
+-/******************************************************************************
+- *
+- * Name: skgei2c.h
+- * Project: Gigabit Ethernet Adapters, TWSI-Module
+- * Version: $Revision: 1.25 $
+- * Date: $Date: 2003/10/20 09:06:05 $
+- * Purpose: Special defines for TWSI
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * (C)Copyright 1998-2002 SysKonnect.
+- * (C)Copyright 2002-2003 Marvell.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-/*
+- * SKGEI2C.H contains all SK-98xx specific defines for the TWSI handling
+- */
+-
+-#ifndef _INC_SKGEI2C_H_
+-#define _INC_SKGEI2C_H_
+-
+-/*
+- * Macros to access the B2_I2C_CTRL
+- */
+-#define SK_I2C_CTL(IoC, flag, dev, dev_size, reg, burst) \
+- SK_OUT32(IoC, B2_I2C_CTRL,\
+- (flag ? 0x80000000UL : 0x0L) | \
+- (((SK_U32)reg << 16) & I2C_ADDR) | \
+- (((SK_U32)dev << 9) & I2C_DEV_SEL) | \
+- (dev_size & I2C_DEV_SIZE) | \
+- ((burst << 4) & I2C_BURST_LEN))
+-
+-#define SK_I2C_STOP(IoC) { \
+- SK_U32 I2cCtrl; \
+- SK_IN32(IoC, B2_I2C_CTRL, &I2cCtrl); \
+- SK_OUT32(IoC, B2_I2C_CTRL, I2cCtrl | I2C_STOP); \
+-}
+-
+-#define SK_I2C_GET_CTL(IoC, pI2cCtrl) SK_IN32(IoC, B2_I2C_CTRL, pI2cCtrl)
+-
+-/*
+- * Macros to access the TWSI SW Registers
+- */
+-#define SK_I2C_SET_BIT(IoC, SetBits) { \
+- SK_U8 OrgBits; \
+- SK_IN8(IoC, B2_I2C_SW, &OrgBits); \
+- SK_OUT8(IoC, B2_I2C_SW, OrgBits | (SK_U8)(SetBits)); \
+-}
+-
+-#define SK_I2C_CLR_BIT(IoC, ClrBits) { \
+- SK_U8 OrgBits; \
+- SK_IN8(IoC, B2_I2C_SW, &OrgBits); \
+- SK_OUT8(IoC, B2_I2C_SW, OrgBits & ~((SK_U8)(ClrBits))); \
+-}
+-
+-#define SK_I2C_GET_SW(IoC, pI2cSw) SK_IN8(IoC, B2_I2C_SW, pI2cSw)
+-
+-/*
+- * define the possible sensor states
+- */
+-#define SK_SEN_IDLE 0 /* Idle: sensor not read */
+-#define SK_SEN_VALUE 1 /* Value Read cycle */
+-#define SK_SEN_VALEXT 2 /* Extended Value Read cycle */
+-
+-/*
+- * Conversion factor to convert read Voltage sensor to milli Volt
+- * Conversion factor to convert read Temperature sensor to 10th degree Celsius
+- */
+-#define SK_LM80_VT_LSB 22 /* 22mV LSB resolution */
+-#define SK_LM80_TEMP_LSB 10 /* 1 degree LSB resolution */
+-#define SK_LM80_TEMPEXT_LSB 5 /* 0.5 degree LSB resolution for ext. val. */
+-
+-/*
+- * formula: counter = (22500*60)/(rpm * divisor * pulses/2)
+- * assuming: 6500rpm, 4 pulses, divisor 1
+- */
+-#define SK_LM80_FAN_FAKTOR ((22500L*60)/(1*2))
+-
+-/*
+- * Define sensor management data
+- * Maximum is reached on Genesis copper dual port and Yukon-64
+- * Board specific maximum is in pAC->I2c.MaxSens
+- */
+-#define SK_MAX_SENSORS 8 /* maximal no. of installed sensors */
+-#define SK_MIN_SENSORS 5 /* minimal no. of installed sensors */
+-
+-/*
+- * To watch the state machine (SM) use the timer in two ways
+- * instead of one as hitherto
+- */
+-#define SK_TIMER_WATCH_SM 0 /* Watch the SM to finish in a spec. time */
+-#define SK_TIMER_NEW_GAUGING 1 /* Start a new gauging when timer expires */
+-
+-/*
+- * Defines for the individual thresholds
+- */
+-
+-/* Temperature sensor */
+-#define SK_SEN_TEMP_HIGH_ERR 800 /* Temperature High Err Threshold */
+-#define SK_SEN_TEMP_HIGH_WARN 700 /* Temperature High Warn Threshold */
+-#define SK_SEN_TEMP_LOW_WARN 100 /* Temperature Low Warn Threshold */
+-#define SK_SEN_TEMP_LOW_ERR 0 /* Temperature Low Err Threshold */
+-
+-/* VCC which should be 5 V */
+-#define SK_SEN_PCI_5V_HIGH_ERR 5588 /* Voltage PCI High Err Threshold */
+-#define SK_SEN_PCI_5V_HIGH_WARN 5346 /* Voltage PCI High Warn Threshold */
+-#define SK_SEN_PCI_5V_LOW_WARN 4664 /* Voltage PCI Low Warn Threshold */
+-#define SK_SEN_PCI_5V_LOW_ERR 4422 /* Voltage PCI Low Err Threshold */
+-
+-/*
+- * VIO may be 5 V or 3.3 V. Initialization takes two parts:
+- * 1. Initialize lowest lower limit and highest higher limit.
+- * 2. After the first value is read correct the upper or the lower limit to
+- * the appropriate C constant.
+- *
+- * Warning limits are +-5% of the exepected voltage.
+- * Error limits are +-10% of the expected voltage.
+- */
+-
+-/* Bug fix AF: 16.Aug.2001: Correct the init base of LM80 sensor */
+-
+-#define SK_SEN_PCI_IO_5V_HIGH_ERR 5566 /* + 10% V PCI-IO High Err Threshold */
+-#define SK_SEN_PCI_IO_5V_HIGH_WARN 5324 /* + 5% V PCI-IO High Warn Threshold */
+- /* 5000 mVolt */
+-#define SK_SEN_PCI_IO_5V_LOW_WARN 4686 /* - 5% V PCI-IO Low Warn Threshold */
+-#define SK_SEN_PCI_IO_5V_LOW_ERR 4444 /* - 10% V PCI-IO Low Err Threshold */
+-
+-#define SK_SEN_PCI_IO_RANGE_LIMITER 4000 /* 4000 mV range delimiter */
+-
+-/* correction values for the second pass */
+-#define SK_SEN_PCI_IO_3V3_HIGH_ERR 3850 /* + 15% V PCI-IO High Err Threshold */
+-#define SK_SEN_PCI_IO_3V3_HIGH_WARN 3674 /* + 10% V PCI-IO High Warn Threshold */
+- /* 3300 mVolt */
+-#define SK_SEN_PCI_IO_3V3_LOW_WARN 2926 /* - 10% V PCI-IO Low Warn Threshold */
+-#define SK_SEN_PCI_IO_3V3_LOW_ERR 2772 /* - 15% V PCI-IO Low Err Threshold */
+-
+-/*
+- * VDD voltage
+- */
+-#define SK_SEN_VDD_HIGH_ERR 3630 /* Voltage ASIC High Err Threshold */
+-#define SK_SEN_VDD_HIGH_WARN 3476 /* Voltage ASIC High Warn Threshold */
+-#define SK_SEN_VDD_LOW_WARN 3146 /* Voltage ASIC Low Warn Threshold */
+-#define SK_SEN_VDD_LOW_ERR 2970 /* Voltage ASIC Low Err Threshold */
+-
+-/*
+- * PHY PLL 3V3 voltage
+- */
+-#define SK_SEN_PLL_3V3_HIGH_ERR 3630 /* Voltage PMA High Err Threshold */
+-#define SK_SEN_PLL_3V3_HIGH_WARN 3476 /* Voltage PMA High Warn Threshold */
+-#define SK_SEN_PLL_3V3_LOW_WARN 3146 /* Voltage PMA Low Warn Threshold */
+-#define SK_SEN_PLL_3V3_LOW_ERR 2970 /* Voltage PMA Low Err Threshold */
+-
+-/*
+- * VAUX (YUKON only)
+- */
+-#define SK_SEN_VAUX_3V3_HIGH_ERR 3630 /* Voltage VAUX High Err Threshold */
+-#define SK_SEN_VAUX_3V3_HIGH_WARN 3476 /* Voltage VAUX High Warn Threshold */
+-#define SK_SEN_VAUX_3V3_LOW_WARN 3146 /* Voltage VAUX Low Warn Threshold */
+-#define SK_SEN_VAUX_3V3_LOW_ERR 2970 /* Voltage VAUX Low Err Threshold */
+-#define SK_SEN_VAUX_0V_WARN_ERR 0 /* if VAUX not present */
+-#define SK_SEN_VAUX_RANGE_LIMITER 1000 /* 1000 mV range delimiter */
+-
+-/*
+- * PHY 2V5 voltage
+- */
+-#define SK_SEN_PHY_2V5_HIGH_ERR 2750 /* Voltage PHY High Err Threshold */
+-#define SK_SEN_PHY_2V5_HIGH_WARN 2640 /* Voltage PHY High Warn Threshold */
+-#define SK_SEN_PHY_2V5_LOW_WARN 2376 /* Voltage PHY Low Warn Threshold */
+-#define SK_SEN_PHY_2V5_LOW_ERR 2222 /* Voltage PHY Low Err Threshold */
+-
+-/*
+- * ASIC Core 1V5 voltage (YUKON only)
+- */
+-#define SK_SEN_CORE_1V5_HIGH_ERR 1650 /* Voltage ASIC Core High Err Threshold */
+-#define SK_SEN_CORE_1V5_HIGH_WARN 1575 /* Voltage ASIC Core High Warn Threshold */
+-#define SK_SEN_CORE_1V5_LOW_WARN 1425 /* Voltage ASIC Core Low Warn Threshold */
+-#define SK_SEN_CORE_1V5_LOW_ERR 1350 /* Voltage ASIC Core Low Err Threshold */
+-
+-/*
+- * FAN 1 speed
+- */
+-/* assuming: 6500rpm +-15%, 4 pulses,
+- * warning at: 80 %
+- * error at: 70 %
+- * no upper limit
+- */
+-#define SK_SEN_FAN_HIGH_ERR 20000 /* FAN Speed High Err Threshold */
+-#define SK_SEN_FAN_HIGH_WARN 20000 /* FAN Speed High Warn Threshold */
+-#define SK_SEN_FAN_LOW_WARN 5200 /* FAN Speed Low Warn Threshold */
+-#define SK_SEN_FAN_LOW_ERR 4550 /* FAN Speed Low Err Threshold */
+-
+-/*
+- * Some Voltages need dynamic thresholds
+- */
+-#define SK_SEN_DYN_INIT_NONE 0 /* No dynamic init of thresholds */
+-#define SK_SEN_DYN_INIT_PCI_IO 10 /* Init PCI-IO with new thresholds */
+-#define SK_SEN_DYN_INIT_VAUX 11 /* Init VAUX with new thresholds */
+-
+-extern int SkLm80ReadSensor(SK_AC *pAC, SK_IOC IoC, SK_SENSOR *pSen);
+-#endif /* n_INC_SKGEI2C_H */
+diff -ruN linux/drivers/net/sk98lin/h/skgeinit.h linux-new/drivers/net/sk98lin/h/skgeinit.h
+--- linux/drivers/net/sk98lin/h/skgeinit.h 2005-09-26 13:32:48.000000000 +0400
++++ linux-new/drivers/net/sk98lin/h/skgeinit.h 2005-08-09 17:15:51.000000000 +0400
+@@ -2,8 +2,8 @@
+ *
+ * Name: skgeinit.h
+ * Project: Gigabit Ethernet Adapters, Common Modules
+- * Version: $Revision: 1.83 $
+- * Date: $Date: 2003/09/16 14:07:37 $
++ * Version: $Revision: 2.40 $
++ * Date: $Date: 2005/07/19 15:24:21 $
+ * Purpose: Structures and prototypes for the GE Init Module
+ *
+ ******************************************************************************/
+@@ -11,13 +11,12 @@
+ /******************************************************************************
+ *
+ * (C)Copyright 1998-2002 SysKonnect.
+- * (C)Copyright 2002-2003 Marvell.
++ * (C)Copyright 2002-2005 Marvell.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+- *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+@@ -60,14 +59,17 @@
+ #define SK_XMIT_DUR 0x002faf08UL /* 50 ms */
+ #define SK_BLK_DUR 0x01dcd650UL /* 500 ms */
+
+-#define SK_DPOLL_DEF 0x00ee6b28UL /* 250 ms at 62.5 MHz */
++#define SK_DPOLL_DEF 0x00ee6b28UL /* 250 ms at 62.5 MHz (Genesis) */
++#define SK_DPOLL_DEF_Y2 0x0000124fUL /* 75 us (Yukon-2) */
+
+ #define SK_DPOLL_MAX 0x00ffffffUL /* 268 ms at 62.5 MHz */
+- /* 215 ms at 78.12 MHz */
++ /* 215 ms at 78.12 MHz (Yukon) */
+
+ #define SK_FACT_62 100 /* is given in percent */
+-#define SK_FACT_53 85 /* on GENESIS: 53.12 MHz */
++#define SK_FACT_53 85 /* on GENESIS: 53.12 MHz */
+ #define SK_FACT_78 125 /* on YUKON: 78.12 MHz */
++#define SK_FACT_100 161 /* on YUKON-FE: 100 MHz */
++#define SK_FACT_125 202 /* on YUKON-EC: 125 MHz */
+
+ /* Timeout values */
+ #define SK_MAC_TO_53 72 /* MAC arbiter timeout */
+@@ -83,10 +85,16 @@
+ #define SK_RB_LLPP_B (16 * 1024) /* Lower Level for big Queues */
+
+ #ifndef SK_BMU_RX_WM
+-#define SK_BMU_RX_WM 0x600 /* BMU Rx Watermark */
++#define SK_BMU_RX_WM 0x600 /* BMU Rx Watermark */
+ #endif
++
+ #ifndef SK_BMU_TX_WM
+-#define SK_BMU_TX_WM 0x600 /* BMU Tx Watermark */
++#define SK_BMU_TX_WM 0x600 /* BMU Tx Watermark */
++#endif
++
++/* performance sensitive drivers should set this define to 0x80 */
++#ifndef SK_BMU_RX_WM_PEX
++#define SK_BMU_RX_WM_PEX 0x600 /* BMU Rx Watermark for PEX */
+ #endif
+
+ /* XMAC II Rx High Watermark */
+@@ -98,37 +106,31 @@
+ #define SK_XM_THR_MULL 0x01fb /* .. for multiple link usage */
+ #define SK_XM_THR_JUMBO 0x03fc /* .. for jumbo frame usage */
+
+-/* values for GIPortUsage */
++/* values for PortUsage */
+ #define SK_RED_LINK 1 /* redundant link usage */
+ #define SK_MUL_LINK 2 /* multiple link usage */
+ #define SK_JUMBO_LINK 3 /* driver uses jumbo frames */
+
+ /* Minimum RAM Buffer Rx Queue Size */
+-#define SK_MIN_RXQ_SIZE 16 /* 16 kB */
++#define SK_MIN_RXQ_SIZE (((pAC)->GIni.GIYukon2) ? 10 : 16) /* 10/16 kB */
+
+ /* Minimum RAM Buffer Tx Queue Size */
+-#define SK_MIN_TXQ_SIZE 16 /* 16 kB */
++#define SK_MIN_TXQ_SIZE (((pAC)->GIni.GIYukon2) ? 10 : 16) /* 10/16 kB */
+
+-/* Queue Size units */
+-#define QZ_UNITS 0x7
++/* Queue Size units (Genesis/Yukon) */
++#define QZ_UNITS 7
+ #define QZ_STEP 8
+
++/* Queue Size units (Yukon-2) */
++#define QZ_STEP_Y2 1
++
+ /* Percentage of queue size from whole memory */
+ /* 80 % for receive */
+-#define RAM_QUOTA_RX 80L
+-/* 0% for sync transfer */
+-#define RAM_QUOTA_SYNC 0L
++#define RAM_QUOTA_RX 80
++/* 0 % for sync transfer */
++#define RAM_QUOTA_SYNC 0
+ /* the rest (20%) is taken for async transfer */
+
+-/* Get the rounded queue size in Bytes in 8k steps */
+-#define ROUND_QUEUE_SIZE(SizeInBytes) \
+- ((((unsigned long) (SizeInBytes) + (QZ_STEP*1024L)-1) / 1024) & \
+- ~(QZ_STEP-1))
+-
+-/* Get the rounded queue size in KBytes in 8k steps */
+-#define ROUND_QUEUE_SIZE_KB(Kilobytes) \
+- ROUND_QUEUE_SIZE((Kilobytes) * 1024L)
+-
+ /* Types of RAM Buffer Queues */
+ #define SK_RX_SRAM_Q 1 /* small receive queue */
+ #define SK_RX_BRAM_Q 2 /* big receive queue */
+@@ -167,11 +169,11 @@
+
+
+ /* Link Speed Capabilities */
+-#define SK_LSPEED_CAP_AUTO (1<<0) /* Automatic resolution */
+-#define SK_LSPEED_CAP_10MBPS (1<<1) /* 10 Mbps */
+-#define SK_LSPEED_CAP_100MBPS (1<<2) /* 100 Mbps */
+-#define SK_LSPEED_CAP_1000MBPS (1<<3) /* 1000 Mbps */
+-#define SK_LSPEED_CAP_INDETERMINATED (1<<4) /* indeterminated */
++#define SK_LSPEED_CAP_AUTO BIT_0S /* Automatic resolution */
++#define SK_LSPEED_CAP_10MBPS BIT_1S /* 10 Mbps */
++#define SK_LSPEED_CAP_100MBPS BIT_2S /* 100 Mbps */
++#define SK_LSPEED_CAP_1000MBPS BIT_3S /* 1000 Mbps */
++#define SK_LSPEED_CAP_INDETERMINATED BIT_4S /* indeterminated */
+
+ /* Link Speed Parameter */
+ #define SK_LSPEED_AUTO 1 /* Automatic resolution */
+@@ -189,11 +191,11 @@
+
+
+ /* Link Capability Parameter */
+-#define SK_LMODE_CAP_HALF (1<<0) /* Half Duplex Mode */
+-#define SK_LMODE_CAP_FULL (1<<1) /* Full Duplex Mode */
+-#define SK_LMODE_CAP_AUTOHALF (1<<2) /* AutoHalf Duplex Mode */
+-#define SK_LMODE_CAP_AUTOFULL (1<<3) /* AutoFull Duplex Mode */
+-#define SK_LMODE_CAP_INDETERMINATED (1<<4) /* indeterminated */
++#define SK_LMODE_CAP_HALF BIT_0S /* Half Duplex Mode */
++#define SK_LMODE_CAP_FULL BIT_1S /* Full Duplex Mode */
++#define SK_LMODE_CAP_AUTOHALF BIT_2S /* AutoHalf Duplex Mode */
++#define SK_LMODE_CAP_AUTOFULL BIT_3S /* AutoFull Duplex Mode */
++#define SK_LMODE_CAP_INDETERMINATED BIT_4S /* indeterminated */
+
+ /* Link Mode Current State */
+ #define SK_LMODE_STAT_UNKNOWN 1 /* Unknown Duplex Mode */
+@@ -220,10 +222,10 @@
+ #define SK_FLOW_STAT_INDETERMINATED 5 /* indeterminated */
+
+ /* Master/Slave Mode Capabilities */
+-#define SK_MS_CAP_AUTO (1<<0) /* Automatic resolution */
+-#define SK_MS_CAP_MASTER (1<<1) /* This station is master */
+-#define SK_MS_CAP_SLAVE (1<<2) /* This station is slave */
+-#define SK_MS_CAP_INDETERMINATED (1<<3) /* indeterminated */
++#define SK_MS_CAP_AUTO BIT_0S /* Automatic resolution */
++#define SK_MS_CAP_MASTER BIT_1S /* This station is master */
++#define SK_MS_CAP_SLAVE BIT_2S /* This station is slave */
++#define SK_MS_CAP_INDETERMINATED BIT_3S /* indeterminated */
+
+ /* Set Master/Slave Mode Parameter (and capabilities) */
+ #define SK_MS_MODE_AUTO 1 /* Automatic resolution */
+@@ -238,25 +240,25 @@
+ #define SK_MS_STAT_FAULT 4 /* M/S resolution failed */
+ #define SK_MS_STAT_INDETERMINATED 5 /* indeterminated */
+
+-/* parameter 'Mode' when calling SkXmSetRxCmd() */
+-#define SK_STRIP_FCS_ON (1<<0) /* Enable FCS stripping of Rx frames */
+-#define SK_STRIP_FCS_OFF (1<<1) /* Disable FCS stripping of Rx frames */
+-#define SK_STRIP_PAD_ON (1<<2) /* Enable pad byte stripping of Rx fr */
+-#define SK_STRIP_PAD_OFF (1<<3) /* Disable pad byte stripping of Rx fr */
+-#define SK_LENERR_OK_ON (1<<4) /* Don't chk fr for in range len error */
+-#define SK_LENERR_OK_OFF (1<<5) /* Check frames for in range len error */
+-#define SK_BIG_PK_OK_ON (1<<6) /* Don't set Rx Error bit for big frames */
+-#define SK_BIG_PK_OK_OFF (1<<7) /* Set Rx Error bit for big frames */
+-#define SK_SELF_RX_ON (1<<8) /* Enable Rx of own packets */
+-#define SK_SELF_RX_OFF (1<<9) /* Disable Rx of own packets */
++/* parameter 'Mode' when calling SkMacSetRxCmd() */
++#define SK_STRIP_FCS_ON BIT_0S /* Enable FCS stripping of Rx frames */
++#define SK_STRIP_FCS_OFF BIT_1S /* Disable FCS stripping of Rx frames */
++#define SK_STRIP_PAD_ON BIT_2S /* Enable pad byte stripping of Rx fr */
++#define SK_STRIP_PAD_OFF BIT_3S /* Disable pad byte stripping of Rx fr */
++#define SK_LENERR_OK_ON BIT_4S /* Don't chk fr for in range len error */
++#define SK_LENERR_OK_OFF BIT_5S /* Check frames for in range len error */
++#define SK_BIG_PK_OK_ON BIT_6S /* Don't set Rx Error bit for big frames */
++#define SK_BIG_PK_OK_OFF BIT_7S /* Set Rx Error bit for big frames */
++#define SK_SELF_RX_ON BIT_8S /* Enable Rx of own packets */
++#define SK_SELF_RX_OFF BIT_9S /* Disable Rx of own packets */
+
+ /* parameter 'Para' when calling SkMacSetRxTxEn() */
+-#define SK_MAC_LOOPB_ON (1<<0) /* Enable MAC Loopback Mode */
+-#define SK_MAC_LOOPB_OFF (1<<1) /* Disable MAC Loopback Mode */
+-#define SK_PHY_LOOPB_ON (1<<2) /* Enable PHY Loopback Mode */
+-#define SK_PHY_LOOPB_OFF (1<<3) /* Disable PHY Loopback Mode */
+-#define SK_PHY_FULLD_ON (1<<4) /* Enable GMII Full Duplex */
+-#define SK_PHY_FULLD_OFF (1<<5) /* Disable GMII Full Duplex */
++#define SK_MAC_LOOPB_ON BIT_0S /* Enable MAC Loopback Mode */
++#define SK_MAC_LOOPB_OFF BIT_1S /* Disable MAC Loopback Mode */
++#define SK_PHY_LOOPB_ON BIT_2S /* Enable PHY Loopback Mode */
++#define SK_PHY_LOOPB_OFF BIT_3S /* Disable PHY Loopback Mode */
++#define SK_PHY_FULLD_ON BIT_4S /* Enable GMII Full Duplex */
++#define SK_PHY_FULLD_OFF BIT_5S /* Disable GMII Full Duplex */
+
+ /* States of PState */
+ #define SK_PRT_RESET 0 /* the port is reset */
+@@ -266,18 +268,24 @@
+
+ /* PHY power down modes */
+ #define PHY_PM_OPERATIONAL_MODE 0 /* PHY operational mode */
+-#define PHY_PM_DEEP_SLEEP 1 /* coma mode --> minimal power */
++#define PHY_PM_DEEP_SLEEP 1 /* Coma mode --> minimal power */
+ #define PHY_PM_IEEE_POWER_DOWN 2 /* IEEE 22.2.4.1.5 compl. power down */
+-#define PHY_PM_ENERGY_DETECT 3 /* energy detect */
+-#define PHY_PM_ENERGY_DETECT_PLUS 4 /* energy detect plus */
++#define PHY_PM_ENERGY_DETECT 3 /* Energy detect */
++#define PHY_PM_ENERGY_DETECT_PLUS 4 /* Energy detect plus */
++
++/* PCI Bus Types */
++#define SK_PCI_BUS BIT_0S /* normal PCI bus */
++#define SK_PCIX_BUS BIT_1S /* PCI-X bus */
++#define SK_PEX_BUS BIT_2S /* PCI-Express bus */
+
+ /* Default receive frame limit for Workaround of XMAC Errata */
+ #define SK_DEF_RX_WA_LIM SK_CONSTU64(100)
+
+ /* values for GILedBlinkCtrl (LED Blink Control) */
+-#define SK_ACT_LED_BLINK (1<<0) /* Active LED blinking */
+-#define SK_DUP_LED_NORMAL (1<<1) /* Duplex LED normal */
+-#define SK_LED_LINK100_ON (1<<2) /* Link 100M LED on */
++#define SK_ACT_LED_BLINK BIT_0S /* Active LED blinking */
++#define SK_DUP_LED_NORMAL BIT_1S /* Duplex LED normal */
++#define SK_LED_LINK100_ON BIT_2S /* Link 100M LED on */
++#define SK_DUAL_LED_ACT_LNK BIT_3S /* Dual LED ACT/LNK configuration */
+
+ /* Link Partner Status */
+ #define SK_LIPA_UNKNOWN 0 /* Link partner is in unknown state */
+@@ -290,18 +298,166 @@
+ /* Max. Auto-neg. timeouts before link detection in sense mode is reset */
+ #define SK_MAX_ANEG_TO 10 /* Max. 10 times the sense mode is reset */
+
++
++/******************************************************************************
++ *
++ * HW_FEATURE() macro
++ */
++
++/* DWORD 0: Features */
++#define HWF_CLK_GATING_ENABLE 0x02000000UL /* Enable Clock Gating */
++#define HWF_RED_CORE_CLK_SUP 0x01000000UL /* Reduced Core Clock supp. */
++#define HWF_SYNC_TX_SUP 0x00800000UL /* Synch. Tx Queue available */
++#define HWF_SINGLE_PORT_DEVICE 0x00400000UL /* Device has only one LAN IF */
++#define HWF_JUMBO_FRAMES_SUP 0x00200000UL /* Jumbo Frames supported */
++#define HWF_TX_TCP_CSUM_SUP 0x00100000UL /* TCP Tx checksum supported */
++#define HWF_TX_UDP_CSUM_SUP 0x00080000UL /* UDP Tx checksum supported */
++#define HWF_RX_CSUM_SUP 0x00040000UL /* RX checksum supported */
++#define HWF_TCP_SEGM_SUP 0x00020000UL /* TCP segmentation supported */
++#define HWF_RSS_HASH_SUP 0x00010000UL /* RSS Hash supported */
++#define HWF_PORT_VLAN_SUP 0x00008000UL /* VLAN can be config per port*/
++#define HWF_ROLE_PARAM_SUP 0x00004000UL /* Role parameter supported */
++#define HWF_LOW_PMODE_SUP 0x00002000UL /* Low Power Mode supported */
++#define HWF_ENERGIE_DEMO_SUP 0x00001000UL /* Energy Detect mode supp. */
++#define HWF_SPEED1000_SUP 0x00000800UL /* Line Speed 1000 supported */
++#define HWF_SPEED100_SUP 0x00000400UL /* Line Speed 100 supported */
++#define HWF_SPEED10_SUP 0x00000200UL /* Line Speed 10 supported */
++#define HWF_AUTONEGSENSE_SUP 0x00000100UL /* Autoneg Sense supported */
++#define HWF_PHY_LOOPB_MD_SUP 0x00000080UL /* PHY loopback mode supp. */
++#define HWF_ASF_SUP 0x00000040UL /* ASF support possible */
++#define HWF_QS_STEPS_1KB 0x00000020UL /* The Rx/Tx queues can be */
++ /* configured with 1 kB res. */
++#define HWF_OWN_RAM_PER_PORT 0x00000010UL /* Each port has a separate */
++ /* RAM buffer */
++#define HWF_MIN_LED_IF 0x00000008UL /* Minimal LED interface */
++ /* (e.g. for Yukon-EC) */
++#define HWF_LIST_ELEMENTS_USED 0x00000004UL /* HW uses list elements */
++ /* (otherwise desc. are used) */
++#define HWF_GMAC_INSIDE 0x00000002UL /* Device contains GMAC */
++#define HWF_TWSI_PRESENT 0x00000001UL /* TWSI sensor bus present */
++
++/*-RMV- DWORD 1: Deviations */
++#define HWF_WA_DEV_4115 0x10010000UL /*-RMV- 4.115 (Rx MAC FIFO) */
++#define HWF_WA_DEV_4109 0x10008000UL /*-RMV- 4.109 (BIU hang) */
++#define HWF_WA_DEV_483 0x10004000UL /*-RMV- 4.83 (Rx TCP wrong) */
++#define HWF_WA_DEV_479 0x10002000UL /*-RMV- 4.79 (Rx BMU hang II) */
++#define HWF_WA_DEV_472 0x10001000UL /*-RMV- 4.72 (GPHY2 MDC clk) */
++#define HWF_WA_DEV_463 0x10000800UL /*-RMV- 4.63 (Rx BMU hang I) */
++#define HWF_WA_DEV_427 0x10000400UL /*-RMV- 4.27 (Tx Done Rep) */
++#define HWF_WA_DEV_42 0x10000200UL /*-RMV- 4.2 (pref unit burst) */
++#define HWF_WA_DEV_46 0x10000100UL /*-RMV- 4.6 (CPU crash II) */
++#define HWF_WA_DEV_43_418 0x10000080UL /*-RMV- 4.3 & 4.18 (PCI unexp */
++ /*-RMV- compl&Stat BMU deadl) */
++#define HWF_WA_DEV_420 0x10000040UL /*-RMV- 4.20 (Status BMU ov) */
++#define HWF_WA_DEV_423 0x10000020UL /*-RMV- 4.23 (TCP Segm Hang) */
++#define HWF_WA_DEV_424 0x10000010UL /*-RMV- 4.24 (MAC reg overwr) */
++#define HWF_WA_DEV_425 0x10000008UL /*-RMV- 4.25 (Magic packet */
++ /*-RMV- with odd offset) */
++#define HWF_WA_DEV_428 0x10000004UL /*-RMV- 4.28 (Poll-U &BigEndi)*/
++#define HWF_WA_FIFO_FLUSH_YLA0 0x10000002UL /*-RMV- dis Rx GMAC FIFO Flush*/
++ /*-RMV- for Yu-L Rev. A0 only */
++#define HWF_WA_COMA_MODE 0x10000001UL /*-RMV- Coma Mode WA req */
++
++/* DWORD 2: still unused */
++/* DWORD 3: still unused */
++
++
++/*
++ * HW_FEATURE() - returns whether the feature is serviced or not
++ */
++#define HW_FEATURE(pAC, ReqFeature) \
++ (((pAC)->GIni.HwF.Features[((ReqFeature) & 0x30000000UL) >> 28] &\
++ ((ReqFeature) & 0x0fffffffUL)) != 0)
++
++#define HW_FEAT_LIST 0
++#define HW_DEV_LIST 1
++
++#define SET_HW_FEATURE_MASK(pAC, List, OffMaskValue, OnMaskValue) { \
++ if ((List) == HW_FEAT_LIST || (List) == HW_DEV_LIST) { \
++ (pAC)->GIni.HwF.OffMask[List] = (OffMaskValue); \
++ (pAC)->GIni.HwF.OnMask[List] = (OnMaskValue); \
++ } \
++}
++
++/* driver access macros for GIni structure ***********************************/
++
++#define CHIP_ID_YUKON_2(pAC) ((pAC)->GIni.GIYukon2)
++#define HW_SYNC_TX_SUPPORTED(pAC) \
++ ((pAC)->GIni.GIChipId != CHIP_ID_YUKON_EC && \
++ (pAC)->GIni.GIChipId != CHIP_ID_YUKON_FE)
++
++#define HW_MS_TO_TICKS(pAC, MsTime) \
++ ((MsTime) * (62500L/100) * (pAC)->GIni.GIHstClkFact)
++
++#ifdef XXX
++/* still under construction */
++#define HW_IS_SINGLE_PORT(pAC) ((pAC)->GIni.GIMacsFound == 1)
++#define HW_NUMBER_OF_PORTS(pAC) ((pAC)->GIni.GIMacsFound)
++
++#define HW_TX_UDP_CSUM_SUPPORTED(pAC) \
++ ((((pAC)->GIni.GIChipId >= CHIP_ID_YUKON) && ((pAC)->GIni.GIChipRev != 0))
++
++#define HW_DEFAULT_LINESPEED(pAC) \
++ ((!(pAC)->GIni.GIGenesis && (pAC)->GIni.GICopperType) ? \
++ SK_LSPEED_AUTO : SK_LSPEED_1000MBPS)
++
++#define HW_ROLE_PARAM_SUPPORTED(pAC) ((pAC)->GIni.GICopperType)
++
++#define HW_SPEED1000_SUPPORTED(pAC, Port) \
++ ((pAC)->GIni.GP[Port].PLinkSpeedCap & SK_LSPEED_CAP_1000MBPS)
++
++#define HW_SPEED100_SUPPORTED(pAC, Port) \
++ ((pAC)->GIni.GP[Port].PLinkSpeedCap & SK_LSPEED_CAP_100MBPS)
++
++#define HW_SPEED10_SUPPORTED(pAC, Port) \
++ ((pAC)->GIni.GP[Port].PLinkSpeedCap & SK_LSPEED_CAP_10MBPS)
++
++#define HW_AUTONEGSENSE_SUPPORTED(pAC) ((pAC)->GIni.GP[0].PhyType==SK_PHY_XMAC)
++
++#define HW_FREQ_TO_CARD_TICKS(pAC, AdapterClkSpeed, Freq) \
++ (((AdapterClkSpeed / 100) * (pAC)->GIni.GIHstClkFact) / Freq)
++
++#define HW_IS_LINK_UP(pAC, Port) ((pAC)->GIni.GP[Port].PHWLinkUp)
++#define HW_LINK_SPEED_USED(pAC, Port) ((pAC)->GIni.GP[Port].PLinkSpeedUsed)
++#define HW_RAM_SIZE(pAC) ((pAC)->GIni.GIRamSize)
++
++#define HW_PHY_LP_MODE_SUPPORTED(pAC) (pAC0->???
++#define HW_ASF_ACTIVE(pAC) ???
++#define RAWIO_OUT32(pAC, pAC->RegIrqMask, pAC->GIni.GIValIrqMask)...
++
++/* macro to check whether Tx checksum is supported */
++#define HW_TX_CSUM_SUPPORTED(pAC) ((pAC)->GIni.GIChipId != CHIP_ID_GENESIS)
++
++BMU_UDP_CHECK : BMU_TCP_CHECK;
++
++/* macro for - Own Bit mirrored to DWORD7 (Yukon LP receive descriptor) */
++#endif /* 0 */
++
++
+ /* structures *****************************************************************/
+
+ /*
++ * HW Feature structure
++ */
++typedef struct s_HwFeatures {
++ SK_U32 Features[4]; /* Feature list */
++ SK_U32 OffMask[4]; /* Off Mask */
++ SK_U32 OnMask[4]; /* On Mask */
++} SK_HW_FEATURES;
++
++/*
+ * MAC specific functions
+ */
+ typedef struct s_GeMacFunc {
+- int (*pFnMacUpdateStats)(SK_AC *pAC, SK_IOC IoC, unsigned int Port);
+- int (*pFnMacStatistic)(SK_AC *pAC, SK_IOC IoC, unsigned int Port,
+- SK_U16 StatAddr, SK_U32 SK_FAR *pVal);
+- int (*pFnMacResetCounter)(SK_AC *pAC, SK_IOC IoC, unsigned int Port);
+- int (*pFnMacOverflow)(SK_AC *pAC, SK_IOC IoC, unsigned int Port,
+- SK_U16 IStatus, SK_U64 SK_FAR *pVal);
++ int (*pFnMacUpdateStats)(SK_AC *, SK_IOC, unsigned int);
++ int (*pFnMacStatistic)(SK_AC *, SK_IOC, unsigned int, SK_U16, SK_U32 SK_FAR *);
++ int (*pFnMacResetCounter)(SK_AC *, SK_IOC, unsigned int);
++ int (*pFnMacOverflow)(SK_AC *, SK_IOC, unsigned int, SK_U16, SK_U64 SK_FAR *);
++ void (*pSkGeSirqIsr)(SK_AC *, SK_IOC, SK_U32);
++#ifdef SK_DIAG
++ int (*pFnMacPhyRead)(SK_AC *, SK_IOC, int, int, SK_U16 SK_FAR *);
++ int (*pFnMacPhyWrite)(SK_AC *, SK_IOC, int, int, SK_U16);
++#endif /* SK_DIAG */
+ } SK_GEMACFUNC;
+
+ /*
+@@ -311,7 +467,7 @@
+ #ifndef SK_DIAG
+ SK_TIMER PWaTimer; /* Workaround Timer */
+ SK_TIMER HalfDupChkTimer;
+-#endif /* SK_DIAG */
++#endif /* !SK_DIAG */
+ SK_U32 PPrevShorts; /* Previous Short Counter checking */
+ SK_U32 PPrevFcs; /* Previous FCS Error Counter checking */
+ SK_U64 PPrevRx; /* Previous RxOk Counter checking */
+@@ -335,6 +491,7 @@
+ int PXaQOff; /* Asynchronous Tx Queue Address Offset */
+ int PhyType; /* PHY used on this port */
+ int PState; /* Port status (reset, stop, init, run) */
++ int PPortUsage; /* Driver Port Usage */
+ SK_U16 PhyId1; /* PHY Id1 on this port */
+ SK_U16 PhyAddr; /* MDIO/MDC PHY address */
+ SK_U16 PIsave; /* Saved Interrupt status word */
+@@ -367,7 +524,10 @@
+ int PMacJamLen; /* MAC Jam length */
+ int PMacJamIpgVal; /* MAC Jam IPG */
+ int PMacJamIpgData; /* MAC IPG Jam to Data */
++ int PMacBackOffLim; /* MAC Back-off Limit */
++ int PMacDataBlind; /* MAC Data Blinder */
+ int PMacIpgData; /* MAC Data IPG */
++ SK_U16 PMacAddr[3]; /* MAC address */
+ SK_BOOL PMacLimit4; /* reset collision counter and backoff algorithm */
+ } SK_GEPORT;
+
+@@ -379,27 +539,37 @@
+ int GIChipId; /* Chip Identification Number */
+ int GIChipRev; /* Chip Revision Number */
+ SK_U8 GIPciHwRev; /* PCI HW Revision Number */
++ SK_U8 GIPciBus; /* PCI Bus Type (PCI / PCI-X / PCI-Express) */
++ SK_U8 GIPciMode; /* PCI / PCI-X Mode @ Clock */
++ SK_U8 GIPexWidth; /* PCI-Express Negotiated Link Width */
+ SK_BOOL GIGenesis; /* Genesis adapter ? */
+- SK_BOOL GIYukon; /* YUKON-A1/Bx chip */
++ SK_BOOL GIYukon; /* YUKON family (1 and 2) */
+ SK_BOOL GIYukonLite; /* YUKON-Lite chip */
++ SK_BOOL GIYukon2; /* YUKON-2 chip (-XL, -EC or -FE) */
++ SK_U8 GIConTyp; /* Connector Type */
++ SK_U8 GIPmdTyp; /* PMD Type */
+ SK_BOOL GICopperType; /* Copper Type adapter ? */
+ SK_BOOL GIPciSlot64; /* 64-bit PCI Slot */
+ SK_BOOL GIPciClock66; /* 66 MHz PCI Clock */
+ SK_BOOL GIVauxAvail; /* VAUX available (YUKON) */
+ SK_BOOL GIYukon32Bit; /* 32-Bit YUKON adapter */
++ SK_BOOL GIAsfEnabled; /* ASF subsystem enabled */
++ SK_BOOL GIAsfRunning; /* ASF subsystem running */
+ SK_U16 GILedBlinkCtrl; /* LED Blink Control */
+ int GIMacsFound; /* Number of MACs found on this adapter */
+ int GIMacType; /* MAC Type used on this adapter */
+- int GIHstClkFact; /* Host Clock Factor (62.5 / HstClk * 100) */
+- int GIPortUsage; /* Driver Port Usage */
++ int GIChipCap; /* Adapter's Capabilities */
++ int GIHstClkFact; /* Host Clock Factor (HstClk / 62.5 * 100) */
+ int GILevel; /* Initialization Level completed */
+ int GIRamSize; /* The RAM size of the adapter in kB */
+ int GIWolOffs; /* WOL Register Offset (HW-Bug in Rev. A) */
+ SK_U32 GIRamOffs; /* RAM Address Offset for addr calculation */
+ SK_U32 GIPollTimerVal; /* Descr. Poll Timer Init Val (HstClk ticks) */
+ SK_U32 GIValIrqMask; /* Value for Interrupt Mask */
++ SK_U32 GIValHwIrqMask; /* Value for Interrupt Mask */
+ SK_U32 GITimeStampCnt; /* Time Stamp High Counter (YUKON only) */
+ SK_GEPORT GP[SK_MAX_MACS];/* Port Dependent Information */
++ SK_HW_FEATURES HwF; /* HW Features struct */
+ SK_GEMACFUNC GIFunc; /* MAC depedent functions */
+ } SK_GEINIT;
+
+@@ -417,7 +587,7 @@
+ #define SKERR_HWI_E005 (SKERR_HWI_E004+1)
+ #define SKERR_HWI_E005MSG "SkGeInitPort(): cannot init running ports"
+ #define SKERR_HWI_E006 (SKERR_HWI_E005+1)
+-#define SKERR_HWI_E006MSG "SkGeMacInit(): PState does not match HW state"
++#define SKERR_HWI_E006MSG "SkGeInit() called with illegal Chip Id"
+ #define SKERR_HWI_E007 (SKERR_HWI_E006+1)
+ #define SKERR_HWI_E007MSG "SkXmInitDupMd() called with invalid Dup Mode"
+ #define SKERR_HWI_E008 (SKERR_HWI_E007+1)
+@@ -433,11 +603,11 @@
+ #define SKERR_HWI_E013 (SKERR_HWI_E012+1)
+ #define SKERR_HWI_E013MSG "SkGeInitPort(): cfg changed for running queue"
+ #define SKERR_HWI_E014 (SKERR_HWI_E013+1)
+-#define SKERR_HWI_E014MSG "SkGeInitPort(): unknown GIPortUsage specified"
++#define SKERR_HWI_E014MSG "SkGeInitPort(): unknown PortUsage specified"
+ #define SKERR_HWI_E015 (SKERR_HWI_E014+1)
+-#define SKERR_HWI_E015MSG "Illegal Link mode parameter"
++#define SKERR_HWI_E015MSG "Illegal Link Mode parameter"
+ #define SKERR_HWI_E016 (SKERR_HWI_E015+1)
+-#define SKERR_HWI_E016MSG "Illegal Flow control mode parameter"
++#define SKERR_HWI_E016MSG "Illegal Flow Control Mode parameter"
+ #define SKERR_HWI_E017 (SKERR_HWI_E016+1)
+ #define SKERR_HWI_E017MSG "Illegal value specified for GIPollTimerVal"
+ #define SKERR_HWI_E018 (SKERR_HWI_E017+1)
+@@ -447,9 +617,9 @@
+ #define SKERR_HWI_E020 (SKERR_HWI_E019+1)
+ #define SKERR_HWI_E020MSG "Illegal Master/Slave parameter"
+ #define SKERR_HWI_E021 (SKERR_HWI_E020+1)
+-#define SKERR_HWI_E021MSG "MacUpdateStats(): cannot update statistic counter"
+-#define SKERR_HWI_E022 (SKERR_HWI_E021+1)
+-#define SKERR_HWI_E022MSG "MacStatistic(): illegal statistic base address"
++#define SKERR_HWI_E021MSG "MacUpdateStats(): cannot update statistic counter"
++#define SKERR_HWI_E022 (SKERR_HWI_E021+1)
++#define SKERR_HWI_E022MSG "MacStatistic(): illegal statistic base address"
+ #define SKERR_HWI_E023 (SKERR_HWI_E022+1)
+ #define SKERR_HWI_E023MSG "SkGeInitPort(): Transmit Queue Size too small"
+ #define SKERR_HWI_E024 (SKERR_HWI_E023+1)
+@@ -464,6 +634,24 @@
+ /*
+ * public functions in skgeinit.c
+ */
++extern void SkGePortVlan(
++ SK_AC *pAC,
++ SK_IOC IoC,
++ int Port,
++ SK_BOOL Enable);
++
++extern void SkGeRxRss(
++ SK_AC *pAC,
++ SK_IOC IoC,
++ int Port,
++ SK_BOOL Enable);
++
++extern void SkGeRxCsum(
++ SK_AC *pAC,
++ SK_IOC IoC,
++ int Port,
++ SK_BOOL Enable);
++
+ extern void SkGePollRxD(
+ SK_AC *pAC,
+ SK_IOC IoC,
+@@ -528,9 +716,14 @@
+
+ extern int SkGeInitAssignRamToQueues(
+ SK_AC *pAC,
+- int ActivePort,
++ int Port,
+ SK_BOOL DualNet);
+
++extern int SkYuk2RestartRxBmu(
++ SK_AC *pAC,
++ SK_IOC IoC,
++ int Port);
++
+ /*
+ * public functions in skxmac2.c
+ */
+@@ -601,13 +794,13 @@
+ int Port,
+ SK_U16 IStatus);
+
+-extern void SkMacSetRxTxEn(
++extern void SkMacSetRxTxEn(
+ SK_AC *pAC,
+ SK_IOC IoC,
+ int Port,
+ int Para);
+
+-extern int SkMacRxTxEnable(
++extern int SkMacRxTxEnable(
+ SK_AC *pAC,
+ SK_IOC IoC,
+ int Port);
+@@ -624,28 +817,28 @@
+ int Port,
+ SK_BOOL Enable);
+
+-extern void SkXmPhyRead(
++extern int SkXmPhyRead(
+ SK_AC *pAC,
+ SK_IOC IoC,
+ int Port,
+ int Addr,
+ SK_U16 SK_FAR *pVal);
+
+-extern void SkXmPhyWrite(
++extern int SkXmPhyWrite(
+ SK_AC *pAC,
+ SK_IOC IoC,
+ int Port,
+ int Addr,
+ SK_U16 Val);
+
+-extern void SkGmPhyRead(
++extern int SkGmPhyRead(
+ SK_AC *pAC,
+ SK_IOC IoC,
+ int Port,
+ int Addr,
+ SK_U16 SK_FAR *pVal);
+
+-extern void SkGmPhyWrite(
++extern int SkGmPhyWrite(
+ SK_AC *pAC,
+ SK_IOC IoC,
+ int Port,
+@@ -713,7 +906,7 @@
+ SK_AC *pAC,
+ SK_IOC IoC,
+ unsigned int Port,
+- SK_U16 IStatus,
++ SK_U16 IStatus,
+ SK_U64 SK_FAR *pStatus);
+
+ extern int SkGmOverflowStatus(
+@@ -729,6 +922,7 @@
+ int Port,
+ SK_BOOL StartTest);
+
++#ifdef SK_PHY_LP_MODE
+ extern int SkGmEnterLowPowerMode(
+ SK_AC *pAC,
+ SK_IOC IoC,
+@@ -739,6 +933,7 @@
+ SK_AC *pAC,
+ SK_IOC IoC,
+ int Port);
++#endif /* SK_PHY_LP_MODE */
+
+ #ifdef SK_DIAG
+ extern void SkGePhyRead(
+@@ -794,31 +989,35 @@
+ extern void SkGeXmitLED();
+ extern void SkGeInitRamIface();
+ extern int SkGeInitAssignRamToQueues();
++extern void SkGePortVlan();
++extern void SkGeRxCsum();
++extern void SkGeRxRss();
++extern int SkYuk2RestartRxBmu();
+
+ /*
+ * public functions in skxmac2.c
+ */
+-extern void SkMacRxTxDisable();
++extern void SkMacRxTxDisable();
+ extern void SkMacSoftRst();
+ extern void SkMacHardRst();
+ extern void SkMacClearRst();
+-extern void SkMacInitPhy();
+-extern int SkMacRxTxEnable();
+-extern void SkMacPromiscMode();
+-extern void SkMacHashing();
+-extern void SkMacIrqDisable();
++extern void SkMacInitPhy();
++extern int SkMacRxTxEnable();
++extern void SkMacPromiscMode();
++extern void SkMacHashing();
++extern void SkMacIrqDisable();
+ extern void SkMacFlushTxFifo();
+ extern void SkMacFlushRxFifo();
+ extern void SkMacIrq();
+ extern int SkMacAutoNegDone();
+ extern void SkMacAutoNegLipaPhy();
+-extern void SkMacSetRxTxEn();
++extern void SkMacSetRxTxEn();
+ extern void SkXmInitMac();
+-extern void SkXmPhyRead();
+-extern void SkXmPhyWrite();
++extern int SkXmPhyRead();
++extern int SkXmPhyWrite();
+ extern void SkGmInitMac();
+-extern void SkGmPhyRead();
+-extern void SkGmPhyWrite();
++extern int SkGmPhyRead();
++extern int SkGmPhyWrite();
+ extern void SkXmClrExactAddr();
+ extern void SkXmInitDupMd();
+ extern void SkXmInitPauseMd();
+@@ -832,8 +1031,10 @@
+ extern int SkXmOverflowStatus();
+ extern int SkGmOverflowStatus();
+ extern int SkGmCableDiagStatus();
++#ifdef SK_PHY_LP_MODE
+ extern int SkGmEnterLowPowerMode();
+ extern int SkGmLeaveLowPowerMode();
++#endif /* SK_PHY_LP_MODE */
+
+ #ifdef SK_DIAG
+ extern void SkGePhyRead();
+@@ -844,10 +1045,11 @@
+ extern void SkXmSendCont();
+ #endif /* SK_DIAG */
+
+-#endif /* SK_KR_PROTO */
++#endif /* SK_KR_PROTO */
+
+ #ifdef __cplusplus
+ }
+ #endif /* __cplusplus */
+
+ #endif /* __INC_SKGEINIT_H_ */
++
+diff -ruN linux/drivers/net/sk98lin/h/skgepnm2.h linux-new/drivers/net/sk98lin/h/skgepnm2.h
+--- linux/drivers/net/sk98lin/h/skgepnm2.h 2005-09-26 13:32:48.000000000 +0400
++++ linux-new/drivers/net/sk98lin/h/skgepnm2.h 2005-08-09 17:15:51.000000000 +0400
+@@ -2,8 +2,8 @@
+ *
+ * Name: skgepnm2.h
+ * Project: GEnesis, PCI Gigabit Ethernet Adapter
+- * Version: $Revision: 1.36 $
+- * Date: $Date: 2003/05/23 12:45:13 $
++ * Version: $Revision: 2.4 $
++ * Date: $Date: 2005/05/03 06:42:43 $
+ * Purpose: Defines for Private Network Management Interface
+ *
+ ****************************************************************************/
+@@ -28,8 +28,13 @@
+ /*
+ * General definitions
+ */
+-#define SK_PNMI_CHIPSET_XMAC 1 /* XMAC11800FP */
+-#define SK_PNMI_CHIPSET_YUKON 2 /* YUKON */
++#define SK_PNMI_CHIPSET_XMAC 1 /* XMAC11800FP */
++#define SK_PNMI_CHIPSET_YUKON 2 /* YUKON */
++#define SK_PNMI_CHIPSET_YUKON_LITE 3 /* YUKON-Lite (Rev. A1-A3) */
++#define SK_PNMI_CHIPSET_YUKON_LP 4 /* YUKON-LP */
++#define SK_PNMI_CHIPSET_YUKON_XL 5 /* YUKON-2 XL */
++#define SK_PNMI_CHIPSET_YUKON_EC 6 /* YUKON-2 EC */
++#define SK_PNMI_CHIPSET_YUKON_FE 7 /* YUKON-2 FE */
+
+ #define SK_PNMI_BUS_PCI 1 /* PCI bus*/
+
+@@ -70,9 +75,9 @@
+ /*
+ * VCT internal status values
+ */
+-#define SK_PNMI_VCT_PENDING 32
+-#define SK_PNMI_VCT_TEST_DONE 64
+-#define SK_PNMI_VCT_LINK 128
++#define SK_PNMI_VCT_PENDING 0x20
++#define SK_PNMI_VCT_TEST_DONE 0x40
++#define SK_PNMI_VCT_LINK 0x80
+
+ /*
+ * Internal table definitions
+@@ -323,7 +328,7 @@
+ vSt, \
+ pAC->Pnmi.MacUpdatedFlag, \
+ pAC->Pnmi.RlmtUpdatedFlag, \
+- pAC->Pnmi.SirqUpdatedFlag))}}
++ pAC->Pnmi.SirqUpdatedFlag));}}
+
+ #else /* !DEBUG */
+
+diff -ruN linux/drivers/net/sk98lin/h/skgepnmi.h linux-new/drivers/net/sk98lin/h/skgepnmi.h
+--- linux/drivers/net/sk98lin/h/skgepnmi.h 2005-09-26 13:32:47.000000000 +0400
++++ linux-new/drivers/net/sk98lin/h/skgepnmi.h 2005-08-09 17:15:51.000000000 +0400
+@@ -1,9 +1,9 @@
+ /*****************************************************************************
+ *
+ * Name: skgepnmi.h
+- * Project: GEnesis, PCI Gigabit Ethernet Adapter
+- * Version: $Revision: 1.62 $
+- * Date: $Date: 2003/08/15 12:31:52 $
++ * Project: Gigabit Ethernet Adapters, PNMI-Module
++ * Version: $Revision: 2.11 $
++ * Date: $Date: 2005/08/09 09:02:12 $
+ * Purpose: Defines for Private Network Management Interface
+ *
+ ****************************************************************************/
+@@ -31,7 +31,7 @@
+ #include "h/sktypes.h"
+ #include "h/skerror.h"
+ #include "h/sktimer.h"
+-#include "h/ski2c.h"
++#include "h/sktwsi.h"
+ #include "h/skaddr.h"
+ #include "h/skrlmt.h"
+ #include "h/skvpd.h"
+@@ -41,7 +41,6 @@
+ */
+ #define SK_PNMI_MDB_VERSION 0x00030001 /* 3.1 */
+
+-
+ /*
+ * Event definitions
+ */
+@@ -54,16 +53,13 @@
+ #define SK_PNMI_EVT_UTILIZATION_TIMER 7 /* Timer event for Utiliza. */
+ #define SK_PNMI_EVT_CLEAR_COUNTER 8 /* Clear statistic counters */
+ #define SK_PNMI_EVT_XMAC_RESET 9 /* XMAC will be reset */
+-
+ #define SK_PNMI_EVT_RLMT_PORT_UP 10 /* Port came logically up */
+ #define SK_PNMI_EVT_RLMT_PORT_DOWN 11 /* Port went logically down */
+ #define SK_PNMI_EVT_RLMT_SEGMENTATION 13 /* Two SP root bridges found */
+ #define SK_PNMI_EVT_RLMT_ACTIVE_DOWN 14 /* Port went logically down */
+ #define SK_PNMI_EVT_RLMT_ACTIVE_UP 15 /* Port came logically up */
+-#define SK_PNMI_EVT_RLMT_SET_NETS 16 /* 1. Parameter is number of nets
+- 1 = single net; 2 = dual net */
+-#define SK_PNMI_EVT_VCT_RESET 17 /* VCT port reset timer event started with SET. */
+-
++#define SK_PNMI_EVT_RLMT_SET_NETS 16 /* Number of nets (1 or 2). */
++#define SK_PNMI_EVT_VCT_RESET 17 /* VCT port reset timer event started with SET. */
+
+ /*
+ * Return values
+@@ -78,7 +74,6 @@
+ #define SK_PNMI_ERR_UNKNOWN_NET 7
+ #define SK_PNMI_ERR_NOT_SUPPORTED 10
+
+-
+ /*
+ * Return values of driver reset function SK_DRIVER_RESET() and
+ * driver event function SK_DRIVER_EVENT()
+@@ -86,19 +81,17 @@
+ #define SK_PNMI_ERR_OK 0
+ #define SK_PNMI_ERR_FAIL 1
+
+-
+ /*
+ * Return values of driver test function SK_DRIVER_SELFTEST()
+ */
+ #define SK_PNMI_TST_UNKNOWN (1 << 0)
+-#define SK_PNMI_TST_TRANCEIVER (1 << 1)
++#define SK_PNMI_TST_TRANCEIVER (1 << 1)
+ #define SK_PNMI_TST_ASIC (1 << 2)
+ #define SK_PNMI_TST_SENSOR (1 << 3)
+-#define SK_PNMI_TST_POWERMGMT (1 << 4)
++#define SK_PNMI_TST_POWERMGMT (1 << 4)
+ #define SK_PNMI_TST_PCI (1 << 5)
+ #define SK_PNMI_TST_MAC (1 << 6)
+
+-
+ /*
+ * RLMT specific definitions
+ */
+@@ -223,7 +216,17 @@
+ #define OID_SKGE_RLMT_PORT_NUMBER 0xFF010141
+ #define OID_SKGE_RLMT_PORT_ACTIVE 0xFF010142
+ #define OID_SKGE_RLMT_PORT_PREFERRED 0xFF010143
+-#define OID_SKGE_INTERMEDIATE_SUPPORT 0xFF010160
++
++#define OID_SKGE_RLMT_MONITOR_NUMBER 0xFF010150
++#define OID_SKGE_RLMT_MONITOR_INDEX 0xFF010151
++#define OID_SKGE_RLMT_MONITOR_ADDR 0xFF010152
++#define OID_SKGE_RLMT_MONITOR_ERRS 0xFF010153
++#define OID_SKGE_RLMT_MONITOR_TIMESTAMP 0xFF010154
++#define OID_SKGE_RLMT_MONITOR_ADMIN 0xFF010155
++
++#define OID_SKGE_INTERMEDIATE_SUPPORT 0xFF010160
++#define OID_SKGE_SET_TEAM_MAC_ADDRESS 0xFF010161
++#define OID_SKGE_DEVICE_INFORMATION 0xFF010162
+
+ #define OID_SKGE_SPEED_CAP 0xFF010170
+ #define OID_SKGE_SPEED_MODE 0xFF010171
+@@ -322,13 +325,6 @@
+ #define OID_SKGE_RLMT_TX_SP_REQ_CTS 0xFF020168
+ #define OID_SKGE_RLMT_RX_SP_CTS 0xFF020169
+
+-#define OID_SKGE_RLMT_MONITOR_NUMBER 0xFF010150
+-#define OID_SKGE_RLMT_MONITOR_INDEX 0xFF010151
+-#define OID_SKGE_RLMT_MONITOR_ADDR 0xFF010152
+-#define OID_SKGE_RLMT_MONITOR_ERRS 0xFF010153
+-#define OID_SKGE_RLMT_MONITOR_TIMESTAMP 0xFF010154
+-#define OID_SKGE_RLMT_MONITOR_ADMIN 0xFF010155
+-
+ #define OID_SKGE_TX_SW_QUEUE_LEN 0xFF020170
+ #define OID_SKGE_TX_SW_QUEUE_MAX 0xFF020171
+ #define OID_SKGE_TX_RETRY 0xFF020172
+@@ -352,6 +348,7 @@
+ #define OID_SKGE_VCT_GET 0xFF020200
+ #define OID_SKGE_VCT_SET 0xFF020201
+ #define OID_SKGE_VCT_STATUS 0xFF020202
++#define OID_SKGE_VCT_CAPABILITIES 0xFF020203
+
+ #ifdef SK_DIAG_SUPPORT
+ /* Defines for driver DIAG mode. */
+@@ -367,22 +364,79 @@
+ #define OID_SKGE_PHY_TYPE 0xFF020215
+ #define OID_SKGE_PHY_LP_MODE 0xFF020216
+
++/*
++ * Added for new DualNet IM driver V2
++ * these OIDs should later be in pnmi.h
++ */
++#define OID_SKGE_MAC_COUNT 0xFF020217
++#define OID_SKGE_DUALNET_MODE 0xFF020218
++#define OID_SKGE_SET_TAGHEADER 0xFF020219
++
++#ifdef SK_ASF
++/* Defines for ASF */
++#define OID_SKGE_ASF 0xFF02021a
++#define OID_SKGE_ASF_STORE_CONFIG 0xFF02021b
++#define OID_SKGE_ASF_ENA 0xFF02021c
++#define OID_SKGE_ASF_RETRANS 0xFF02021d
++#define OID_SKGE_ASF_RETRANS_INT 0xFF02021e
++#define OID_SKGE_ASF_HB_ENA 0xFF02021f
++#define OID_SKGE_ASF_HB_INT 0xFF020220
++#define OID_SKGE_ASF_WD_ENA 0xFF020221
++#define OID_SKGE_ASF_WD_TIME 0xFF020222
++#define OID_SKGE_ASF_IP_SOURCE 0xFF020223
++#define OID_SKGE_ASF_MAC_SOURCE 0xFF020224
++#define OID_SKGE_ASF_IP_DEST 0xFF020225
++#define OID_SKGE_ASF_MAC_DEST 0xFF020226
++#define OID_SKGE_ASF_COMMUNITY_NAME 0xFF020227
++#define OID_SKGE_ASF_RSP_ENA 0xFF020228
++#define OID_SKGE_ASF_RETRANS_COUNT_MIN 0xFF020229
++#define OID_SKGE_ASF_RETRANS_COUNT_MAX 0xFF02022a
++#define OID_SKGE_ASF_RETRANS_INT_MIN 0xFF02022b
++#define OID_SKGE_ASF_RETRANS_INT_MAX 0xFF02022c
++#define OID_SKGE_ASF_HB_INT_MIN 0xFF02022d
++#define OID_SKGE_ASF_HB_INT_MAX 0xFF02022e
++#define OID_SKGE_ASF_WD_TIME_MIN 0xFF02022f
++#define OID_SKGE_ASF_WD_TIME_MAX 0xFF020230
++#define OID_SKGE_ASF_HB_CAP 0xFF020231
++#define OID_SKGE_ASF_WD_TIMER_RES 0xFF020232
++#define OID_SKGE_ASF_GUID 0xFF020233
++#define OID_SKGE_ASF_KEY_OP 0xFF020234
++#define OID_SKGE_ASF_KEY_ADM 0xFF020235
++#define OID_SKGE_ASF_KEY_GEN 0xFF020236
++#define OID_SKGE_ASF_CAP 0xFF020237
++#define OID_SKGE_ASF_PAR_1 0xFF020238
++#define OID_SKGE_ASF_OVERALL_OID 0xFF020239
++#endif /* SK_ASF */
++
++
++// Defined for yukon2 path only
++#define OID_SKGE_UPPER_MINIPORT 0xFF02023D
++
++
++#ifdef SK_ASF
++/* Defines for ASF */
++#define OID_SKGE_ASF_FWVER_OID 0xFF020240
++#define OID_SKGE_ASF_ACPI_OID 0xFF020241
++#define OID_SKGE_ASF_SMBUS_OID 0xFF020242
++#endif /* SK_ASF */
++
++
+ /* VCT struct to store a backup copy of VCT data after a port reset. */
+ typedef struct s_PnmiVct {
+ SK_U8 VctStatus;
+- SK_U8 PCableLen;
+- SK_U32 PMdiPairLen[4];
+- SK_U8 PMdiPairSts[4];
++ SK_U8 CableLen;
++ SK_U32 MdiPairLen[4];
++ SK_U8 MdiPairSts[4];
+ } SK_PNMI_VCT;
+
+
+ /* VCT status values (to be given to CPA via OID_SKGE_VCT_STATUS). */
+-#define SK_PNMI_VCT_NONE 0
+-#define SK_PNMI_VCT_OLD_VCT_DATA 1
+-#define SK_PNMI_VCT_NEW_VCT_DATA 2
+-#define SK_PNMI_VCT_OLD_DSP_DATA 4
+-#define SK_PNMI_VCT_NEW_DSP_DATA 8
+-#define SK_PNMI_VCT_RUNNING 16
++#define SK_PNMI_VCT_NONE 0x00
++#define SK_PNMI_VCT_OLD_VCT_DATA 0x01
++#define SK_PNMI_VCT_NEW_VCT_DATA 0x02
++#define SK_PNMI_VCT_OLD_DSP_DATA 0x04
++#define SK_PNMI_VCT_NEW_DSP_DATA 0x08
++#define SK_PNMI_VCT_RUNNING 0x10
+
+
+ /* VCT cable test status. */
+@@ -390,7 +444,12 @@
+ #define SK_PNMI_VCT_SHORT_CABLE 1
+ #define SK_PNMI_VCT_OPEN_CABLE 2
+ #define SK_PNMI_VCT_TEST_FAIL 3
+-#define SK_PNMI_VCT_IMPEDANCE_MISMATCH 4
++#define SK_PNMI_VCT_IMPEDANCE_MISMATCH 4
++#define SK_PNMI_VCT_NOT_PRESENT 5
++
++/* VCT capabilities (needed for OID_SKGE_VCT_CAPABILITIES. */
++#define SK_PNMI_VCT_SUPPORTED 1
++#define SK_PNMI_VCT_NOT_SUPPORTED 0
+
+ #define OID_SKGE_TRAP_SEN_WAR_LOW 500
+ #define OID_SKGE_TRAP_SEN_WAR_UPP 501
+@@ -419,7 +478,6 @@
+ #define SK_SET_FULL_MIB 5
+ #define SK_PRESET_FULL_MIB 6
+
+-
+ /*
+ * Define error numbers and messages for syslog
+ */
+@@ -452,7 +510,7 @@
+ #define SK_PNMI_ERR014 (SK_ERRBASE_PNMI + 14)
+ #define SK_PNMI_ERR014MSG "Vpd: Cannot read VPD keys"
+ #define SK_PNMI_ERR015 (SK_ERRBASE_PNMI + 15)
+-#define SK_PNMI_ERR015MSG "Vpd: Internal array for VPD keys to small"
++#define SK_PNMI_ERR015MSG "Vpd: Internal array for VPD keys too small"
+ #define SK_PNMI_ERR016 (SK_ERRBASE_PNMI + 16)
+ #define SK_PNMI_ERR016MSG "Vpd: Key string too long"
+ #define SK_PNMI_ERR017 (SK_ERRBASE_PNMI + 17)
+@@ -494,9 +552,9 @@
+ #define SK_PNMI_ERR036 (SK_ERRBASE_PNMI + 36)
+ #define SK_PNMI_ERR036MSG ""
+ #define SK_PNMI_ERR037 (SK_ERRBASE_PNMI + 37)
+-#define SK_PNMI_ERR037MSG "Rlmt: SK_RLMT_MODE_CHANGE event return not 0"
++#define SK_PNMI_ERR037MSG "Rlmt: SK_RLMT_MODE_CHANGE event returned not 0"
+ #define SK_PNMI_ERR038 (SK_ERRBASE_PNMI + 38)
+-#define SK_PNMI_ERR038MSG "Rlmt: SK_RLMT_PREFPORT_CHANGE event return not 0"
++#define SK_PNMI_ERR038MSG "Rlmt: SK_RLMT_PREFPORT_CHANGE event returned not 0"
+ #define SK_PNMI_ERR039 (SK_ERRBASE_PNMI + 39)
+ #define SK_PNMI_ERR039MSG "RlmtStat: Unknown OID"
+ #define SK_PNMI_ERR040 (SK_ERRBASE_PNMI + 40)
+@@ -514,9 +572,9 @@
+ #define SK_PNMI_ERR046 (SK_ERRBASE_PNMI + 46)
+ #define SK_PNMI_ERR046MSG "Monitor: Unknown OID"
+ #define SK_PNMI_ERR047 (SK_ERRBASE_PNMI + 47)
+-#define SK_PNMI_ERR047MSG "SirqUpdate: Event function returns not 0"
++#define SK_PNMI_ERR047MSG "SirqUpdate: Event function returned not 0"
+ #define SK_PNMI_ERR048 (SK_ERRBASE_PNMI + 48)
+-#define SK_PNMI_ERR048MSG "RlmtUpdate: Event function returns not 0"
++#define SK_PNMI_ERR048MSG "RlmtUpdate: Event function returned not 0"
+ #define SK_PNMI_ERR049 (SK_ERRBASE_PNMI + 49)
+ #define SK_PNMI_ERR049MSG "SkPnmiInit: Invalid size of 'CounterOffset' struct!!"
+ #define SK_PNMI_ERR050 (SK_ERRBASE_PNMI + 50)
+@@ -826,23 +884,25 @@
+ } SK_PNMI_STRUCT_DATA;
+
+ #define SK_PNMI_STRUCT_SIZE (sizeof(SK_PNMI_STRUCT_DATA))
++
++/* The ReturnStatus field must be located before VpdFreeBytes! */
+ #define SK_PNMI_MIN_STRUCT_SIZE ((unsigned int)(SK_UPTR)\
+ &(((SK_PNMI_STRUCT_DATA *)0)->VpdFreeBytes))
+- /*
+- * ReturnStatus field
+- * must be located
+- * before VpdFreeBytes
+- */
+
+ /*
+ * Various definitions
+ */
++#define SK_PNMI_EVT_TIMER_CHECK 28125000L /* 28125 ms */
++
++#define SK_PNMI_VCT_TIMER_CHECK 4000000L /* 4 sec. */
++
+ #define SK_PNMI_MAX_PROTOS 3
+
+-#define SK_PNMI_CNT_NO 66 /* Must have the value of the enum
+- * SK_PNMI_MAX_IDX. Define SK_PNMI_CHECK
+- * for check while init phase 1
+- */
++/*
++ * SK_PNMI_CNT_NO must have the value of the enum SK_PNMI_MAX_IDX.
++ * Define SK_PNMI_CHECK to check this during init level SK_INIT_IO.
++ */
++#define SK_PNMI_CNT_NO 66
+
+ /*
+ * Estimate data structure
+@@ -856,14 +916,6 @@
+
+
+ /*
+- * VCT timer data structure
+- */
+-typedef struct s_VctTimer {
+- SK_TIMER VctTimer;
+-} SK_PNMI_VCT_TIMER;
+-
+-
+-/*
+ * PNMI specific adapter context structure
+ */
+ typedef struct s_PnmiPort {
+@@ -933,12 +985,13 @@
+ unsigned int TrapQueueEnd;
+ unsigned int TrapBufPad;
+ unsigned int TrapUnique;
+- SK_U8 VctStatus[SK_MAX_MACS];
+- SK_PNMI_VCT VctBackup[SK_MAX_MACS];
+- SK_PNMI_VCT_TIMER VctTimeout[SK_MAX_MACS];
++ SK_U8 VctStatus[SK_MAX_MACS];
++ SK_PNMI_VCT VctBackup[SK_MAX_MACS];
++ SK_TIMER VctTimeout[SK_MAX_MACS];
+ #ifdef SK_DIAG_SUPPORT
+ SK_U32 DiagAttached;
+ #endif /* SK_DIAG_SUPPORT */
++ SK_BOOL VpdKeyReadError;
+ } SK_PNMI;
+
+
+diff -ruN linux/drivers/net/sk98lin/h/skgesirq.h linux-new/drivers/net/sk98lin/h/skgesirq.h
+--- linux/drivers/net/sk98lin/h/skgesirq.h 2005-09-26 13:32:48.000000000 +0400
++++ linux-new/drivers/net/sk98lin/h/skgesirq.h 2005-08-09 17:15:51.000000000 +0400
+@@ -2,22 +2,21 @@
+ *
+ * Name: skgesirq.h
+ * Project: Gigabit Ethernet Adapters, Common Modules
+- * Version: $Revision: 1.30 $
+- * Date: $Date: 2003/07/04 12:34:13 $
+- * Purpose: SK specific Gigabit Ethernet special IRQ functions
++ * Version: $Revision: 2.4 $
++ * Date: $Date: 2005/07/14 10:28:34 $
++ * Purpose: Gigabit Ethernet special IRQ functions
+ *
+ ******************************************************************************/
+
+ /******************************************************************************
+ *
+ * (C)Copyright 1998-2002 SysKonnect.
+- * (C)Copyright 2002-2003 Marvell.
++ * (C)Copyright 2002-2005 Marvell.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+- *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+@@ -26,9 +25,9 @@
+ #define _INC_SKGESIRQ_H_
+
+ /* Define return codes of SkGePortCheckUp and CheckShort */
+-#define SK_HW_PS_NONE 0 /* No action needed */
+-#define SK_HW_PS_RESTART 1 /* Restart needed */
+-#define SK_HW_PS_LINK 2 /* Link Up actions needed */
++#define SK_HW_PS_NONE 0 /* No action needed */
++#define SK_HW_PS_RESTART 1 /* Restart needed */
++#define SK_HW_PS_LINK 2 /* Link Up actions needed */
+
+ /*
+ * Define the Event the special IRQ/INI module can handle
+@@ -44,10 +43,10 @@
+ #define SK_HWEV_SET_SPEED 9 /* Set Link Speed by PNMI */
+ #define SK_HWEV_HALFDUP_CHK 10 /* Half Duplex Hangup Workaround */
+
+-#define SK_WA_ACT_TIME (5000000UL) /* 5 sec */
+-#define SK_WA_INA_TIME (100000UL) /* 100 msec */
++#define SK_WA_ACT_TIME 1000000UL /* 1000 msec (1 sec) */
++#define SK_WA_INA_TIME 100000UL /* 100 msec */
+
+-#define SK_HALFDUP_CHK_TIME (10000UL) /* 10 msec */
++#define SK_HALFDUP_CHK_TIME 10000UL /* 10 msec */
+
+ /*
+ * Define the error numbers and messages
+@@ -75,9 +74,9 @@
+ #define SKERR_SIRQ_E011 (SKERR_SIRQ_E010+1)
+ #define SKERR_SIRQ_E011MSG "CHECK failure XA2"
+ #define SKERR_SIRQ_E012 (SKERR_SIRQ_E011+1)
+-#define SKERR_SIRQ_E012MSG "unexpected IRQ Master error"
++#define SKERR_SIRQ_E012MSG "Unexpected IRQ Master error"
+ #define SKERR_SIRQ_E013 (SKERR_SIRQ_E012+1)
+-#define SKERR_SIRQ_E013MSG "unexpected IRQ Status error"
++#define SKERR_SIRQ_E013MSG "Unexpected IRQ Status error"
+ #define SKERR_SIRQ_E014 (SKERR_SIRQ_E013+1)
+ #define SKERR_SIRQ_E014MSG "Parity error on RAM (read)"
+ #define SKERR_SIRQ_E015 (SKERR_SIRQ_E014+1)
+@@ -102,10 +101,35 @@
+ #define SKERR_SIRQ_E024MSG "FIFO overflow error"
+ #define SKERR_SIRQ_E025 (SKERR_SIRQ_E024+1)
+ #define SKERR_SIRQ_E025MSG "2 Pair Downshift detected"
++#define SKERR_SIRQ_E026 (SKERR_SIRQ_E025+1)
++#define SKERR_SIRQ_E026MSG "Uncorrectable PCI Express error"
++#define SKERR_SIRQ_E027 (SKERR_SIRQ_E026+1)
++#define SKERR_SIRQ_E027MSG "PCI Bus Abort detected"
++#define SKERR_SIRQ_E028 (SKERR_SIRQ_E027+1)
++#define SKERR_SIRQ_E028MSG "Parity error on RAM 1 (read)"
++#define SKERR_SIRQ_E029 (SKERR_SIRQ_E028+1)
++#define SKERR_SIRQ_E029MSG "Parity error on RAM 1 (write)"
++#define SKERR_SIRQ_E030 (SKERR_SIRQ_E029+1)
++#define SKERR_SIRQ_E030MSG "Parity error on RAM 2 (read)"
++#define SKERR_SIRQ_E031 (SKERR_SIRQ_E030+1)
++#define SKERR_SIRQ_E031MSG "Parity error on RAM 2 (write)"
++#define SKERR_SIRQ_E032 (SKERR_SIRQ_E031+1)
++#define SKERR_SIRQ_E032MSG "TCP segmentation error async. queue 1"
++#define SKERR_SIRQ_E033 (SKERR_SIRQ_E032+1)
++#define SKERR_SIRQ_E033MSG "TCP segmentation error sync. queue 1"
++#define SKERR_SIRQ_E034 (SKERR_SIRQ_E033+1)
++#define SKERR_SIRQ_E034MSG "TCP segmentation error async. queue 2"
++#define SKERR_SIRQ_E035 (SKERR_SIRQ_E034+1)
++#define SKERR_SIRQ_E035MSG "TCP segmentation error sync. queue 2"
++#define SKERR_SIRQ_E036 (SKERR_SIRQ_E035+1)
++#define SKERR_SIRQ_E036MSG "CHECK failure polling unit"
+
+ extern void SkGeSirqIsr(SK_AC *pAC, SK_IOC IoC, SK_U32 Istatus);
+ extern int SkGeSirqEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event, SK_EVPARA Para);
+ extern void SkHWLinkUp(SK_AC *pAC, SK_IOC IoC, int Port);
+ extern void SkHWLinkDown(SK_AC *pAC, SK_IOC IoC, int Port);
++extern void SkGeYuSirqIsr(SK_AC *pAC, SK_IOC IoC, SK_U32 Istatus);
++extern void SkYuk2SirqIsr(SK_AC *pAC, SK_IOC IoC, SK_U32 Istatus);
+
+ #endif /* _INC_SKGESIRQ_H_ */
++
+diff -ruN linux/drivers/net/sk98lin/h/skgetwsi.h linux-new/drivers/net/sk98lin/h/skgetwsi.h
+--- linux/drivers/net/sk98lin/h/skgetwsi.h 1970-01-01 03:00:00.000000000 +0300
++++ linux-new/drivers/net/sk98lin/h/skgetwsi.h 2005-08-09 17:15:51.000000000 +0400
+@@ -0,0 +1,241 @@
++/******************************************************************************
++ *
++ * Name: skgetwsi.h
++ * Project: Gigabit Ethernet Adapters, TWSI-Module
++ * Version: $Revision: 1.7 $
++ * Date: $Date: 2004/12/20 14:48:51 $
++ * Purpose: Special defines for TWSI
++ *
++ ******************************************************************************/
++
++/******************************************************************************
++ *
++ * (C)Copyright 1998-2002 SysKonnect.
++ * (C)Copyright 2002-2004 Marvell.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ * The information in this file is provided "AS IS" without warranty.
++ *
++ ******************************************************************************/
++
++/*
++ * SKGETWSI.H contains all SK-98xx specific defines for the TWSI handling
++ */
++
++#ifndef _INC_SKGETWSI_H_
++#define _INC_SKGETWSI_H_
++
++/*
++ * Macros to access the B2_I2C_CTRL
++ */
++#define SK_I2C_CTL(IoC, flag, dev, dev_size, reg, burst) \
++ SK_OUT32(IoC, B2_I2C_CTRL,\
++ (flag ? 0x80000000UL : 0x0L) | \
++ (((SK_U32)reg << 16) & I2C_ADDR) | \
++ (((SK_U32)dev << 9) & I2C_DEV_SEL) | \
++ (dev_size & I2C_DEV_SIZE) | \
++ ((burst << 4) & I2C_BURST_LEN))
++
++#define SK_I2C_STOP(IoC) { \
++ SK_U32 I2cCtrl; \
++ SK_IN32(IoC, B2_I2C_CTRL, &I2cCtrl); \
++ SK_OUT32(IoC, B2_I2C_CTRL, I2cCtrl | I2C_STOP); \
++}
++
++#define SK_I2C_GET_CTL(IoC, pI2cCtrl) SK_IN32(IoC, B2_I2C_CTRL, pI2cCtrl)
++
++/*
++ * Macros to access the TWSI SW Registers
++ */
++#define SK_I2C_SET_BIT(IoC, SetBits) { \
++ SK_U8 OrgBits; \
++ SK_IN8(IoC, B2_I2C_SW, &OrgBits); \
++ SK_OUT8(IoC, B2_I2C_SW, OrgBits | (SK_U8)(SetBits)); \
++}
++
++#define SK_I2C_CLR_BIT(IoC, ClrBits) { \
++ SK_U8 OrgBits; \
++ SK_IN8(IoC, B2_I2C_SW, &OrgBits); \
++ SK_OUT8(IoC, B2_I2C_SW, OrgBits & ~((SK_U8)(ClrBits))); \
++}
++
++#define SK_I2C_GET_SW(IoC, pI2cSw) SK_IN8(IoC, B2_I2C_SW, pI2cSw)
++
++/*
++ * define the possible sensor states
++ */
++#define SK_SEN_IDLE 0 /* Idle: sensor not read */
++#define SK_SEN_VALUE 1 /* Value Read cycle */
++#define SK_SEN_VALEXT 2 /* Extended Value Read cycle */
++
++/*
++ * Conversion factor to convert read Voltage sensor to milli Volt
++ * Conversion factor to convert read Temperature sensor to 10th degree Celsius
++ */
++#define SK_LM80_VT_LSB 22 /* 22mV LSB resolution */
++#define SK_LM80_TEMP_LSB 10 /* 1 degree LSB resolution */
++#define SK_LM80_TEMPEXT_LSB 5 /* 0.5 degree LSB resolution for ext. val. */
++
++/*
++ * formula: counter = (22500*60)/(rpm * divisor * pulses/2)
++ * assuming: 6500rpm, 4 pulses, divisor 1
++ */
++#define SK_LM80_FAN_FAKTOR ((22500L*60)/(1*2))
++
++/*
++ * Define sensor management data
++ * Maximum is reached on Genesis copper dual port and Yukon-64
++ * Board specific maximum is in pAC->I2c.MaxSens
++ */
++#define SK_MAX_SENSORS 8 /* maximal no. of installed sensors */
++#define SK_MIN_SENSORS 5 /* minimal no. of installed sensors */
++
++/*
++ * To watch the state machine (SM) use the timer in two ways
++ * instead of one as hitherto
++ */
++#define SK_TIMER_WATCH_SM 0 /* Watch the SM to finish in a spec. time */
++#define SK_TIMER_NEW_GAUGING 1 /* Start a new gauging when timer expires */
++
++/*
++ * Defines for the individual thresholds
++ */
++
++#define C_PLUS_20 120 / 100
++#define C_PLUS_15 115 / 100
++#define C_PLUS_10 110 / 100
++#define C_PLUS_5 105 / 100
++#define C_MINUS_5 95 / 100
++#define C_MINUS_10 90 / 100
++#define C_MINUS_15 85 / 100
++
++/* Temperature sensor */
++#define SK_SEN_TEMP_HIGH_ERR 800 /* Temperature High Err Threshold */
++#define SK_SEN_TEMP_HIGH_WARN 700 /* Temperature High Warn Threshold */
++#define SK_SEN_TEMP_LOW_WARN 100 /* Temperature Low Warn Threshold */
++#define SK_SEN_TEMP_LOW_ERR 0 /* Temperature Low Err Threshold */
++
++/* VCC which should be 5 V */
++#define SK_SEN_PCI_5V_HIGH_ERR 5588 /* Voltage PCI High Err Threshold */
++#define SK_SEN_PCI_5V_HIGH_WARN 5346 /* Voltage PCI High Warn Threshold */
++#define SK_SEN_PCI_5V_LOW_WARN 4664 /* Voltage PCI Low Warn Threshold */
++#define SK_SEN_PCI_5V_LOW_ERR 4422 /* Voltage PCI Low Err Threshold */
++
++/*
++ * VIO may be 5 V or 3.3 V. Initialization takes two parts:
++ * 1. Initialize lowest lower limit and highest higher limit.
++ * 2. After the first value is read correct the upper or the lower limit to
++ * the appropriate C constant.
++ *
++ * Warning limits are +-5% of the exepected voltage.
++ * Error limits are +-10% of the expected voltage.
++ */
++
++/* Bug fix AF: 16.Aug.2001: Correct the init base of LM80 sensor */
++
++#define SK_SEN_PCI_IO_5V_HIGH_ERR 5566 /* + 10% V PCI-IO High Err Threshold */
++#define SK_SEN_PCI_IO_5V_HIGH_WARN 5324 /* + 5% V PCI-IO High Warn Threshold */
++ /* 5000 mVolt */
++#define SK_SEN_PCI_IO_5V_LOW_WARN 4686 /* - 5% V PCI-IO Low Warn Threshold */
++#define SK_SEN_PCI_IO_5V_LOW_ERR 4444 /* - 10% V PCI-IO Low Err Threshold */
++
++#define SK_SEN_PCI_IO_RANGE_LIMITER 4000 /* 4000 mV range delimiter */
++
++/* correction values for the second pass */
++#define SK_SEN_PCI_IO_3V3_HIGH_ERR 3850 /* + 15% V PCI-IO High Err Threshold */
++#define SK_SEN_PCI_IO_3V3_HIGH_WARN 3674 /* + 10% V PCI-IO High Warn Threshold */
++ /* 3300 mVolt */
++#define SK_SEN_PCI_IO_3V3_LOW_WARN 2926 /* - 10% V PCI-IO Low Warn Threshold */
++#define SK_SEN_PCI_IO_3V3_LOW_ERR 2772 /* - 15% V PCI-IO Low Err Threshold */
++
++/*
++ * VDD voltage
++ */
++#define SK_SEN_VDD_HIGH_ERR 3630 /* Voltage ASIC High Err Threshold */
++#define SK_SEN_VDD_HIGH_WARN 3476 /* Voltage ASIC High Warn Threshold */
++#define SK_SEN_VDD_LOW_WARN 3146 /* Voltage ASIC Low Warn Threshold */
++#define SK_SEN_VDD_LOW_ERR 2970 /* Voltage ASIC Low Err Threshold */
++
++/*
++ * PHY PLL 3V3 voltage
++ */
++#define SK_SEN_PLL_3V3_HIGH_ERR 3630 /* Voltage PMA High Err Threshold */
++#define SK_SEN_PLL_3V3_HIGH_WARN 3476 /* Voltage PMA High Warn Threshold */
++#define SK_SEN_PLL_3V3_LOW_WARN 3146 /* Voltage PMA Low Warn Threshold */
++#define SK_SEN_PLL_3V3_LOW_ERR 2970 /* Voltage PMA Low Err Threshold */
++
++/*
++ * VAUX (YUKON only)
++ */
++#define SK_SEN_VAUX_3V3_VAL 3300 /* Voltage VAUX 3.3 Volt */
++
++#define SK_SEN_VAUX_3V3_HIGH_ERR (SK_I32)(SK_SEN_VAUX_3V3_VAL * C_PLUS_10)
++#define SK_SEN_VAUX_3V3_HIGH_WARN (SK_I32)(SK_SEN_VAUX_3V3_VAL * C_PLUS_5)
++#define SK_SEN_VAUX_3V3_LOW_WARN (SK_I32)(SK_SEN_VAUX_3V3_VAL * C_MINUS_5)
++#define SK_SEN_VAUX_3V3_LOW_ERR (SK_I32)(SK_SEN_VAUX_3V3_VAL * C_MINUS_10)
++
++#define SK_SEN_VAUX_RANGE_LIMITER 1000 /* 1000 mV range delimiter */
++
++/*
++ * PHY 2V5 voltage
++ */
++#define SK_SEN_PHY_2V5_VAL 2500 /* Voltage PHY 2.5 Volt */
++
++#define SK_SEN_PHY_2V5_HIGH_ERR (SK_I32)(SK_SEN_PHY_2V5_VAL * C_PLUS_10)
++#define SK_SEN_PHY_2V5_HIGH_WARN (SK_I32)(SK_SEN_PHY_2V5_VAL * C_PLUS_5)
++#define SK_SEN_PHY_2V5_LOW_WARN (SK_I32)(SK_SEN_PHY_2V5_VAL * C_MINUS_5)
++#define SK_SEN_PHY_2V5_LOW_ERR (SK_I32)(SK_SEN_PHY_2V5_VAL * C_MINUS_10)
++
++/*
++ * ASIC Core 1V5 voltage (YUKON only)
++ */
++#define SK_SEN_CORE_1V5_VAL 1500 /* Voltage ASIC Core 1.5 Volt */
++
++#define SK_SEN_CORE_1V5_HIGH_ERR (SK_I32)(SK_SEN_CORE_1V5_VAL * C_PLUS_10)
++#define SK_SEN_CORE_1V5_HIGH_WARN (SK_I32)(SK_SEN_CORE_1V5_VAL * C_PLUS_5)
++#define SK_SEN_CORE_1V5_LOW_WARN (SK_I32)(SK_SEN_CORE_1V5_VAL * C_MINUS_5)
++#define SK_SEN_CORE_1V5_LOW_ERR (SK_I32)(SK_SEN_CORE_1V5_VAL * C_MINUS_10)
++
++/*
++ * ASIC Core 1V2 (1V3) voltage (YUKON-2 only)
++ */
++#define SK_SEN_CORE_1V2_VAL 1200 /* Voltage ASIC Core 1.2 Volt */
++
++#define SK_SEN_CORE_1V2_HIGH_ERR (SK_I32)(SK_SEN_CORE_1V2_VAL * C_PLUS_20)
++#define SK_SEN_CORE_1V2_HIGH_WARN (SK_I32)(SK_SEN_CORE_1V2_VAL * C_PLUS_15)
++#define SK_SEN_CORE_1V2_LOW_WARN (SK_I32)(SK_SEN_CORE_1V2_VAL * C_MINUS_5)
++#define SK_SEN_CORE_1V2_LOW_ERR (SK_I32)(SK_SEN_CORE_1V2_VAL * C_MINUS_10)
++
++#define SK_SEN_CORE_1V3_VAL 1300 /* Voltage ASIC Core 1.3 Volt */
++
++#define SK_SEN_CORE_1V3_HIGH_ERR (SK_I32)(SK_SEN_CORE_1V3_VAL * C_PLUS_15)
++#define SK_SEN_CORE_1V3_HIGH_WARN (SK_I32)(SK_SEN_CORE_1V3_VAL * C_PLUS_10)
++#define SK_SEN_CORE_1V3_LOW_WARN (SK_I32)(SK_SEN_CORE_1V3_VAL * C_MINUS_5)
++#define SK_SEN_CORE_1V3_LOW_ERR (SK_I32)(SK_SEN_CORE_1V3_VAL * C_MINUS_10)
++
++/*
++ * FAN 1 speed
++ */
++/* assuming: 6500rpm +-15%, 4 pulses,
++ * warning at: 80 %
++ * error at: 70 %
++ * no upper limit
++ */
++#define SK_SEN_FAN_HIGH_ERR 20000 /* FAN Speed High Err Threshold */
++#define SK_SEN_FAN_HIGH_WARN 20000 /* FAN Speed High Warn Threshold */
++#define SK_SEN_FAN_LOW_WARN 5200 /* FAN Speed Low Warn Threshold */
++#define SK_SEN_FAN_LOW_ERR 4550 /* FAN Speed Low Err Threshold */
++
++/*
++ * Some Voltages need dynamic thresholds
++ */
++#define SK_SEN_DYN_INIT_NONE 0 /* No dynamic init of thresholds */
++#define SK_SEN_DYN_INIT_PCI_IO 10 /* Init PCI-IO with new thresholds */
++#define SK_SEN_DYN_INIT_VAUX 11 /* Init VAUX with new thresholds */
++
++extern int SkLm80ReadSensor(SK_AC *pAC, SK_IOC IoC, SK_SENSOR *pSen);
++#endif /* n_INC_SKGETWSI_H */
++
+diff -ruN linux/drivers/net/sk98lin/h/ski2c.h linux-new/drivers/net/sk98lin/h/ski2c.h
+--- linux/drivers/net/sk98lin/h/ski2c.h 2005-09-26 13:32:47.000000000 +0400
++++ linux-new/drivers/net/sk98lin/h/ski2c.h 1970-01-01 03:00:00.000000000 +0300
+@@ -1,177 +0,0 @@
+-/******************************************************************************
+- *
+- * Name: ski2c.h
+- * Project: Gigabit Ethernet Adapters, TWSI-Module
+- * Version: $Revision: 1.35 $
+- * Date: $Date: 2003/10/20 09:06:30 $
+- * Purpose: Defines to access Voltage and Temperature Sensor
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * (C)Copyright 1998-2002 SysKonnect.
+- * (C)Copyright 2002-2003 Marvell.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-/*
+- * SKI2C.H contains all I2C specific defines
+- */
+-
+-#ifndef _SKI2C_H_
+-#define _SKI2C_H_
+-
+-typedef struct s_Sensor SK_SENSOR;
+-
+-#include "h/skgei2c.h"
+-
+-/*
+- * Define the I2C events.
+- */
+-#define SK_I2CEV_IRQ 1 /* IRQ happened Event */
+-#define SK_I2CEV_TIM 2 /* Timeout event */
+-#define SK_I2CEV_CLEAR 3 /* Clear MIB Values */
+-
+-/*
+- * Define READ and WRITE Constants.
+- */
+-#define I2C_READ 0
+-#define I2C_WRITE 1
+-#define I2C_BURST 1
+-#define I2C_SINGLE 0
+-
+-#define SKERR_I2C_E001 (SK_ERRBASE_I2C+0)
+-#define SKERR_I2C_E001MSG "Sensor index unknown"
+-#define SKERR_I2C_E002 (SKERR_I2C_E001+1)
+-#define SKERR_I2C_E002MSG "TWSI: transfer does not complete"
+-#define SKERR_I2C_E003 (SKERR_I2C_E002+1)
+-#define SKERR_I2C_E003MSG "LM80: NAK on device send"
+-#define SKERR_I2C_E004 (SKERR_I2C_E003+1)
+-#define SKERR_I2C_E004MSG "LM80: NAK on register send"
+-#define SKERR_I2C_E005 (SKERR_I2C_E004+1)
+-#define SKERR_I2C_E005MSG "LM80: NAK on device (2) send"
+-#define SKERR_I2C_E006 (SKERR_I2C_E005+1)
+-#define SKERR_I2C_E006MSG "Unknown event"
+-#define SKERR_I2C_E007 (SKERR_I2C_E006+1)
+-#define SKERR_I2C_E007MSG "LM80 read out of state"
+-#define SKERR_I2C_E008 (SKERR_I2C_E007+1)
+-#define SKERR_I2C_E008MSG "Unexpected sensor read completed"
+-#define SKERR_I2C_E009 (SKERR_I2C_E008+1)
+-#define SKERR_I2C_E009MSG "WARNING: temperature sensor out of range"
+-#define SKERR_I2C_E010 (SKERR_I2C_E009+1)
+-#define SKERR_I2C_E010MSG "WARNING: voltage sensor out of range"
+-#define SKERR_I2C_E011 (SKERR_I2C_E010+1)
+-#define SKERR_I2C_E011MSG "ERROR: temperature sensor out of range"
+-#define SKERR_I2C_E012 (SKERR_I2C_E011+1)
+-#define SKERR_I2C_E012MSG "ERROR: voltage sensor out of range"
+-#define SKERR_I2C_E013 (SKERR_I2C_E012+1)
+-#define SKERR_I2C_E013MSG "ERROR: couldn't init sensor"
+-#define SKERR_I2C_E014 (SKERR_I2C_E013+1)
+-#define SKERR_I2C_E014MSG "WARNING: fan sensor out of range"
+-#define SKERR_I2C_E015 (SKERR_I2C_E014+1)
+-#define SKERR_I2C_E015MSG "ERROR: fan sensor out of range"
+-#define SKERR_I2C_E016 (SKERR_I2C_E015+1)
+-#define SKERR_I2C_E016MSG "TWSI: active transfer does not complete"
+-
+-/*
+- * Define Timeout values
+- */
+-#define SK_I2C_TIM_LONG 2000000L /* 2 seconds */
+-#define SK_I2C_TIM_SHORT 100000L /* 100 milliseconds */
+-#define SK_I2C_TIM_WATCH 1000000L /* 1 second */
+-
+-/*
+- * Define trap and error log hold times
+- */
+-#ifndef SK_SEN_ERR_TR_HOLD
+-#define SK_SEN_ERR_TR_HOLD (4*SK_TICKS_PER_SEC)
+-#endif
+-#ifndef SK_SEN_ERR_LOG_HOLD
+-#define SK_SEN_ERR_LOG_HOLD (60*SK_TICKS_PER_SEC)
+-#endif
+-#ifndef SK_SEN_WARN_TR_HOLD
+-#define SK_SEN_WARN_TR_HOLD (15*SK_TICKS_PER_SEC)
+-#endif
+-#ifndef SK_SEN_WARN_LOG_HOLD
+-#define SK_SEN_WARN_LOG_HOLD (15*60*SK_TICKS_PER_SEC)
+-#endif
+-
+-/*
+- * Defines for SenType
+- */
+-#define SK_SEN_UNKNOWN 0
+-#define SK_SEN_TEMP 1
+-#define SK_SEN_VOLT 2
+-#define SK_SEN_FAN 3
+-
+-/*
+- * Define for the SenErrorFlag
+- */
+-#define SK_SEN_ERR_NOT_PRESENT 0 /* Error Flag: Sensor not present */
+-#define SK_SEN_ERR_OK 1 /* Error Flag: O.K. */
+-#define SK_SEN_ERR_WARN 2 /* Error Flag: Warning */
+-#define SK_SEN_ERR_ERR 3 /* Error Flag: Error */
+-#define SK_SEN_ERR_FAULTY 4 /* Error Flag: Faulty */
+-
+-/*
+- * Define the Sensor struct
+- */
+-struct s_Sensor {
+- char *SenDesc; /* Description */
+- int SenType; /* Voltage or Temperature */
+- SK_I32 SenValue; /* Current value of the sensor */
+- SK_I32 SenThreErrHigh; /* High error Threshhold of this sensor */
+- SK_I32 SenThreWarnHigh; /* High warning Threshhold of this sensor */
+- SK_I32 SenThreErrLow; /* Lower error Threshold of the sensor */
+- SK_I32 SenThreWarnLow; /* Lower warning Threshold of the sensor */
+- int SenErrFlag; /* Sensor indicated an error */
+- SK_BOOL SenInit; /* Is sensor initialized ? */
+- SK_U64 SenErrCts; /* Error trap counter */
+- SK_U64 SenWarnCts; /* Warning trap counter */
+- SK_U64 SenBegErrTS; /* Begin error timestamp */
+- SK_U64 SenBegWarnTS; /* Begin warning timestamp */
+- SK_U64 SenLastErrTrapTS; /* Last error trap timestamp */
+- SK_U64 SenLastErrLogTS; /* Last error log timestamp */
+- SK_U64 SenLastWarnTrapTS; /* Last warning trap timestamp */
+- SK_U64 SenLastWarnLogTS; /* Last warning log timestamp */
+- int SenState; /* Sensor State (see HW specific include) */
+- int (*SenRead)(SK_AC *pAC, SK_IOC IoC, struct s_Sensor *pSen);
+- /* Sensors read function */
+- SK_U16 SenReg; /* Register Address for this sensor */
+- SK_U8 SenDev; /* Device Selection for this sensor */
+-};
+-
+-typedef struct s_I2c {
+- SK_SENSOR SenTable[SK_MAX_SENSORS]; /* Sensor Table */
+- int CurrSens; /* Which sensor is currently queried */
+- int MaxSens; /* Max. number of sensors */
+- int TimerMode; /* Use the timer also to watch the state machine */
+- int InitLevel; /* Initialized Level */
+-#ifndef SK_DIAG
+- int DummyReads; /* Number of non-checked dummy reads */
+- SK_TIMER SenTimer; /* Sensors timer */
+-#endif /* !SK_DIAG */
+-} SK_I2C;
+-
+-extern int SkI2cInit(SK_AC *pAC, SK_IOC IoC, int Level);
+-extern int SkI2cWrite(SK_AC *pAC, SK_IOC IoC, SK_U32 Data, int Dev, int Size,
+- int Reg, int Burst);
+-extern int SkI2cReadSensor(SK_AC *pAC, SK_IOC IoC, SK_SENSOR *pSen);
+-#ifdef SK_DIAG
+-extern SK_U32 SkI2cRead(SK_AC *pAC, SK_IOC IoC, int Dev, int Size, int Reg,
+- int Burst);
+-#else /* !SK_DIAG */
+-extern int SkI2cEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event, SK_EVPARA Para);
+-extern void SkI2cWaitIrq(SK_AC *pAC, SK_IOC IoC);
+-extern void SkI2cIsr(SK_AC *pAC, SK_IOC IoC);
+-#endif /* !SK_DIAG */
+-#endif /* n_SKI2C_H */
+-
+diff -ruN linux/drivers/net/sk98lin/h/skqueue.h linux-new/drivers/net/sk98lin/h/skqueue.h
+--- linux/drivers/net/sk98lin/h/skqueue.h 2005-09-26 13:32:48.000000000 +0400
++++ linux-new/drivers/net/sk98lin/h/skqueue.h 2005-08-09 17:15:51.000000000 +0400
+@@ -2,8 +2,8 @@
+ *
+ * Name: skqueue.h
+ * Project: Gigabit Ethernet Adapters, Event Scheduler Module
+- * Version: $Revision: 1.16 $
+- * Date: $Date: 2003/09/16 12:50:32 $
++ * Version: $Revision: 2.3 $
++ * Date: $Date: 2004/05/14 13:39:15 $
+ * Purpose: Defines for the Event queue
+ *
+ ******************************************************************************/
+@@ -45,6 +45,9 @@
+ #define SKGE_RSF 11 /* RSF Aggregation Event Class */
+ #define SKGE_MARKER 12 /* MARKER Aggregation Event Class */
+ #define SKGE_FD 13 /* FD Distributor Event Class */
++#ifdef SK_ASF
++#define SKGE_ASF 14 /* ASF Event Class */
++#endif
+
+ /*
+ * define event queue as circular buffer
+@@ -90,5 +93,11 @@
+ #define SKERR_Q_E001MSG "Event queue overflow"
+ #define SKERR_Q_E002 (SKERR_Q_E001+1)
+ #define SKERR_Q_E002MSG "Undefined event class"
++#define SKERR_Q_E003 (SKERR_Q_E001+2)
++#define SKERR_Q_E003MSG "Event queued in Init Level 0"
++#define SKERR_Q_E004 (SKERR_Q_E001+3)
++#define SKERR_Q_E004MSG "Error Reported from Event Fuction (Queue Blocked)"
++#define SKERR_Q_E005 (SKERR_Q_E001+4)
++#define SKERR_Q_E005MSG "Event scheduler called in Init Level 0 or 1"
+ #endif /* _SKQUEUE_H_ */
+
+diff -ruN linux/drivers/net/sk98lin/h/skrlmt.h linux-new/drivers/net/sk98lin/h/skrlmt.h
+--- linux/drivers/net/sk98lin/h/skrlmt.h 2005-09-26 13:32:48.000000000 +0400
++++ linux-new/drivers/net/sk98lin/h/skrlmt.h 2005-08-09 17:15:51.000000000 +0400
+@@ -2,8 +2,8 @@
+ *
+ * Name: skrlmt.h
+ * Project: GEnesis, PCI Gigabit Ethernet Adapter
+- * Version: $Revision: 1.37 $
+- * Date: $Date: 2003/04/15 09:43:43 $
++ * Version: $Revision: 2.1 $
++ * Date: $Date: 2003/10/27 14:16:09 $
+ * Purpose: Header file for Redundant Link ManagemenT.
+ *
+ ******************************************************************************/
+diff -ruN linux/drivers/net/sk98lin/h/sktimer.h linux-new/drivers/net/sk98lin/h/sktimer.h
+--- linux/drivers/net/sk98lin/h/sktimer.h 2005-09-26 13:32:47.000000000 +0400
++++ linux-new/drivers/net/sk98lin/h/sktimer.h 2005-08-09 17:15:51.000000000 +0400
+@@ -2,8 +2,8 @@
+ *
+ * Name: sktimer.h
+ * Project: Gigabit Ethernet Adapters, Event Scheduler Module
+- * Version: $Revision: 1.11 $
+- * Date: $Date: 2003/09/16 12:58:18 $
++ * Version: $Revision: 2.1 $
++ * Date: $Date: 2003/10/27 14:16:09 $
+ * Purpose: Defines for the timer functions
+ *
+ ******************************************************************************/
+diff -ruN linux/drivers/net/sk98lin/h/sktwsi.h linux-new/drivers/net/sk98lin/h/sktwsi.h
+--- linux/drivers/net/sk98lin/h/sktwsi.h 1970-01-01 03:00:00.000000000 +0300
++++ linux-new/drivers/net/sk98lin/h/sktwsi.h 2005-08-09 17:15:51.000000000 +0400
+@@ -0,0 +1,177 @@
++/******************************************************************************
++ *
++ * Name: sktwsi.h
++ * Project: Gigabit Ethernet Adapters, TWSI-Module
++ * Version: $Revision: 1.1 $
++ * Date: $Date: 2003/12/19 14:02:56 $
++ * Purpose: Defines to access Voltage and Temperature Sensor
++ *
++ ******************************************************************************/
++
++/******************************************************************************
++ *
++ * (C)Copyright 1998-2002 SysKonnect.
++ * (C)Copyright 2002-2003 Marvell.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * The information in this file is provided "AS IS" without warranty.
++ *
++ ******************************************************************************/
++
++/*
++ * SKTWSI.H contains all TWSI specific defines
++ */
++
++#ifndef _SKTWSI_H_
++#define _SKTWSI_H_
++
++typedef struct s_Sensor SK_SENSOR;
++
++#include "h/skgetwsi.h"
++
++/*
++ * Define the TWSI events.
++ */
++#define SK_I2CEV_IRQ 1 /* IRQ happened Event */
++#define SK_I2CEV_TIM 2 /* Timeout event */
++#define SK_I2CEV_CLEAR 3 /* Clear MIB Values */
++
++/*
++ * Define READ and WRITE Constants.
++ */
++#define I2C_READ 0
++#define I2C_WRITE 1
++#define I2C_BURST 1
++#define I2C_SINGLE 0
++
++#define SKERR_I2C_E001 (SK_ERRBASE_I2C+0)
++#define SKERR_I2C_E001MSG "Sensor index unknown"
++#define SKERR_I2C_E002 (SKERR_I2C_E001+1)
++#define SKERR_I2C_E002MSG "TWSI: transfer does not complete"
++#define SKERR_I2C_E003 (SKERR_I2C_E002+1)
++#define SKERR_I2C_E003MSG "LM80: NAK on device send"
++#define SKERR_I2C_E004 (SKERR_I2C_E003+1)
++#define SKERR_I2C_E004MSG "LM80: NAK on register send"
++#define SKERR_I2C_E005 (SKERR_I2C_E004+1)
++#define SKERR_I2C_E005MSG "LM80: NAK on device (2) send"
++#define SKERR_I2C_E006 (SKERR_I2C_E005+1)
++#define SKERR_I2C_E006MSG "Unknown event"
++#define SKERR_I2C_E007 (SKERR_I2C_E006+1)
++#define SKERR_I2C_E007MSG "LM80 read out of state"
++#define SKERR_I2C_E008 (SKERR_I2C_E007+1)
++#define SKERR_I2C_E008MSG "Unexpected sensor read completed"
++#define SKERR_I2C_E009 (SKERR_I2C_E008+1)
++#define SKERR_I2C_E009MSG "WARNING: temperature sensor out of range"
++#define SKERR_I2C_E010 (SKERR_I2C_E009+1)
++#define SKERR_I2C_E010MSG "WARNING: voltage sensor out of range"
++#define SKERR_I2C_E011 (SKERR_I2C_E010+1)
++#define SKERR_I2C_E011MSG "ERROR: temperature sensor out of range"
++#define SKERR_I2C_E012 (SKERR_I2C_E011+1)
++#define SKERR_I2C_E012MSG "ERROR: voltage sensor out of range"
++#define SKERR_I2C_E013 (SKERR_I2C_E012+1)
++#define SKERR_I2C_E013MSG "ERROR: couldn't init sensor"
++#define SKERR_I2C_E014 (SKERR_I2C_E013+1)
++#define SKERR_I2C_E014MSG "WARNING: fan sensor out of range"
++#define SKERR_I2C_E015 (SKERR_I2C_E014+1)
++#define SKERR_I2C_E015MSG "ERROR: fan sensor out of range"
++#define SKERR_I2C_E016 (SKERR_I2C_E015+1)
++#define SKERR_I2C_E016MSG "TWSI: active transfer does not complete"
++
++/*
++ * Define Timeout values
++ */
++#define SK_I2C_TIM_LONG 2000000L /* 2 seconds */
++#define SK_I2C_TIM_SHORT 100000L /* 100 milliseconds */
++#define SK_I2C_TIM_WATCH 1000000L /* 1 second */
++
++/*
++ * Define trap and error log hold times
++ */
++#ifndef SK_SEN_ERR_TR_HOLD
++#define SK_SEN_ERR_TR_HOLD (4*SK_TICKS_PER_SEC)
++#endif
++#ifndef SK_SEN_ERR_LOG_HOLD
++#define SK_SEN_ERR_LOG_HOLD (60*SK_TICKS_PER_SEC)
++#endif
++#ifndef SK_SEN_WARN_TR_HOLD
++#define SK_SEN_WARN_TR_HOLD (15*SK_TICKS_PER_SEC)
++#endif
++#ifndef SK_SEN_WARN_LOG_HOLD
++#define SK_SEN_WARN_LOG_HOLD (15*60*SK_TICKS_PER_SEC)
++#endif
++
++/*
++ * Defines for SenType
++ */
++#define SK_SEN_UNKNOWN 0
++#define SK_SEN_TEMP 1
++#define SK_SEN_VOLT 2
++#define SK_SEN_FAN 3
++
++/*
++ * Define for the SenErrorFlag
++ */
++#define SK_SEN_ERR_NOT_PRESENT 0 /* Error Flag: Sensor not present */
++#define SK_SEN_ERR_OK 1 /* Error Flag: O.K. */
++#define SK_SEN_ERR_WARN 2 /* Error Flag: Warning */
++#define SK_SEN_ERR_ERR 3 /* Error Flag: Error */
++#define SK_SEN_ERR_FAULTY 4 /* Error Flag: Faulty */
++
++/*
++ * Define the Sensor struct
++ */
++struct s_Sensor {
++ char *SenDesc; /* Description */
++ int SenType; /* Voltage or Temperature */
++ SK_I32 SenValue; /* Current value of the sensor */
++ SK_I32 SenThreErrHigh; /* High error Threshhold of this sensor */
++ SK_I32 SenThreWarnHigh; /* High warning Threshhold of this sensor */
++ SK_I32 SenThreErrLow; /* Lower error Threshold of the sensor */
++ SK_I32 SenThreWarnLow; /* Lower warning Threshold of the sensor */
++ int SenErrFlag; /* Sensor indicated an error */
++ SK_BOOL SenInit; /* Is sensor initialized ? */
++ SK_U64 SenErrCts; /* Error trap counter */
++ SK_U64 SenWarnCts; /* Warning trap counter */
++ SK_U64 SenBegErrTS; /* Begin error timestamp */
++ SK_U64 SenBegWarnTS; /* Begin warning timestamp */
++ SK_U64 SenLastErrTrapTS; /* Last error trap timestamp */
++ SK_U64 SenLastErrLogTS; /* Last error log timestamp */
++ SK_U64 SenLastWarnTrapTS; /* Last warning trap timestamp */
++ SK_U64 SenLastWarnLogTS; /* Last warning log timestamp */
++ int SenState; /* Sensor State (see HW specific include) */
++ int (*SenRead)(SK_AC *pAC, SK_IOC IoC, struct s_Sensor *pSen);
++ /* Sensors read function */
++ SK_U16 SenReg; /* Register Address for this sensor */
++ SK_U8 SenDev; /* Device Selection for this sensor */
++};
++
++typedef struct s_I2c {
++ SK_SENSOR SenTable[SK_MAX_SENSORS]; /* Sensor Table */
++ int CurrSens; /* Which sensor is currently queried */
++ int MaxSens; /* Max. number of sensors */
++ int TimerMode; /* Use the timer also to watch the state machine */
++ int InitLevel; /* Initialized Level */
++#ifndef SK_DIAG
++ int DummyReads; /* Number of non-checked dummy reads */
++ SK_TIMER SenTimer; /* Sensors timer */
++#endif /* !SK_DIAG */
++} SK_I2C;
++
++extern int SkI2cInit(SK_AC *pAC, SK_IOC IoC, int Level);
++extern int SkI2cWrite(SK_AC *pAC, SK_IOC IoC, SK_U32 Data, int Dev, int Size,
++ int Reg, int Burst);
++extern int SkI2cReadSensor(SK_AC *pAC, SK_IOC IoC, SK_SENSOR *pSen);
++#ifdef SK_DIAG
++extern SK_U32 SkI2cRead(SK_AC *pAC, SK_IOC IoC, int Dev, int Size, int Reg,
++ int Burst);
++#else /* !SK_DIAG */
++extern int SkI2cEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event, SK_EVPARA Para);
++extern void SkI2cWaitIrq(SK_AC *pAC, SK_IOC IoC);
++extern void SkI2cIsr(SK_AC *pAC, SK_IOC IoC);
++#endif /* !SK_DIAG */
++#endif /* n_SKTWSI_H */
++
+diff -ruN linux/drivers/net/sk98lin/h/sktypes.h linux-new/drivers/net/sk98lin/h/sktypes.h
+--- linux/drivers/net/sk98lin/h/sktypes.h 2005-09-26 13:32:48.000000000 +0400
++++ linux-new/drivers/net/sk98lin/h/sktypes.h 2005-08-09 17:15:51.000000000 +0400
+@@ -2,8 +2,8 @@
+ *
+ * Name: sktypes.h
+ * Project: GEnesis, PCI Gigabit Ethernet Adapter
+- * Version: $Revision: 1.2 $
+- * Date: $Date: 2003/10/07 08:16:51 $
++ * Version: $Revision: 1.2.2.1 $
++ * Date: $Date: 2005/04/11 09:00:53 $
+ * Purpose: Define data types for Linux
+ *
+ ******************************************************************************/
+@@ -11,7 +11,7 @@
+ /******************************************************************************
+ *
+ * (C)Copyright 1998-2002 SysKonnect GmbH.
+- * (C)Copyright 2002-2003 Marvell.
++ * (C)Copyright 2002-2005 Marvell.
+ *
+ * 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
+@@ -22,48 +22,28 @@
+ *
+ ******************************************************************************/
+
+-/******************************************************************************
+- *
+- * Description:
+- *
+- * In this file, all data types that are needed by the common modules
+- * are mapped to Linux data types.
+- *
+- *
+- * Include File Hierarchy:
+- *
+- *
+- ******************************************************************************/
+-
+ #ifndef __INC_SKTYPES_H
+ #define __INC_SKTYPES_H
+
+-
+-/* defines *******************************************************************/
+-
+-/*
+- * Data types with a specific size. 'I' = signed, 'U' = unsigned.
+- */
+-#define SK_I8 s8
+-#define SK_U8 u8
+-#define SK_I16 s16
+-#define SK_U16 u16
+-#define SK_I32 s32
+-#define SK_U32 u32
+-#define SK_I64 s64
+-#define SK_U64 u64
+-
+-#define SK_UPTR ulong /* casting pointer <-> integral */
+-
+-/*
+-* Boolean type.
+-*/
+-#define SK_BOOL SK_U8
+-#define SK_FALSE 0
+-#define SK_TRUE (!SK_FALSE)
+-
+-/* typedefs *******************************************************************/
+-
+-/* function prototypes ********************************************************/
++#define SK_I8 s8 /* 8 bits (1 byte) signed */
++#define SK_U8 u8 /* 8 bits (1 byte) unsigned */
++#define SK_I16 s16 /* 16 bits (2 bytes) signed */
++#define SK_U16 u16 /* 16 bits (2 bytes) unsigned */
++#define SK_I32 s32 /* 32 bits (4 bytes) signed */
++#define SK_U32 u32 /* 32 bits (4 bytes) unsigned */
++#define SK_I64 s64 /* 64 bits (8 bytes) signed */
++#define SK_U64 u64 /* 64 bits (8 bytes) unsigned */
++
++#define SK_UPTR ulong /* casting pointer <-> integral */
++
++#define SK_BOOL SK_U8
++#define SK_FALSE 0
++#define SK_TRUE (!SK_FALSE)
+
+ #endif /* __INC_SKTYPES_H */
++
++/*******************************************************************************
++ *
++ * End of file
++ *
++ ******************************************************************************/
+diff -ruN linux/drivers/net/sk98lin/h/skversion.h linux-new/drivers/net/sk98lin/h/skversion.h
+--- linux/drivers/net/sk98lin/h/skversion.h 2005-09-26 13:32:47.000000000 +0400
++++ linux-new/drivers/net/sk98lin/h/skversion.h 2005-08-09 17:15:51.000000000 +0400
+@@ -1,17 +1,17 @@
+ /******************************************************************************
+ *
+- * Name: version.h
++ * Name: skversion.h
+ * Project: GEnesis, PCI Gigabit Ethernet Adapter
+- * Version: $Revision: 1.5 $
+- * Date: $Date: 2003/10/07 08:16:51 $
+- * Purpose: SK specific Error log support
++ * Version: $Revision: 1.3.2.1 $
++ * Date: $Date: 2005/04/11 09:00:53 $
++ * Purpose: specific version strings and numbers
+ *
+ ******************************************************************************/
+
+ /******************************************************************************
+ *
+ * (C)Copyright 1998-2002 SysKonnect GmbH.
+- * (C)Copyright 2002-2003 Marvell.
++ * (C)Copyright 2002-2005 Marvell.
+ *
+ * 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
+@@ -22,17 +22,15 @@
+ *
+ ******************************************************************************/
+
+-#ifdef lint
+-static const char SysKonnectFileId[] = "@(#) (C) SysKonnect GmbH.";
+-static const char SysKonnectBuildNumber[] =
+- "@(#)SK-BUILD: 6.23 PL: 01";
+-#endif /* !defined(lint) */
+-
+-#define BOOT_STRING "sk98lin: Network Device Driver v6.23\n" \
+- "(C)Copyright 1999-2004 Marvell(R)."
+-
+-#define VER_STRING "6.23"
+-#define DRIVER_FILE_NAME "sk98lin"
+-#define DRIVER_REL_DATE "Feb-13-2004"
+-
++#define BOOT_STRING "sk98lin: Network Device Driver v8.24.1.3\n" \
++ "(C)Copyright 1999-2005 Marvell(R)."
++#define VER_STRING "8.24.1.3"
++#define PATCHLEVEL "01"
++#define DRIVER_FILE_NAME "sk98lin"
++#define DRIVER_REL_DATE "Aug-09-2005"
+
++/*******************************************************************************
++ *
++ * End of file
++ *
++ ******************************************************************************/
+diff -ruN linux/drivers/net/sk98lin/h/skvpd.h linux-new/drivers/net/sk98lin/h/skvpd.h
+--- linux/drivers/net/sk98lin/h/skvpd.h 2005-09-26 13:32:47.000000000 +0400
++++ linux-new/drivers/net/sk98lin/h/skvpd.h 2005-08-09 17:15:51.000000000 +0400
+@@ -1,22 +1,22 @@
+ /******************************************************************************
+ *
+ * Name: skvpd.h
+- * Project: GEnesis, PCI Gigabit Ethernet Adapter
+- * Version: $Revision: 1.15 $
+- * Date: $Date: 2003/01/13 10:39:38 $
++ * Project: Gigabit Ethernet Adapters, VPD-Module
++ * Version: $Revision: 2.6 $
++ * Date: $Date: 2004/11/09 15:18:00 $
+ * Purpose: Defines and Macros for VPD handling
+ *
+ ******************************************************************************/
+
+ /******************************************************************************
+ *
+- * (C)Copyright 1998-2003 SysKonnect GmbH.
++ * (C)Copyright 1998-2002 SysKonnect.
++ * (C)Copyright 2002-2004 Marvell.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+- *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+@@ -31,7 +31,7 @@
+ /*
+ * Define Resource Type Identifiers and VPD keywords
+ */
+-#define RES_ID 0x82 /* Resource Type ID String (Product Name) */
++#define RES_ID 0x82 /* Resource Type ID String (Product Name) */
+ #define RES_VPD_R 0x90 /* start of VPD read only area */
+ #define RES_VPD_W 0x91 /* start of VPD read/write area */
+ #define RES_END 0x78 /* Resource Type End Tag */
+@@ -40,14 +40,16 @@
+ #define VPD_NAME "Name" /* Product Name, VPD name of RES_ID */
+ #endif /* VPD_NAME */
+ #define VPD_PN "PN" /* Adapter Part Number */
+-#define VPD_EC "EC" /* Adapter Engineering Level */
++#define VPD_EC "EC" /* Adapter Engineering Level */
+ #define VPD_MN "MN" /* Manufacture ID */
+ #define VPD_SN "SN" /* Serial Number */
+ #define VPD_CP "CP" /* Extended Capability */
+ #define VPD_RV "RV" /* Checksum and Reserved */
+-#define VPD_YA "YA" /* Asset Tag Identifier */
++#define VPD_YA "YA" /* Asset Tag Identifier */
+ #define VPD_VL "VL" /* First Error Log Message (SK specific) */
+ #define VPD_VF "VF" /* Second Error Log Message (SK specific) */
++#define VPD_VB "VB" /* Boot Agent ROM Configuration (SK specific) */
++#define VPD_VE "VE" /* EFI UNDI Configuration (SK specific) */
+ #define VPD_RW "RW" /* Remaining Read / Write Area */
+
+ /* 'type' values for vpd_setup_para() */
+@@ -55,7 +57,7 @@
+ #define VPD_RW_KEY 2 /* RW keys are "Yx", "Vx", and "RW" */
+
+ /* 'op' values for vpd_setup_para() */
+-#define ADD_KEY 1 /* add the key at the pos "RV" or "RW" */
++#define ADD_KEY 1 /* add the key at the pos "RV" or "RW" */
+ #define OWR_KEY 2 /* overwrite key if already exists */
+
+ /*
+@@ -64,18 +66,18 @@
+
+ #define VPD_DEV_ID_GENESIS 0x4300
+
+-#define VPD_SIZE_YUKON 256
+-#define VPD_SIZE_GENESIS 512
+-#define VPD_SIZE 512
++#define VPD_SIZE_YUKON 256
++#define VPD_SIZE_GENESIS 512
++#define VPD_SIZE 512
+ #define VPD_READ 0x0000
+ #define VPD_WRITE 0x8000
+
+ #define VPD_STOP(pAC,IoC) VPD_OUT16(pAC,IoC,PCI_VPD_ADR_REG,VPD_WRITE)
+
+-#define VPD_GET_RES_LEN(p) ((unsigned int) \
+- (* (SK_U8 *)&(p)[1]) |\
+- ((* (SK_U8 *)&(p)[2]) << 8))
+-#define VPD_GET_VPD_LEN(p) ((unsigned int)(* (SK_U8 *)&(p)[2]))
++#define VPD_GET_RES_LEN(p) ((unsigned int)\
++ (*(SK_U8 *)&(p)[1]) |\
++ ((*(SK_U8 *)&(p)[2]) << 8))
++#define VPD_GET_VPD_LEN(p) ((unsigned int)(*(SK_U8 *)&(p)[2]))
+ #define VPD_GET_VAL(p) ((char *)&(p)[3])
+
+ #define VPD_MAX_LEN 50
+@@ -126,7 +128,7 @@
+ /*
+ * System specific VPD macros
+ */
+-#ifndef SKDIAG
++#ifndef SK_DIAG
+ #ifndef VPD_DO_IO
+ #define VPD_OUT8(pAC,IoC,Addr,Val) (void)SkPciWriteCfgByte(pAC,Addr,Val)
+ #define VPD_OUT16(pAC,IoC,Addr,Val) (void)SkPciWriteCfgWord(pAC,Addr,Val)
+@@ -135,61 +137,61 @@
+ #define VPD_IN16(pAC,IoC,Addr,pVal) (void)SkPciReadCfgWord(pAC,Addr,pVal)
+ #define VPD_IN32(pAC,IoC,Addr,pVal) (void)SkPciReadCfgDWord(pAC,Addr,pVal)
+ #else /* VPD_DO_IO */
+-#define VPD_OUT8(pAC,IoC,Addr,Val) SK_OUT8(IoC,PCI_C(Addr),Val)
+-#define VPD_OUT16(pAC,IoC,Addr,Val) SK_OUT16(IoC,PCI_C(Addr),Val)
+-#define VPD_OUT32(pAC,IoC,Addr,Val) SK_OUT32(IoC,PCI_C(Addr),Val)
+-#define VPD_IN8(pAC,IoC,Addr,pVal) SK_IN8(IoC,PCI_C(Addr),pVal)
+-#define VPD_IN16(pAC,IoC,Addr,pVal) SK_IN16(IoC,PCI_C(Addr),pVal)
+-#define VPD_IN32(pAC,IoC,Addr,pVal) SK_IN32(IoC,PCI_C(Addr),pVal)
++#define VPD_OUT8(pAC,IoC,Addr,Val) SK_OUT8(IoC,PCI_C(pAC,Addr),Val)
++#define VPD_OUT16(pAC,IoC,Addr,Val) SK_OUT16(IoC,PCI_C(pAC,Addr),Val)
++#define VPD_OUT32(pAC,IoC,Addr,Val) SK_OUT32(IoC,PCI_C(pAC,Addr),Val)
++#define VPD_IN8(pAC,IoC,Addr,pVal) SK_IN8(IoC,PCI_C(pAC,Addr),pVal)
++#define VPD_IN16(pAC,IoC,Addr,pVal) SK_IN16(IoC,PCI_C(pAC,Addr),pVal)
++#define VPD_IN32(pAC,IoC,Addr,pVal) SK_IN32(IoC,PCI_C(pAC,Addr),pVal)
+ #endif /* VPD_DO_IO */
+-#else /* SKDIAG */
++#else /* SK_DIAG */
+ #define VPD_OUT8(pAC,Ioc,Addr,Val) { \
+ if ((pAC)->DgT.DgUseCfgCycle) \
+ SkPciWriteCfgByte(pAC,Addr,Val); \
+ else \
+- SK_OUT8(pAC,PCI_C(Addr),Val); \
++ SK_OUT8(pAC,PCI_C(pAC,Addr),Val); \
+ }
+ #define VPD_OUT16(pAC,Ioc,Addr,Val) { \
+ if ((pAC)->DgT.DgUseCfgCycle) \
+ SkPciWriteCfgWord(pAC,Addr,Val); \
+ else \
+- SK_OUT16(pAC,PCI_C(Addr),Val); \
++ SK_OUT16(pAC,PCI_C(pAC,Addr),Val); \
+ }
+ #define VPD_OUT32(pAC,Ioc,Addr,Val) { \
+ if ((pAC)->DgT.DgUseCfgCycle) \
+ SkPciWriteCfgDWord(pAC,Addr,Val); \
+ else \
+- SK_OUT32(pAC,PCI_C(Addr),Val); \
++ SK_OUT32(pAC,PCI_C(pAC,Addr),Val); \
+ }
+ #define VPD_IN8(pAC,Ioc,Addr,pVal) { \
+- if ((pAC)->DgT.DgUseCfgCycle) \
++ if ((pAC)->DgT.DgUseCfgCycle) \
+ SkPciReadCfgByte(pAC,Addr,pVal); \
+ else \
+- SK_IN8(pAC,PCI_C(Addr),pVal); \
++ SK_IN8(pAC,PCI_C(pAC,Addr),pVal); \
+ }
+ #define VPD_IN16(pAC,Ioc,Addr,pVal) { \
+- if ((pAC)->DgT.DgUseCfgCycle) \
++ if ((pAC)->DgT.DgUseCfgCycle) \
+ SkPciReadCfgWord(pAC,Addr,pVal); \
+ else \
+- SK_IN16(pAC,PCI_C(Addr),pVal); \
++ SK_IN16(pAC,PCI_C(pAC,Addr),pVal); \
+ }
+ #define VPD_IN32(pAC,Ioc,Addr,pVal) { \
+ if ((pAC)->DgT.DgUseCfgCycle) \
+ SkPciReadCfgDWord(pAC,Addr,pVal); \
+ else \
+- SK_IN32(pAC,PCI_C(Addr),pVal); \
++ SK_IN32(pAC,PCI_C(pAC,Addr),pVal); \
+ }
+-#endif /* nSKDIAG */
++#endif /* SK_DIAG */
+
+ /* function prototypes ********************************************************/
+
+ #ifndef SK_KR_PROTO
+-#ifdef SKDIAG
++#ifdef SK_DIAG
+ extern SK_U32 VpdReadDWord(
+ SK_AC *pAC,
+ SK_IOC IoC,
+ int addr);
+-#endif /* SKDIAG */
++#endif /* SK_DIAG */
+
+ extern int VpdSetupPara(
+ SK_AC *pAC,
+@@ -240,7 +242,12 @@
+ SK_IOC IoC,
+ char *msg);
+
+-#ifdef SKDIAG
++int VpdInit(
++ SK_AC *pAC,
++ SK_IOC IoC);
++
++#if defined(SK_DIAG) || defined(SK_ASF)
++
+ extern int VpdReadBlock(
+ SK_AC *pAC,
+ SK_IOC IoC,
+@@ -254,7 +261,9 @@
+ char *buf,
+ int addr,
+ int len);
+-#endif /* SKDIAG */
++
++#endif /* SK_DIAG || SK_ASF */
++
+ #else /* SK_KR_PROTO */
+ extern SK_U32 VpdReadDWord();
+ extern int VpdSetupPara();
+@@ -269,3 +278,4 @@
+ #endif /* SK_KR_PROTO */
+
+ #endif /* __INC_SKVPD_H_ */
++
+diff -ruN linux/drivers/net/sk98lin/h/sky2le.h linux-new/drivers/net/sk98lin/h/sky2le.h
+--- linux/drivers/net/sk98lin/h/sky2le.h 1970-01-01 03:00:00.000000000 +0300
++++ linux-new/drivers/net/sk98lin/h/sky2le.h 2005-08-09 17:15:51.000000000 +0400
+@@ -0,0 +1,891 @@
++/******************************************************************************
++ *
++ * Name: sky2le.h
++ * Project: Gigabit Ethernet Adapters, Common Modules
++ * Version: $Revision: 1.9 $
++ * Date: $Date: 2005/01/26 10:53:34 $
++ * Purpose: Common list element definitions and access macros.
++ *
++ ******************************************************************************/
++
++/******************************************************************************
++ *
++ * (C)Copyright 2003-2004 Marvell
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ * The information in this file is provided "AS IS" without warranty.
++ *
++ ******************************************************************************/
++
++#ifndef __INC_SKY2LE_H
++#define __INC_SKY2LE_H
++
++#ifdef __cplusplus
++extern "C" {
++#endif /* __cplusplus */
++
++/* defines ********************************************************************/
++
++#define MIN_LEN_OF_LE_TAB 128
++#define MAX_LEN_OF_LE_TAB 4096
++#ifdef USE_POLLING_UNIT
++#define NUM_LE_POLLING_UNIT 2
++#endif
++#define MAX_FRAG_OVERHEAD 10
++
++/* Macro for aligning a given value */
++#define SK_ALIGN_SIZE(Value, Alignment, AlignedVal) { \
++ (AlignedVal) = (((Value) + (Alignment) - 1) & (~((Alignment) - 1)));\
++}
++
++/******************************************************************************
++ *
++ * LE2DWord() - Converts the given Little Endian value to machine order value
++ *
++ * Description:
++ * This function converts the Little Endian value received as an argument to
++ * the machine order value.
++ *
++ * Returns:
++ * The converted value
++ *
++ */
++
++#ifdef SK_LITTLE_ENDIAN
++
++#ifndef SK_USE_REV_DESC
++#define LE2DWord(value) (value)
++#else /* SK_USE_REV_DESC */
++#define LE2DWord(value) \
++ ((((value)<<24L) & 0xff000000L) + \
++ (((value)<< 8L) & 0x00ff0000L) + \
++ (((value)>> 8L) & 0x0000ff00L) + \
++ (((value)>>24L) & 0x000000ffL))
++#endif /* SK_USE_REV_DESC */
++
++#else /* !SK_LITTLE_ENDIAN */
++
++#ifndef SK_USE_REV_DESC
++#define LE2DWord(value) \
++ ((((value)<<24L) & 0xff000000L) + \
++ (((value)<< 8L) & 0x00ff0000L) + \
++ (((value)>> 8L) & 0x0000ff00L) + \
++ (((value)>>24L) & 0x000000ffL))
++#else /* SK_USE_REV_DESC */
++#define LE2DWord(value) (value)
++#endif /* SK_USE_REV_DESC */
++
++#endif /* !SK_LITTLE_ENDIAN */
++
++/******************************************************************************
++ *
++ * DWord2LE() - Converts the given value to a Little Endian value
++ *
++ * Description:
++ * This function converts the value received as an argument to a Little Endian
++ * value on Big Endian machines. If the machine running the code is Little
++ * Endian, then no conversion is done.
++ *
++ * Returns:
++ * The converted value
++ *
++ */
++
++#ifdef SK_LITTLE_ENDIAN
++
++#ifndef SK_USE_REV_DESC
++#define DWord2LE(value) (value)
++#else /* SK_USE_REV_DESC */
++#define DWord2LE(value) \
++ ((((value)<<24L) & 0xff000000L) + \
++ (((value)<< 8L) & 0x00ff0000L) + \
++ (((value)>> 8L) & 0x0000ff00L) + \
++ (((value)>>24L) & 0x000000ffL))
++#endif /* SK_USE_REV_DESC */
++
++#else /* !SK_LITTLE_ENDIAN */
++
++#ifndef SK_USE_REV_DESC
++#define DWord2LE(value) \
++ ((((value)<<24L) & 0xff000000L) + \
++ (((value)<< 8L) & 0x00ff0000L) + \
++ (((value)>> 8L) & 0x0000ff00L) + \
++ (((value)>>24L) & 0x000000ffL))
++#else /* SK_USE_REV_DESC */
++#define DWord2LE(value) (value)
++#endif /* SK_USE_REV_DESC */
++#endif /* !SK_LITTLE_ENDIAN */
++
++/******************************************************************************
++ *
++ * LE2Word() - Converts the given Little Endian value to machine order value
++ *
++ * Description:
++ * This function converts the Little Endian value received as an argument to
++ * the machine order value.
++ *
++ * Returns:
++ * The converted value
++ *
++ */
++
++#ifdef SK_LITTLE_ENDIAN
++#ifndef SK_USE_REV_DESC
++#define LE2Word(value) (value)
++#else /* SK_USE_REV_DESC */
++#define LE2Word(value) \
++ ((((value)<< 8L) & 0xff00) + \
++ (((value)>> 8L) & 0x00ff))
++#endif /* SK_USE_REV_DESC */
++
++#else /* !SK_LITTLE_ENDIAN */
++#ifndef SK_USE_REV_DESC
++#define LE2Word(value) \
++ ((((value)<< 8L) & 0xff00) + \
++ (((value)>> 8L) & 0x00ff))
++#else /* SK_USE_REV_DESC */
++#define LE2Word(value) (value)
++#endif /* SK_USE_REV_DESC */
++#endif /* !SK_LITTLE_ENDIAN */
++
++/******************************************************************************
++ *
++ * Word2LE() - Converts the given value to a Little Endian value
++ *
++ * Description:
++ * This function converts the value received as an argument to a Little Endian
++ * value on Big Endian machines. If the machine running the code is Little
++ * Endian, then no conversion is done.
++ *
++ * Returns:
++ * The converted value
++ *
++ */
++
++#ifdef SK_LITTLE_ENDIAN
++#ifndef SK_USE_REV_DESC
++#define Word2LE(value) (value)
++#else /* SK_USE_REV_DESC */
++#define Word2LE(value) \
++ ((((value)<< 8L) & 0xff00) + \
++ (((value)>> 8L) & 0x00ff))
++#endif /* SK_USE_REV_DESC */
++
++#else /* !SK_LITTLE_ENDIAN */
++#ifndef SK_USE_REV_DESC
++#define Word2LE(value) \
++ ((((value)<< 8L) & 0xff00) + \
++ (((value)>> 8L) & 0x00ff))
++#else /* SK_USE_REV_DESC */
++#define Word2LE(value) (value)
++#endif /* SK_USE_REV_DESC */
++#endif /* !SK_LITTLE_ENDIAN */
++
++/******************************************************************************
++ *
++ * Transmit list element macros
++ *
++ */
++
++#define TXLE_SET_ADDR(pLE, Addr) \
++ ((pLE)->Tx.TxUn.BufAddr = DWord2LE(Addr))
++#define TXLE_SET_LSLEN(pLE, Len) \
++ ((pLE)->Tx.TxUn.LargeSend.Length = Word2LE(Len))
++#define TXLE_SET_STACS(pLE, Start) \
++ ((pLE)->Tx.TxUn.ChkSum.TxTcpSp = Word2LE(Start))
++#define TXLE_SET_WRICS(pLE, Write) \
++ ((pLE)->Tx.TxUn.ChkSum.TxTcpWp = Word2LE(Write))
++#define TXLE_SET_INICS(pLE, Ini) ((pLE)->Tx.Send.InitCsum = Word2LE(Ini))
++#define TXLE_SET_LEN(pLE, Len) ((pLE)->Tx.Send.BufLen = Word2LE(Len))
++#define TXLE_SET_VLAN(pLE, Vlan) ((pLE)->Tx.Send.VlanTag = Word2LE(Vlan))
++#define TXLE_SET_LCKCS(pLE, Lock) ((pLE)->Tx.ControlFlags = (Lock))
++#define TXLE_SET_CTRL(pLE, Ctrl) ((pLE)->Tx.ControlFlags = (Ctrl))
++#define TXLE_SET_OPC(pLE, Opc) ((pLE)->Tx.Opcode = (Opc))
++
++#define TXLE_GET_ADDR(pLE) LE2DWord((pLE)->Tx.TxUn.BufAddr)
++#define TXLE_GET_LSLEN(pLE) LE2Word((pLE)->Tx.TxUn.LargeSend.Length)
++#define TXLE_GET_STACS(pLE) LE2Word((pLE)->Tx.TxUn.ChkSum.TxTcpSp)
++#define TXLE_GET_WRICS(pLE) LE2Word((pLE)->Tx.TxUn.ChkSum.TxTcpWp)
++#define TXLE_GET_INICS(pLE) LE2Word((pLE)->Tx.Send.InitCsum)
++#define TXLE_GET_LEN(pLE) LE2Word((pLE)->Tx.Send.BufLen)
++#define TXLE_GET_VLAN(pLE) LE2Word((pLE)->Tx.Send.VlanTag)
++#define TXLE_GET_LCKCS(pLE) ((pLE)->Tx.ControlFlags)
++#define TXLE_GET_CTRL(pLE) ((pLE)->Tx.ControlFlags)
++#define TXLE_GET_OPC(pLE) ((pLE)->Tx.Opcode)
++
++/******************************************************************************
++ *
++ * Receive list element macros
++ *
++ */
++
++#define RXLE_SET_ADDR(pLE, Addr) \
++ ((pLE)->Rx.RxUn.BufAddr = (SK_U32) DWord2LE(Addr))
++#define RXLE_SET_STACS2(pLE, Offs) \
++ ((pLE)->Rx.RxUn.ChkSum.RxTcpSp2 = Word2LE(Offs))
++#define RXLE_SET_STACS1(pLE, Offs) \
++ ((pLE)->Rx.RxUn.ChkSum.RxTcpSp1 = Word2LE(Offs))
++#define RXLE_SET_LEN(pLE, Len) ((pLE)->Rx.BufferLength = Word2LE(Len))
++#define RXLE_SET_CTRL(pLE, Ctrl) ((pLE)->Rx.ControlFlags = (Ctrl))
++#define RXLE_SET_OPC(pLE, Opc) ((pLE)->Rx.Opcode = (Opc))
++
++#define RXLE_GET_ADDR(pLE) LE2DWord((pLE)->Rx.RxUn.BufAddr)
++#define RXLE_GET_STACS2(pLE) LE2Word((pLE)->Rx.RxUn.ChkSum.RxTcpSp2)
++#define RXLE_GET_STACS1(pLE) LE2Word((pLE)->Rx.RxUn.ChkSum.RxTcpSp1)
++#define RXLE_GET_LEN(pLE) LE2Word((pLE)->Rx.BufferLength)
++#define RXLE_GET_CTRL(pLE) ((pLE)->Rx.ControlFlags)
++#define RXLE_GET_OPC(pLE) ((pLE)->Rx.Opcode)
++
++/******************************************************************************
++ *
++ * Status list element macros
++ *
++ */
++
++#define STLE_SET_OPC(pLE, Opc) ((pLE)->St.Opcode = (Opc))
++
++#define STLE_GET_FRSTATUS(pLE) LE2DWord((pLE)->St.StUn.StRxStatWord)
++#define STLE_GET_TIST(pLE) LE2DWord((pLE)->St.StUn.StRxTimeStamp)
++#define STLE_GET_TCP1(pLE) LE2Word((pLE)->St.StUn.StRxTCPCSum.RxTCPSum1)
++#define STLE_GET_TCP2(pLE) LE2Word((pLE)->St.StUn.StRxTCPCSum.RxTCPSum2)
++#define STLE_GET_LEN(pLE) LE2Word((pLE)->St.Stat.BufLen)
++#define STLE_GET_VLAN(pLE) LE2Word((pLE)->St.Stat.VlanTag)
++#define STLE_GET_LINK(pLE) ((pLE)->St.Link)
++#define STLE_GET_OPC(pLE) ((pLE)->St.Opcode)
++#define STLE_GET_DONE_IDX(pLE,LowVal,HighVal) { \
++ (LowVal) = LE2DWord((pLE)->St.StUn.StTxStatLow); \
++ (HighVal) = LE2Word((pLE)->St.Stat.StTxStatHi); \
++}
++
++#define STLE_GET_RSS(pLE) LE2DWord((pLE)->St.StUn.StRxRssValue)
++#define STLE_GET_IPBIT(pLE) ((pLE)->St.Stat.Rss.FlagField & RSS_IP_FLAG)
++#define STLE_GET_TCPBIT(pLE) ((pLE)->St.Stat.Rss.FlagField & RSS_TCP_FLAG)
++
++
++/* I always take both values as a paramter to avoid typos */
++#define STLE_GET_DONE_IDX_TXA1(LowVal,HighVal) \
++ (((LowVal) & STLE_TXA1_MSKL) >> STLE_TXA1_SHIFTL)
++#define STLE_GET_DONE_IDX_TXS1(LowVal,HighVal) \
++ ((LowVal & STLE_TXS1_MSKL) >> STLE_TXS1_SHIFTL)
++#define STLE_GET_DONE_IDX_TXA2(LowVal,HighVal) \
++ (((LowVal & STLE_TXA2_MSKL) >> STLE_TXA2_SHIFTL) + \
++ ((HighVal & STLE_TXA2_MSKH) << STLE_TXA2_SHIFTH))
++#define STLE_GET_DONE_IDX_TXS2(LowVal,HighVal) \
++ ((HighVal & STLE_TXS2_MSKH) >> STLE_TXS2_SHIFTH)
++
++
++#define SK_Y2_RXSTAT_CHECK_PKT(Len, RxStat, IsOk) { \
++ (IsOk) = (((RxStat) & GMR_FS_RX_OK) != 0) && \
++ (((RxStat) & GMR_FS_ANY_ERR) == 0); \
++ \
++ if ((IsOk) && ((SK_U16)(((RxStat) & GMR_FS_LEN_MSK) >> \
++ GMR_FS_LEN_SHIFT) != (Len))) { \
++ /* length in MAC status differs from length in LE */\
++ (IsOk) = SK_FALSE; \
++ } \
++}
++
++
++/******************************************************************************
++ *
++ * Polling unit list element macros
++ *
++ * NOTE: the Idx must be <= 0xfff and PU_PUTIDX_VALID makes them valid
++ *
++ */
++
++#ifdef USE_POLLING_UNIT
++
++#define POLE_SET_OPC(pLE, Opc) ((pLE)->Sa.Opcode = (Opc))
++#define POLE_SET_LINK(pLE, Port) ((pLE)->Sa.Link = (Port))
++#define POLE_SET_RXIDX(pLE, Idx) ((pLE)->Sa.RxIdxVld = Word2LE(Idx))
++#define POLE_SET_TXAIDX(pLE, Idx) ((pLE)->Sa.TxAIdxVld = Word2LE(Idx))
++#define POLE_SET_TXSIDX(pLE, Idx) ((pLE)->Sa.TxSIdxVld = Word2LE(Idx))
++
++#define POLE_GET_OPC(pLE) ((pLE)->Sa.Opcode)
++#define POLE_GET_LINK(pLE) ((pLE)->Sa.Link)
++#define POLE_GET_RXIDX(pLE) LE2Word((pLE)->Sa.RxIdxVld)
++#define POLE_GET_TXAIDX(pLE) LE2Word((pLE)->Sa.TxAIdxVld)
++#define POLE_GET_TXSIDX(pLE) LE2Word((pLE)->Sa.TxSIdxVld)
++
++#endif /* USE_POLLING_UNIT */
++
++/******************************************************************************
++ *
++ * Debug macros for list elements
++ *
++ */
++
++#ifdef DEBUG
++
++#define SK_DBG_DUMP_RX_LE(pLE) { \
++ SK_U8 Opcode; \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("=== RX_LIST_ELEMENT @addr: %p cont: %02x %02x %02x %02x %02x %02x %02x %02x\n", \
++ pLE, ((SK_U8 *) pLE)[0], ((SK_U8 *) pLE)[1], ((SK_U8 *) pLE)[2],\
++ ((SK_U8 *) pLE)[3], ((SK_U8 *) pLE)[4], ((SK_U8 *) pLE)[5], \
++ ((SK_U8 *) pLE)[6], ((SK_U8 *) pLE)[7])); \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\t (16bit) %04x %04x %04x %04x\n", \
++ ((SK_U16 *) pLE)[0], ((SK_U16 *) pLE)[1], ((SK_U16 *) pLE)[2], \
++ ((SK_U16 *) pLE)[3])); \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\t (32bit) %08x %08x\n", \
++ ((SK_U32 *) pLE)[0], ((SK_U32 *) pLE)[1])); \
++ Opcode = RXLE_GET_OPC(pLE); \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tOwn belongs to %s\n", ((Opcode & HW_OWNER) == HW_OWNER) ? \
++ "Hardware" : "Software")); \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tOpc: 0x%x ",Opcode)); \
++ switch (Opcode & (~HW_OWNER)) { \
++ case OP_BUFFER: \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tOP_BUFFER\n")); \
++ break; \
++ case OP_PACKET: \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tOP_PACKET\n")); \
++ break; \
++ case OP_ADDR64: \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tOP_ADDR64\n")); \
++ break; \
++ case OP_TCPSTART: \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tOP_TCPPAR\n")); \
++ break; \
++ case SW_OWNER: \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tunused LE\n")); \
++ break; \
++ default: \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tunknown Opcode!!!\n")); \
++ break; \
++ } \
++ if ((Opcode & OP_BUFFER) == OP_BUFFER) { \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tControl: 0x%x\n", RXLE_GET_CTRL(pLE))); \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tBufLen: 0x%x\n", RXLE_GET_LEN(pLE))); \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tLowAddr: 0x%x\n", RXLE_GET_ADDR(pLE))); \
++ } \
++ if ((Opcode & OP_ADDR64) == OP_ADDR64) { \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tHighAddr: 0x%x\n", RXLE_GET_ADDR(pLE))); \
++ } \
++ if ((Opcode & OP_TCPSTART) == OP_TCPSTART) { \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tTCP Sum Start 1 : 0x%x\n", RXLE_GET_STACS1(pLE))); \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tTCP Sum Start 2 : 0x%x\n", RXLE_GET_STACS2(pLE))); \
++ } \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("=====================\n")); \
++}
++
++#define SK_DBG_DUMP_TX_LE(pLE) { \
++ SK_U8 Opcode; \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("=== TX_LIST_ELEMENT @addr: %p cont: %02x %02x %02x %02x %02x %02x %02x %02x\n", \
++ pLE, ((SK_U8 *) pLE)[0], ((SK_U8 *) pLE)[1], ((SK_U8 *) pLE)[2],\
++ ((SK_U8 *) pLE)[3], ((SK_U8 *) pLE)[4], ((SK_U8 *) pLE)[5], \
++ ((SK_U8 *) pLE)[6], ((SK_U8 *) pLE)[7])); \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\t (16bit) %04x %04x %04x %04x\n", \
++ ((SK_U16 *) pLE)[0], ((SK_U16 *) pLE)[1], ((SK_U16 *) pLE)[2], \
++ ((SK_U16 *) pLE)[3])); \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\t (32bit) %08x %08x\n", \
++ ((SK_U32 *) pLE)[0], ((SK_U32 *) pLE)[1])); \
++ Opcode = TXLE_GET_OPC(pLE); \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tOwn belongs to %s\n", ((Opcode & HW_OWNER) == HW_OWNER) ? \
++ "Hardware" : "Software")); \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tOpc: 0x%x ",Opcode)); \
++ switch (Opcode & (~HW_OWNER)) { \
++ case OP_TCPCHKSUM: \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tOP_TCPCHKSUM\n")); \
++ break; \
++ case OP_TCPIS: \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tOP_TCPIS\n")); \
++ break; \
++ case OP_TCPLCK: \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tOP_TCPLCK\n")); \
++ break; \
++ case OP_TCPLW: \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tOP_TCPLW\n")); \
++ break; \
++ case OP_TCPLSW: \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tOP_TCPLSW\n")); \
++ break; \
++ case OP_TCPLISW: \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tOP_TCPLISW\n")); \
++ break; \
++ case OP_ADDR64: \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tOP_ADDR64\n")); \
++ break; \
++ case OP_VLAN: \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tOP_VLAN\n")); \
++ break; \
++ case OP_ADDR64VLAN: \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tOP_ADDR64VLAN\n")); \
++ break; \
++ case OP_LRGLEN: \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tOP_LRGLEN\n")); \
++ break; \
++ case OP_LRGLENVLAN: \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tOP_LRGLENVLAN\n")); \
++ break; \
++ case OP_BUFFER: \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tOP_BUFFER\n")); \
++ break; \
++ case OP_PACKET: \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tOP_PACKET\n")); \
++ break; \
++ case OP_LARGESEND: \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tOP_LARGESEND\n")); \
++ break; \
++ case SW_OWNER: \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tunused LE\n")); \
++ break; \
++ default: \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tunknown Opcode!!!\n")); \
++ break; \
++ } \
++ if ((Opcode & OP_BUFFER) == OP_BUFFER) { \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tControl: 0x%x\n", TXLE_GET_CTRL(pLE))); \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tBufLen: 0x%x\n", TXLE_GET_LEN(pLE))); \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tLowAddr: 0x%x\n", TXLE_GET_ADDR(pLE))); \
++ } \
++ if ((Opcode & OP_ADDR64) == OP_ADDR64) { \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tHighAddr: 0x%x\n", TXLE_GET_ADDR(pLE))); \
++ } \
++ if ((Opcode & OP_VLAN) == OP_VLAN) { \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tVLAN Id: 0x%x\n", TXLE_GET_VLAN(pLE))); \
++ } \
++ if ((Opcode & OP_LRGLEN) == OP_LRGLEN) { \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tLarge send length: 0x%x\n", TXLE_GET_LSLEN(pLE))); \
++ } \
++ if ((Opcode &(~HW_OWNER)) <= OP_ADDR64) { \
++ if ((Opcode & OP_TCPWRITE) == OP_TCPWRITE) { \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tTCP Sum Write: 0x%x\n", TXLE_GET_WRICS(pLE))); \
++ } \
++ if ((Opcode & OP_TCPSTART) == OP_TCPSTART) { \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tTCP Sum Start: 0x%x\n", TXLE_GET_STACS(pLE))); \
++ } \
++ if ((Opcode & OP_TCPINIT) == OP_TCPINIT) { \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tTCP Sum Init: 0x%x\n", TXLE_GET_INICS(pLE))); \
++ } \
++ if ((Opcode & OP_TCPLCK) == OP_TCPLCK) { \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tTCP Sum Lock: 0x%x\n", TXLE_GET_LCKCS(pLE))); \
++ } \
++ } \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("=====================\n")); \
++}
++
++#define SK_DBG_DUMP_ST_LE(pLE) { \
++ SK_U8 Opcode; \
++ SK_U16 HighVal; \
++ SK_U32 LowVal; \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("=== ST_LIST_ELEMENT @addr: %p contains: %02x %02x %02x %02x %02x %02x %02x %02x\n",\
++ pLE, ((SK_U8 *) pLE)[0], ((SK_U8 *) pLE)[1], ((SK_U8 *) pLE)[2],\
++ ((SK_U8 *) pLE)[3], ((SK_U8 *) pLE)[4], ((SK_U8 *) pLE)[5], \
++ ((SK_U8 *) pLE)[6], ((SK_U8 *) pLE)[7])); \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\t (16bit) %04x %04x %04x %04x\n", \
++ ((SK_U16 *) pLE)[0], ((SK_U16 *) pLE)[1], ((SK_U16 *) pLE)[2], \
++ ((SK_U16 *) pLE)[3])); \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\t (32bit) %08x %08x\n", \
++ ((SK_U32 *) pLE)[0], ((SK_U32 *) pLE)[1])); \
++ Opcode = STLE_GET_OPC(pLE); \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tOwn belongs to %s\n", ((Opcode & HW_OWNER) == SW_OWNER) ? \
++ "Hardware" : "Software")); \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tOpc: 0x%x", Opcode)); \
++ Opcode &= (~HW_OWNER); \
++ switch (Opcode) { \
++ case OP_RXSTAT: \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tOP_RXSTAT\n")); \
++ break; \
++ case OP_RXTIMESTAMP: \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tOP_RXTIMESTAMP\n")); \
++ break; \
++ case OP_RXVLAN: \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tOP_RXVLAN\n")); \
++ break; \
++ case OP_RXCHKS: \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tOP_RXCHKS\n")); \
++ break; \
++ case OP_RXCHKSVLAN: \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tOP_RXCHKSVLAN\n")); \
++ break; \
++ case OP_RXTIMEVLAN: \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tOP_RXTIMEVLAN\n")); \
++ break; \
++ case OP_RSS_HASH: \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tOP_RSS_HASH\n")); \
++ break; \
++ case OP_TXINDEXLE: \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tOP_TXINDEXLE\n")); \
++ break; \
++ case HW_OWNER: \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tunused LE\n")); \
++ break; \
++ default: \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tunknown status list element!!!\n")); \
++ break; \
++ } \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tPort: %c\n", 'A' + STLE_GET_LINK(pLE))); \
++ if (Opcode == OP_RXSTAT) { \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tFrameLen: 0x%x\n", STLE_GET_LEN(pLE))); \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tFrameStat: 0x%x\n", STLE_GET_FRSTATUS(pLE))); \
++ } \
++ if ((Opcode & OP_RXVLAN) == OP_RXVLAN) { \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tVLAN Id: 0x%x\n", STLE_GET_VLAN(pLE))); \
++ } \
++ if ((Opcode & OP_RXTIMESTAMP) == OP_RXTIMESTAMP) { \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tTimestamp: 0x%x\n", STLE_GET_TIST(pLE))); \
++ } \
++ if ((Opcode & OP_RXCHKS) == OP_RXCHKS) { \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tTCP: 0x%x 0x%x\n", STLE_GET_TCP1(pLE), \
++ STLE_GET_TCP2(pLE))); \
++ } \
++ if (Opcode == OP_TXINDEXLE) { \
++ STLE_GET_DONE_IDX(pLE, LowVal, HighVal); \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tTx Index TxA1: 0x%x\n", \
++ STLE_GET_DONE_IDX_TXA1(LowVal,HighVal))); \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tTx Index TxS1: 0x%x\n", \
++ STLE_GET_DONE_IDX_TXS1(LowVal,HighVal))); \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tTx Index TxA2: 0x%x\n", \
++ STLE_GET_DONE_IDX_TXA2(LowVal,HighVal))); \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tTx Index TxS2: 0x%x\n", \
++ STLE_GET_DONE_IDX_TXS2(LowVal,HighVal))); \
++ } \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("=====================\n")); \
++}
++
++#ifdef USE_POLLING_UNIT
++#define SK_DBG_DUMP_PO_LE(pLE) { \
++ SK_U8 Opcode; \
++ SK_U16 Idx; \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("=== PO_LIST_ELEMENT @addr: %p cont: %02x %02x %02x %02x %02x %02x %02x %02x\n", \
++ pLE, ((SK_U8 *) pLE)[0], ((SK_U8 *) pLE)[1], ((SK_U8 *) pLE)[2],\
++ ((SK_U8 *) pLE)[3], ((SK_U8 *) pLE)[4], ((SK_U8 *) pLE)[5], \
++ ((SK_U8 *) pLE)[6], ((SK_U8 *) pLE)[7])); \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\t (16bit) %04x %04x %04x %04x\n", \
++ ((SK_U16 *) pLE)[0], ((SK_U16 *) pLE)[1], ((SK_U16 *) pLE)[2], \
++ ((SK_U16 *) pLE)[3])); \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\t (32bit) %08x %08x\n", \
++ ((SK_U32 *) pLE)[0], ((SK_U32 *) pLE)[1])); \
++ Opcode = POLE_GET_OPC(pLE); \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tOwn belongs to %s\n", ((Opcode & HW_OWNER) == HW_OWNER) ? \
++ "Hardware" : "Software")); \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tOpc: 0x%x ",Opcode)); \
++ if ((Opcode & ~HW_OWNER) == OP_PUTIDX) { \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tOP_PUTIDX\n")); \
++ } \
++ else { \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tunknown Opcode!!!\n")); \
++ } \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tPort %c\n", 'A' + POLE_GET_LINK(pLE))); \
++ Idx = POLE_GET_TXAIDX(pLE); \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tTxA Index is 0x%X and %svalid\n", Idx, \
++ (Idx & PU_PUTIDX_VALID) ? "" : "not ")); \
++ Idx = POLE_GET_TXSIDX(pLE); \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tTxS Index is 0x%X and %svalid\n", Idx, \
++ (Idx & PU_PUTIDX_VALID) ? "" : "not ")); \
++ Idx = POLE_GET_RXIDX(pLE); \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("\tRx Index is 0x%X and %svalid\n", Idx, \
++ (Idx & PU_PUTIDX_VALID) ? "" : "not ")); \
++ SK_DBG_MSG(pAc, SK_DBGMOD_HWM, SK_DBGCAT_INIT, \
++ ("=====================\n")); \
++}
++#endif /* USE_POLLING_UNIT */
++
++#else /* !DEBUG */
++
++#define SK_DBG_DUMP_RX_LE(pLE)
++#define SK_DBG_DUMP_TX_LE(pLE)
++#define SK_DBG_DUMP_ST_LE(pLE)
++#define SK_DBG_DUMP_PO_LE(pLE)
++
++#endif /* !DEBUG */
++
++/******************************************************************************
++ *
++ * Macros for listelement tables
++ *
++ *
++ */
++
++#define LE_SIZE sizeof(SK_HWLE)
++#define LE_TAB_SIZE(NumElements) ((NumElements) * LE_SIZE)
++
++/* Number of unused list elements in table
++ * this macro always returns the number of free listelements - 1
++ * this way we want to guarantee that always one LE remains unused
++ */
++#define NUM_FREE_LE_IN_TABLE(pTable) \
++ ( ((pTable)->Put >= (pTable)->Done) ? \
++ (NUM_LE_IN_TABLE(pTable) - (pTable)->Put + (pTable)->Done - 1) :\
++ ((pTable)->Done - (pTable)->Put - 1) )
++
++/* total number of list elements in table */
++#define NUM_LE_IN_TABLE(pTable) ((pTable)->Num)
++
++/* get next unused Rx list element */
++#define GET_RX_LE(pLE, pTable) { \
++ pLE = &(pTable)->pLETab[(pTable)->Put]; \
++ (pTable)->Put = ((pTable)->Put + 1) & (NUM_LE_IN_TABLE(pTable) - 1);\
++}
++
++/* get next unused Tx list element */
++#define GET_TX_LE(pLE, pTable) GET_RX_LE(pLE, pTable)
++
++/* get next status list element expected to be finished by hw */
++#define GET_ST_LE(pLE, pTable) { \
++ pLE = &(pTable)->pLETab[(pTable)->Done]; \
++ (pTable)->Done = ((pTable)->Done +1) & (NUM_LE_IN_TABLE(pTable) - 1);\
++}
++
++#ifdef USE_POLLING_UNIT
++/* get next polling unit list element for port */
++#define GET_PO_LE(pLE, pTable, Port) { \
++ pLE = &(pTable)->pLETab[(Port)]; \
++}
++#endif /* USE_POLLING_UNIT */
++
++#define GET_PUT_IDX(pTable) ((pTable)->Put)
++
++#define UPDATE_HWPUT_IDX(pTable) {(pTable)->HwPut = (pTable)->Put; }
++
++/*
++ * get own bit of next status LE
++ * if the result is != 0 there has been at least one status LE finished
++ */
++#define OWN_OF_FIRST_LE(pTable) \
++ (STLE_GET_OPC(&(pTable)->pLETab[(pTable)->Done]) & HW_OWNER)
++
++#define SET_DONE_INDEX(pTable, Idx) (pTable)->Done = (Idx);
++
++#define GET_DONE_INDEX(pTable) ((pTable)->Done)
++
++#ifdef SAFE_BUT_SLOW
++
++/* check own bit of LE before current done idx */
++#define CHECK_STLE_OVERFLOW(pTable, IsOk) { \
++ unsigned i; \
++ if ((i = (pTable)->Done) == 0) { \
++ i = NUM_LE_IN_TABLE(pTable); \
++ } \
++ else { \
++ i = i - 1; \
++ } \
++ if (STLE_GET_OPC(&(pTable)->pLETab[i]) == HW_OWNER) { \
++ (IsOk) = SK_TRUE; \
++ } \
++ else { \
++ (IsOk) = SK_FALSE; \
++ } \
++ }
++
++
++/*
++ * for Yukon-2 the hardware is not polling the list elements, so it
++ * is not necessary to change the own-bit of Rx or Tx LEs before
++ * reusing them
++ * but it might make debugging easier if one simply can see whether
++ * a LE has been worked on
++ */
++
++#define CLEAR_LE_OWN(pTable, Idx) \
++ STLE_SET_OPC(&(pTable)->pLETab[(Idx)], SW_OWNER)
++
++/*
++ * clear all own bits starting from old done index up to the LE before
++ * the new done index
++ */
++#define CLEAR_LE_OWN_FROM_DONE_TO(pTable, To) { \
++ int i; \
++ i = (pTable)->Done; \
++ while (i != To) { \
++ CLEAR_LE_OWN(pTable, i); \
++ i = (i + 1) & (NUM_LE_IN_TABLE(pTable) - 1); \
++ } \
++ }
++
++#else /* !SAFE_BUT_SLOW */
++
++#define CHECK_STLE_OVERFLOW(pTable, IsOk)
++#define CLEAR_LE_OWN(pTable, Idx)
++#define CLEAR_LE_OWN_FROM_DONE_TO(pTable, To)
++
++#endif /* !SAFE_BUT_SLOW */
++
++
++/* typedefs *******************************************************************/
++
++typedef struct s_LetRxTx {
++ SK_U16 VlanId; /* VLAN Id given down last time */
++ SK_U16 TcpWp; /* TCP Checksum Write Position */
++ SK_U16 TcpSp1; /* TCP Checksum Calculation Start Position 1 */
++ SK_U16 TcpSp2; /* TCP Checksum Calculation Start Position 2 */
++ SK_U16 MssValue; /* Maximum Segment Size */
++ SK_U16 Reserved1; /* reserved word for furture extensions */
++ SK_U16 Reserved2; /* reserved word for furture extensions */
++ SK_U16 Reserved3; /* reserved word for furture extensions */
++} SK_LET_RX_TX;
++
++typedef struct s_LetStat {
++ SK_U32 RxTimeStamp; /* Receive Timestamp */
++ SK_U32 RssHashValue; /* RSS Hash Value */
++ SK_BOOL RssIsIp; /* RSS Hash Value: IP packet detected */
++ SK_BOOL RssIsTcp; /* RSS Hash Value: IP+TCP packet detected */
++ SK_U16 VlanId; /* VLAN Id given received by Status BMU */
++ SK_U16 TcpSum1; /* TCP checksum 1 (status BMU) */
++ SK_U16 TcpSum2; /* TCP checksum 2 (status BMU) */
++} SK_LET_STAT;
++
++typedef union s_LetBmuSpec {
++ SK_LET_RX_TX RxTx; /* Rx/Tx BMU specific variables */
++ SK_LET_STAT Stat; /* Status BMU specific variables */
++} SK_LET_BMU_S;
++
++typedef struct s_le_table {
++ /* all LE's between Done and HWPut are owned by the hardware */
++ /* all LE's between Put and Done can be used from Software */
++ /* all LE's between HWPut and Put are currently processed in DriverSend */
++ unsigned Done; /* done index - consumed from HW and available */
++ unsigned Put; /* put index - to be given to hardware */
++ unsigned HwPut; /* put index actually given to hardware */
++ unsigned Num; /* total number of list elements */
++ SK_HWLE *pLETab; /* virtual address of list element table */
++ SK_U32 pPhyLETABLow; /* physical address of list element table */
++ SK_U32 pPhyLETABHigh; /* physical address of list element table */
++ /* values to remember in order to save some LEs */
++ SK_U32 BufHighAddr; /* high addr given down last time */
++ SK_LET_BMU_S Bmu; /* contains BMU specific information */
++ SK_U32 private; /* driver private variable free usable */
++ SK_U16 TcpInitCsum; /* Init. Checksum */
++} SK_LE_TABLE;
++
++/* function prototypes ********************************************************/
++
++#ifndef SK_KR_PROTO
++
++/*
++ * public functions in sky2le.c
++ */
++extern void SkGeY2SetPutIndex(
++ SK_AC *pAC,
++ SK_IOC IoC,
++ SK_U32 StartAddrPrefetchUnit,
++ SK_LE_TABLE *pLETab);
++
++extern void SkGeY2InitPrefetchUnit(
++ SK_AC *pAC,
++ SK_IOC IoC,
++ unsigned int Queue,
++ SK_LE_TABLE *pLETab);
++
++extern void SkGeY2InitStatBmu(
++ SK_AC *pAC,
++ SK_IOC IoC,
++ SK_LE_TABLE *pLETab);
++
++extern void SkGeY2InitPollUnit(
++ SK_AC *pAC,
++ SK_IOC IoC,
++ SK_LE_TABLE *pLETab);
++
++extern void SkGeY2InitSingleLETable(
++ SK_AC *pAC,
++ SK_LE_TABLE *pLETab,
++ unsigned int NumLE,
++ void *pVMem,
++ SK_U32 PMemLowAddr,
++ SK_U32 PMemHighAddr);
++
++#else /* SK_KR_PROTO */
++extern void SkGeY2SetPutIndex();
++extern void SkGeY2InitPrefetchUnit();
++extern void SkGeY2InitStatBmu();
++extern void SkGeY2InitPollUnit();
++extern void SkGeY2InitSingleLETable();
++#endif /* SK_KR_PROTO */
++
++#ifdef __cplusplus
++}
++#endif /* __cplusplus */
++
++#endif /* __INC_SKY2LE_H */
++
+diff -ruN linux/drivers/net/sk98lin/h/xmac_ii.h linux-new/drivers/net/sk98lin/h/xmac_ii.h
+--- linux/drivers/net/sk98lin/h/xmac_ii.h 2005-09-26 13:32:48.000000000 +0400
++++ linux-new/drivers/net/sk98lin/h/xmac_ii.h 2005-08-09 17:15:51.000000000 +0400
+@@ -2,8 +2,8 @@
+ *
+ * Name: xmac_ii.h
+ * Project: Gigabit Ethernet Adapters, Common Modules
+- * Version: $Revision: 1.52 $
+- * Date: $Date: 2003/10/02 16:35:50 $
++ * Version: $Revision: 2.11 $
++ * Date: $Date: 2005/01/04 14:14:20 $
+ * Purpose: Defines and Macros for Gigabit Ethernet Controller
+ *
+ ******************************************************************************/
+@@ -11,13 +11,12 @@
+ /******************************************************************************
+ *
+ * (C)Copyright 1998-2002 SysKonnect.
+- * (C)Copyright 2002-2003 Marvell.
++ * (C)Copyright 2002-2004 Marvell.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+- *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+@@ -449,7 +448,7 @@
+ /*
+ * Receive Frame Status Encoding
+ */
+-#define XMR_FS_LEN (0x3fffUL<<18) /* Bit 31..18: Rx Frame Length */
++#define XMR_FS_LEN_MSK (0x3fffUL<<18) /* Bit 31..18: Rx Frame Length */
+ #define XMR_FS_2L_VLAN (1L<<17) /* Bit 17: tagged wh 2Lev VLAN ID*/
+ #define XMR_FS_1L_VLAN (1L<<16) /* Bit 16: tagged wh 1Lev VLAN ID*/
+ #define XMR_FS_BC (1L<<15) /* Bit 15: Broadcast Frame */
+@@ -469,6 +468,8 @@
+ #define XMR_FS_ERR (1L<<1) /* Bit 1: Frame Error */
+ #define XMR_FS_MCTRL (1L<<0) /* Bit 0: MAC Control Packet */
+
++#define XMR_FS_LEN_SHIFT 18
++
+ /*
+ * XMR_FS_ERR will be set if
+ * XMR_FS_FCS_ERR, XMR_FS_LNG_ERR, XMR_FS_RUNT,
+@@ -510,7 +511,7 @@
+ #define PHY_BCOM_NEPG 0x07 /* 16 bit r/w Next Page Register */
+ #define PHY_BCOM_NEPG_LP 0x08 /* 16 bit r/o Next Page Link Partner */
+ /* Broadcom-specific registers */
+-#define PHY_BCOM_1000T_CTRL 0x09 /* 16 bit r/w 1000Base-T Ctrl Reg */
++#define PHY_BCOM_1000T_CTRL 0x09 /* 16 bit r/w 1000Base-T Control Reg */
+ #define PHY_BCOM_1000T_STAT 0x0a /* 16 bit r/o 1000Base-T Status Reg */
+ /* 0x0b - 0x0e: reserved */
+ #define PHY_BCOM_EXT_STAT 0x0f /* 16 bit r/o Extended Status Reg */
+@@ -541,24 +542,32 @@
+ #define PHY_MARV_NEPG 0x07 /* 16 bit r/w Next Page Register */
+ #define PHY_MARV_NEPG_LP 0x08 /* 16 bit r/o Next Page Link Partner */
+ /* Marvel-specific registers */
+-#define PHY_MARV_1000T_CTRL 0x09 /* 16 bit r/w 1000Base-T Ctrl Reg */
++#define PHY_MARV_1000T_CTRL 0x09 /* 16 bit r/w 1000Base-T Control Reg */
+ #define PHY_MARV_1000T_STAT 0x0a /* 16 bit r/o 1000Base-T Status Reg */
+ /* 0x0b - 0x0e: reserved */
+ #define PHY_MARV_EXT_STAT 0x0f /* 16 bit r/o Extended Status Reg */
+-#define PHY_MARV_PHY_CTRL 0x10 /* 16 bit r/w PHY Specific Ctrl Reg */
+-#define PHY_MARV_PHY_STAT 0x11 /* 16 bit r/o PHY Specific Stat Reg */
++#define PHY_MARV_PHY_CTRL 0x10 /* 16 bit r/w PHY Specific Control Reg */
++#define PHY_MARV_PHY_STAT 0x11 /* 16 bit r/o PHY Specific Status Reg */
+ #define PHY_MARV_INT_MASK 0x12 /* 16 bit r/w Interrupt Mask Reg */
+ #define PHY_MARV_INT_STAT 0x13 /* 16 bit r/o Interrupt Status Reg */
+ #define PHY_MARV_EXT_CTRL 0x14 /* 16 bit r/w Ext. PHY Specific Ctrl */
+ #define PHY_MARV_RXE_CNT 0x15 /* 16 bit r/w Receive Error Counter */
+ #define PHY_MARV_EXT_ADR 0x16 /* 16 bit r/w Ext. Ad. for Cable Diag. */
+- /* 0x17: reserved */
++#define PHY_MARV_PORT_IRQ 0x17 /* 16 bit r/o Port 0 IRQ (88E1111 only) */
+ #define PHY_MARV_LED_CTRL 0x18 /* 16 bit r/w LED Control Reg */
+ #define PHY_MARV_LED_OVER 0x19 /* 16 bit r/w Manual LED Override Reg */
+ #define PHY_MARV_EXT_CTRL_2 0x1a /* 16 bit r/w Ext. PHY Specific Ctrl 2 */
+ #define PHY_MARV_EXT_P_STAT 0x1b /* 16 bit r/w Ext. PHY Spec. Stat Reg */
+ #define PHY_MARV_CABLE_DIAG 0x1c /* 16 bit r/o Cable Diagnostic Reg */
+- /* 0x1d - 0x1f: reserved */
++#define PHY_MARV_PAGE_ADDR 0x1d /* 16 bit r/w Extended Page Address Reg */
++#define PHY_MARV_PAGE_DATA 0x1e /* 16 bit r/w Extended Page Data Reg */
++
++/* for 10/100 Fast Ethernet PHY (88E3082 only) */
++#define PHY_MARV_FE_LED_PAR 0x16 /* 16 bit r/w LED Parallel Select Reg. */
++#define PHY_MARV_FE_LED_SER 0x17 /* 16 bit r/w LED Stream Select S. LED */
++#define PHY_MARV_FE_VCT_TX 0x1a /* 16 bit r/w VCT Reg. for TXP/N Pins */
++#define PHY_MARV_FE_VCT_RX 0x1b /* 16 bit r/o VCT Reg. for RXP/N Pins */
++#define PHY_MARV_FE_SPEC_2 0x1c /* 16 bit r/w Specific Control Reg. 2 */
+
+ /*----------------------------------------------------------------------------*/
+ /*
+@@ -574,9 +583,9 @@
+ #define PHY_LONE_NEPG 0x07 /* 16 bit r/w Next Page Register */
+ #define PHY_LONE_NEPG_LP 0x08 /* 16 bit r/o Next Page Link Partner */
+ /* Level One-specific registers */
+-#define PHY_LONE_1000T_CTRL 0x09 /* 16 bit r/w 1000Base-T Control Reg*/
++#define PHY_LONE_1000T_CTRL 0x09 /* 16 bit r/w 1000Base-T Control Reg */
+ #define PHY_LONE_1000T_STAT 0x0a /* 16 bit r/o 1000Base-T Status Reg */
+- /* 0x0b -0x0e: reserved */
++ /* 0x0b - 0x0e: reserved */
+ #define PHY_LONE_EXT_STAT 0x0f /* 16 bit r/o Extended Status Reg */
+ #define PHY_LONE_PORT_CFG 0x10 /* 16 bit r/w Port Configuration Reg*/
+ #define PHY_LONE_Q_STAT 0x11 /* 16 bit r/o Quick Status Reg */
+@@ -585,7 +594,7 @@
+ #define PHY_LONE_LED_CFG 0x14 /* 16 bit r/w LED Configuration Reg */
+ #define PHY_LONE_PORT_CTRL 0x15 /* 16 bit r/w Port Control Reg */
+ #define PHY_LONE_CIM 0x16 /* 16 bit r/o CIM Reg */
+- /* 0x17 -0x1c: reserved */
++ /* 0x17 - 0x1c: reserved */
+
+ /*----------------------------------------------------------------------------*/
+ /*
+@@ -603,14 +612,14 @@
+ /* National-specific registers */
+ #define PHY_NAT_1000T_CTRL 0x09 /* 16 bit r/w 1000Base-T Control Reg */
+ #define PHY_NAT_1000T_STAT 0x0a /* 16 bit r/o 1000Base-T Status Reg */
+- /* 0x0b -0x0e: reserved */
++ /* 0x0b - 0x0e: reserved */
+ #define PHY_NAT_EXT_STAT 0x0f /* 16 bit r/o Extended Status Register */
+ #define PHY_NAT_EXT_CTRL1 0x10 /* 16 bit r/o Extended Control Reg1 */
+ #define PHY_NAT_Q_STAT1 0x11 /* 16 bit r/o Quick Status Reg1 */
+ #define PHY_NAT_10B_OP 0x12 /* 16 bit r/o 10Base-T Operations Reg */
+ #define PHY_NAT_EXT_CTRL2 0x13 /* 16 bit r/o Extended Control Reg1 */
+ #define PHY_NAT_Q_STAT2 0x14 /* 16 bit r/o Quick Status Reg2 */
+- /* 0x15 -0x18: reserved */
++ /* 0x15 - 0x18: reserved */
+ #define PHY_NAT_PHY_ADDR 0x19 /* 16 bit r/o PHY Address Register */
+
+
+@@ -618,7 +627,7 @@
+
+ /*
+ * PHY bit definitions
+- * Bits defined as PHY_X_..., PHY_B_..., PHY_L_... or PHY_N_... are
++ * Bits defined as PHY_X_..., PHY_B_..., PHY_L_..., PHY_N_... or PHY_M_... are
+ * XMAC/Broadcom/LevelOne/National/Marvell-specific.
+ * All other are general.
+ */
+@@ -629,14 +638,14 @@
+ /***** PHY_LONE_CTRL 16 bit r/w PHY Control Register *****/
+ #define PHY_CT_RESET (1<<15) /* Bit 15: (sc) clear all PHY related regs */
+ #define PHY_CT_LOOP (1<<14) /* Bit 14: enable Loopback over PHY */
+-#define PHY_CT_SPS_LSB (1<<13) /* Bit 13: (BC,L1) Speed select, lower bit */
++#define PHY_CT_SPS_LSB (1<<13) /* Bit 13: Speed select, lower bit */
+ #define PHY_CT_ANE (1<<12) /* Bit 12: Auto-Negotiation Enabled */
+-#define PHY_CT_PDOWN (1<<11) /* Bit 11: (BC,L1) Power Down Mode */
+-#define PHY_CT_ISOL (1<<10) /* Bit 10: (BC,L1) Isolate Mode */
+-#define PHY_CT_RE_CFG (1<<9) /* Bit 9: (sc) Restart Auto-Negotiation */
++#define PHY_CT_PDOWN (1<<11) /* Bit 11: Power Down Mode */
++#define PHY_CT_ISOL (1<<10) /* Bit 10: Isolate Mode */
++#define PHY_CT_RE_CFG (1<<9) /* Bit 9: (sc) Restart Auto-Negotiation */
+ #define PHY_CT_DUP_MD (1<<8) /* Bit 8: Duplex Mode */
+-#define PHY_CT_COL_TST (1<<7) /* Bit 7: (BC,L1) Collision Test enabled */
+-#define PHY_CT_SPS_MSB (1<<6) /* Bit 6: (BC,L1) Speed select, upper bit */
++#define PHY_CT_COL_TST (1<<7) /* Bit 7: Collision Test enabled */
++#define PHY_CT_SPS_MSB (1<<6) /* Bit 6: Speed select, upper bit */
+ /* Bit 5..0: reserved */
+
+ #define PHY_CT_SP1000 PHY_CT_SPS_MSB /* enable speed of 1000 Mbps */
+@@ -649,25 +658,25 @@
+ /***** PHY_MARV_STAT 16 bit r/w PHY Status Register *****/
+ /***** PHY_LONE_STAT 16 bit r/w PHY Status Register *****/
+ /* Bit 15..9: reserved */
+- /* (BC/L1) 100/10 Mbps cap bits ignored*/
++ /* (BC/L1) 100/10 Mbps cap bits ignored */
+ #define PHY_ST_EXT_ST (1<<8) /* Bit 8: Extended Status Present */
+ /* Bit 7: reserved */
+-#define PHY_ST_PRE_SUP (1<<6) /* Bit 6: (BC/L1) preamble suppression */
++#define PHY_ST_PRE_SUP (1<<6) /* Bit 6: Preamble Suppression */
+ #define PHY_ST_AN_OVER (1<<5) /* Bit 5: Auto-Negotiation Over */
+ #define PHY_ST_REM_FLT (1<<4) /* Bit 4: Remote Fault Condition Occured */
+ #define PHY_ST_AN_CAP (1<<3) /* Bit 3: Auto-Negotiation Capability */
+ #define PHY_ST_LSYNC (1<<2) /* Bit 2: Link Synchronized */
+-#define PHY_ST_JAB_DET (1<<1) /* Bit 1: (BC/L1) Jabber Detected */
++#define PHY_ST_JAB_DET (1<<1) /* Bit 1: Jabber Detected */
+ #define PHY_ST_EXT_REG (1<<0) /* Bit 0: Extended Register available */
+
+
+-/***** PHY_XMAC_ID1 16 bit r/o PHY ID1 Register */
+-/***** PHY_BCOM_ID1 16 bit r/o PHY ID1 Register */
+-/***** PHY_MARV_ID1 16 bit r/o PHY ID1 Register */
+-/***** PHY_LONE_ID1 16 bit r/o PHY ID1 Register */
++/***** PHY_XMAC_ID1 16 bit r/o PHY ID1 Register */
++/***** PHY_BCOM_ID1 16 bit r/o PHY ID1 Register */
++/***** PHY_MARV_ID1 16 bit r/o PHY ID1 Register */
++/***** PHY_LONE_ID1 16 bit r/o PHY ID1 Register */
+ #define PHY_I1_OUI_MSK (0x3f<<10) /* Bit 15..10: Organization Unique ID */
+ #define PHY_I1_MOD_NUM (0x3f<<4) /* Bit 9.. 4: Model Number */
+-#define PHY_I1_REV_MSK 0x0f /* Bit 3.. 0: Revision Number */
++#define PHY_I1_REV_MSK 0xf /* Bit 3.. 0: Revision Number */
+
+ /* different Broadcom PHY Ids */
+ #define PHY_BCOM_ID1_A1 0x6041
+@@ -675,11 +684,19 @@
+ #define PHY_BCOM_ID1_C0 0x6044
+ #define PHY_BCOM_ID1_C5 0x6047
+
++/* different Marvell PHY Ids */
++#define PHY_MARV_ID0_VAL 0x0141 /* Marvell Unique Identifier */
++
++#define PHY_MARV_ID1_B0 0x0C23 /* Yukon (PHY 88E1011) */
++#define PHY_MARV_ID1_B2 0x0C25 /* Yukon-Plus (PHY 88E1011) */
++#define PHY_MARV_ID1_C2 0x0CC2 /* Yukon-EC (PHY 88E1111) */
++#define PHY_MARV_ID1_Y2 0x0C91 /* Yukon-2 (PHY 88E1112) */
++
+
+ /***** PHY_XMAC_AUNE_ADV 16 bit r/w Auto-Negotiation Advertisement *****/
+ /***** PHY_XMAC_AUNE_LP 16 bit r/o Link Partner Ability Reg *****/
+ #define PHY_AN_NXT_PG (1<<15) /* Bit 15: Request Next Page */
+-#define PHY_X_AN_ACK (1<<14) /* Bit 14: (ro) Acknowledge Received */
++#define PHY_X_AN_ACK (1<<14) /* Bit 14: (ro) Acknowledge Received */
+ #define PHY_X_AN_RFB (3<<12) /* Bit 13..12: Remote Fault Bits */
+ /* Bit 11.. 9: reserved */
+ #define PHY_X_AN_PAUSE (3<<7) /* Bit 8.. 7: Pause Bits */
+@@ -827,7 +844,7 @@
+ #define PHY_B_PEC_BY_MLT3 (1<<8) /* Bit 8: Bypass MLT3 Encoder */
+ #define PHY_B_PEC_BY_RXA (1<<7) /* Bit 7: Bypass Rx Alignm. */
+ #define PHY_B_PEC_RES_SCR (1<<6) /* Bit 6: Reset Scrambler */
+-#define PHY_B_PEC_EN_LTR (1<<5) /* Bit 5: Ena LED Traffic Mode */
++#define PHY_B_PEC_EN_LTR (1<<5) /* Bit 5: Enable LED Traffic Mode */
+ #define PHY_B_PEC_LED_ON (1<<4) /* Bit 4: Force LED's on */
+ #define PHY_B_PEC_LED_OFF (1<<3) /* Bit 3: Force LED's off */
+ #define PHY_B_PEC_EX_IPG (1<<2) /* Bit 2: Extend Tx IPG Mode */
+@@ -981,7 +998,7 @@
+ #define PHY_L_QS_DUP_MOD (1<<9) /* Bit 9: Full/Half Duplex */
+ #define PHY_L_QS_AN (1<<8) /* Bit 8: AutoNeg is On */
+ #define PHY_L_QS_AN_C (1<<7) /* Bit 7: AN is Complete */
+-#define PHY_L_QS_LLE (7<<4) /* Bit 6: Line Length Estim. */
++#define PHY_L_QS_LLE (7<<4) /* Bit 6..4: Line Length Estim. */
+ #define PHY_L_QS_PAUSE (1<<3) /* Bit 3: LP advertised Pause */
+ #define PHY_L_QS_AS_PAUSE (1<<2) /* Bit 2: LP adv. asym. Pause */
+ #define PHY_L_QS_ISOLATE (1<<1) /* Bit 1: CIM Isolated */
+@@ -1029,9 +1046,8 @@
+ /* Bit 9..0: not described */
+
+ /***** PHY_LONE_CIM 16 bit r/o CIM Reg *****/
+-#define PHY_L_CIM_ISOL (255<<8)/* Bit 15..8: Isolate Count */
+-#define PHY_L_CIM_FALSE_CAR (255<<0)/* Bit 7..0: False Carrier Count */
+-
++#define PHY_L_CIM_ISOL (0xff<<8) /* Bit 15..8: Isolate Count */
++#define PHY_L_CIM_FALSE_CAR 0xff /* Bit 7..0: False Carrier Count */
+
+ /*
+ * Pause Bits (PHY_L_AN_ASP and PHY_L_AN_PC) encoding
+@@ -1041,7 +1057,6 @@
+ #define PHY_L_P_ASYM_MD (2<<10) /* Bit 11..10: asymmetric Pause Mode */
+ #define PHY_L_P_BOTH_MD (3<<10) /* Bit 11..10: both Pause Mode */
+
+-
+ /*
+ * National-Specific
+ */
+@@ -1086,22 +1101,24 @@
+ */
+ /***** PHY_MARV_AUNE_ADV 16 bit r/w Auto-Negotiation Advertisement *****/
+ /***** PHY_MARV_AUNE_LP 16 bit r/w Link Part Ability Reg *****/
+-#define PHY_M_AN_NXT_PG BIT_15 /* Request Next Page */
+-#define PHY_M_AN_ACK BIT_14 /* (ro) Acknowledge Received */
+-#define PHY_M_AN_RF BIT_13 /* Remote Fault */
+- /* Bit 12: reserved */
+-#define PHY_M_AN_ASP BIT_11 /* Asymmetric Pause */
+-#define PHY_M_AN_PC BIT_10 /* MAC Pause implemented */
+-#define PHY_M_AN_100_FD BIT_8 /* Advertise 100Base-TX Full Duplex */
+-#define PHY_M_AN_100_HD BIT_7 /* Advertise 100Base-TX Half Duplex */
+-#define PHY_M_AN_10_FD BIT_6 /* Advertise 10Base-TX Full Duplex */
+-#define PHY_M_AN_10_HD BIT_5 /* Advertise 10Base-TX Half Duplex */
++#define PHY_M_AN_NXT_PG BIT_15S /* Request Next Page */
++#define PHY_M_AN_ACK BIT_14S /* (ro) Acknowledge Received */
++#define PHY_M_AN_RF BIT_13S /* Remote Fault */
++ /* Bit 12: reserved */
++#define PHY_M_AN_ASP BIT_11S /* Asymmetric Pause */
++#define PHY_M_AN_PC BIT_10S /* MAC Pause implemented */
++#define PHY_M_AN_100_T4 BIT_9S /* Not cap. 100Base-T4 (always 0) */
++#define PHY_M_AN_100_FD BIT_8S /* Advertise 100Base-TX Full Duplex */
++#define PHY_M_AN_100_HD BIT_7S /* Advertise 100Base-TX Half Duplex */
++#define PHY_M_AN_10_FD BIT_6S /* Advertise 10Base-TX Full Duplex */
++#define PHY_M_AN_10_HD BIT_5S /* Advertise 10Base-TX Half Duplex */
++#define PHY_M_AN_SEL_MSK (0x1f<<4) /* Bit 4.. 0: Selector Field Mask */
+
+ /* special defines for FIBER (88E1011S only) */
+-#define PHY_M_AN_ASP_X BIT_8 /* Asymmetric Pause */
+-#define PHY_M_AN_PC_X BIT_7 /* MAC Pause implemented */
+-#define PHY_M_AN_1000X_AHD BIT_6 /* Advertise 10000Base-X Half Duplex */
+-#define PHY_M_AN_1000X_AFD BIT_5 /* Advertise 10000Base-X Full Duplex */
++#define PHY_M_AN_ASP_X BIT_8S /* Asymmetric Pause */
++#define PHY_M_AN_PC_X BIT_7S /* MAC Pause implemented */
++#define PHY_M_AN_1000X_AHD BIT_6S /* Advertise 10000Base-X Half Duplex */
++#define PHY_M_AN_1000X_AFD BIT_5S /* Advertise 10000Base-X Full Duplex */
+
+ /* Pause Bits (PHY_M_AN_ASP_X and PHY_M_AN_PC_X) encoding */
+ #define PHY_M_P_NO_PAUSE_X (0<<7) /* Bit 8.. 7: no Pause Mode */
+@@ -1111,105 +1128,162 @@
+
+ /***** PHY_MARV_1000T_CTRL 16 bit r/w 1000Base-T Control Reg *****/
+ #define PHY_M_1000C_TEST (7<<13) /* Bit 15..13: Test Modes */
+-#define PHY_M_1000C_MSE (1<<12) /* Bit 12: Manual Master/Slave Enable */
+-#define PHY_M_1000C_MSC (1<<11) /* Bit 11: M/S Configuration (1=Master) */
+-#define PHY_M_1000C_MPD (1<<10) /* Bit 10: Multi-Port Device */
+-#define PHY_M_1000C_AFD (1<<9) /* Bit 9: Advertise Full Duplex */
+-#define PHY_M_1000C_AHD (1<<8) /* Bit 8: Advertise Half Duplex */
++#define PHY_M_1000C_MSE BIT_12S /* Manual Master/Slave Enable */
++#define PHY_M_1000C_MSC BIT_11S /* M/S Configuration (1=Master) */
++#define PHY_M_1000C_MPD BIT_10S /* Multi-Port Device */
++#define PHY_M_1000C_AFD BIT_9S /* Advertise Full Duplex */
++#define PHY_M_1000C_AHD BIT_8S /* Advertise Half Duplex */
+ /* Bit 7..0: reserved */
+
+ /***** PHY_MARV_PHY_CTRL 16 bit r/w PHY Specific Ctrl Reg *****/
+-#define PHY_M_PC_TX_FFD_MSK (3<<14) /* Bit 15..14: Tx FIFO Depth Mask */
+-#define PHY_M_PC_RX_FFD_MSK (3<<12) /* Bit 13..12: Rx FIFO Depth Mask */
+-#define PHY_M_PC_ASS_CRS_TX (1<<11) /* Bit 11: Assert CRS on Transmit */
+-#define PHY_M_PC_FL_GOOD (1<<10) /* Bit 10: Force Link Good */
+-#define PHY_M_PC_EN_DET_MSK (3<<8) /* Bit 9.. 8: Energy Detect Mask */
+-#define PHY_M_PC_ENA_EXT_D (1<<7) /* Bit 7: Enable Ext. Distance (10BT) */
+-#define PHY_M_PC_MDIX_MSK (3<<5) /* Bit 6.. 5: MDI/MDIX Config. Mask */
+-#define PHY_M_PC_DIS_125CLK (1<<4) /* Bit 4: Disable 125 CLK */
+-#define PHY_M_PC_MAC_POW_UP (1<<3) /* Bit 3: MAC Power up */
+-#define PHY_M_PC_SQE_T_ENA (1<<2) /* Bit 2: SQE Test Enabled */
+-#define PHY_M_PC_POL_R_DIS (1<<1) /* Bit 1: Polarity Reversal Disabled */
+-#define PHY_M_PC_DIS_JABBER (1<<0) /* Bit 0: Disable Jabber */
++#define PHY_M_PC_TX_FFD_MSK (3<<14) /* Bit 15..14: Tx FIFO Depth Mask */
++#define PHY_M_PC_RX_FFD_MSK (3<<12) /* Bit 13..12: Rx FIFO Depth Mask */
++#define PHY_M_PC_ASS_CRS_TX BIT_11S /* Assert CRS on Transmit */
++#define PHY_M_PC_FL_GOOD BIT_10S /* Force Link Good */
++#define PHY_M_PC_EN_DET_MSK (3<<8) /* Bit 9.. 8: Energy Detect Mask */
++#define PHY_M_PC_ENA_EXT_D BIT_7S /* Enable Ext. Distance (10BT) */
++#define PHY_M_PC_MDIX_MSK (3<<5) /* Bit 6.. 5: MDI/MDIX Config. Mask */
++#define PHY_M_PC_DIS_125CLK BIT_4S /* Disable 125 CLK */
++#define PHY_M_PC_MAC_POW_UP BIT_3S /* MAC Power up */
++#define PHY_M_PC_SQE_T_ENA BIT_2S /* SQE Test Enabled */
++#define PHY_M_PC_POL_R_DIS BIT_1S /* Polarity Reversal Disabled */
++#define PHY_M_PC_DIS_JABBER BIT_0S /* Disable Jabber */
+
+ #define PHY_M_PC_EN_DET SHIFT8(2) /* Energy Detect (Mode 1) */
+ #define PHY_M_PC_EN_DET_PLUS SHIFT8(3) /* Energy Detect Plus (Mode 2) */
+
+-#define PHY_M_PC_MDI_XMODE(x) SHIFT5(x)
+-#define PHY_M_PC_MAN_MDI 0 /* 00 = Manual MDI configuration */
++#define PHY_M_PC_MDI_XMODE(x) (SHIFT5(x) & PHY_M_PC_MDIX_MSK)
++
++#define PHY_M_PC_MAN_MDI 0 /* 00 = Manual MDI configuration */
+ #define PHY_M_PC_MAN_MDIX 1 /* 01 = Manual MDIX configuration */
+ #define PHY_M_PC_ENA_AUTO 3 /* 11 = Enable Automatic Crossover */
+
++/* for Yukon-2 Gigabit Ethernet PHY (88E1112 only) */
++#define PHY_M_PC_DIS_LINK_P BIT_15S /* Disable Link Pulses */
++#define PHY_M_PC_DSC_MSK (7<<12) /* Bit 14..12: Downshift Counter */
++#define PHY_M_PC_DOWN_S_ENA BIT_11S /* Downshift Enable */
++ /* !!! Errata in spec. (1 = disable) */
++
++#define PHY_M_PC_DSC(x) (SHIFT12(x) & PHY_M_PC_DSC_MSK)
++ /* 000=1x; 001=2x; 010=3x; 011=4x */
++ /* 100=5x; 101=6x; 110=7x; 111=8x */
++
++/* for 10/100 Fast Ethernet PHY (88E3082 only) */
++#define PHY_M_PC_ENA_DTE_DT BIT_15S /* Enable Data Terminal Equ. (DTE) Detect */
++#define PHY_M_PC_ENA_ENE_DT BIT_14S /* Enable Energy Detect (sense & pulse) */
++#define PHY_M_PC_DIS_NLP_CK BIT_13S /* Disable Normal Link Puls (NLP) Check */
++#define PHY_M_PC_ENA_LIP_NP BIT_12S /* Enable Link Partner Next Page Reg. */
++#define PHY_M_PC_DIS_NLP_GN BIT_11S /* Disable Normal Link Puls Generation */
++
++#define PHY_M_PC_DIS_SCRAMB BIT_9S /* Disable Scrambler */
++#define PHY_M_PC_DIS_FEFI BIT_8S /* Disable Far End Fault Indic. (FEFI) */
++
++#define PHY_M_PC_SH_TP_SEL BIT_6S /* Shielded Twisted Pair Select */
++#define PHY_M_PC_RX_FD_MSK (3<<2) /* Bit 3.. 2: Rx FIFO Depth Mask */
++
+ /***** PHY_MARV_PHY_STAT 16 bit r/o PHY Specific Status Reg *****/
+-#define PHY_M_PS_SPEED_MSK (3<<14) /* Bit 15..14: Speed Mask */
+-#define PHY_M_PS_SPEED_1000 (1<<15) /* 10 = 1000 Mbps */
+-#define PHY_M_PS_SPEED_100 (1<<14) /* 01 = 100 Mbps */
+-#define PHY_M_PS_SPEED_10 0 /* 00 = 10 Mbps */
+-#define PHY_M_PS_FULL_DUP (1<<13) /* Bit 13: Full Duplex */
+-#define PHY_M_PS_PAGE_REC (1<<12) /* Bit 12: Page Received */
+-#define PHY_M_PS_SPDUP_RES (1<<11) /* Bit 11: Speed & Duplex Resolved */
+-#define PHY_M_PS_LINK_UP (1<<10) /* Bit 10: Link Up */
+-#define PHY_M_PS_CABLE_MSK (3<<7) /* Bit 9.. 7: Cable Length Mask */
+-#define PHY_M_PS_MDI_X_STAT (1<<6) /* Bit 6: MDI Crossover Stat (1=MDIX) */
+-#define PHY_M_PS_DOWNS_STAT (1<<5) /* Bit 5: Downshift Status (1=downsh.) */
+-#define PHY_M_PS_ENDET_STAT (1<<4) /* Bit 4: Energy Detect Status (1=act) */
+-#define PHY_M_PS_TX_P_EN (1<<3) /* Bit 3: Tx Pause Enabled */
+-#define PHY_M_PS_RX_P_EN (1<<2) /* Bit 2: Rx Pause Enabled */
+-#define PHY_M_PS_POL_REV (1<<1) /* Bit 1: Polarity Reversed */
+-#define PHY_M_PC_JABBER (1<<0) /* Bit 0: Jabber */
++#define PHY_M_PS_SPEED_MSK (3<<14) /* Bit 15..14: Speed Mask */
++#define PHY_M_PS_SPEED_1000 BIT_15S /* 10 = 1000 Mbps */
++#define PHY_M_PS_SPEED_100 BIT_14S /* 01 = 100 Mbps */
++#define PHY_M_PS_SPEED_10 0 /* 00 = 10 Mbps */
++#define PHY_M_PS_FULL_DUP BIT_13S /* Full Duplex */
++#define PHY_M_PS_PAGE_REC BIT_12S /* Page Received */
++#define PHY_M_PS_SPDUP_RES BIT_11S /* Speed & Duplex Resolved */
++#define PHY_M_PS_LINK_UP BIT_10S /* Link Up */
++#define PHY_M_PS_CABLE_MSK (7<<7) /* Bit 9.. 7: Cable Length Mask */
++#define PHY_M_PS_MDI_X_STAT BIT_6S /* MDI Crossover Stat (1=MDIX) */
++#define PHY_M_PS_DOWNS_STAT BIT_5S /* Downshift Status (1=downsh.) */
++#define PHY_M_PS_ENDET_STAT BIT_4S /* Energy Detect Status (1=act) */
++#define PHY_M_PS_TX_P_EN BIT_3S /* Tx Pause Enabled */
++#define PHY_M_PS_RX_P_EN BIT_2S /* Rx Pause Enabled */
++#define PHY_M_PS_POL_REV BIT_1S /* Polarity Reversed */
++#define PHY_M_PS_JABBER BIT_0S /* Jabber */
+
+ #define PHY_M_PS_PAUSE_MSK (PHY_M_PS_TX_P_EN | PHY_M_PS_RX_P_EN)
+
++/* for 10/100 Fast Ethernet PHY (88E3082 only) */
++#define PHY_M_PS_DTE_DETECT BIT_15S /* Data Terminal Equipment (DTE) Detected */
++#define PHY_M_PS_RES_SPEED BIT_14S /* Resolved Speed (1=100 Mbps, 0=10 Mbps */
++
+ /***** PHY_MARV_INT_MASK 16 bit r/w Interrupt Mask Reg *****/
+ /***** PHY_MARV_INT_STAT 16 bit r/o Interrupt Status Reg *****/
+-#define PHY_M_IS_AN_ERROR (1<<15) /* Bit 15: Auto-Negotiation Error */
+-#define PHY_M_IS_LSP_CHANGE (1<<14) /* Bit 14: Link Speed Changed */
+-#define PHY_M_IS_DUP_CHANGE (1<<13) /* Bit 13: Duplex Mode Changed */
+-#define PHY_M_IS_AN_PR (1<<12) /* Bit 12: Page Received */
+-#define PHY_M_IS_AN_COMPL (1<<11) /* Bit 11: Auto-Negotiation Completed */
+-#define PHY_M_IS_LST_CHANGE (1<<10) /* Bit 10: Link Status Changed */
+-#define PHY_M_IS_SYMB_ERROR (1<<9) /* Bit 9: Symbol Error */
+-#define PHY_M_IS_FALSE_CARR (1<<8) /* Bit 8: False Carrier */
+-#define PHY_M_IS_FIFO_ERROR (1<<7) /* Bit 7: FIFO Overflow/Underrun Error */
+-#define PHY_M_IS_MDI_CHANGE (1<<6) /* Bit 6: MDI Crossover Changed */
+-#define PHY_M_IS_DOWNSH_DET (1<<5) /* Bit 5: Downshift Detected */
+-#define PHY_M_IS_END_CHANGE (1<<4) /* Bit 4: Energy Detect Changed */
+- /* Bit 3..2: reserved */
+-#define PHY_M_IS_POL_CHANGE (1<<1) /* Bit 1: Polarity Changed */
+-#define PHY_M_IS_JABBER (1<<0) /* Bit 0: Jabber */
++#define PHY_M_IS_AN_ERROR BIT_15S /* Auto-Negotiation Error */
++#define PHY_M_IS_LSP_CHANGE BIT_14S /* Link Speed Changed */
++#define PHY_M_IS_DUP_CHANGE BIT_13S /* Duplex Mode Changed */
++#define PHY_M_IS_AN_PR BIT_12S /* Page Received */
++#define PHY_M_IS_AN_COMPL BIT_11S /* Auto-Negotiation Completed */
++#define PHY_M_IS_LST_CHANGE BIT_10S /* Link Status Changed */
++#define PHY_M_IS_SYMB_ERROR BIT_9S /* Symbol Error */
++#define PHY_M_IS_FALSE_CARR BIT_8S /* False Carrier */
++#define PHY_M_IS_FIFO_ERROR BIT_7S /* FIFO Overflow/Underrun Error */
++#define PHY_M_IS_MDI_CHANGE BIT_6S /* MDI Crossover Changed */
++#define PHY_M_IS_DOWNSH_DET BIT_5S /* Downshift Detected */
++#define PHY_M_IS_END_CHANGE BIT_4S /* Energy Detect Changed */
++ /* Bit 3: reserved */
++#define PHY_M_IS_DTE_CHANGE BIT_2S /* DTE Power Det. Status Changed */
++ /* (88E1111 only) */
++#define PHY_M_IS_POL_CHANGE BIT_1S /* Polarity Changed */
++#define PHY_M_IS_JABBER BIT_0S /* Jabber */
+
+ #define PHY_M_DEF_MSK (PHY_M_IS_AN_ERROR | PHY_M_IS_AN_PR | \
+ PHY_M_IS_LST_CHANGE | PHY_M_IS_FIFO_ERROR)
+
+ /***** PHY_MARV_EXT_CTRL 16 bit r/w Ext. PHY Specific Ctrl *****/
+-#define PHY_M_EC_M_DSC_MSK (3<<10) /* Bit 11..10: Master downshift counter */
+-#define PHY_M_EC_S_DSC_MSK (3<<8) /* Bit 9.. 8: Slave downshift counter */
++#define PHY_M_EC_ENA_BC_EXT BIT_15S /* Enable Block Carr. Ext. (88E1111 only) */
++#define PHY_M_EC_ENA_LIN_LB BIT_14S /* Enable Line Loopback (88E1111 only) */
++ /* Bit 13: reserved */
++#define PHY_M_EC_DIS_LINK_P BIT_12S /* Disable Link Pulses (88E1111 only) */
++#define PHY_M_EC_M_DSC_MSK (3<<10) /* Bit 11..10: Master Downshift Counter */
++ /* (88E1011 only) */
++#define PHY_M_EC_S_DSC_MSK (3<<8) /* Bit 9.. 8: Slave Downshift Counter */
++ /* (88E1011 only) */
++#define PHY_M_EC_DSC_MSK_2 (7<<9) /* Bit 11.. 9: Downshift Counter */
++ /* (88E1111 only) */
++#define PHY_M_EC_DOWN_S_ENA BIT_8S /* Downshift Enable (88E1111 only) */
++ /* !!! Errata in spec. (1 = disable) */
++#define PHY_M_EC_RX_TIM_CT BIT_7S /* RGMII Rx Timing Control*/
+ #define PHY_M_EC_MAC_S_MSK (7<<4) /* Bit 6.. 4: Def. MAC interface speed */
+-#define PHY_M_EC_FIB_AN_ENA (1<<3) /* Bit 3: Fiber Auto-Neg. Enable */
+-
+-#define PHY_M_EC_M_DSC(x) SHIFT10(x) /* 00=1x; 01=2x; 10=3x; 11=4x */
+-#define PHY_M_EC_S_DSC(x) SHIFT8(x) /* 00=dis; 01=1x; 10=2x; 11=3x */
+-#define PHY_M_EC_MAC_S(x) SHIFT4(x) /* 01X=0; 110=2.5; 111=25 (MHz) */
+-
++#define PHY_M_EC_FIB_AN_ENA BIT_3S /* Fiber Auto-Neg. Enable (88E1011S only) */
++#define PHY_M_EC_DTE_D_ENA BIT_2S /* DTE Detect Enable (88E1111 only) */
++#define PHY_M_EC_TX_TIM_CT BIT_1S /* RGMII Tx Timing Control */
++#define PHY_M_EC_TRANS_DIS BIT_0S /* Transmitter Disable (88E1111 only) */
++
++#define PHY_M_EC_M_DSC(x) (SHIFT10(x) & PHY_M_EC_M_DSC_MSK)
++ /* 00=1x; 01=2x; 10=3x; 11=4x */
++#define PHY_M_EC_S_DSC(x) (SHIFT8(x) & PHY_M_EC_S_DSC_MSK)
++ /* 00=dis; 01=1x; 10=2x; 11=3x */
++#define PHY_M_EC_MAC_S(x) (SHIFT4(x) & PHY_M_EC_MAC_S_MSK)
++ /* 01X=0; 110=2.5; 111=25 (MHz) */
++
++#define PHY_M_EC_DSC_2(x) (SHIFT9(x) & PHY_M_EC_DSC_MSK_2)
++ /* 000=1x; 001=2x; 010=3x; 011=4x */
++ /* 100=5x; 101=6x; 110=7x; 111=8x */
+ #define MAC_TX_CLK_0_MHZ 2
+ #define MAC_TX_CLK_2_5_MHZ 6
+ #define MAC_TX_CLK_25_MHZ 7
+
+ /***** PHY_MARV_LED_CTRL 16 bit r/w LED Control Reg *****/
+-#define PHY_M_LEDC_DIS_LED (1<<15) /* Bit 15: Disable LED */
+-#define PHY_M_LEDC_PULS_MSK (7<<12) /* Bit 14..12: Pulse Stretch Mask */
+-#define PHY_M_LEDC_F_INT (1<<11) /* Bit 11: Force Interrupt */
+-#define PHY_M_LEDC_BL_R_MSK (7<<8) /* Bit 10.. 8: Blink Rate Mask */
+- /* Bit 7.. 5: reserved */
+-#define PHY_M_LEDC_LINK_MSK (3<<3) /* Bit 4.. 3: Link Control Mask */
+-#define PHY_M_LEDC_DP_CTRL (1<<2) /* Bit 2: Duplex Control */
+-#define PHY_M_LEDC_RX_CTRL (1<<1) /* Bit 1: Rx activity / Link */
+-#define PHY_M_LEDC_TX_CTRL (1<<0) /* Bit 0: Tx activity / Link */
++#define PHY_M_LEDC_DIS_LED BIT_15S /* Disable LED */
++#define PHY_M_LEDC_PULS_MSK (7<<12) /* Bit 14..12: Pulse Stretch Mask */
++#define PHY_M_LEDC_F_INT BIT_11S /* Force Interrupt */
++#define PHY_M_LEDC_BL_R_MSK (7<<8) /* Bit 10.. 8: Blink Rate Mask */
++#define PHY_M_LEDC_DP_C_LSB BIT_7S /* Duplex Control (LSB, 88E1111 only) */
++#define PHY_M_LEDC_TX_C_LSB BIT_6S /* Tx Control (LSB, 88E1111 only) */
++#define PHY_M_LEDC_LK_C_MSK (7<<3) /* Bit 5.. 3: Link Control Mask */
++ /* (88E1111 only) */
++ /* Bit 7.. 5: reserved (88E1011 only) */
++#define PHY_M_LEDC_LINK_MSK (3<<3) /* Bit 4.. 3: Link Control Mask */
++ /* (88E1011 only) */
++#define PHY_M_LEDC_DP_CTRL BIT_2S /* Duplex Control */
++#define PHY_M_LEDC_DP_C_MSB BIT_2S /* Duplex Control (MSB, 88E1111 only) */
++#define PHY_M_LEDC_RX_CTRL BIT_1S /* Rx Activity / Link */
++#define PHY_M_LEDC_TX_CTRL BIT_0S /* Tx Activity / Link */
++#define PHY_M_LEDC_TX_C_MSB BIT_0S /* Tx Control (MSB, 88E1111 only) */
+
+-#define PHY_M_LED_PULS_DUR(x) SHIFT12(x) /* Pulse Stretch Duration */
++#define PHY_M_LED_PULS_DUR(x) (SHIFT12(x) & PHY_M_LEDC_PULS_MSK)
+
+-#define PULS_NO_STR 0 /* no pulse stretching */
+-#define PULS_21MS 1 /* 21 ms to 42 ms */
++#define PULS_NO_STR 0 /* no pulse stretching */
++#define PULS_21MS 1 /* 21 ms to 42 ms */
+ #define PULS_42MS 2 /* 42 ms to 84 ms */
+ #define PULS_84MS 3 /* 84 ms to 170 ms */
+ #define PULS_170MS 4 /* 170 ms to 340 ms */
+@@ -1217,7 +1291,7 @@
+ #define PULS_670MS 6 /* 670 ms to 1.3 s */
+ #define PULS_1300MS 7 /* 1.3 s to 2.7 s */
+
+-#define PHY_M_LED_BLINK_RT(x) SHIFT8(x) /* Blink Rate */
++#define PHY_M_LED_BLINK_RT(x) (SHIFT8(x) & PHY_M_LEDC_BL_R_MSK)
+
+ #define BLINK_42MS 0 /* 42 ms */
+ #define BLINK_84MS 1 /* 84 ms */
+@@ -1227,6 +1301,8 @@
+ /* values 5 - 7: reserved */
+
+ /***** PHY_MARV_LED_OVER 16 bit r/w Manual LED Override Reg *****/
++#define PHY_M_LED_MO_SGMII(x) SHIFT14(x) /* Bit 15..14: SGMII AN Timer */
++ /* Bit 13..12: reserved */
+ #define PHY_M_LED_MO_DUP(x) SHIFT10(x) /* Bit 11..10: Duplex */
+ #define PHY_M_LED_MO_10(x) SHIFT8(x) /* Bit 9.. 8: Link 10 */
+ #define PHY_M_LED_MO_100(x) SHIFT6(x) /* Bit 7.. 6: Link 100 */
+@@ -1240,30 +1316,35 @@
+ #define MO_LED_ON 3
+
+ /***** PHY_MARV_EXT_CTRL_2 16 bit r/w Ext. PHY Specific Ctrl 2 *****/
+- /* Bit 15.. 7: reserved */
+-#define PHY_M_EC2_FI_IMPED (1<<6) /* Bit 6: Fiber Input Impedance */
+-#define PHY_M_EC2_FO_IMPED (1<<5) /* Bit 5: Fiber Output Impedance */
+-#define PHY_M_EC2_FO_M_CLK (1<<4) /* Bit 4: Fiber Mode Clock Enable */
+-#define PHY_M_EC2_FO_BOOST (1<<3) /* Bit 3: Fiber Output Boost */
++ /* Bit 15.. 7: reserved */
++#define PHY_M_EC2_FI_IMPED BIT_6S /* Fiber Input Impedance */
++#define PHY_M_EC2_FO_IMPED BIT_5S /* Fiber Output Impedance */
++#define PHY_M_EC2_FO_M_CLK BIT_4S /* Fiber Mode Clock Enable */
++#define PHY_M_EC2_FO_BOOST BIT_3S /* Fiber Output Boost */
+ #define PHY_M_EC2_FO_AM_MSK 7 /* Bit 2.. 0: Fiber Output Amplitude */
+
+-/***** PHY_MARV_EXT_P_STAT 16 bit r/w Ext. PHY Specific Status *****/
+-#define PHY_M_FC_AUTO_SEL (1<<15) /* Bit 15: Fiber/Copper Auto Sel. dis. */
+-#define PHY_M_FC_AN_REG_ACC (1<<14) /* Bit 14: Fiber/Copper Autoneg. reg acc */
+-#define PHY_M_FC_RESULUTION (1<<13) /* Bit 13: Fiber/Copper Resulution */
+-#define PHY_M_SER_IF_AN_BP (1<<12) /* Bit 12: Ser IF autoneg. bypass enable */
+-#define PHY_M_SER_IF_BP_ST (1<<11) /* Bit 11: Ser IF autoneg. bypass status */
+-#define PHY_M_IRQ_POLARITY (1<<10) /* Bit 10: IRQ polarity */
+- /* Bit 9..4: reserved */
+-#define PHY_M_UNDOC1 (1<< 7) /* undocumented bit !! */
+-#define PHY_M_MODE_MASK (0xf<<0)/* Bit 3..0: copy of HWCFG MODE[3:0] */
+-
++/***** PHY_MARV_EXT_P_STAT 16 bit r/w Ext. PHY Specific Status *****/
++#define PHY_M_FC_AUTO_SEL BIT_15S /* Fiber/Copper Auto Sel. Dis. */
++#define PHY_M_FC_AN_REG_ACC BIT_14S /* Fiber/Copper AN Reg. Access */
++#define PHY_M_FC_RESOLUTION BIT_13S /* Fiber/Copper Resolution */
++#define PHY_M_SER_IF_AN_BP BIT_12S /* Ser. IF AN Bypass Enable */
++#define PHY_M_SER_IF_BP_ST BIT_11S /* Ser. IF AN Bypass Status */
++#define PHY_M_IRQ_POLARITY BIT_10S /* IRQ polarity */
++#define PHY_M_DIS_AUT_MED BIT_9S /* Disable Aut. Medium Reg. Selection */
++ /* (88E1111 only) */
++ /* Bit 9.. 4: reserved (88E1011 only) */
++#define PHY_M_UNDOC1 BIT_7S /* undocumented bit !! */
++#define PHY_M_DTE_POW_STAT BIT_4S /* DTE Power Status (88E1111 only) */
++#define PHY_M_MODE_MASK 0xf /* Bit 3.. 0: copy of HWCFG MODE[3:0] */
+
+ /***** PHY_MARV_CABLE_DIAG 16 bit r/o Cable Diagnostic Reg *****/
+-#define PHY_M_CABD_ENA_TEST (1<<15) /* Bit 15: Enable Test */
+-#define PHY_M_CABD_STAT_MSK (3<<13) /* Bit 14..13: Status */
+- /* Bit 12.. 8: reserved */
+-#define PHY_M_CABD_DIST_MSK 0xff /* Bit 7.. 0: Distance */
++#define PHY_M_CABD_ENA_TEST BIT_15S /* Enable Test (Page 0) */
++#define PHY_M_CABD_DIS_WAIT BIT_15S /* Disable Waiting Period (Page 1) */
++ /* (88E1111 only) */
++#define PHY_M_CABD_STAT_MSK (3<<13) /* Bit 14..13: Status Mask */
++#define PHY_M_CABD_AMPL_MSK (0x1f<<8) /* Bit 12.. 8: Amplitude Mask */
++ /* (88E1111 only) */
++#define PHY_M_CABD_DIST_MSK 0xff /* Bit 7.. 0: Distance Mask */
+
+ /* values for Cable Diagnostic Status (11=fail; 00=OK; 10=open; 01=short) */
+ #define CABD_STAT_NORMAL 0
+@@ -1271,6 +1352,72 @@
+ #define CABD_STAT_OPEN 2
+ #define CABD_STAT_FAIL 3
+
++/* for 10/100 Fast Ethernet PHY (88E3082 only) */
++/***** PHY_MARV_FE_LED_PAR 16 bit r/w LED Parallel Select Reg. *****/
++ /* Bit 15..12: reserved (used internally) */
++#define PHY_M_FELP_LED2_MSK (0xf<<8) /* Bit 11.. 8: LED2 Mask (LINK) */
++#define PHY_M_FELP_LED1_MSK (0xf<<4) /* Bit 7.. 4: LED1 Mask (ACT) */
++#define PHY_M_FELP_LED0_MSK 0xf /* Bit 3.. 0: LED0 Mask (SPEED) */
++
++#define PHY_M_FELP_LED2_CTRL(x) (SHIFT8(x) & PHY_M_FELP_LED2_MSK)
++#define PHY_M_FELP_LED1_CTRL(x) (SHIFT4(x) & PHY_M_FELP_LED1_MSK)
++#define PHY_M_FELP_LED0_CTRL(x) (SHIFT0(x) & PHY_M_FELP_LED0_MSK)
++
++#define LED_PAR_CTRL_COLX 0x00
++#define LED_PAR_CTRL_ERROR 0x01
++#define LED_PAR_CTRL_DUPLEX 0x02
++#define LED_PAR_CTRL_DP_COL 0x03
++#define LED_PAR_CTRL_SPEED 0x04
++#define LED_PAR_CTRL_LINK 0x05
++#define LED_PAR_CTRL_TX 0x06
++#define LED_PAR_CTRL_RX 0x07
++#define LED_PAR_CTRL_ACT 0x08
++#define LED_PAR_CTRL_LNK_RX 0x09
++#define LED_PAR_CTRL_LNK_AC 0x0a
++#define LED_PAR_CTRL_ACT_BL 0x0b
++#define LED_PAR_CTRL_TX_BL 0x0c
++#define LED_PAR_CTRL_RX_BL 0x0d
++#define LED_PAR_CTRL_COL_BL 0x0e
++#define LED_PAR_CTRL_INACT 0x0f
++
++/***** PHY_MARV_FE_SPEC_2 16 bit r/w Specific Control Reg. 2 *****/
++#define PHY_M_FESC_DIS_WAIT BIT_2S /* Disable TDR Waiting Period */
++#define PHY_M_FESC_ENA_MCLK BIT_1S /* Enable MAC Rx Clock in sleep mode */
++#define PHY_M_FESC_SEL_CL_A BIT_0S /* Select Class A driver (100B-TX) */
++
++/* for Yukon-2 Gigabit Ethernet PHY (88E1112 only) */
++/***** PHY_MARV_PHY_CTRL (page 2) 16 bit r/w MAC Specific Ctrl *****/
++#define PHY_M_MAC_MD_MSK (7<<7) /* Bit 9.. 7: Mode Select Mask */
++#define PHY_M_MAC_MD_AUTO 3 /* Auto Copper/1000Base-X */
++#define PHY_M_MAC_MD_COPPER 5 /* Copper only */
++#define PHY_M_MAC_MD_1000BX 7 /* 1000Base-X only */
++#define PHY_M_MAC_MODE_SEL(x) (SHIFT7(x) & PHY_M_MAC_MD_MSK)
++
++/***** PHY_MARV_PHY_CTRL (page 3) 16 bit r/w LED Control Reg. *****/
++#define PHY_M_LEDC_LOS_MSK (0xf<<12) /* Bit 15..12: LOS LED Ctrl. Mask */
++#define PHY_M_LEDC_INIT_MSK (0xf<<8) /* Bit 11.. 8: INIT LED Ctrl. Mask */
++#define PHY_M_LEDC_STA1_MSK (0xf<<4) /* Bit 7.. 4: STAT1 LED Ctrl. Mask */
++#define PHY_M_LEDC_STA0_MSK 0xf /* Bit 3.. 0: STAT0 LED Ctrl. Mask */
++
++#define PHY_M_LEDC_LOS_CTRL(x) (SHIFT12(x) & PHY_M_LEDC_LOS_MSK)
++#define PHY_M_LEDC_INIT_CTRL(x) (SHIFT8(x) & PHY_M_LEDC_INIT_MSK)
++#define PHY_M_LEDC_STA1_CTRL(x) (SHIFT4(x) & PHY_M_LEDC_STA1_MSK)
++#define PHY_M_LEDC_STA0_CTRL(x) (SHIFT0(x) & PHY_M_LEDC_STA0_MSK)
++
++/***** PHY_MARV_PHY_STAT (page 3) 16 bit r/w Polarity Control Reg. *****/
++#define PHY_M_POLC_LS1M_MSK (0xf<<12) /* Bit 15..12: LOS,STAT1 Mix % Mask */
++#define PHY_M_POLC_IS0M_MSK (0xf<<8) /* Bit 11.. 8: INIT,STAT0 Mix % Mask */
++#define PHY_M_POLC_LOS_MSK (0x3<<6) /* Bit 7.. 6: LOS Pol. Ctrl. Mask */
++#define PHY_M_POLC_INIT_MSK (0x3<<4) /* Bit 5.. 4: INIT Pol. Ctrl. Mask */
++#define PHY_M_POLC_STA1_MSK (0x3<<2) /* Bit 3.. 2: STAT1 Pol. Ctrl. Mask */
++#define PHY_M_POLC_STA0_MSK 0x3 /* Bit 1.. 0: STAT0 Pol. Ctrl. Mask */
++
++#define PHY_M_POLC_LS1_P_MIX(x) (SHIFT12(x) & PHY_M_POLC_LS1M_MSK)
++#define PHY_M_POLC_IS0_P_MIX(x) (SHIFT8(x) & PHY_M_POLC_IS0M_MSK)
++#define PHY_M_POLC_LOS_CTRL(x) (SHIFT6(x) & PHY_M_POLC_LOS_MSK)
++#define PHY_M_POLC_INIT_CTRL(x) (SHIFT4(x) & PHY_M_POLC_INIT_MSK)
++#define PHY_M_POLC_STA1_CTRL(x) (SHIFT2(x) & PHY_M_POLC_STA1_MSK)
++#define PHY_M_POLC_STA0_CTRL(x) (SHIFT0(x) & PHY_M_POLC_STA0_MSK)
+
+ /*
+ * GMAC registers
+@@ -1431,141 +1578,159 @@
+ */
+
+ /* GM_GP_STAT 16 bit r/o General Purpose Status Register */
+-#define GM_GPSR_SPEED (1<<15) /* Bit 15: Port Speed (1 = 100 Mbps) */
+-#define GM_GPSR_DUPLEX (1<<14) /* Bit 14: Duplex Mode (1 = Full) */
+-#define GM_GPSR_FC_TX_DIS (1<<13) /* Bit 13: Tx Flow-Control Mode Disabled */
+-#define GM_GPSR_LINK_UP (1<<12) /* Bit 12: Link Up Status */
+-#define GM_GPSR_PAUSE (1<<11) /* Bit 11: Pause State */
+-#define GM_GPSR_TX_ACTIVE (1<<10) /* Bit 10: Tx in Progress */
+-#define GM_GPSR_EXC_COL (1<<9) /* Bit 9: Excessive Collisions Occured */
+-#define GM_GPSR_LAT_COL (1<<8) /* Bit 8: Late Collisions Occured */
+- /* Bit 7..6: reserved */
+-#define GM_GPSR_PHY_ST_CH (1<<5) /* Bit 5: PHY Status Change */
+-#define GM_GPSR_GIG_SPEED (1<<4) /* Bit 4: Gigabit Speed (1 = 1000 Mbps) */
+-#define GM_GPSR_PART_MODE (1<<3) /* Bit 3: Partition mode */
+-#define GM_GPSR_FC_RX_DIS (1<<2) /* Bit 2: Rx Flow-Control Mode Disabled */
+-#define GM_GPSR_PROM_EN (1<<1) /* Bit 1: Promiscuous Mode Enabled */
+- /* Bit 0: reserved */
+-
++#define GM_GPSR_SPEED BIT_15S /* Port Speed (1 = 100 Mbps) */
++#define GM_GPSR_DUPLEX BIT_14S /* Duplex Mode (1 = Full) */
++#define GM_GPSR_FC_TX_DIS BIT_13S /* Tx Flow-Control Mode Disabled */
++#define GM_GPSR_LINK_UP BIT_12S /* Link Up Status */
++#define GM_GPSR_PAUSE BIT_11S /* Pause State */
++#define GM_GPSR_TX_ACTIVE BIT_10S /* Tx in Progress */
++#define GM_GPSR_EXC_COL BIT_9S /* Excessive Collisions Occured */
++#define GM_GPSR_LAT_COL BIT_8S /* Late Collisions Occured */
++ /* Bit 7.. 6: reserved */
++#define GM_GPSR_PHY_ST_CH BIT_5S /* PHY Status Change */
++#define GM_GPSR_GIG_SPEED BIT_4S /* Gigabit Speed (1 = 1000 Mbps) */
++#define GM_GPSR_PART_MODE BIT_3S /* Partition mode */
++#define GM_GPSR_FC_RX_DIS BIT_2S /* Rx Flow-Control Mode Disabled */
++ /* Bit 2.. 0: reserved */
++
+ /* GM_GP_CTRL 16 bit r/w General Purpose Control Register */
+- /* Bit 15: reserved */
+-#define GM_GPCR_PROM_ENA (1<<14) /* Bit 14: Enable Promiscuous Mode */
+-#define GM_GPCR_FC_TX_DIS (1<<13) /* Bit 13: Disable Tx Flow-Control Mode */
+-#define GM_GPCR_TX_ENA (1<<12) /* Bit 12: Enable Transmit */
+-#define GM_GPCR_RX_ENA (1<<11) /* Bit 11: Enable Receive */
+-#define GM_GPCR_BURST_ENA (1<<10) /* Bit 10: Enable Burst Mode */
+-#define GM_GPCR_LOOP_ENA (1<<9) /* Bit 9: Enable MAC Loopback Mode */
+-#define GM_GPCR_PART_ENA (1<<8) /* Bit 8: Enable Partition Mode */
+-#define GM_GPCR_GIGS_ENA (1<<7) /* Bit 7: Gigabit Speed (1000 Mbps) */
+-#define GM_GPCR_FL_PASS (1<<6) /* Bit 6: Force Link Pass */
+-#define GM_GPCR_DUP_FULL (1<<5) /* Bit 5: Full Duplex Mode */
+-#define GM_GPCR_FC_RX_DIS (1<<4) /* Bit 4: Disable Rx Flow-Control Mode */
+-#define GM_GPCR_SPEED_100 (1<<3) /* Bit 3: Port Speed 100 Mbps */
+-#define GM_GPCR_AU_DUP_DIS (1<<2) /* Bit 2: Disable Auto-Update Duplex */
+-#define GM_GPCR_AU_FCT_DIS (1<<1) /* Bit 1: Disable Auto-Update Flow-C. */
+-#define GM_GPCR_AU_SPD_DIS (1<<0) /* Bit 0: Disable Auto-Update Speed */
++#define GM_GPCR_RMII_PH_ENA BIT_15S /* Enable RMII for PHY (Yukon-FE only) */
++#define GM_GPCR_RMII_LB_ENA BIT_14S /* Enable RMII Loopback (Yukon-FE only) */
++#define GM_GPCR_FC_TX_DIS BIT_13S /* Disable Tx Flow-Control Mode */
++#define GM_GPCR_TX_ENA BIT_12S /* Enable Transmit */
++#define GM_GPCR_RX_ENA BIT_11S /* Enable Receive */
++ /* Bit 10: reserved */
++#define GM_GPCR_LOOP_ENA BIT_9S /* Enable MAC Loopback Mode */
++#define GM_GPCR_PART_ENA BIT_8S /* Enable Partition Mode */
++#define GM_GPCR_GIGS_ENA BIT_7S /* Gigabit Speed (1000 Mbps) */
++#define GM_GPCR_FL_PASS BIT_6S /* Force Link Pass */
++#define GM_GPCR_DUP_FULL BIT_5S /* Full Duplex Mode */
++#define GM_GPCR_FC_RX_DIS BIT_4S /* Disable Rx Flow-Control Mode */
++#define GM_GPCR_SPEED_100 BIT_3S /* Port Speed 100 Mbps */
++#define GM_GPCR_AU_DUP_DIS BIT_2S /* Disable Auto-Update Duplex */
++#define GM_GPCR_AU_FCT_DIS BIT_1S /* Disable Auto-Update Flow-C. */
++#define GM_GPCR_AU_SPD_DIS BIT_0S /* Disable Auto-Update Speed */
+
+ #define GM_GPCR_SPEED_1000 (GM_GPCR_GIGS_ENA | GM_GPCR_SPEED_100)
+ #define GM_GPCR_AU_ALL_DIS (GM_GPCR_AU_DUP_DIS | GM_GPCR_AU_FCT_DIS |\
+ GM_GPCR_AU_SPD_DIS)
+-
++
+ /* GM_TX_CTRL 16 bit r/w Transmit Control Register */
+-#define GM_TXCR_FORCE_JAM (1<<15) /* Bit 15: Force Jam / Flow-Control */
+-#define GM_TXCR_CRC_DIS (1<<14) /* Bit 14: Disable insertion of CRC */
+-#define GM_TXCR_PAD_DIS (1<<13) /* Bit 13: Disable padding of packets */
+-#define GM_TXCR_COL_THR_MSK (1<<10) /* Bit 12..10: Collision Threshold */
++#define GM_TXCR_FORCE_JAM BIT_15S /* Force Jam / Flow-Control */
++#define GM_TXCR_CRC_DIS BIT_14S /* Disable insertion of CRC */
++#define GM_TXCR_PAD_DIS BIT_13S /* Disable padding of packets */
++#define GM_TXCR_COL_THR_MSK (7<<10) /* Bit 12..10: Collision Threshold Mask */
++ /* Bit 9.. 8: reserved */
++#define GM_TXCR_PAD_PAT_MSK 0xff /* Bit 7.. 0: Padding Pattern Mask */
++ /* (Yukon-2 only) */
+
+ #define TX_COL_THR(x) (SHIFT10(x) & GM_TXCR_COL_THR_MSK)
+
+ #define TX_COL_DEF 0x04
+-
++
+ /* GM_RX_CTRL 16 bit r/w Receive Control Register */
+-#define GM_RXCR_UCF_ENA (1<<15) /* Bit 15: Enable Unicast filtering */
+-#define GM_RXCR_MCF_ENA (1<<14) /* Bit 14: Enable Multicast filtering */
+-#define GM_RXCR_CRC_DIS (1<<13) /* Bit 13: Remove 4-byte CRC */
+-#define GM_RXCR_PASS_FC (1<<12) /* Bit 12: Pass FC packets to FIFO */
+-
++#define GM_RXCR_UCF_ENA BIT_15S /* Enable Unicast filtering */
++#define GM_RXCR_MCF_ENA BIT_14S /* Enable Multicast filtering */
++#define GM_RXCR_CRC_DIS BIT_13S /* Remove 4-byte CRC */
++#define GM_RXCR_PASS_FC BIT_12S /* Pass FC packets to FIFO (Yukon-1 only) */
++ /* Bit 11.. 0: reserved */
++
+ /* GM_TX_PARAM 16 bit r/w Transmit Parameter Register */
+-#define GM_TXPA_JAMLEN_MSK (0x03<<14) /* Bit 15..14: Jam Length */
+-#define GM_TXPA_JAMIPG_MSK (0x1f<<9) /* Bit 13..9: Jam IPG */
+-#define GM_TXPA_JAMDAT_MSK (0x1f<<4) /* Bit 8..4: IPG Jam to Data */
+- /* Bit 3..0: reserved */
++#define GM_TXPA_JAMLEN_MSK (3<<14) /* Bit 15..14: Jam Length Mask */
++#define GM_TXPA_JAMIPG_MSK (0x1f<<9) /* Bit 13.. 9: Jam IPG Mask */
++#define GM_TXPA_JAMDAT_MSK (0x1f<<4) /* Bit 8.. 4: IPG Jam to Data Mask */
++#define GM_TXPA_BO_LIM_MSK 0x0f /* Bit 3.. 0: Backoff Limit Mask */
++ /* (Yukon-2 only) */
+
+ #define TX_JAM_LEN_VAL(x) (SHIFT14(x) & GM_TXPA_JAMLEN_MSK)
+ #define TX_JAM_IPG_VAL(x) (SHIFT9(x) & GM_TXPA_JAMIPG_MSK)
+ #define TX_IPG_JAM_DATA(x) (SHIFT4(x) & GM_TXPA_JAMDAT_MSK)
++#define TX_BACK_OFF_LIM(x) ((x) & GM_TXPA_BO_LIM_MSK)
+
+ #define TX_JAM_LEN_DEF 0x03
+ #define TX_JAM_IPG_DEF 0x0b
+ #define TX_IPG_JAM_DEF 0x1c
++#define TX_BOF_LIM_DEF 0x04
+
+ /* GM_SERIAL_MODE 16 bit r/w Serial Mode Register */
+-#define GM_SMOD_DATABL_MSK (0x1f<<11) /* Bit 15..11: Data Blinder (r/o) */
+-#define GM_SMOD_LIMIT_4 (1<<10) /* Bit 10: 4 consecutive Tx trials */
+-#define GM_SMOD_VLAN_ENA (1<<9) /* Bit 9: Enable VLAN (Max. Frame Len) */
+-#define GM_SMOD_JUMBO_ENA (1<<8) /* Bit 8: Enable Jumbo (Max. Frame Len) */
+- /* Bit 7..5: reserved */
+-#define GM_SMOD_IPG_MSK 0x1f /* Bit 4..0: Inter-Packet Gap (IPG) */
+-
++#define GM_SMOD_DATABL_MSK (0x1f<<11) /* Bit 15..11: Data Blinder */
++ /* r/o on Yukon, r/w on Yukon-EC */
++#define GM_SMOD_LIMIT_4 BIT_10S /* 4 consecutive Tx trials */
++#define GM_SMOD_VLAN_ENA BIT_9S /* Enable VLAN (Max. Frame Len) */
++#define GM_SMOD_JUMBO_ENA BIT_8S /* Enable Jumbo (Max. Frame Len) */
++ /* Bit 7.. 5: reserved */
++#define GM_SMOD_IPG_MSK 0x1f /* Bit 4.. 0: Inter-Packet Gap (IPG) */
++
+ #define DATA_BLIND_VAL(x) (SHIFT11(x) & GM_SMOD_DATABL_MSK)
+-#define DATA_BLIND_DEF 0x04
++#define IPG_DATA_VAL(x) ((x) & GM_SMOD_IPG_MSK)
+
+-#define IPG_DATA_VAL(x) (x & GM_SMOD_IPG_MSK)
++#define DATA_BLIND_DEF 0x04
+ #define IPG_DATA_DEF 0x1e
+
+ /* GM_SMI_CTRL 16 bit r/w SMI Control Register */
+ #define GM_SMI_CT_PHY_A_MSK (0x1f<<11) /* Bit 15..11: PHY Device Address */
+ #define GM_SMI_CT_REG_A_MSK (0x1f<<6) /* Bit 10.. 6: PHY Register Address */
+-#define GM_SMI_CT_OP_RD (1<<5) /* Bit 5: OpCode Read (0=Write)*/
+-#define GM_SMI_CT_RD_VAL (1<<4) /* Bit 4: Read Valid (Read completed) */
+-#define GM_SMI_CT_BUSY (1<<3) /* Bit 3: Busy (Operation in progress) */
+- /* Bit 2..0: reserved */
+-
++#define GM_SMI_CT_OP_RD BIT_5S /* OpCode Read (0=Write)*/
++#define GM_SMI_CT_RD_VAL BIT_4S /* Read Valid (Read completed) */
++#define GM_SMI_CT_BUSY BIT_3S /* Busy (Operation in progress) */
++ /* Bit 2.. 0: reserved */
++
+ #define GM_SMI_CT_PHY_AD(x) (SHIFT11(x) & GM_SMI_CT_PHY_A_MSK)
+ #define GM_SMI_CT_REG_AD(x) (SHIFT6(x) & GM_SMI_CT_REG_A_MSK)
+
+ /* GM_PHY_ADDR 16 bit r/w GPHY Address Register */
+- /* Bit 15..6: reserved */
+-#define GM_PAR_MIB_CLR (1<<5) /* Bit 5: Set MIB Clear Counter Mode */
+-#define GM_PAR_MIB_TST (1<<4) /* Bit 4: MIB Load Counter (Test Mode) */
+- /* Bit 3..0: reserved */
+-
++ /* Bit 15.. 6: reserved */
++#define GM_PAR_MIB_CLR BIT_5S /* Set MIB Clear Counter Mode */
++#define GM_PAR_MIB_TST BIT_4S /* MIB Load Counter (Test Mode) */
++ /* Bit 3.. 0: reserved */
++
+ /* Receive Frame Status Encoding */
+-#define GMR_FS_LEN (0xffffUL<<16) /* Bit 31..16: Rx Frame Length */
++#define GMR_FS_LEN_MSK (0xffffUL<<16) /* Bit 31..16: Rx Frame Length */
+ /* Bit 15..14: reserved */
+-#define GMR_FS_VLAN (1L<<13) /* Bit 13: VLAN Packet */
+-#define GMR_FS_JABBER (1L<<12) /* Bit 12: Jabber Packet */
+-#define GMR_FS_UN_SIZE (1L<<11) /* Bit 11: Undersize Packet */
+-#define GMR_FS_MC (1L<<10) /* Bit 10: Multicast Packet */
+-#define GMR_FS_BC (1L<<9) /* Bit 9: Broadcast Packet */
+-#define GMR_FS_RX_OK (1L<<8) /* Bit 8: Receive OK (Good Packet) */
+-#define GMR_FS_GOOD_FC (1L<<7) /* Bit 7: Good Flow-Control Packet */
+-#define GMR_FS_BAD_FC (1L<<6) /* Bit 6: Bad Flow-Control Packet */
+-#define GMR_FS_MII_ERR (1L<<5) /* Bit 5: MII Error */
+-#define GMR_FS_LONG_ERR (1L<<4) /* Bit 4: Too Long Packet */
+-#define GMR_FS_FRAGMENT (1L<<3) /* Bit 3: Fragment */
++#define GMR_FS_VLAN BIT_13 /* VLAN Packet */
++#define GMR_FS_JABBER BIT_12 /* Jabber Packet */
++#define GMR_FS_UN_SIZE BIT_11 /* Undersize Packet */
++#define GMR_FS_MC BIT_10 /* Multicast Packet */
++#define GMR_FS_BC BIT_9 /* Broadcast Packet */
++#define GMR_FS_RX_OK BIT_8 /* Receive OK (Good Packet) */
++#define GMR_FS_GOOD_FC BIT_7 /* Good Flow-Control Packet */
++#define GMR_FS_BAD_FC BIT_6 /* Bad Flow-Control Packet */
++#define GMR_FS_MII_ERR BIT_5 /* MII Error */
++#define GMR_FS_LONG_ERR BIT_4 /* Too Long Packet */
++#define GMR_FS_FRAGMENT BIT_3 /* Fragment */
+ /* Bit 2: reserved */
+-#define GMR_FS_CRC_ERR (1L<<1) /* Bit 1: CRC Error */
+-#define GMR_FS_RX_FF_OV (1L<<0) /* Bit 0: Rx FIFO Overflow */
++#define GMR_FS_CRC_ERR BIT_1 /* CRC Error */
++#define GMR_FS_RX_FF_OV BIT_0 /* Rx FIFO Overflow */
++
++#define GMR_FS_LEN_SHIFT 16
+
+ /*
+ * GMR_FS_ANY_ERR (analogous to XMR_FS_ANY_ERR)
+ */
+-#define GMR_FS_ANY_ERR (GMR_FS_CRC_ERR | \
+- GMR_FS_LONG_ERR | \
++#ifdef SK_DIAG
++#define GMR_FS_ANY_ERR ( \
++ GMR_FS_RX_FF_OV | \
++ GMR_FS_CRC_ERR | \
++ GMR_FS_FRAGMENT | \
+ GMR_FS_MII_ERR | \
+ GMR_FS_BAD_FC | \
+ GMR_FS_GOOD_FC | \
+ GMR_FS_JABBER)
+-
+-/* Rx GMAC FIFO Flush Mask (default) */
+-#define RX_FF_FL_DEF_MSK (GMR_FS_CRC_ERR | \
++#else
++#define GMR_FS_ANY_ERR ( \
+ GMR_FS_RX_FF_OV | \
++ GMR_FS_CRC_ERR | \
++ GMR_FS_FRAGMENT | \
++ GMR_FS_LONG_ERR | \
+ GMR_FS_MII_ERR | \
+ GMR_FS_BAD_FC | \
+ GMR_FS_GOOD_FC | \
+ GMR_FS_UN_SIZE | \
+ GMR_FS_JABBER)
++#endif
++
++/* Rx GMAC FIFO Flush Mask (default) */
++#define RX_FF_FL_DEF_MSK GMR_FS_ANY_ERR
+
+ /* typedefs *******************************************************************/
+
+diff -ruN linux/drivers/net/sk98lin/Makefile linux-new/drivers/net/sk98lin/Makefile
+--- linux/drivers/net/sk98lin/Makefile 2005-09-26 13:32:47.000000000 +0400
++++ linux-new/drivers/net/sk98lin/Makefile 2005-10-21 11:35:50.738459104 +0400
+@@ -1,6 +1,59 @@
++#******************************************************************************
+ #
+-# Makefile for the SysKonnect SK-98xx device driver.
++# Name: skge.c
++# Project: GEnesis, PCI Gigabit Ethernet Adapter
++# Version: $Revision: 1.9.2.1 $
++# Date: $Date: 2005/04/11 09:01:18 $
++# Purpose: The main driver source module
+ #
++#******************************************************************************
++
++#******************************************************************************
++#
++# (C)Copyright 1998-2002 SysKonnect GmbH.
++# (C)Copyright 2002-2005 Marvell.
++#
++# Makefile for Marvell Yukon chipset and SysKonnect Gigabit Ethernet
++# Server Adapter driver. (Kernel 2.6)
++#
++# Author: Mirko Lindner (mlindner@syskonnect.de)
++# Ralph Roesler (rroesler@syskonnect.de)
++#
++# Address all question to: linux@syskonnect.de
++#
++# This program is free software; you can redistribute it and/or modify
++# it under the terms of the GNU General Public License as published by
++# the Free Software Foundation; either version 2 of the License, or
++# (at your option) any later version.
++#
++# The information in this file is provided "AS IS" without warranty.
++#
++#******************************************************************************
++
++#******************************************************************************
++#
++# History:
++#
++# $Log: Makefile2.6,v $
++# Revision 1.9.2.1 2005/04/11 09:01:18 mlindner
++# Fix: Copyright year changed
++#
++# Revision 1.9 2004/07/13 15:54:50 rroesler
++# Add: file skethtool.c
++# Fix: corrected header regarding copyright
++# Fix: minor typos corrected
++#
++# Revision 1.8 2004/06/08 08:39:38 mlindner
++# Fix: Add CONFIG_SK98LIN_ZEROCOPY as default
++#
++# Revision 1.7 2004/06/03 16:06:56 mlindner
++# Fix: Added compile flag SK_DIAG_SUPPORT
++#
++# Revision 1.6 2004/06/02 08:02:59 mlindner
++# Add: Changed header information and inserted a GPL statement
++#
++#
++#******************************************************************************
+
+
+ #
+@@ -13,13 +66,16 @@
+ obj-$(CONFIG_SK98LIN) += sk98lin.o
+ sk98lin-objs := \
+ skge.o \
++ sky2.o \
++ skethtool.o \
++ sky2le.o \
+ skdim.o \
+ skaddr.o \
+ skgehwt.o \
+ skgeinit.o \
+ skgepnmi.o \
+ skgesirq.o \
+- ski2c.o \
++ sktwsi.o \
+ sklm80.o \
+ skqueue.o \
+ skrlmt.o \
+@@ -76,13 +132,11 @@
+ # SK_DBGCAT_DRV_INT_SRC 0x04000000 interrupts sources
+ # SK_DBGCAT_DRV_EVENT 0x08000000 driver events
+
+-EXTRA_CFLAGS += -Idrivers/net/sk98lin -DSK_DIAG_SUPPORT -DSK_USE_CSUM -DGENESIS -DYUKON $(DBGDEF) $(SKPARAM)
++EXTRA_CFLAGS += -Idrivers/net/sk98lin -DSK_USE_CSUM -DSK_DIAG_SUPPORT \
++ -DGENESIS -DYUKON -DYUK2 -DCONFIG_SK98LIN_ZEROCOPY \
++ $(DBGDEF) $(SKPARAM)
+
+ clean:
+ rm -f core *.o *.a *.s
+
+
+-
+-
+-
+-
+diff -ruN linux/drivers/net/sk98lin/skaddr.c linux-new/drivers/net/sk98lin/skaddr.c
+--- linux/drivers/net/sk98lin/skaddr.c 2005-09-26 13:32:48.000000000 +0400
++++ linux-new/drivers/net/sk98lin/skaddr.c 2005-08-09 17:15:51.000000000 +0400
+@@ -2,8 +2,8 @@
+ *
+ * Name: skaddr.c
+ * Project: Gigabit Ethernet Adapters, ADDR-Module
+- * Version: $Revision: 1.52 $
+- * Date: $Date: 2003/06/02 13:46:15 $
++ * Version: $Revision: 2.8 $
++ * Date: $Date: 2005/07/21 12:01:30 $
+ * Purpose: Manage Addresses (Multicast and Unicast) and Promiscuous Mode.
+ *
+ ******************************************************************************/
+@@ -11,7 +11,7 @@
+ /******************************************************************************
+ *
+ * (C)Copyright 1998-2002 SysKonnect GmbH.
+- * (C)Copyright 2002-2003 Marvell.
++ * (C)Copyright 2002-2005 Marvell.
+ *
+ * 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
+@@ -44,7 +44,7 @@
+
+ #if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
+ static const char SysKonnectFileId[] =
+- "@(#) $Id: skaddr.c,v 1.52 2003/06/02 13:46:15 tschilli Exp $ (C) Marvell.";
++ "@(#) $Id: skaddr.c,v 2.8 2005/07/21 12:01:30 tschilli Exp $ (C) Marvell.";
+ #endif /* DEBUG ||!LINT || !SK_SLIM */
+
+ #define __SKADDR_C
+@@ -58,11 +58,10 @@
+
+ /* defines ********************************************************************/
+
+-
+ #define XMAC_POLY 0xEDB88320UL /* CRC32-Poly - XMAC: Little Endian */
+ #define GMAC_POLY 0x04C11DB7L /* CRC16-Poly - GMAC: Little Endian */
+ #define HASH_BITS 6 /* #bits in hash */
+-#define SK_MC_BIT 0x01
++#define SK_MC_BIT 0x01
+
+ /* Error numbers and messages. */
+
+@@ -79,7 +78,7 @@
+
+ /* 64-bit hash values with all bits set. */
+
+-SK_U16 OnesHash[4] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF};
++SK_U16 OnesHash[4] = {0xffff, 0xffff, 0xffff, 0xffff};
+
+ /* local variables ************************************************************/
+
+@@ -136,13 +135,12 @@
+
+ switch (Level) {
+ case SK_INIT_DATA:
+- SK_MEMSET((char *) &pAC->Addr, (SK_U8) 0,
+- (SK_U16) sizeof(SK_ADDR));
++ SK_MEMSET((char *)&pAC->Addr, (SK_U8)0, (SK_U16)sizeof(SK_ADDR));
+
+ for (i = 0; i < SK_MAX_MACS; i++) {
+ pAPort = &pAC->Addr.Port[i];
+ pAPort->PromMode = SK_PROM_MODE_NONE;
+-
++
+ pAPort->FirstExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT;
+ pAPort->FirstExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV;
+ pAPort->NextExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT;
+@@ -159,7 +157,7 @@
+ /* pAC->Addr.InitDone = SK_INIT_DATA; */
+ break;
+
+- case SK_INIT_IO:
++ case SK_INIT_IO:
+ #ifndef SK_NO_RLMT
+ for (i = 0; i < SK_MAX_NETS; i++) {
+ pAC->Addr.Net[i].ActivePort = pAC->Rlmt.Net[i].ActivePort;
+@@ -173,7 +171,7 @@
+ }
+ }
+ #endif /* DEBUG */
+-
++
+ /* Read permanent logical MAC address from Control Register File. */
+ for (j = 0; j < SK_MAC_ADDR_LEN; j++) {
+ InAddr = (SK_U8 *) &pAC->Addr.Net[0].PermanentMacAddress.a[j];
+@@ -191,11 +189,11 @@
+ pAC->Addr.Port[pAC->Addr.Net[0].ActivePort].Exact[0] =
+ pAC->Addr.Net[0].CurrentMacAddress;
+ #if SK_MAX_NETS > 1
+- /* Set logical MAC address for net 2 to (log | 3). */
++ /* Set logical MAC address for net 2 to. */
+ if (!pAC->Addr.Net[1].CurrentMacAddressSet) {
+ pAC->Addr.Net[1].PermanentMacAddress =
+ pAC->Addr.Net[0].PermanentMacAddress;
+- pAC->Addr.Net[1].PermanentMacAddress.a[5] |= 3;
++ pAC->Addr.Net[1].PermanentMacAddress.a[5] += 1;
+ /* Set the current logical MAC address to the permanent one. */
+ pAC->Addr.Net[1].CurrentMacAddress =
+ pAC->Addr.Net[1].PermanentMacAddress;
+@@ -213,8 +211,8 @@
+ pAC->Addr.Net[i].PermanentMacAddress.a[2],
+ pAC->Addr.Net[i].PermanentMacAddress.a[3],
+ pAC->Addr.Net[i].PermanentMacAddress.a[4],
+- pAC->Addr.Net[i].PermanentMacAddress.a[5]))
+-
++ pAC->Addr.Net[i].PermanentMacAddress.a[5]));
++
+ SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
+ ("Logical MAC Address (Net%d): %02X %02X %02X %02X %02X %02X\n",
+ i,
+@@ -223,7 +221,7 @@
+ pAC->Addr.Net[i].CurrentMacAddress.a[2],
+ pAC->Addr.Net[i].CurrentMacAddress.a[3],
+ pAC->Addr.Net[i].CurrentMacAddress.a[4],
+- pAC->Addr.Net[i].CurrentMacAddress.a[5]))
++ pAC->Addr.Net[i].CurrentMacAddress.a[5]));
+ }
+ #endif /* DEBUG */
+
+@@ -266,8 +264,8 @@
+ pAPort->PermanentMacAddress.a[2],
+ pAPort->PermanentMacAddress.a[3],
+ pAPort->PermanentMacAddress.a[4],
+- pAPort->PermanentMacAddress.a[5]))
+-
++ pAPort->PermanentMacAddress.a[5]));
++
+ SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT,
+ ("SkAddrInit: Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
+ pAPort->CurrentMacAddress.a[0],
+@@ -275,7 +273,7 @@
+ pAPort->CurrentMacAddress.a[2],
+ pAPort->CurrentMacAddress.a[3],
+ pAPort->CurrentMacAddress.a[4],
+- pAPort->CurrentMacAddress.a[5]))
++ pAPort->CurrentMacAddress.a[5]));
+ #endif /* DEBUG */
+ }
+ /* pAC->Addr.InitDone = SK_INIT_IO; */
+@@ -299,7 +297,7 @@
+ }
+
+ return (SK_ADDR_SUCCESS);
+-
++
+ } /* SkAddrInit */
+
+ #ifndef SK_SLIM
+@@ -333,16 +331,20 @@
+ int Flags) /* permanent/non-perm, sw-only */
+ {
+ int ReturnCode;
+-
++
+ if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
+ return (SK_ADDR_ILLEGAL_PORT);
+ }
+-
++
+ if (pAC->GIni.GIGenesis) {
++#ifdef GENESIS
+ ReturnCode = SkAddrXmacMcClear(pAC, IoC, PortNumber, Flags);
++#endif
+ }
+ else {
++#ifdef YUKON
+ ReturnCode = SkAddrGmacMcClear(pAC, IoC, PortNumber, Flags);
++#endif
+ }
+
+ return (ReturnCode);
+@@ -352,7 +354,7 @@
+ #endif /* !SK_SLIM */
+
+ #ifndef SK_SLIM
+-
++#ifdef GENESIS
+ /******************************************************************************
+ *
+ * SkAddrXmacMcClear - clear the multicast table
+@@ -402,13 +404,13 @@
+ }
+
+ return (SK_ADDR_SUCCESS);
+-
+-} /* SkAddrXmacMcClear */
+
++} /* SkAddrXmacMcClear */
++#endif /* GENESIS */
+ #endif /* !SK_SLIM */
+
+ #ifndef SK_SLIM
+-
++#ifdef YUKON
+ /******************************************************************************
+ *
+ * SkAddrGmacMcClear - clear the multicast table
+@@ -447,38 +449,37 @@
+ pAC->Addr.Port[PortNumber].InexactFilter.Bytes[4],
+ pAC->Addr.Port[PortNumber].InexactFilter.Bytes[5],
+ pAC->Addr.Port[PortNumber].InexactFilter.Bytes[6],
+- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[7]))
++ pAC->Addr.Port[PortNumber].InexactFilter.Bytes[7]));
+ #endif /* DEBUG */
+
+ /* Clear InexactFilter */
+ for (i = 0; i < 8; i++) {
+ pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0;
+ }
+-
++
+ if (Flags & SK_ADDR_PERMANENT) { /* permanent => RLMT */
+-
++
+ /* Copy DRV bits to InexactFilter. */
+ for (i = 0; i < 8; i++) {
+ pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
+ pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i];
+-
++
+ /* Clear InexactRlmtFilter. */
+ pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i] = 0;
+-
+- }
++ }
+ }
+ else { /* not permanent => DRV */
+-
++
+ /* Copy RLMT bits to InexactFilter. */
+ for (i = 0; i < 8; i++) {
+ pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
+ pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i];
+-
++
+ /* Clear InexactDrvFilter. */
+ pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i] = 0;
+ }
+ }
+-
++
+ #ifdef DEBUG
+ SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
+ ("GMAC InexactFilter (cleared): %02X %02X %02X %02X %02X %02X %02X %02X\n",
+@@ -489,19 +490,20 @@
+ pAC->Addr.Port[PortNumber].InexactFilter.Bytes[4],
+ pAC->Addr.Port[PortNumber].InexactFilter.Bytes[5],
+ pAC->Addr.Port[PortNumber].InexactFilter.Bytes[6],
+- pAC->Addr.Port[PortNumber].InexactFilter.Bytes[7]))
++ pAC->Addr.Port[PortNumber].InexactFilter.Bytes[7]));
+ #endif /* DEBUG */
+-
++
+ if (!(Flags & SK_MC_SW_ONLY)) {
+ (void) SkAddrGmacMcUpdate(pAC, IoC, PortNumber);
+ }
+-
++
+ return (SK_ADDR_SUCCESS);
+
+ } /* SkAddrGmacMcClear */
++#endif /* YUKON */
+
+ #ifndef SK_ADDR_CHEAT
+-
++#ifdef GENESIS
+ /******************************************************************************
+ *
+ * SkXmacMcHash - hash multicast address
+@@ -538,8 +540,9 @@
+ return (Crc & ((1 << HASH_BITS) - 1));
+
+ } /* SkXmacMcHash */
++#endif /* GENESIS */
+
+-
++#ifdef YUKON
+ /******************************************************************************
+ *
+ * SkGmacMcHash - hash multicast address
+@@ -570,7 +573,7 @@
+ for (Byte = 0; Byte < 6; Byte++) {
+ /* Get next byte. */
+ Data = (SK_U32) pMc[Byte];
+-
++
+ /* Change bit order in byte. */
+ TmpData = Data;
+ for (Bit = 0; Bit < 8; Bit++) {
+@@ -582,7 +585,7 @@
+ }
+ TmpData >>= 1;
+ }
+-
++
+ Crc ^= (Data << 24);
+ for (Bit = 0; Bit < 8; Bit++) {
+ if (Crc & 0x80000000) {
+@@ -593,11 +596,11 @@
+ }
+ }
+ }
+-
++
+ return (Crc & ((1 << HASH_BITS) - 1));
+
+ } /* SkGmacMcHash */
+-
++#endif /* YUKON */
+ #endif /* !SK_ADDR_CHEAT */
+
+ /******************************************************************************
+@@ -632,23 +635,27 @@
+ int Flags) /* permanent/non-permanent */
+ {
+ int ReturnCode;
+-
++
+ if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
+ return (SK_ADDR_ILLEGAL_PORT);
+ }
+-
++
+ if (pAC->GIni.GIGenesis) {
++#ifdef GENESIS
+ ReturnCode = SkAddrXmacMcAdd(pAC, IoC, PortNumber, pMc, Flags);
++#endif
+ }
+ else {
++#ifdef YUKON
+ ReturnCode = SkAddrGmacMcAdd(pAC, IoC, PortNumber, pMc, Flags);
++#endif
+ }
+
+ return (ReturnCode);
+
+ } /* SkAddrMcAdd */
+
+-
++#ifdef GENESIS
+ /******************************************************************************
+ *
+ * SkAddrXmacMcAdd - add a multicast address to a port
+@@ -693,7 +700,7 @@
+ return (SK_MC_RLMT_OVERFLOW);
+ }
+ #endif /* DEBUG */
+-
++
+ if (pAC->Addr.Port[PortNumber].NextExactMatchRlmt >
+ SK_ADDR_LAST_MATCH_RLMT) {
+ return (SK_MC_RLMT_OVERFLOW);
+@@ -714,7 +721,7 @@
+ return (SK_MC_RLMT_OVERFLOW);
+ }
+ #endif /* DEBUG */
+-
++
+ if (pAC->Addr.Port[PortNumber].NextExactMatchDrv <= SK_ADDR_LAST_MATCH_DRV) {
+
+ /* Set exact match entry. */
+@@ -758,8 +765,9 @@
+ }
+
+ } /* SkAddrXmacMcAdd */
++#endif /* GENESIS */
+
+-
++#ifdef YUKON
+ /******************************************************************************
+ *
+ * SkAddrGmacMcAdd - add a multicast address to a port
+@@ -789,28 +797,29 @@
+ #ifndef SK_ADDR_CHEAT
+ SK_U32 HashBit;
+ #endif /* !defined(SK_ADDR_CHEAT) */
+-
++
+ if (!(pMc->a[0] & SK_MC_BIT)) {
+ /* Hashing only possible with multicast addresses */
+ return (SK_MC_ILLEGAL_ADDRESS);
+ }
+-
++
+ #ifndef SK_ADDR_CHEAT
+-
++
+ /* Compute hash value of address. */
+ HashBit = SkGmacMcHash(&pMc->a[0]);
+-
++
+ if (Flags & SK_ADDR_PERMANENT) { /* permanent => RLMT */
+-
++
+ /* Add bit to InexactRlmtFilter. */
+ pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[HashBit / 8] |=
+ 1 << (HashBit % 8);
+-
++
+ /* Copy bit to InexactFilter. */
+ for (i = 0; i < 8; i++) {
+ pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
+ pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i];
+ }
++
+ #ifdef DEBUG
+ SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
+ ("GMAC InexactRlmtFilter: %02X %02X %02X %02X %02X %02X %02X %02X\n",
+@@ -821,20 +830,21 @@
+ pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[4],
+ pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[5],
+ pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[6],
+- pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[7]))
++ pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[7]));
+ #endif /* DEBUG */
+ }
+ else { /* not permanent => DRV */
+-
++
+ /* Add bit to InexactDrvFilter. */
+ pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[HashBit / 8] |=
+ 1 << (HashBit % 8);
+-
++
+ /* Copy bit to InexactFilter. */
+ for (i = 0; i < 8; i++) {
+ pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |=
+ pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i];
+ }
++
+ #ifdef DEBUG
+ SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
+ ("GMAC InexactDrvFilter: %02X %02X %02X %02X %02X %02X %02X %02X\n",
+@@ -845,22 +855,22 @@
+ pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[4],
+ pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[5],
+ pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[6],
+- pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[7]))
++ pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[7]));
+ #endif /* DEBUG */
+ }
+-
++
+ #else /* SK_ADDR_CHEAT */
+-
++
+ /* Set all bits in InexactFilter. */
+ for (i = 0; i < 8; i++) {
+ pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0xFF;
+ }
+ #endif /* SK_ADDR_CHEAT */
+-
++
+ return (SK_MC_FILTERING_INEXACT);
+-
+-} /* SkAddrGmacMcAdd */
+
++} /* SkAddrGmacMcAdd */
++#endif /* YUKON */
+ #endif /* !SK_SLIM */
+
+ /******************************************************************************
+@@ -892,7 +902,8 @@
+ SK_IOC IoC, /* I/O context */
+ SK_U32 PortNumber) /* Port Number */
+ {
+- int ReturnCode;
++ int ReturnCode = SK_ADDR_ILLEGAL_PORT;
++
+ #if (!defined(SK_SLIM) || defined(DEBUG))
+ if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
+ return (SK_ADDR_ILLEGAL_PORT);
+@@ -948,13 +959,13 @@
+ SK_ADDR_PORT *pAPort;
+
+ SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
+- ("SkAddrXmacMcUpdate on Port %u.\n", PortNumber))
+-
++ ("SkAddrXmacMcUpdate on Port %u.\n", PortNumber));
++
+ pAPort = &pAC->Addr.Port[PortNumber];
+
+ #ifdef DEBUG
+ SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
+- ("Next0 on Port %d: %d\n", PortNumber, Next0[PortNumber]))
++ ("Next0 on Port %d: %d\n", PortNumber, Next0[PortNumber]));
+ #endif /* DEBUG */
+
+ /* Start with 0 to also program the logical MAC address. */
+@@ -966,7 +977,7 @@
+
+ /* Clear other permanent exact match addresses on XMAC */
+ if (pAPort->NextExactMatchRlmt <= SK_ADDR_LAST_MATCH_RLMT) {
+-
++
+ SkXmClrExactAddr(pAC, IoC, PortNumber, pAPort->NextExactMatchRlmt,
+ SK_ADDR_LAST_MATCH_RLMT);
+ }
+@@ -978,7 +989,7 @@
+
+ /* Clear other non-permanent exact match addresses on XMAC */
+ if (pAPort->NextExactMatchDrv <= SK_ADDR_LAST_MATCH_DRV) {
+-
++
+ SkXmClrExactAddr(pAC, IoC, PortNumber, pAPort->NextExactMatchDrv,
+ SK_ADDR_LAST_MATCH_DRV);
+ }
+@@ -988,18 +999,18 @@
+ }
+
+ if (pAPort->PromMode & SK_PROM_MODE_ALL_MC) {
+-
++
+ /* Set all bits in 64-bit hash register. */
+ XM_OUTHASH(IoC, PortNumber, XM_HSM, &OnesHash);
+-
++
+ /* Enable Hashing */
+ SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
+ }
+ else if (Inexact != 0) {
+-
++
+ /* Set 64-bit hash register to InexactFilter. */
+ XM_OUTHASH(IoC, PortNumber, XM_HSM, &pAPort->InexactFilter.Bytes[0]);
+-
++
+ /* Enable Hashing */
+ SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
+ }
+@@ -1014,7 +1025,7 @@
+
+ /* Set port's current physical MAC address. */
+ OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0];
+-
++
+ XM_OUTADDR(IoC, PortNumber, XM_SA, OutAddr);
+
+ #ifdef xDEBUG
+@@ -1024,9 +1035,9 @@
+
+ /* Get exact match address i from port PortNumber. */
+ InAddr = (SK_U16 *) &InAddr8[0];
+-
++
+ XM_INADDR(IoC, PortNumber, XM_EXM(i), InAddr);
+-
++
+ SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
+ ("SkAddrXmacMcUpdate: MC address %d on Port %u: ",
+ "%02x %02x %02x %02x %02x %02x -- %02x %02x %02x %02x %02x %02x\n",
+@@ -1043,7 +1054,7 @@
+ pAPort->Exact[i].a[2],
+ pAPort->Exact[i].a[3],
+ pAPort->Exact[i].a[4],
+- pAPort->Exact[i].a[5]))
++ pAPort->Exact[i].a[5]));
+ }
+ #endif /* DEBUG */
+
+@@ -1054,7 +1065,7 @@
+ else {
+ return (SK_MC_FILTERING_INEXACT);
+ }
+-
++
+ } /* SkAddrXmacMcUpdate */
+
+ #endif /* GENESIS */
+@@ -1095,37 +1106,37 @@
+ SK_ADDR_PORT *pAPort;
+
+ SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
+- ("SkAddrGmacMcUpdate on Port %u.\n", PortNumber))
+-
++ ("SkAddrGmacMcUpdate on Port %u.\n", PortNumber));
++
+ pAPort = &pAC->Addr.Port[PortNumber];
+
+ #ifdef DEBUG
+ SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
+- ("Next0 on Port %d: %d\n", PortNumber, Next0[PortNumber]))
++ ("Next0 on Port %d: %d\n", PortNumber, Next0[PortNumber]));
+ #endif /* DEBUG */
+-
++
+ #ifndef SK_SLIM
+ for (Inexact = 0, i = 0; i < 8; i++) {
+ Inexact |= pAPort->InexactFilter.Bytes[i];
+ }
+-
++
+ /* Set 64-bit hash register to InexactFilter. */
+ GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1,
+ &pAPort->InexactFilter.Bytes[0]);
+-
+- if (pAPort->PromMode & SK_PROM_MODE_ALL_MC) {
+-
++
++ if (pAPort->PromMode & SK_PROM_MODE_ALL_MC) {
++
+ /* Set all bits in 64-bit hash register. */
+ GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, &OnesHash);
+-
++
+ /* Enable Hashing */
+ SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
+ }
+- else {
++ else {
+ /* Enable Hashing. */
+ SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
+ }
+-
++
+ if (pAPort->PromMode != SK_PROM_MODE_NONE) {
+ (void) SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode);
+ }
+@@ -1136,19 +1147,19 @@
+
+ /* Enable Hashing */
+ SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
+-
++
+ (void) SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode);
+-
++
+ #endif /* SK_SLIM */
+-
++
+ /* Set port's current physical MAC address. */
+ OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0];
+ GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_1L, OutAddr);
+-
++
+ /* Set port's current logical MAC address. */
+ OutAddr = (SK_U16 *) &pAPort->Exact[0].a[0];
+ GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_2L, OutAddr);
+-
++
+ #ifdef DEBUG
+ SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
+ ("SkAddrGmacMcUpdate: Permanent Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
+@@ -1157,8 +1168,8 @@
+ pAPort->Exact[0].a[2],
+ pAPort->Exact[0].a[3],
+ pAPort->Exact[0].a[4],
+- pAPort->Exact[0].a[5]))
+-
++ pAPort->Exact[0].a[5]));
++
+ SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
+ ("SkAddrGmacMcUpdate: Physical MAC Address: %02X %02X %02X %02X %02X %02X\n",
+ pAPort->CurrentMacAddress.a[0],
+@@ -1166,9 +1177,9 @@
+ pAPort->CurrentMacAddress.a[2],
+ pAPort->CurrentMacAddress.a[3],
+ pAPort->CurrentMacAddress.a[4],
+- pAPort->CurrentMacAddress.a[5]))
++ pAPort->CurrentMacAddress.a[5]));
+ #endif /* DEBUG */
+-
++
+ #ifndef SK_SLIM
+ /* Determine return value. */
+ if (Inexact == 0 && pAPort->PromMode == 0) {
+@@ -1180,7 +1191,7 @@
+ #else /* SK_SLIM */
+ return (SK_MC_FILTERING_INEXACT);
+ #endif /* SK_SLIM */
+-
++
+ } /* SkAddrGmacMcUpdate */
+
+ #endif /* YUKON */
+@@ -1275,26 +1286,46 @@
+ (void) SkAddrMcUpdate(pAC, IoC, PortNumber);
+ }
+ else if (Flags & SK_ADDR_PHYSICAL_ADDRESS) { /* Physical MAC address. */
+- if (SK_ADDR_EQUAL(pNewAddr->a,
+- pAC->Addr.Net[NetNumber].CurrentMacAddress.a)) {
+- return (SK_ADDR_DUPLICATE_ADDRESS);
+- }
+-
+ for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
+ if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
+ return (SK_ADDR_TOO_EARLY);
+ }
++ }
+
++ /*
++ * In dual net mode it should be possible to set all MAC
++ * addresses independently. Therefore the equality checks
++ * against the locical address of the same port and the
++ * physical address of the other port are suppressed here.
++ */
++#ifndef SK_NO_RLMT
++ if (pAC->Rlmt.NumNets == 1) {
++#endif /* SK_NO_RLMT */
+ if (SK_ADDR_EQUAL(pNewAddr->a,
+- pAC->Addr.Port[i].CurrentMacAddress.a)) {
+- if (i == PortNumber) {
+- return (SK_ADDR_SUCCESS);
+- }
+- else {
+- return (SK_ADDR_DUPLICATE_ADDRESS);
++ pAC->Addr.Net[NetNumber].CurrentMacAddress.a)) {
++ return (SK_ADDR_DUPLICATE_ADDRESS);
++ }
++
++ for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
++ if (SK_ADDR_EQUAL(pNewAddr->a,
++ pAC->Addr.Port[i].CurrentMacAddress.a)) {
++ if (i == PortNumber) {
++ return (SK_ADDR_SUCCESS);
++ }
++ else {
++ return (SK_ADDR_DUPLICATE_ADDRESS);
++ }
+ }
+ }
++#ifndef SK_NO_RLMT
+ }
++ else {
++ if (SK_ADDR_EQUAL(pNewAddr->a,
++ pAC->Addr.Port[PortNumber].CurrentMacAddress.a)) {
++ return (SK_ADDR_SUCCESS);
++ }
++ }
++#endif /* SK_NO_RLMT */
+
+ pAC->Addr.Port[PortNumber].PreviousMacAddress =
+ pAC->Addr.Port[PortNumber].CurrentMacAddress;
+@@ -1325,18 +1356,32 @@
+ pAC->Addr.Net[NetNumber].CurrentMacAddress.a)) {
+ return (SK_ADDR_SUCCESS);
+ }
+-
++
+ for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
+ if (!pAC->Addr.Port[i].CurrentMacAddressSet) {
+ return (SK_ADDR_TOO_EARLY);
+ }
++ }
+
+- if (SK_ADDR_EQUAL(pNewAddr->a,
+- pAC->Addr.Port[i].CurrentMacAddress.a)) {
+- return (SK_ADDR_DUPLICATE_ADDRESS);
++ /*
++ * In dual net mode on Yukon-2 adapters the physical address
++ * of port 0 and the logical address of port 1 are equal - in
++ * this case the equality check of the physical address leads
++ * to an error and is suppressed here.
++ */
++#ifndef SK_NO_RLMT
++ if (pAC->Rlmt.NumNets == 1) {
++#endif /* SK_NO_RLMT */
++ for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) {
++ if (SK_ADDR_EQUAL(pNewAddr->a,
++ pAC->Addr.Port[i].CurrentMacAddress.a)) {
++ return (SK_ADDR_DUPLICATE_ADDRESS);
++ }
+ }
++#ifndef SK_NO_RLMT
+ }
+-
++#endif /* SK_NO_RLMT */
++
+ /*
+ * In case that the physical and the logical MAC addresses are equal
+ * we must also change the physical MAC address here.
+@@ -1345,11 +1390,11 @@
+ */
+ if (SK_ADDR_EQUAL(pAC->Addr.Port[PortNumber].CurrentMacAddress.a,
+ pAC->Addr.Port[PortNumber].Exact[0].a)) {
+-
++
+ pAC->Addr.Port[PortNumber].PreviousMacAddress =
+ pAC->Addr.Port[PortNumber].CurrentMacAddress;
+ pAC->Addr.Port[PortNumber].CurrentMacAddress = *pNewAddr;
+-
++
+ #ifndef SK_NO_RLMT
+ /* Report address change to RLMT. */
+ Para.Para32[0] = PortNumber;
+@@ -1357,7 +1402,7 @@
+ SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_PORT_ADDR, Para);
+ #endif /* !SK_NO_RLMT */
+ }
+-
++
+ #ifndef SK_NO_RLMT
+ /* Set PortNumber to number of net's active port. */
+ PortNumber = pAC->Rlmt.Net[NetNumber].
+@@ -1373,8 +1418,8 @@
+ pAC->Addr.Net[NetNumber].PermanentMacAddress.a[2],
+ pAC->Addr.Net[NetNumber].PermanentMacAddress.a[3],
+ pAC->Addr.Net[NetNumber].PermanentMacAddress.a[4],
+- pAC->Addr.Net[NetNumber].PermanentMacAddress.a[5]))
+-
++ pAC->Addr.Net[NetNumber].PermanentMacAddress.a[5]));
++
+ SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL,
+ ("SkAddrOverride: New logical MAC Address: %02X %02X %02X %02X %02X %02X\n",
+ pAC->Addr.Net[NetNumber].CurrentMacAddress.a[0],
+@@ -1382,17 +1427,16 @@
+ pAC->Addr.Net[NetNumber].CurrentMacAddress.a[2],
+ pAC->Addr.Net[NetNumber].CurrentMacAddress.a[3],
+ pAC->Addr.Net[NetNumber].CurrentMacAddress.a[4],
+- pAC->Addr.Net[NetNumber].CurrentMacAddress.a[5]))
++ pAC->Addr.Net[NetNumber].CurrentMacAddress.a[5]));
+ #endif /* DEBUG */
+
+- /* Write address to first exact match entry of active port. */
+- (void) SkAddrMcUpdate(pAC, IoC, PortNumber);
++ /* Write address to first exact match entry of active port. */
++ (void)SkAddrMcUpdate(pAC, IoC, PortNumber);
+ }
+
+ return (SK_ADDR_SUCCESS);
+-
+-} /* SkAddrOverride */
+
++} /* SkAddrOverride */
+
+ #endif /* SK_NO_MAO */
+
+@@ -1424,7 +1468,8 @@
+ SK_U32 PortNumber, /* port whose promiscuous mode changes */
+ int NewPromMode) /* new promiscuous mode */
+ {
+- int ReturnCode;
++ int ReturnCode = SK_ADDR_ILLEGAL_PORT;
++
+ #if (!defined(SK_SLIM) || defined(DEBUG))
+ if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) {
+ return (SK_ADDR_ILLEGAL_PORT);
+@@ -1489,17 +1534,18 @@
+ /* Promiscuous mode! */
+ CurPromMode |= SK_PROM_MODE_LLC;
+ }
+-
++
+ for (Inexact = 0xFF, i = 0; i < 8; i++) {
+ Inexact &= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i];
+ }
++
+ if (Inexact == 0xFF) {
+ CurPromMode |= (pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_ALL_MC);
+ }
+ else {
+ /* Get InexactModeBit (bit XM_MD_ENA_HASH in mode register) */
+ XM_IN16(IoC, PortNumber, XM_MODE, &LoMode);
+-
++
+ InexactModeBit = (LoMode & XM_MD_ENA_HASH) != 0;
+
+ /* Read 64-bit hash register from XMAC */
+@@ -1522,7 +1568,7 @@
+
+ if ((NewPromMode & SK_PROM_MODE_ALL_MC) &&
+ !(CurPromMode & SK_PROM_MODE_ALL_MC)) { /* All MC. */
+-
++
+ /* Set all bits in 64-bit hash register. */
+ XM_OUTHASH(IoC, PortNumber, XM_HSM, &OnesHash);
+
+@@ -1558,9 +1604,9 @@
+ /* Clear Promiscuous Mode */
+ SkMacPromiscMode(pAC, IoC, (int) PortNumber, SK_FALSE);
+ }
+-
++
+ return (SK_ADDR_SUCCESS);
+-
++
+ } /* SkAddrXmacPromiscuousChange */
+
+ #endif /* GENESIS */
+@@ -1607,22 +1653,25 @@
+ CurPromMode |= (pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_ALL_MC);
+ }
+
++ /* dummy read after GM_IN16() */
++ SK_IN16(IoC, B0_RAP, &ReceiveControl);
++
+ pAC->Addr.Port[PortNumber].PromMode = NewPromMode;
+
+ if (NewPromMode == CurPromMode) {
+ return (SK_ADDR_SUCCESS);
+ }
+-
++
+ if ((NewPromMode & SK_PROM_MODE_ALL_MC) &&
+ !(CurPromMode & SK_PROM_MODE_ALL_MC)) { /* All MC */
+-
++
+ /* Set all bits in 64-bit hash register. */
+ GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, &OnesHash);
+-
++
+ /* Enable Hashing */
+ SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE);
+ }
+-
++
+ if ((CurPromMode & SK_PROM_MODE_ALL_MC) &&
+ !(NewPromMode & SK_PROM_MODE_ALL_MC)) { /* Norm. MC */
+
+@@ -1636,19 +1685,19 @@
+
+ if ((NewPromMode & SK_PROM_MODE_LLC) &&
+ !(CurPromMode & SK_PROM_MODE_LLC)) { /* Prom. LLC */
+-
++
+ /* Set the MAC to Promiscuous Mode. */
+ SkMacPromiscMode(pAC, IoC, (int) PortNumber, SK_TRUE);
+ }
+ else if ((CurPromMode & SK_PROM_MODE_LLC) &&
+ !(NewPromMode & SK_PROM_MODE_LLC)) { /* Norm. LLC */
+-
++
+ /* Clear Promiscuous Mode. */
+ SkMacPromiscMode(pAC, IoC, (int) PortNumber, SK_FALSE);
+ }
+
+ return (SK_ADDR_SUCCESS);
+-
++
+ } /* SkAddrGmacPromiscuousChange */
+
+ #endif /* YUKON */
+@@ -1720,33 +1769,33 @@
+ pAC->Addr.Port[ToPortNumber].InexactFilter.Bytes[i];
+ pAC->Addr.Port[ToPortNumber].InexactFilter.Bytes[i] = Byte;
+ }
+-
++
+ i = pAC->Addr.Port[FromPortNumber].PromMode;
+ pAC->Addr.Port[FromPortNumber].PromMode = pAC->Addr.Port[ToPortNumber].PromMode;
+ pAC->Addr.Port[ToPortNumber].PromMode = i;
+-
++
+ if (pAC->GIni.GIGenesis) {
+ DWord = pAC->Addr.Port[FromPortNumber].FirstExactMatchRlmt;
+ pAC->Addr.Port[FromPortNumber].FirstExactMatchRlmt =
+ pAC->Addr.Port[ToPortNumber].FirstExactMatchRlmt;
+ pAC->Addr.Port[ToPortNumber].FirstExactMatchRlmt = DWord;
+-
++
+ DWord = pAC->Addr.Port[FromPortNumber].NextExactMatchRlmt;
+ pAC->Addr.Port[FromPortNumber].NextExactMatchRlmt =
+ pAC->Addr.Port[ToPortNumber].NextExactMatchRlmt;
+ pAC->Addr.Port[ToPortNumber].NextExactMatchRlmt = DWord;
+-
++
+ DWord = pAC->Addr.Port[FromPortNumber].FirstExactMatchDrv;
+ pAC->Addr.Port[FromPortNumber].FirstExactMatchDrv =
+ pAC->Addr.Port[ToPortNumber].FirstExactMatchDrv;
+ pAC->Addr.Port[ToPortNumber].FirstExactMatchDrv = DWord;
+-
++
+ DWord = pAC->Addr.Port[FromPortNumber].NextExactMatchDrv;
+ pAC->Addr.Port[FromPortNumber].NextExactMatchDrv =
+ pAC->Addr.Port[ToPortNumber].NextExactMatchDrv;
+ pAC->Addr.Port[ToPortNumber].NextExactMatchDrv = DWord;
+ }
+-
++
+ /* CAUTION: Solution works if only ports of one adapter are in use. */
+ for (i = 0; (SK_U32) i < pAC->Rlmt.Net[pAC->Rlmt.Port[ToPortNumber].
+ Net->NetNumber].NumPorts; i++) {
+@@ -1757,12 +1806,12 @@
+ /* 20001207 RA: Was "ToPortNumber;". */
+ }
+ }
+-
++
+ (void) SkAddrMcUpdate(pAC, IoC, FromPortNumber);
+ (void) SkAddrMcUpdate(pAC, IoC, ToPortNumber);
+
+ return (SK_ADDR_SUCCESS);
+-
++
+ } /* SkAddrSwap */
+
+ #endif /* !SK_SLIM */
+diff -ruN linux/drivers/net/sk98lin/skcsum.c linux-new/drivers/net/sk98lin/skcsum.c
+--- linux/drivers/net/sk98lin/skcsum.c 2005-09-26 13:32:48.000000000 +0400
++++ linux-new/drivers/net/sk98lin/skcsum.c 2005-08-09 17:15:51.000000000 +0400
+@@ -2,8 +2,8 @@
+ *
+ * Name: skcsum.c
+ * Project: GEnesis, PCI Gigabit Ethernet Adapter
+- * Version: $Revision: 1.12 $
+- * Date: $Date: 2003/08/20 13:55:53 $
++ * Version: $Revision: 2.1 $
++ * Date: $Date: 2003/10/27 14:16:08 $
+ * Purpose: Store/verify Internet checksum in send/receive packets.
+ *
+ ******************************************************************************/
+@@ -25,7 +25,7 @@
+
+ #ifndef lint
+ static const char SysKonnectFileId[] =
+- "@(#) $Id: skcsum.c,v 1.12 2003/08/20 13:55:53 mschmid Exp $ (C) SysKonnect.";
++ "@(#) $Id: skcsum.c,v 2.1 2003/10/27 14:16:08 amock Exp $ (C) SysKonnect.";
+ #endif /* !lint */
+
+ /******************************************************************************
+diff -ruN linux/drivers/net/sk98lin/skdim.c linux-new/drivers/net/sk98lin/skdim.c
+--- linux/drivers/net/sk98lin/skdim.c 2005-09-26 13:32:48.000000000 +0400
++++ linux-new/drivers/net/sk98lin/skdim.c 2005-08-09 17:15:51.000000000 +0400
+@@ -1,17 +1,25 @@
+ /******************************************************************************
+ *
+- * Name: skdim.c
+- * Project: GEnesis, PCI Gigabit Ethernet Adapter
+- * Version: $Revision: 1.5 $
+- * Date: $Date: 2003/11/28 12:55:40 $
+- * Purpose: All functions to maintain interrupt moderation
++ * Name: skdim.c
++ * Project: GEnesis, PCI Gigabit Ethernet Adapter
++ * Version: $Revision: 1.5.2.2 $
++ * Date: $Date: 2005/05/23 13:47:33 $
++ * Purpose: All functions regardig interrupt moderation
+ *
+ ******************************************************************************/
+
+ /******************************************************************************
+ *
+ * (C)Copyright 1998-2002 SysKonnect GmbH.
+- * (C)Copyright 2002-2003 Marvell.
++ * (C)Copyright 2002-2005 Marvell.
++ *
++ * Driver for Marvell Yukon/2 chipset and SysKonnect Gigabit Ethernet
++ * Server Adapters.
++ *
++ * Author: Ralph Roesler (rroesler@syskonnect.de)
++ * Mirko Lindner (mlindner@syskonnect.de)
++ *
++ * Address all question to: linux@syskonnect.de
+ *
+ * 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
+@@ -20,723 +28,367 @@
+ *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+- ******************************************************************************/
++ *****************************************************************************/
+
+-/******************************************************************************
+- *
+- * Description:
+- *
+- * This module is intended to manage the dynamic interrupt moderation on both
+- * GEnesis and Yukon adapters.
+- *
+- * Include File Hierarchy:
+- *
+- * "skdrv1st.h"
+- * "skdrv2nd.h"
+- *
+- ******************************************************************************/
+-
+-#ifndef lint
+-static const char SysKonnectFileId[] =
+- "@(#) $Id: skdim.c,v 1.5 2003/11/28 12:55:40 rroesler Exp $ (C) SysKonnect.";
+-#endif
+-
+-#define __SKADDR_C
+-
+-#ifdef __cplusplus
+-#error C++ is not yet supported.
+-extern "C" {
+-#endif
+-
+-/*******************************************************************************
+-**
+-** Includes
+-**
+-*******************************************************************************/
+-
+-#ifndef __INC_SKDRV1ST_H
+ #include "h/skdrv1st.h"
+-#endif
+-
+-#ifndef __INC_SKDRV2ND_H
+ #include "h/skdrv2nd.h"
+-#endif
+
+-#include <linux/kernel_stat.h>
+-
+-/*******************************************************************************
+-**
+-** Defines
+-**
+-*******************************************************************************/
+-
+-/*******************************************************************************
+-**
+-** Typedefs
+-**
+-*******************************************************************************/
++/******************************************************************************
++ *
++ * Local Function Prototypes
++ *
++ *****************************************************************************/
+
+-/*******************************************************************************
+-**
+-** Local function prototypes
+-**
+-*******************************************************************************/
+-
+-static unsigned int GetCurrentSystemLoad(SK_AC *pAC);
+-static SK_U64 GetIsrCalls(SK_AC *pAC);
+-static SK_BOOL IsIntModEnabled(SK_AC *pAC);
+-static void SetCurrIntCtr(SK_AC *pAC);
+-static void EnableIntMod(SK_AC *pAC);
+-static void DisableIntMod(SK_AC *pAC);
+-static void ResizeDimTimerDuration(SK_AC *pAC);
+-static void DisplaySelectedModerationType(SK_AC *pAC);
+-static void DisplaySelectedModerationMask(SK_AC *pAC);
+-static void DisplayDescrRatio(SK_AC *pAC);
++static SK_U64 getIsrCalls(SK_AC *pAC);
++static SK_BOOL isIntModEnabled(SK_AC *pAC);
++static void setCurrIntCtr(SK_AC *pAC);
++static void enableIntMod(SK_AC *pAC);
++static void disableIntMod(SK_AC *pAC);
+
+-/*******************************************************************************
+-**
+-** Global variables
+-**
+-*******************************************************************************/
++#define M_DIMINFO pAC->DynIrqModInfo
+
+-/*******************************************************************************
+-**
+-** Local variables
+-**
+-*******************************************************************************/
++/******************************************************************************
++ *
++ * Global Functions
++ *
++ *****************************************************************************/
+
+-/*******************************************************************************
+-**
+-** Global functions
+-**
+-*******************************************************************************/
++/*****************************************************************************
++ *
++ * SkDimModerate - Moderates the IRQs depending on the current needs
++ *
++ * Description:
++ * Moderation of IRQs depends on the number of occurred IRQs with
++ * respect to the previous moderation cycle.
++ *
++ * Returns: N/A
++ *
++ */
++void SkDimModerate(
++SK_AC *pAC) /* pointer to adapter control context */
++{
++ SK_U64 IsrCalls = getIsrCalls(pAC);
++
++ SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG,("==> SkDimModerate\n"));
++
++ if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_DYNAMIC) {
++ if (isIntModEnabled(pAC)) {
++ if (IsrCalls < M_DIMINFO.MaxModIntsPerSecLowerLimit) {
++ disableIntMod(pAC);
++ }
++ } else {
++ if (IsrCalls > M_DIMINFO.MaxModIntsPerSecUpperLimit) {
++ enableIntMod(pAC);
++ }
++ }
++ }
++ setCurrIntCtr(pAC);
+
+-/*******************************************************************************
+-** Function : SkDimModerate
+-** Description : Called in every ISR to check if moderation is to be applied
+-** or not for the current number of interrupts
+-** Programmer : Ralph Roesler
+-** Last Modified: 22-mar-03
+-** Returns : void (!)
+-** Notes : -
+-*******************************************************************************/
+-
+-void
+-SkDimModerate(SK_AC *pAC) {
+- unsigned int CurrSysLoad = 0; /* expressed in percent */
+- unsigned int LoadIncrease = 0; /* expressed in percent */
+- SK_U64 ThresholdInts = 0;
+- SK_U64 IsrCallsPerSec = 0;
++ SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG,("<== SkDimModerate\n"));
++}
+
+-#define M_DIMINFO pAC->DynIrqModInfo
++/*****************************************************************************
++ *
++ * SkDimStartModerationTimer - Starts the moderation timer
++ *
++ * Description:
++ * Dynamic interrupt moderation is regularly checked using the
++ * so-called moderation timer. This timer is started with this function.
++ *
++ * Returns: N/A
++ */
++void SkDimStartModerationTimer(
++SK_AC *pAC) /* pointer to adapter control context */
++{
++ SK_EVPARA EventParam; /* Event struct for timer event */
++
++ SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG,
++ ("==> SkDimStartModerationTimer\n"));
+
+- if (!IsIntModEnabled(pAC)) {
+- if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_DYNAMIC) {
+- CurrSysLoad = GetCurrentSystemLoad(pAC);
+- if (CurrSysLoad > 75) {
+- /*
+- ** More than 75% total system load! Enable the moderation
+- ** to shield the system against too many interrupts.
+- */
+- EnableIntMod(pAC);
+- } else if (CurrSysLoad > M_DIMINFO.PrevSysLoad) {
+- LoadIncrease = (CurrSysLoad - M_DIMINFO.PrevSysLoad);
+- if (LoadIncrease > ((M_DIMINFO.PrevSysLoad *
+- C_INT_MOD_ENABLE_PERCENTAGE) / 100)) {
+- if (CurrSysLoad > 10) {
+- /*
+- ** More than 50% increase with respect to the
+- ** previous load of the system. Most likely this
+- ** is due to our ISR-proc...
+- */
+- EnableIntMod(pAC);
+- }
+- }
+- } else {
+- /*
+- ** Neither too much system load at all nor too much increase
+- ** with respect to the previous system load. Hence, we can leave
+- ** the ISR-handling like it is without enabling moderation.
+- */
+- }
+- M_DIMINFO.PrevSysLoad = CurrSysLoad;
+- }
+- } else {
+- if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_DYNAMIC) {
+- ThresholdInts = ((M_DIMINFO.MaxModIntsPerSec *
+- C_INT_MOD_DISABLE_PERCENTAGE) / 100);
+- IsrCallsPerSec = GetIsrCalls(pAC);
+- if (IsrCallsPerSec <= ThresholdInts) {
+- /*
+- ** The number of interrupts within the last second is
+- ** lower than the disable_percentage of the desried
+- ** maxrate. Therefore we can disable the moderation.
+- */
+- DisableIntMod(pAC);
+- M_DIMINFO.MaxModIntsPerSec =
+- (M_DIMINFO.MaxModIntsPerSecUpperLimit +
+- M_DIMINFO.MaxModIntsPerSecLowerLimit) / 2;
+- } else {
+- /*
+- ** The number of interrupts per sec is the same as expected.
+- ** Evalulate the descriptor-ratio. If it has changed, a resize
+- ** in the moderation timer might be usefull
+- */
+- if (M_DIMINFO.AutoSizing) {
+- ResizeDimTimerDuration(pAC);
+- }
+- }
+- }
+- }
+-
+- /*
+- ** Some information to the log...
+- */
+- if (M_DIMINFO.DisplayStats) {
+- DisplaySelectedModerationType(pAC);
+- DisplaySelectedModerationMask(pAC);
+- DisplayDescrRatio(pAC);
+- }
++ if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_DYNAMIC) {
++ SK_MEMSET((char *) &EventParam, 0, sizeof(EventParam));
++ EventParam.Para32[0] = SK_DRV_MODERATION_TIMER;
++ SkTimerStart(pAC, pAC->IoBase,
++ &pAC->DynIrqModInfo.ModTimer,
++ pAC->DynIrqModInfo.DynIrqModSampleInterval * 1000000,
++ SKGE_DRV, SK_DRV_TIMER, EventParam);
++ }
+
+- M_DIMINFO.NbrProcessedDescr = 0;
+- SetCurrIntCtr(pAC);
++ SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG,
++ ("<== SkDimStartModerationTimer\n"));
+ }
+
+-/*******************************************************************************
+-** Function : SkDimStartModerationTimer
+-** Description : Starts the audit-timer for the dynamic interrupt moderation
+-** Programmer : Ralph Roesler
+-** Last Modified: 22-mar-03
+-** Returns : void (!)
+-** Notes : -
+-*******************************************************************************/
+-
+-void
+-SkDimStartModerationTimer(SK_AC *pAC) {
+- SK_EVPARA EventParam; /* Event struct for timer event */
+-
+- SK_MEMSET((char *) &EventParam, 0, sizeof(EventParam));
+- EventParam.Para32[0] = SK_DRV_MODERATION_TIMER;
+- SkTimerStart(pAC, pAC->IoBase, &pAC->DynIrqModInfo.ModTimer,
+- SK_DRV_MODERATION_TIMER_LENGTH,
+- SKGE_DRV, SK_DRV_TIMER, EventParam);
+-}
++/*****************************************************************************
++ *
++ * SkDimEnableModerationIfNeeded - Enables or disables any moderationtype
++ *
++ * Description:
++ * This function effectively initializes the IRQ moderation of a network
++ * adapter. Depending on the configuration, this might be either static
++ * or dynamic. If no moderation is configured, this function will do
++ * nothing.
++ *
++ * Returns: N/A
++ */
++void SkDimEnableModerationIfNeeded(
++SK_AC *pAC) /* pointer to adapter control context */
++{
++ SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG,
++ ("==> SkDimEnableModerationIfNeeded\n"));
++
++ if (M_DIMINFO.IntModTypeSelect != C_INT_MOD_NONE) {
++ if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_STATIC) {
++ enableIntMod(pAC);
++ } else { /* must be C_INT_MOD_DYNAMIC */
++ SkDimStartModerationTimer(pAC);
++ }
++ }
+
+-/*******************************************************************************
+-** Function : SkDimEnableModerationIfNeeded
+-** Description : Either enables or disables moderation
+-** Programmer : Ralph Roesler
+-** Last Modified: 22-mar-03
+-** Returns : void (!)
+-** Notes : This function is called when a particular adapter is opened
+-** There is no Disable function, because when all interrupts
+-** might be disable, the moderation timer has no meaning at all
+-******************************************************************************/
+-
+-void
+-SkDimEnableModerationIfNeeded(SK_AC *pAC) {
+-
+- if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_STATIC) {
+- EnableIntMod(pAC); /* notification print in this function */
+- } else if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_DYNAMIC) {
+- SkDimStartModerationTimer(pAC);
+- if (M_DIMINFO.DisplayStats) {
+- printk("Dynamic moderation has been enabled\n");
+- }
+- } else {
+- if (M_DIMINFO.DisplayStats) {
+- printk("No moderation has been enabled\n");
+- }
+- }
++ SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG,
++ ("<== SkDimEnableModerationIfNeeded\n"));
+ }
+
+-/*******************************************************************************
+-** Function : SkDimDisplayModerationSettings
+-** Description : Displays the current settings regaring interrupt moderation
+-** Programmer : Ralph Roesler
+-** Last Modified: 22-mar-03
+-** Returns : void (!)
+-** Notes : -
+-*******************************************************************************/
+-
+-void
+-SkDimDisplayModerationSettings(SK_AC *pAC) {
+- DisplaySelectedModerationType(pAC);
+- DisplaySelectedModerationMask(pAC);
+-}
++/*****************************************************************************
++ *
++ * SkDimDisableModeration - disables moderation if it is enabled
++ *
++ * Description:
++ * Disabling of the moderation requires that is enabled already.
++ *
++ * Returns: N/A
++ */
++void SkDimDisableModeration(
++SK_AC *pAC, /* pointer to adapter control context */
++int CurrentModeration) /* type of current moderation */
++{
++ SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG,
++ ("==> SkDimDisableModeration\n"));
++
++ if (M_DIMINFO.IntModTypeSelect != C_INT_MOD_NONE) {
++ if (CurrentModeration == C_INT_MOD_STATIC) {
++ disableIntMod(pAC);
++ } else { /* must be C_INT_MOD_DYNAMIC */
++ SkTimerStop(pAC, pAC->IoBase, &M_DIMINFO.ModTimer);
++ disableIntMod(pAC);
++ }
++ }
+
+-/*******************************************************************************
+-**
+-** Local functions
+-**
+-*******************************************************************************/
++ SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG,
++ ("<== SkDimDisableModeration\n"));
++}
+
+-/*******************************************************************************
+-** Function : GetCurrentSystemLoad
+-** Description : Retrieves the current system load of the system. This load
+-** is evaluated for all processors within the system.
+-** Programmer : Ralph Roesler
+-** Last Modified: 22-mar-03
+-** Returns : unsigned int: load expressed in percentage
+-** Notes : The possible range being returned is from 0 up to 100.
+-** Whereas 0 means 'no load at all' and 100 'system fully loaded'
+-** It is impossible to determine what actually causes the system
+-** to be in 100%, but maybe that is due to too much interrupts.
+-*******************************************************************************/
+-
+-static unsigned int
+-GetCurrentSystemLoad(SK_AC *pAC) {
+- unsigned long jif = jiffies;
+- unsigned int UserTime = 0;
+- unsigned int SystemTime = 0;
+- unsigned int NiceTime = 0;
+- unsigned int IdleTime = 0;
+- unsigned int TotalTime = 0;
+- unsigned int UsedTime = 0;
+- unsigned int SystemLoad = 0;
++/******************************************************************************
++ *
++ * Local Functions
++ *
++ *****************************************************************************/
+
+- /* unsigned int NbrCpu = 0; */
++/*****************************************************************************
++ *
++ * getIsrCalls - evaluate the number of IRQs handled in mod interval
++ *
++ * Description:
++ * Depending on the selected moderation mask, this function will return
++ * the number of interrupts handled in the previous moderation interval.
++ * This evaluated number is based on the current number of interrupts
++ * stored in PNMI-context and the previous stored interrupts.
++ *
++ * Returns:
++ * the number of IRQs handled
++ */
++static SK_U64 getIsrCalls(
++SK_AC *pAC) /* pointer to adapter control context */
++{
++ SK_U64 RxPort0IntDiff = 0, RxPort1IntDiff = 0;
++ SK_U64 TxPort0IntDiff = 0, TxPort1IntDiff = 0;
++ SK_U64 StatusPort0IntDiff = 0, StatusPort1IntDiff = 0;
++
++ SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG,("==>getIsrCalls\n"));
++
++ if (!CHIP_ID_YUKON_2(pAC)) {
++ if ((M_DIMINFO.MaskIrqModeration == IRQ_MASK_TX_ONLY) ||
++ (M_DIMINFO.MaskIrqModeration == IRQ_MASK_SP_TX)) {
++ if (pAC->GIni.GIMacsFound == 2) {
++ TxPort1IntDiff =
++ pAC->Pnmi.Port[1].TxIntrCts -
++ M_DIMINFO.PrevPort1TxIntrCts;
++ }
++ TxPort0IntDiff = pAC->Pnmi.Port[0].TxIntrCts -
++ M_DIMINFO.PrevPort0TxIntrCts;
++ } else if ((M_DIMINFO.MaskIrqModeration == IRQ_MASK_RX_ONLY) ||
++ (M_DIMINFO.MaskIrqModeration == IRQ_MASK_SP_RX)) {
++ if (pAC->GIni.GIMacsFound == 2) {
++ RxPort1IntDiff =
++ pAC->Pnmi.Port[1].RxIntrCts -
++ M_DIMINFO.PrevPort1RxIntrCts;
++ }
++ RxPort0IntDiff = pAC->Pnmi.Port[0].RxIntrCts -
++ M_DIMINFO.PrevPort0RxIntrCts;
++ } else {
++ if (pAC->GIni.GIMacsFound == 2) {
++ RxPort1IntDiff =
++ pAC->Pnmi.Port[1].RxIntrCts -
++ M_DIMINFO.PrevPort1RxIntrCts;
++ TxPort1IntDiff =
++ pAC->Pnmi.Port[1].TxIntrCts -
++ M_DIMINFO.PrevPort1TxIntrCts;
++ }
++ RxPort0IntDiff = pAC->Pnmi.Port[0].RxIntrCts -
++ M_DIMINFO.PrevPort0RxIntrCts;
++ TxPort0IntDiff = pAC->Pnmi.Port[0].TxIntrCts -
++ M_DIMINFO.PrevPort0TxIntrCts;
++ }
++ SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG,
++ ("==>getIsrCalls (!CHIP_ID_YUKON_2)\n"));
++ return (RxPort0IntDiff + RxPort1IntDiff +
++ TxPort0IntDiff + TxPort1IntDiff);
++ }
+
+ /*
+- ** The following lines have been commented out, because
+- ** from kernel 2.5.44 onwards, the kernel-owned structure
+- **
+- ** struct kernel_stat kstat
+- **
+- ** is not marked as an exported symbol in the file
++ ** We have a Yukon2 compliant chipset if we come up to here
+ **
+- ** kernel/ksyms.c
+- **
+- ** As a consequence, using this driver as KLM is not possible
+- ** and any access of the structure kernel_stat via the
+- ** dedicated macros kstat_cpu(i).cpustat.xxx is to be avoided.
+- **
+- ** The kstat-information might be added again in future
+- ** versions of the 2.5.xx kernel, but for the time being,
+- ** number of interrupts will serve as indication how much
+- ** load we currently have...
+- **
+- ** for (NbrCpu = 0; NbrCpu < num_online_cpus(); NbrCpu++) {
+- ** UserTime = UserTime + kstat_cpu(NbrCpu).cpustat.user;
+- ** NiceTime = NiceTime + kstat_cpu(NbrCpu).cpustat.nice;
+- ** SystemTime = SystemTime + kstat_cpu(NbrCpu).cpustat.system;
+- ** }
++ if (pAC->GIni.GIMacsFound == 2) {
++ StatusPort1IntDiff = pAC->Pnmi.Port[1].StatusLeIntrCts -
++ M_DIMINFO.PrevPort1StatusIntrCts;
++ }
++ StatusPort0IntDiff = pAC->Pnmi.Port[0].StatusLeIntrCts -
++ M_DIMINFO.PrevPort0StatusIntrCts;
+ */
+- SK_U64 ThresholdInts = 0;
+- SK_U64 IsrCallsPerSec = 0;
+-
+- ThresholdInts = ((M_DIMINFO.MaxModIntsPerSec *
+- C_INT_MOD_ENABLE_PERCENTAGE) + 100);
+- IsrCallsPerSec = GetIsrCalls(pAC);
+- if (IsrCallsPerSec >= ThresholdInts) {
+- /*
+- ** We do not know how much the real CPU-load is!
+- ** Return 80% as a default in order to activate DIM
+- */
+- SystemLoad = 80;
+- return (SystemLoad);
+- }
+-
+- UsedTime = UserTime + NiceTime + SystemTime;
+-
+- IdleTime = jif * num_online_cpus() - UsedTime;
+- TotalTime = UsedTime + IdleTime;
+-
+- SystemLoad = ( 100 * (UsedTime - M_DIMINFO.PrevUsedTime) ) /
+- (TotalTime - M_DIMINFO.PrevTotalTime);
++ SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG,
++ ("==>getIsrCalls (CHIP_ID_YUKON_2)\n"));
++ return (StatusPort0IntDiff + StatusPort1IntDiff);
++}
+
+- if (M_DIMINFO.DisplayStats) {
+- printk("Current system load is: %u\n", SystemLoad);
++/*****************************************************************************
++ *
++ * setCurrIntCtr - stores the current number of interrupts
++ *
++ * Description:
++ * Stores the current number of occurred interrupts in the adapter
++ * context. This is needed to evaluate the umber of interrupts within
++ * the moderation interval.
++ *
++ * Returns: N/A
++ *
++ */
++static void setCurrIntCtr(
++SK_AC *pAC) /* pointer to adapter control context */
++{
++ SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG,("==>setCurrIntCtr\n"));
++
++ if (!CHIP_ID_YUKON_2(pAC)) {
++ if (pAC->GIni.GIMacsFound == 2) {
++ M_DIMINFO.PrevPort1RxIntrCts = pAC->Pnmi.Port[1].RxIntrCts;
++ M_DIMINFO.PrevPort1TxIntrCts = pAC->Pnmi.Port[1].TxIntrCts;
++ }
++ M_DIMINFO.PrevPort0RxIntrCts = pAC->Pnmi.Port[0].RxIntrCts;
++ M_DIMINFO.PrevPort0TxIntrCts = pAC->Pnmi.Port[0].TxIntrCts;
++ SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG,
++ ("<== setCurrIntCtr (!CHIP_ID_YUKON_2)\n"));
++ return;
+ }
+
+- M_DIMINFO.PrevTotalTime = TotalTime;
+- M_DIMINFO.PrevUsedTime = UsedTime;
+-
+- return (SystemLoad);
++ /*
++ ** We have a Yukon2 compliant chipset if we come up to here
++ **
++ if (pAC->GIni.GIMacsFound == 2) {
++ M_DIMINFO.PrevPort1StatusIntrCts = pAC->Pnmi.Port[1].StatusLeIntrCts;
++ }
++ M_DIMINFO.PrevPort0StatusIntrCts = pAC->Pnmi.Port[0].StatusLeIntrCts;
++ */
++ SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG,
++ ("<== setCurrIntCtr (CHIP_ID_YUKON_2)\n"));
+ }
+
+-/*******************************************************************************
+-** Function : GetIsrCalls
+-** Description : Depending on the selected moderation mask, this function will
+-** return the number of interrupts handled in the previous time-
+-** frame. This evaluated number is based on the current number
+-** of interrupts stored in PNMI-context and the previous stored
+-** interrupts.
+-** Programmer : Ralph Roesler
+-** Last Modified: 23-mar-03
+-** Returns : int: the number of interrupts being executed in the last
+-** timeframe
+-** Notes : It makes only sense to call this function, when dynamic
+-** interrupt moderation is applied
+-*******************************************************************************/
+-
+-static SK_U64
+-GetIsrCalls(SK_AC *pAC) {
+- SK_U64 RxPort0IntDiff = 0;
+- SK_U64 RxPort1IntDiff = 0;
+- SK_U64 TxPort0IntDiff = 0;
+- SK_U64 TxPort1IntDiff = 0;
+-
+- if (pAC->DynIrqModInfo.MaskIrqModeration == IRQ_MASK_TX_ONLY) {
+- if (pAC->GIni.GIMacsFound == 2) {
+- TxPort1IntDiff = pAC->Pnmi.Port[1].TxIntrCts -
+- pAC->DynIrqModInfo.PrevPort1TxIntrCts;
+- }
+- TxPort0IntDiff = pAC->Pnmi.Port[0].TxIntrCts -
+- pAC->DynIrqModInfo.PrevPort0TxIntrCts;
+- } else if (pAC->DynIrqModInfo.MaskIrqModeration == IRQ_MASK_RX_ONLY) {
+- if (pAC->GIni.GIMacsFound == 2) {
+- RxPort1IntDiff = pAC->Pnmi.Port[1].RxIntrCts -
+- pAC->DynIrqModInfo.PrevPort1RxIntrCts;
+- }
+- RxPort0IntDiff = pAC->Pnmi.Port[0].RxIntrCts -
+- pAC->DynIrqModInfo.PrevPort0RxIntrCts;
+- } else {
+- if (pAC->GIni.GIMacsFound == 2) {
+- RxPort1IntDiff = pAC->Pnmi.Port[1].RxIntrCts -
+- pAC->DynIrqModInfo.PrevPort1RxIntrCts;
+- TxPort1IntDiff = pAC->Pnmi.Port[1].TxIntrCts -
+- pAC->DynIrqModInfo.PrevPort1TxIntrCts;
+- }
+- RxPort0IntDiff = pAC->Pnmi.Port[0].RxIntrCts -
+- pAC->DynIrqModInfo.PrevPort0RxIntrCts;
+- TxPort0IntDiff = pAC->Pnmi.Port[0].TxIntrCts -
+- pAC->DynIrqModInfo.PrevPort0TxIntrCts;
+- }
+-
+- return (RxPort0IntDiff + RxPort1IntDiff + TxPort0IntDiff + TxPort1IntDiff);
++/*****************************************************************************
++ *
++ * isIntModEnabled - returns the current state of interrupt moderation
++ *
++ * Description:
++ * This function retrieves the current value of the interrupt moderation
++ * command register. Its content determines whether any moderation is
++ * running or not.
++ *
++ * Returns:
++ * SK_TRUE : IRQ moderation is currently active
++ * SK_FALSE: No IRQ moderation is active
++ */
++static SK_BOOL isIntModEnabled(
++SK_AC *pAC) /* pointer to adapter control context */
++{
++ unsigned long CtrCmd;
++
++ SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG,("==>isIntModEnabled\n"));
++
++ SK_IN32(pAC->IoBase, B2_IRQM_CTRL, &CtrCmd);
++ if ((CtrCmd & TIM_START) == TIM_START) {
++ SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG,
++ ("<== isIntModEnabled (SK_TRUE)\n"));
++ return SK_TRUE;
++ }
++ SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG,
++ ("<== isIntModEnabled (SK_FALSE)\n"));
++ return SK_FALSE;
+ }
+
+-/*******************************************************************************
+-** Function : GetRxCalls
+-** Description : This function will return the number of times a receive inter-
+-** rupt was processed. This is needed to evaluate any resizing
+-** factor.
+-** Programmer : Ralph Roesler
+-** Last Modified: 23-mar-03
+-** Returns : SK_U64: the number of RX-ints being processed
+-** Notes : It makes only sense to call this function, when dynamic
+-** interrupt moderation is applied
+-*******************************************************************************/
+-
+-static SK_U64
+-GetRxCalls(SK_AC *pAC) {
+- SK_U64 RxPort0IntDiff = 0;
+- SK_U64 RxPort1IntDiff = 0;
+-
+- if (pAC->GIni.GIMacsFound == 2) {
+- RxPort1IntDiff = pAC->Pnmi.Port[1].RxIntrCts -
+- pAC->DynIrqModInfo.PrevPort1RxIntrCts;
+- }
+- RxPort0IntDiff = pAC->Pnmi.Port[0].RxIntrCts -
+- pAC->DynIrqModInfo.PrevPort0RxIntrCts;
+-
+- return (RxPort0IntDiff + RxPort1IntDiff);
+-}
++/*****************************************************************************
++ *
++ * enableIntMod - enables the interrupt moderation
++ *
++ * Description:
++ * Enabling the interrupt moderation is done by putting the desired
++ * moderation interval in the B2_IRQM_INI register, specifying the
++ * desired maks in the B2_IRQM_MSK register and finally starting the
++ * IRQ moderation timer using the B2_IRQM_CTRL register.
++ *
++ * Returns: N/A
++ *
++ */
++static void enableIntMod(
++SK_AC *pAC) /* pointer to adapter control context */
++{
++ unsigned long ModBase;
++
++ SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG,("==> enableIntMod\n"));
++
++ if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
++ ModBase = C_CLK_FREQ_GENESIS / M_DIMINFO.MaxModIntsPerSec;
++ } else if (pAC->GIni.GIChipId == CHIP_ID_YUKON_EC) {
++ ModBase = C_CLK_FREQ_YUKON_EC / M_DIMINFO.MaxModIntsPerSec;
++ } else {
++ ModBase = C_CLK_FREQ_YUKON / M_DIMINFO.MaxModIntsPerSec;
++ }
+
+-/*******************************************************************************
+-** Function : SetCurrIntCtr
+-** Description : Will store the current number orf occured interrupts in the
+-** adapter context. This is needed to evaluated the number of
+-** interrupts within a current timeframe.
+-** Programmer : Ralph Roesler
+-** Last Modified: 23-mar-03
+-** Returns : void (!)
+-** Notes : -
+-*******************************************************************************/
+-
+-static void
+-SetCurrIntCtr(SK_AC *pAC) {
+- if (pAC->GIni.GIMacsFound == 2) {
+- pAC->DynIrqModInfo.PrevPort1RxIntrCts = pAC->Pnmi.Port[1].RxIntrCts;
+- pAC->DynIrqModInfo.PrevPort1TxIntrCts = pAC->Pnmi.Port[1].TxIntrCts;
+- }
+- pAC->DynIrqModInfo.PrevPort0RxIntrCts = pAC->Pnmi.Port[0].RxIntrCts;
+- pAC->DynIrqModInfo.PrevPort0TxIntrCts = pAC->Pnmi.Port[0].TxIntrCts;
+-}
++ SK_OUT32(pAC->IoBase, B2_IRQM_INI, ModBase);
++ SK_OUT32(pAC->IoBase, B2_IRQM_MSK, M_DIMINFO.MaskIrqModeration);
++ SK_OUT32(pAC->IoBase, B2_IRQM_CTRL, TIM_START);
+
+-/*******************************************************************************
+-** Function : IsIntModEnabled()
+-** Description : Retrieves the current value of the interrupts moderation
+-** command register. Its content determines whether any
+-** moderation is running or not.
+-** Programmer : Ralph Roesler
+-** Last Modified: 23-mar-03
+-** Returns : SK_TRUE : if mod timer running
+-** SK_FALSE : if no moderation is being performed
+-** Notes : -
+-*******************************************************************************/
+-
+-static SK_BOOL
+-IsIntModEnabled(SK_AC *pAC) {
+- unsigned long CtrCmd;
+-
+- SK_IN32(pAC->IoBase, B2_IRQM_CTRL, &CtrCmd);
+- if ((CtrCmd & TIM_START) == TIM_START) {
+- return SK_TRUE;
+- } else {
+- return SK_FALSE;
+- }
++ SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG,("<== enableIntMod\n"));
+ }
+
+-/*******************************************************************************
+-** Function : EnableIntMod()
+-** Description : Enables the interrupt moderation using the values stored in
+-** in the pAC->DynIntMod data structure
+-** Programmer : Ralph Roesler
+-** Last Modified: 22-mar-03
+-** Returns : -
+-** Notes : -
+-*******************************************************************************/
+-
+-static void
+-EnableIntMod(SK_AC *pAC) {
+- unsigned long ModBase;
+-
+- if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
+- ModBase = C_CLK_FREQ_GENESIS / pAC->DynIrqModInfo.MaxModIntsPerSec;
+- } else {
+- ModBase = C_CLK_FREQ_YUKON / pAC->DynIrqModInfo.MaxModIntsPerSec;
+- }
+-
+- SK_OUT32(pAC->IoBase, B2_IRQM_INI, ModBase);
+- SK_OUT32(pAC->IoBase, B2_IRQM_MSK, pAC->DynIrqModInfo.MaskIrqModeration);
+- SK_OUT32(pAC->IoBase, B2_IRQM_CTRL, TIM_START);
+- if (M_DIMINFO.DisplayStats) {
+- printk("Enabled interrupt moderation (%i ints/sec)\n",
+- M_DIMINFO.MaxModIntsPerSec);
+- }
+-}
++/*****************************************************************************
++ *
++ * disableIntMod - disables the interrupt moderation
++ *
++ * Description:
++ * Disabling the interrupt moderation is done by stopping the
++ * IRQ moderation timer using the B2_IRQM_CTRL register.
++ *
++ * Returns: N/A
++ *
++ */
++static void disableIntMod(
++SK_AC *pAC) /* pointer to adapter control context */
++{
++ SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG,("==> disableIntMod\n"));
+
+-/*******************************************************************************
+-** Function : DisableIntMod()
+-** Description : Disbles the interrupt moderation independent of what inter-
+-** rupts are running or not
+-** Programmer : Ralph Roesler
+-** Last Modified: 23-mar-03
+-** Returns : -
+-** Notes : -
+-*******************************************************************************/
+-
+-static void
+-DisableIntMod(SK_AC *pAC) {
+-
+- SK_OUT32(pAC->IoBase, B2_IRQM_CTRL, TIM_STOP);
+- if (M_DIMINFO.DisplayStats) {
+- printk("Disabled interrupt moderation\n");
+- }
+-}
++ SK_OUT32(pAC->IoBase, B2_IRQM_CTRL, TIM_STOP);
+
+-/*******************************************************************************
+-** Function : ResizeDimTimerDuration();
+-** Description : Checks the current used descriptor ratio and resizes the
+-** duration timer (longer/smaller) if possible.
+-** Programmer : Ralph Roesler
+-** Last Modified: 23-mar-03
+-** Returns : -
+-** Notes : There are both maximum and minimum timer duration value.
+-** This function assumes that interrupt moderation is already
+-** enabled!
+-*******************************************************************************/
+-
+-static void
+-ResizeDimTimerDuration(SK_AC *pAC) {
+- SK_BOOL IncreaseTimerDuration;
+- int TotalMaxNbrDescr;
+- int UsedDescrRatio;
+- int RatioDiffAbs;
+- int RatioDiffRel;
+- int NewMaxModIntsPerSec;
+- int ModAdjValue;
+- long ModBase;
+-
+- /*
+- ** Check first if we are allowed to perform any modification
+- */
+- if (IsIntModEnabled(pAC)) {
+- if (M_DIMINFO.IntModTypeSelect != C_INT_MOD_DYNAMIC) {
+- return;
+- } else {
+- if (M_DIMINFO.ModJustEnabled) {
+- M_DIMINFO.ModJustEnabled = SK_FALSE;
+- return;
+- }
+- }
+- }
+-
+- /*
+- ** If we got until here, we have to evaluate the amount of the
+- ** descriptor ratio change...
+- */
+- TotalMaxNbrDescr = pAC->RxDescrPerRing * GetRxCalls(pAC);
+- UsedDescrRatio = (M_DIMINFO.NbrProcessedDescr * 100) / TotalMaxNbrDescr;
+-
+- if (UsedDescrRatio > M_DIMINFO.PrevUsedDescrRatio) {
+- RatioDiffAbs = (UsedDescrRatio - M_DIMINFO.PrevUsedDescrRatio);
+- RatioDiffRel = (RatioDiffAbs * 100) / UsedDescrRatio;
+- M_DIMINFO.PrevUsedDescrRatio = UsedDescrRatio;
+- IncreaseTimerDuration = SK_FALSE; /* in other words: DECREASE */
+- } else if (UsedDescrRatio < M_DIMINFO.PrevUsedDescrRatio) {
+- RatioDiffAbs = (M_DIMINFO.PrevUsedDescrRatio - UsedDescrRatio);
+- RatioDiffRel = (RatioDiffAbs * 100) / M_DIMINFO.PrevUsedDescrRatio;
+- M_DIMINFO.PrevUsedDescrRatio = UsedDescrRatio;
+- IncreaseTimerDuration = SK_TRUE; /* in other words: INCREASE */
+- } else {
+- RatioDiffAbs = (M_DIMINFO.PrevUsedDescrRatio - UsedDescrRatio);
+- RatioDiffRel = (RatioDiffAbs * 100) / M_DIMINFO.PrevUsedDescrRatio;
+- M_DIMINFO.PrevUsedDescrRatio = UsedDescrRatio;
+- IncreaseTimerDuration = SK_TRUE; /* in other words: INCREASE */
+- }
+-
+- /*
+- ** Now we can determine the change in percent
+- */
+- if ((RatioDiffRel >= 0) && (RatioDiffRel <= 5) ) {
+- ModAdjValue = 1; /* 1% change - maybe some other value in future */
+- } else if ((RatioDiffRel > 5) && (RatioDiffRel <= 10) ) {
+- ModAdjValue = 1; /* 1% change - maybe some other value in future */
+- } else if ((RatioDiffRel > 10) && (RatioDiffRel <= 15) ) {
+- ModAdjValue = 1; /* 1% change - maybe some other value in future */
+- } else {
+- ModAdjValue = 1; /* 1% change - maybe some other value in future */
+- }
+-
+- if (IncreaseTimerDuration) {
+- NewMaxModIntsPerSec = M_DIMINFO.MaxModIntsPerSec +
+- (M_DIMINFO.MaxModIntsPerSec * ModAdjValue) / 100;
+- } else {
+- NewMaxModIntsPerSec = M_DIMINFO.MaxModIntsPerSec -
+- (M_DIMINFO.MaxModIntsPerSec * ModAdjValue) / 100;
+- }
+-
+- /*
+- ** Check if we exceed boundaries...
+- */
+- if ( (NewMaxModIntsPerSec > M_DIMINFO.MaxModIntsPerSecUpperLimit) ||
+- (NewMaxModIntsPerSec < M_DIMINFO.MaxModIntsPerSecLowerLimit)) {
+- if (M_DIMINFO.DisplayStats) {
+- printk("Cannot change ModTim from %i to %i ints/sec\n",
+- M_DIMINFO.MaxModIntsPerSec, NewMaxModIntsPerSec);
+- }
+- return;
+- } else {
+- if (M_DIMINFO.DisplayStats) {
+- printk("Resized ModTim from %i to %i ints/sec\n",
+- M_DIMINFO.MaxModIntsPerSec, NewMaxModIntsPerSec);
+- }
+- }
+-
+- M_DIMINFO.MaxModIntsPerSec = NewMaxModIntsPerSec;
+-
+- if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
+- ModBase = C_CLK_FREQ_GENESIS / pAC->DynIrqModInfo.MaxModIntsPerSec;
+- } else {
+- ModBase = C_CLK_FREQ_YUKON / pAC->DynIrqModInfo.MaxModIntsPerSec;
+- }
+-
+- /*
+- ** We do not need to touch any other registers
+- */
+- SK_OUT32(pAC->IoBase, B2_IRQM_INI, ModBase);
++ SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_MSG,("<== disableIntMod\n"));
+ }
+
+ /*******************************************************************************
+-** Function : DisplaySelectedModerationType()
+-** Description : Displays what type of moderation we have
+-** Programmer : Ralph Roesler
+-** Last Modified: 23-mar-03
+-** Returns : void!
+-** Notes : -
+-*******************************************************************************/
+-
+-static void
+-DisplaySelectedModerationType(SK_AC *pAC) {
+-
+- if (pAC->DynIrqModInfo.DisplayStats) {
+- if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_STATIC) {
+- printk("Static int moderation runs with %i INTS/sec\n",
+- pAC->DynIrqModInfo.MaxModIntsPerSec);
+- } else if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_DYNAMIC) {
+- if (IsIntModEnabled(pAC)) {
+- printk("Dynamic int moderation runs with %i INTS/sec\n",
+- pAC->DynIrqModInfo.MaxModIntsPerSec);
+- } else {
+- printk("Dynamic int moderation currently not applied\n");
+- }
+- } else {
+- printk("No interrupt moderation selected!\n");
+- }
+- }
+-}
+-
+-/*******************************************************************************
+-** Function : DisplaySelectedModerationMask()
+-** Description : Displays what interrupts are moderated
+-** Programmer : Ralph Roesler
+-** Last Modified: 23-mar-03
+-** Returns : void!
+-** Notes : -
+-*******************************************************************************/
+-
+-static void
+-DisplaySelectedModerationMask(SK_AC *pAC) {
+-
+- if (pAC->DynIrqModInfo.DisplayStats) {
+- if (pAC->DynIrqModInfo.IntModTypeSelect != C_INT_MOD_NONE) {
+- switch (pAC->DynIrqModInfo.MaskIrqModeration) {
+- case IRQ_MASK_TX_ONLY:
+- printk("Only Tx-interrupts are moderated\n");
+- break;
+- case IRQ_MASK_RX_ONLY:
+- printk("Only Rx-interrupts are moderated\n");
+- break;
+- case IRQ_MASK_SP_ONLY:
+- printk("Only special-interrupts are moderated\n");
+- break;
+- case IRQ_MASK_TX_RX:
+- printk("Tx- and Rx-interrupts are moderated\n");
+- break;
+- case IRQ_MASK_SP_RX:
+- printk("Special- and Rx-interrupts are moderated\n");
+- break;
+- case IRQ_MASK_SP_TX:
+- printk("Special- and Tx-interrupts are moderated\n");
+- break;
+- case IRQ_MASK_RX_TX_SP:
+- printk("All Rx-, Tx and special-interrupts are moderated\n");
+- break;
+- default:
+- printk("Don't know what is moderated\n");
+- break;
+- }
+- } else {
+- printk("No specific interrupts masked for moderation\n");
+- }
+- }
+-}
+-
+-/*******************************************************************************
+-** Function : DisplayDescrRatio
+-** Description : Like the name states...
+-** Programmer : Ralph Roesler
+-** Last Modified: 23-mar-03
+-** Returns : void!
+-** Notes : -
+-*******************************************************************************/
+-
+-static void
+-DisplayDescrRatio(SK_AC *pAC) {
+- int TotalMaxNbrDescr = 0;
+-
+- if (pAC->DynIrqModInfo.DisplayStats) {
+- TotalMaxNbrDescr = pAC->RxDescrPerRing * GetRxCalls(pAC);
+- printk("Ratio descriptors: %i/%i\n",
+- M_DIMINFO.NbrProcessedDescr, TotalMaxNbrDescr);
+- }
+-}
+-
+-/*******************************************************************************
+-**
+-** End of file
+-**
+-*******************************************************************************/
++ *
++ * End of file
++ *
++ ******************************************************************************/
+diff -ruN linux/drivers/net/sk98lin/skethtool.c linux-new/drivers/net/sk98lin/skethtool.c
+--- linux/drivers/net/sk98lin/skethtool.c 1970-01-01 03:00:00.000000000 +0300
++++ linux-new/drivers/net/sk98lin/skethtool.c 2005-08-09 17:15:51.000000000 +0400
+@@ -0,0 +1,1333 @@
++/******************************************************************************
++ *
++ * Name: skethtool.c
++ * Project: GEnesis, PCI Gigabit Ethernet Adapter
++ * Version: $Revision: 1.3.2.9 $
++ * Date: $Date: 2005/05/23 13:47:33 $
++ * Purpose: All functions regarding ethtool handling
++ *
++ ******************************************************************************/
++
++/******************************************************************************
++ *
++ * (C)Copyright 1998-2002 SysKonnect GmbH.
++ * (C)Copyright 2002-2005 Marvell.
++ *
++ * Driver for Marvell Yukon/2 chipset and SysKonnect Gigabit Ethernet
++ * Server Adapters.
++ *
++ * Author: Ralph Roesler (rroesler@syskonnect.de)
++ * Mirko Lindner (mlindner@syskonnect.de)
++ *
++ * Address all question to: linux@syskonnect.de
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * The information in this file is provided "AS IS" without warranty.
++ *
++ *****************************************************************************/
++
++#include "h/skdrv1st.h"
++#include "h/skdrv2nd.h"
++#include "h/skversion.h"
++#include <linux/ethtool.h>
++#include <linux/module.h>
++#include <linux/timer.h>
++
++/******************************************************************************
++ *
++ * External Functions and Data
++ *
++ *****************************************************************************/
++
++extern void SkDimDisableModeration(SK_AC *pAC, int CurrentModeration);
++extern void SkDimEnableModerationIfNeeded(SK_AC *pAC);
++
++/******************************************************************************
++ *
++ * Defines
++ *
++ *****************************************************************************/
++
++#ifndef ETHT_STATSTRING_LEN
++#define ETHT_STATSTRING_LEN 32
++#endif
++
++#define SK98LIN_STAT(m) sizeof(((SK_AC *)0)->m),offsetof(SK_AC, m)
++
++#define SUPP_COPPER_ALL (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | \
++ SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | \
++ SUPPORTED_1000baseT_Half| SUPPORTED_1000baseT_Full| \
++ SUPPORTED_TP)
++
++#define ADV_COPPER_ALL (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | \
++ ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | \
++ ADVERTISED_1000baseT_Half| ADVERTISED_1000baseT_Full| \
++ ADVERTISED_TP)
++
++#define SUPP_FIBRE_ALL (SUPPORTED_1000baseT_Full | \
++ SUPPORTED_FIBRE | \
++ SUPPORTED_Autoneg)
++
++#define ADV_FIBRE_ALL (ADVERTISED_1000baseT_Full | \
++ ADVERTISED_FIBRE | \
++ ADVERTISED_Autoneg)
++
++/******************************************************************************
++ *
++ * Local Function Prototypes
++ *
++ *****************************************************************************/
++
++#ifdef ETHTOOL_GSET
++static void getSettings(SK_AC *pAC, int port, struct ethtool_cmd *ecmd);
++#endif
++#ifdef ETHTOOL_SSET
++static int setSettings(SK_AC *pAC, int port, struct ethtool_cmd *ecmd);
++#endif
++#ifdef ETHTOOL_GPAUSEPARAM
++static void getPauseParams(SK_AC *pAC, int port, struct ethtool_pauseparam *epause);
++#endif
++#ifdef ETHTOOL_SPAUSEPARAM
++static int setPauseParams(SK_AC *pAC, int port, struct ethtool_pauseparam *epause);
++#endif
++#ifdef ETHTOOL_GDRVINFO
++static void getDriverInfo(SK_AC *pAC, int port, struct ethtool_drvinfo *edrvinfo);
++#endif
++#ifdef ETHTOOL_PHYS_ID
++static int startLocateNIC(SK_AC *pAC, int port, struct ethtool_value *blinkSecs);
++static void toggleLeds(unsigned long ptr);
++#endif
++#ifdef ETHTOOL_GCOALESCE
++static void getModerationParams(SK_AC *pAC, int port, struct ethtool_coalesce *ecoalesc);
++#endif
++#ifdef ETHTOOL_SCOALESCE
++static int setModerationParams(SK_AC *pAC, int port, struct ethtool_coalesce *ecoalesc);
++#endif
++#ifdef ETHTOOL_GWOL
++static void getWOLsettings(SK_AC *pAC, int port, struct ethtool_wolinfo *ewol);
++#endif
++#ifdef ETHTOOL_SWOL
++static int setWOLsettings(SK_AC *pAC, int port, struct ethtool_wolinfo *ewol);
++#endif
++
++static int getPortNumber(struct net_device *netdev, struct ifreq *ifr);
++
++/******************************************************************************
++ *
++ * Local Variables
++ *
++ *****************************************************************************/
++
++struct sk98lin_stats {
++ char stat_string[ETHT_STATSTRING_LEN];
++ int sizeof_stat;
++ int stat_offset;
++};
++
++static struct sk98lin_stats sk98lin_etht_stats_port0[] = {
++ { "rx_packets" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxOkCts) },
++ { "tx_packets" , SK98LIN_STAT(PnmiStruct.Stat[0].StatTxOkCts) },
++ { "rx_bytes" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxOctetsOkCts) },
++ { "tx_bytes" , SK98LIN_STAT(PnmiStruct.Stat[0].StatTxOctetsOkCts) },
++ { "rx_errors" , SK98LIN_STAT(PnmiStruct.InErrorsCts) },
++ { "tx_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatTxSingleCollisionCts) },
++ { "rx_dropped" , SK98LIN_STAT(PnmiStruct.RxNoBufCts) },
++ { "tx_dropped" , SK98LIN_STAT(PnmiStruct.TxNoBufCts) },
++ { "multicasts" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxMulticastOkCts) },
++ { "collisions" , SK98LIN_STAT(PnmiStruct.Stat[0].StatTxSingleCollisionCts) },
++ { "rx_length_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxRuntCts) },
++ { "rx_buffer_overflow_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxFifoOverflowCts) },
++ { "rx_crc_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxFcsCts) },
++ { "rx_frame_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxFramingCts) },
++ { "rx_too_short_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxShortsCts) },
++ { "rx_too_long_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxTooLongCts) },
++ { "rx_carrier_extension_errors", SK98LIN_STAT(PnmiStruct.Stat[0].StatRxCextCts) },
++ { "rx_symbol_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxSymbolCts) },
++ { "rx_llc_mac_size_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxIRLengthCts) },
++ { "rx_carrier_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxCarrierCts) },
++ { "rx_jabber_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxJabberCts) },
++ { "rx_missed_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatRxMissedCts) },
++ { "tx_abort_collision_errors" , SK98LIN_STAT(stats.tx_aborted_errors) },
++ { "tx_carrier_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatTxCarrierCts) },
++ { "tx_buffer_underrun_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatTxFifoUnderrunCts) },
++ { "tx_heartbeat_errors" , SK98LIN_STAT(PnmiStruct.Stat[0].StatTxCarrierCts) } ,
++ { "tx_window_errors" , SK98LIN_STAT(stats.tx_window_errors) }
++};
++
++static struct sk98lin_stats sk98lin_etht_stats_port1[] = {
++ { "rx_packets" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxOkCts) },
++ { "tx_packets" , SK98LIN_STAT(PnmiStruct.Stat[1].StatTxOkCts) },
++ { "rx_bytes" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxOctetsOkCts) },
++ { "tx_bytes" , SK98LIN_STAT(PnmiStruct.Stat[1].StatTxOctetsOkCts) },
++ { "rx_errors" , SK98LIN_STAT(PnmiStruct.InErrorsCts) },
++ { "tx_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatTxSingleCollisionCts) },
++ { "rx_dropped" , SK98LIN_STAT(PnmiStruct.RxNoBufCts) },
++ { "tx_dropped" , SK98LIN_STAT(PnmiStruct.TxNoBufCts) },
++ { "multicasts" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxMulticastOkCts) },
++ { "collisions" , SK98LIN_STAT(PnmiStruct.Stat[1].StatTxSingleCollisionCts) },
++ { "rx_length_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxRuntCts) },
++ { "rx_buffer_overflow_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxFifoOverflowCts) },
++ { "rx_crc_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxFcsCts) },
++ { "rx_frame_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxFramingCts) },
++ { "rx_too_short_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxShortsCts) },
++ { "rx_too_long_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxTooLongCts) },
++ { "rx_carrier_extension_errors", SK98LIN_STAT(PnmiStruct.Stat[1].StatRxCextCts) },
++ { "rx_symbol_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxSymbolCts) },
++ { "rx_llc_mac_size_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxIRLengthCts) },
++ { "rx_carrier_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxCarrierCts) },
++ { "rx_jabber_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxJabberCts) },
++ { "rx_missed_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatRxMissedCts) },
++ { "tx_abort_collision_errors" , SK98LIN_STAT(stats.tx_aborted_errors) },
++ { "tx_carrier_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatTxCarrierCts) },
++ { "tx_buffer_underrun_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatTxFifoUnderrunCts) },
++ { "tx_heartbeat_errors" , SK98LIN_STAT(PnmiStruct.Stat[1].StatTxCarrierCts) } ,
++ { "tx_window_errors" , SK98LIN_STAT(stats.tx_window_errors) }
++};
++
++#define SK98LIN_STATS_LEN sizeof(sk98lin_etht_stats_port0) / sizeof(struct sk98lin_stats)
++
++static int nbrBlinkQuarterSeconds;
++static int currentPortIndex;
++static SK_BOOL isLocateNICrunning = SK_FALSE;
++static SK_BOOL isDualNetCard = SK_FALSE;
++static SK_BOOL doSwitchLEDsOn = SK_FALSE;
++static SK_BOOL boardWasDown[2] = { SK_FALSE, SK_FALSE };
++static struct timer_list locateNICtimer;
++
++/******************************************************************************
++ *
++ * Global Functions
++ *
++ *****************************************************************************/
++
++/*****************************************************************************
++ *
++ * SkEthIoctl - IOCTL entry point for all ethtool queries
++ *
++ * Description:
++ * Any IOCTL request that has to deal with the ethtool command tool is
++ * dispatched via this function.
++ *
++ * Returns:
++ * ==0: everything fine, no error
++ * !=0: the return value is the error code of the failure
++ */
++int SkEthIoctl(
++struct net_device *netdev, /* the pointer to netdev structure */
++struct ifreq *ifr) /* what interface the request refers to? */
++{
++ DEV_NET *pNet = (DEV_NET*) netdev->priv;
++ SK_AC *pAC = pNet->pAC;
++ void *pAddr = ifr->ifr_data;
++ int port = getPortNumber(netdev, ifr);
++ SK_PNMI_STRUCT_DATA *pPnmiStruct = &pAC->PnmiStruct;
++ SK_U32 Size = sizeof(SK_PNMI_STRUCT_DATA);
++ SK_U32 cmd;
++ struct sk98lin_stats *sk98lin_etht_stats =
++ (port == 0) ? sk98lin_etht_stats_port0 : sk98lin_etht_stats_port1;
++
++ if (get_user(cmd, (uint32_t *) pAddr)) {
++ return -EFAULT;
++ }
++
++ switch(cmd) {
++#ifdef ETHTOOL_GSET
++ case ETHTOOL_GSET: {
++ struct ethtool_cmd ecmd = { ETHTOOL_GSET };
++ getSettings(pAC, port, &ecmd);
++ if(copy_to_user(pAddr, &ecmd, sizeof(ecmd))) {
++ return -EFAULT;
++ }
++ return 0;
++ }
++ break;
++#endif
++#ifdef ETHTOOL_SSET
++ case ETHTOOL_SSET: {
++ struct ethtool_cmd ecmd;
++ if(copy_from_user(&ecmd, pAddr, sizeof(ecmd))) {
++ return -EFAULT;
++ }
++ return setSettings(pAC, port, &ecmd);
++ }
++ break;
++#endif
++#ifdef ETHTOOL_GDRVINFO
++ case ETHTOOL_GDRVINFO: {
++ struct ethtool_drvinfo drvinfo = { ETHTOOL_GDRVINFO };
++ getDriverInfo(pAC, port, &drvinfo);
++ if(copy_to_user(pAddr, &drvinfo, sizeof(drvinfo))) {
++ return -EFAULT;
++ }
++ return 0;
++ }
++ break;
++#endif
++#ifdef ETHTOOL_GSTRINGS
++ case ETHTOOL_GSTRINGS: {
++ struct ethtool_gstrings gstrings = { ETHTOOL_GSTRINGS };
++ char *strings = NULL;
++ int err = 0;
++ if(copy_from_user(&gstrings, pAddr, sizeof(gstrings))) {
++ return -EFAULT;
++ }
++ switch(gstrings.string_set) {
++#ifdef ETHTOOL_GSTATS
++ case ETH_SS_STATS: {
++ int i;
++ gstrings.len = SK98LIN_STATS_LEN;
++ if ((strings = kmalloc(SK98LIN_STATS_LEN*ETHT_STATSTRING_LEN,GFP_KERNEL)) == NULL) {
++ return -ENOMEM;
++ }
++ for(i=0; i < SK98LIN_STATS_LEN; i++) {
++ memcpy(&strings[i * ETHT_STATSTRING_LEN],
++ &(sk98lin_etht_stats[i].stat_string),
++ ETHT_STATSTRING_LEN);
++ }
++ }
++ break;
++#endif
++ default:
++ return -EOPNOTSUPP;
++ }
++ if(copy_to_user(pAddr, &gstrings, sizeof(gstrings))) {
++ err = -EFAULT;
++ }
++ pAddr = (void *) ((unsigned long int) pAddr + offsetof(struct ethtool_gstrings, data));
++ if(!err && copy_to_user(pAddr, strings, gstrings.len * ETH_GSTRING_LEN)) {
++ err = -EFAULT;
++ }
++ kfree(strings);
++ return err;
++ }
++#endif
++#ifdef ETHTOOL_GSTATS
++ case ETHTOOL_GSTATS: {
++ struct {
++ struct ethtool_stats eth_stats;
++ uint64_t data[SK98LIN_STATS_LEN];
++ } stats = { {ETHTOOL_GSTATS, SK98LIN_STATS_LEN} };
++ int i;
++
++ if (netif_running(pAC->dev[port])) {
++ SkPnmiGetStruct(pAC, pAC->IoBase, pPnmiStruct, &Size, port);
++ }
++ for(i = 0; i < SK98LIN_STATS_LEN; i++) {
++ if (netif_running(pAC->dev[port])) {
++ stats.data[i] = (sk98lin_etht_stats[i].sizeof_stat ==
++ sizeof(uint64_t)) ?
++ *(uint64_t *)((char *)pAC +
++ sk98lin_etht_stats[i].stat_offset) :
++ *(uint32_t *)((char *)pAC +
++ sk98lin_etht_stats[i].stat_offset);
++ } else {
++ stats.data[i] = (sk98lin_etht_stats[i].sizeof_stat ==
++ sizeof(uint64_t)) ? (uint64_t) 0 : (uint32_t) 0;
++ }
++ }
++ if(copy_to_user(pAddr, &stats, sizeof(stats))) {
++ return -EFAULT;
++ }
++ return 0;
++ }
++#endif
++#ifdef ETHTOOL_PHYS_ID
++ case ETHTOOL_PHYS_ID: {
++ struct ethtool_value blinkSecs;
++ if(copy_from_user(&blinkSecs, pAddr, sizeof(blinkSecs))) {
++ return -EFAULT;
++ }
++ return startLocateNIC(pAC, port, &blinkSecs);
++ }
++#endif
++#ifdef ETHTOOL_GPAUSEPARAM
++ case ETHTOOL_GPAUSEPARAM: {
++ struct ethtool_pauseparam epause = { ETHTOOL_GPAUSEPARAM };
++ getPauseParams(pAC, port, &epause);
++ if(copy_to_user(pAddr, &epause, sizeof(epause))) {
++ return -EFAULT;
++ }
++ return 0;
++ }
++#endif
++#ifdef ETHTOOL_SPAUSEPARAM
++ case ETHTOOL_SPAUSEPARAM: {
++ struct ethtool_pauseparam epause;
++ if(copy_from_user(&epause, pAddr, sizeof(epause))) {
++ return -EFAULT;
++ }
++ return setPauseParams(pAC, port, &epause);
++ }
++#endif
++#ifdef ETHTOOL_GSG
++ case ETHTOOL_GSG: {
++ struct ethtool_value edata = { ETHTOOL_GSG };
++ edata.data = (netdev->features & NETIF_F_SG) != 0;
++ if (copy_to_user(pAddr, &edata, sizeof(edata))) {
++ return -EFAULT;
++ }
++ return 0;
++ }
++#endif
++#ifdef ETHTOOL_SSG
++ case ETHTOOL_SSG: {
++ struct ethtool_value edata;
++ if (copy_from_user(&edata, pAddr, sizeof(edata))) {
++ return -EFAULT;
++ }
++ if (pAC->ChipsetType) { /* Don't handle if Genesis */
++ if (edata.data) {
++ netdev->features |= NETIF_F_SG;
++ } else {
++ netdev->features &= ~NETIF_F_SG;
++ }
++ }
++ return 0;
++ }
++#endif
++#ifdef ETHTOOL_GRXCSUM
++ case ETHTOOL_GRXCSUM: {
++ struct ethtool_value edata = { ETHTOOL_GRXCSUM };
++ edata.data = pAC->RxPort[port].UseRxCsum;
++ if (copy_to_user(pAddr, &edata, sizeof(edata))) {
++ return -EFAULT;
++ }
++ return 0;
++ }
++#endif
++#ifdef ETHTOOL_SRXCSUM
++ case ETHTOOL_SRXCSUM: {
++ struct ethtool_value edata;
++ if (copy_from_user(&edata, pAddr, sizeof(edata))) {
++ return -EFAULT;
++ }
++ pAC->RxPort[port].UseRxCsum = edata.data;
++ return 0;
++ }
++#endif
++#ifdef ETHTOOL_GTXCSUM
++ case ETHTOOL_GTXCSUM: {
++ struct ethtool_value edata = { ETHTOOL_GTXCSUM };
++ edata.data = ((netdev->features & NETIF_F_IP_CSUM) != 0);
++ if (copy_to_user(pAddr, &edata, sizeof(edata))) {
++ return -EFAULT;
++ }
++ return 0;
++ }
++#endif
++#ifdef ETHTOOL_STXCSUM
++ case ETHTOOL_STXCSUM: {
++ struct ethtool_value edata;
++ if (copy_from_user(&edata, pAddr, sizeof(edata))) {
++ return -EFAULT;
++ }
++ if (pAC->ChipsetType) { /* Don't handle if Genesis */
++ if (edata.data) {
++ netdev->features |= NETIF_F_IP_CSUM;
++ } else {
++ netdev->features &= ~NETIF_F_IP_CSUM;
++ }
++ }
++ return 0;
++ }
++#endif
++#ifdef ETHTOOL_NWAY_RST
++ case ETHTOOL_NWAY_RST: {
++ if(netif_running(netdev)) {
++ (*netdev->stop)(netdev);
++ (*netdev->open)(netdev);
++ }
++ return 0;
++ }
++#endif
++#ifdef NETIF_F_TSO
++#ifdef ETHTOOL_GTSO
++ case ETHTOOL_GTSO: {
++ struct ethtool_value edata = { ETHTOOL_GTSO };
++ edata.data = (netdev->features & NETIF_F_TSO) != 0;
++ if (copy_to_user(pAddr, &edata, sizeof(edata))) {
++ return -EFAULT;
++ }
++ return 0;
++ }
++#endif
++#ifdef ETHTOOL_STSO
++ case ETHTOOL_STSO: {
++ struct ethtool_value edata;
++ if (CHIP_ID_YUKON_2(pAC)) {
++ if (copy_from_user(&edata, pAddr, sizeof(edata))) {
++ return -EFAULT;
++ }
++ if (edata.data) {
++ netdev->features |= NETIF_F_TSO;
++ } else {
++ netdev->features &= ~NETIF_F_TSO;
++ }
++ return 0;
++ }
++ return -EOPNOTSUPP;
++ }
++#endif
++#endif
++#ifdef ETHTOOL_GCOALESCE
++ case ETHTOOL_GCOALESCE: {
++ struct ethtool_coalesce ecoalesc = { ETHTOOL_GCOALESCE };
++ getModerationParams(pAC, port, &ecoalesc);
++ if(copy_to_user(pAddr, &ecoalesc, sizeof(ecoalesc))) {
++ return -EFAULT;
++ }
++ return 0;
++ }
++#endif
++#ifdef ETHTOOL_SCOALESCE
++ case ETHTOOL_SCOALESCE: {
++ struct ethtool_coalesce ecoalesc;
++ if(copy_from_user(&ecoalesc, pAddr, sizeof(ecoalesc))) {
++ return -EFAULT;
++ }
++ return setModerationParams(pAC, port, &ecoalesc);
++ }
++#endif
++#ifdef ETHTOOL_GWOL
++ case ETHTOOL_GWOL: {
++ struct ethtool_wolinfo ewol = { ETHTOOL_GWOL };
++ getWOLsettings(pAC, port, &ewol);
++ if(copy_to_user(pAddr, &ewol, sizeof(ewol))) {
++ return -EFAULT;
++ }
++ return 0;
++ }
++#endif
++#ifdef ETHTOOL_SWOL
++ case ETHTOOL_SWOL: {
++ struct ethtool_wolinfo ewol;
++ if(copy_from_user(&ewol, pAddr, sizeof(ewol))) {
++ return -EFAULT;
++ }
++ return setWOLsettings(pAC, port, &ewol);
++ }
++#endif
++ default:
++ return -EOPNOTSUPP;
++ }
++} /* SkEthIoctl() */
++
++/******************************************************************************
++ *
++ * Local Functions
++ *
++ *****************************************************************************/
++
++#ifdef ETHTOOL_GSET
++/*****************************************************************************
++ *
++ * getSettings - retrieves the current settings of the selected adapter
++ *
++ * Description:
++ * The current configuration of the selected adapter is returned.
++ * This configuration involves a)speed, b)duplex and c)autoneg plus
++ * a number of other variables.
++ *
++ * Returns: N/A
++ *
++ */
++static void getSettings(
++SK_AC *pAC, /* pointer to adapter control context */
++int port, /* the port of the selected adapter */
++struct ethtool_cmd *ecmd) /* mandatory command structure for results */
++{
++ SK_GEPORT *pPort = &pAC->GIni.GP[port];
++
++ static int DuplexAutoNegConfMap[9][3]= {
++ { -1 , -1 , -1 },
++ { 0 , -1 , -1 },
++ { SK_LMODE_HALF , DUPLEX_HALF, AUTONEG_DISABLE },
++ { SK_LMODE_FULL , DUPLEX_FULL, AUTONEG_DISABLE },
++ { SK_LMODE_AUTOHALF , DUPLEX_HALF, AUTONEG_ENABLE },
++ { SK_LMODE_AUTOFULL , DUPLEX_FULL, AUTONEG_ENABLE },
++ { SK_LMODE_AUTOBOTH , DUPLEX_FULL, AUTONEG_ENABLE },
++ { SK_LMODE_AUTOSENSE , -1 , -1 },
++ { SK_LMODE_INDETERMINATED, -1 , -1 }
++ };
++
++ static int SpeedConfMap[6][2] = {
++ { 0 , -1 },
++ { SK_LSPEED_AUTO , -1 },
++ { SK_LSPEED_10MBPS , SPEED_10 },
++ { SK_LSPEED_100MBPS , SPEED_100 },
++ { SK_LSPEED_1000MBPS , SPEED_1000 },
++ { SK_LSPEED_INDETERMINATED, -1 }
++ };
++
++ static int AdvSpeedMap[6][2] = {
++ { 0 , -1 },
++ { SK_LSPEED_AUTO , -1 },
++ { SK_LSPEED_10MBPS , ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full },
++ { SK_LSPEED_100MBPS , ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full },
++ { SK_LSPEED_1000MBPS , ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full},
++ { SK_LSPEED_INDETERMINATED, -1 }
++ };
++
++ ecmd->phy_address = port;
++ ecmd->speed = SpeedConfMap[pPort->PLinkSpeedUsed][1];
++ ecmd->duplex = DuplexAutoNegConfMap[pPort->PLinkModeStatus][1];
++ ecmd->autoneg = DuplexAutoNegConfMap[pPort->PLinkModeStatus][2];
++ ecmd->transceiver = XCVR_INTERNAL;
++
++ if (pAC->GIni.GICopperType) {
++ ecmd->port = PORT_TP;
++ ecmd->supported = (SUPP_COPPER_ALL|SUPPORTED_Autoneg);
++ if (pAC->GIni.GIGenesis) {
++ ecmd->supported &= ~(SUPPORTED_10baseT_Half);
++ ecmd->supported &= ~(SUPPORTED_10baseT_Full);
++ ecmd->supported &= ~(SUPPORTED_100baseT_Half);
++ ecmd->supported &= ~(SUPPORTED_100baseT_Full);
++ } else {
++ if (pAC->GIni.GIChipId == CHIP_ID_YUKON) {
++ ecmd->supported &= ~(SUPPORTED_1000baseT_Half);
++ }
++ if (pAC->GIni.GIChipId == CHIP_ID_YUKON_FE) {
++ ecmd->supported &= ~(SUPPORTED_1000baseT_Half);
++ ecmd->supported &= ~(SUPPORTED_1000baseT_Full);
++ }
++ }
++ if (pAC->GIni.GP[0].PLinkSpeed != SK_LSPEED_AUTO) {
++ ecmd->advertising = AdvSpeedMap[pPort->PLinkSpeed][1];
++ if (pAC->GIni.GIChipId == CHIP_ID_YUKON) {
++ ecmd->advertising &= ~(SUPPORTED_1000baseT_Half);
++ }
++ } else {
++ ecmd->advertising = ecmd->supported;
++ }
++ if (ecmd->autoneg == AUTONEG_ENABLE) {
++ ecmd->advertising |= ADVERTISED_Autoneg;
++ }
++ } else {
++ ecmd->port = PORT_FIBRE;
++ ecmd->supported = (SUPP_FIBRE_ALL);
++ ecmd->advertising = (ADV_FIBRE_ALL);
++ }
++}
++#endif
++
++#ifdef ETHTOOL_SSET
++/*****************************************************************************
++ *
++ * setSettings - configures the settings of a selected adapter
++ *
++ * Description:
++ * Possible settings that may be altered are a)speed, b)duplex or
++ * c)autonegotiation.
++ *
++ * Returns:
++ * ==0: everything fine, no error
++ * !=0: the return value is the error code of the failure
++ */
++static int setSettings(
++SK_AC *pAC, /* pointer to adapter control context */
++int port, /* the port of the selected adapter */
++struct ethtool_cmd *ecmd) /* command structure containing settings */
++{
++ DEV_NET *pNet = (DEV_NET *) pAC->dev[port]->priv;
++ SK_U32 Instance;
++ char Buf[4];
++ unsigned int Len = 1;
++ int Ret;
++
++ if (port == 0) {
++ Instance = (pAC->RlmtNets == 2) ? 1 : 2;
++ } else {
++ Instance = (pAC->RlmtNets == 2) ? 2 : 3;
++ }
++
++ if (((ecmd->autoneg == AUTONEG_DISABLE) || (ecmd->autoneg == AUTONEG_ENABLE)) &&
++ ((ecmd->duplex == DUPLEX_FULL) || (ecmd->duplex == DUPLEX_HALF))) {
++ if (ecmd->autoneg == AUTONEG_DISABLE) {
++ if (ecmd->duplex == DUPLEX_FULL) {
++ *Buf = (char) SK_LMODE_FULL;
++ } else {
++ *Buf = (char) SK_LMODE_HALF;
++ }
++ } else {
++ if (ecmd->duplex == DUPLEX_FULL) {
++ *Buf = (char) SK_LMODE_AUTOFULL;
++ } else {
++ *Buf = (char) SK_LMODE_AUTOHALF;
++ }
++ }
++
++ Ret = SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_LINK_MODE,
++ &Buf, &Len, Instance, pNet->NetNr);
++
++ if (Ret != SK_PNMI_ERR_OK) {
++ return -EINVAL;
++ }
++ }
++
++ if ((ecmd->speed == SPEED_1000) ||
++ (ecmd->speed == SPEED_100) ||
++ (ecmd->speed == SPEED_10)) {
++ if (ecmd->speed == SPEED_1000) {
++ *Buf = (char) SK_LSPEED_1000MBPS;
++ } else if (ecmd->speed == SPEED_100) {
++ *Buf = (char) SK_LSPEED_100MBPS;
++ } else {
++ *Buf = (char) SK_LSPEED_10MBPS;
++ }
++
++ Ret = SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_SPEED_MODE,
++ &Buf, &Len, Instance, pNet->NetNr);
++
++ if (Ret != SK_PNMI_ERR_OK) {
++ return -EINVAL;
++ }
++ } else {
++ return -EINVAL;
++ }
++ return 0;
++}
++#endif
++
++#ifdef ETHTOOL_GPAUSEPARAM
++/*****************************************************************************
++ *
++ * getPauseParams - retrieves the pause parameters
++ *
++ * Description:
++ * All current pause parameters of a selected adapter are placed
++ * in the passed ethtool_pauseparam structure and are returned.
++ *
++ * Returns: N/A
++ *
++ */
++static void getPauseParams(
++SK_AC *pAC, /* pointer to adapter control context */
++int port, /* the port of the selected adapter */
++struct ethtool_pauseparam *epause) /* pause parameter struct for result */
++{
++ SK_GEPORT *pPort = &pAC->GIni.GP[port];
++
++ epause->rx_pause = 0;
++ epause->tx_pause = 0;
++
++ if (pPort->PFlowCtrlMode == SK_FLOW_MODE_LOC_SEND) {
++ epause->tx_pause = 1;
++ }
++ if ((pPort->PFlowCtrlMode == SK_FLOW_MODE_SYMMETRIC) ||
++ (pPort->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM)) {
++ epause->tx_pause = 1;
++ epause->rx_pause = 1;
++ }
++
++ if ((epause->rx_pause == 0) && (epause->tx_pause == 0)) {
++ epause->autoneg = SK_FALSE;
++ } else {
++ epause->autoneg = SK_TRUE;
++ }
++}
++#endif
++
++#ifdef ETHTOOL_SPAUSEPARAM
++/*****************************************************************************
++ *
++ * setPauseParams - configures the pause parameters of an adapter
++ *
++ * Description:
++ * This function sets the Rx or Tx pause parameters
++ *
++ * Returns:
++ * ==0: everything fine, no error
++ * !=0: the return value is the error code of the failure
++ */
++static int setPauseParams(
++SK_AC *pAC, /* pointer to adapter control context */
++int port, /* the port of the selected adapter */
++struct ethtool_pauseparam *epause) /* pause parameter struct with params */
++{
++ SK_GEPORT *pPort = &pAC->GIni.GP[port];
++ DEV_NET *pNet = (DEV_NET *) pAC->dev[port]->priv;
++ int PrevSpeedVal = pPort->PLinkSpeedUsed;
++
++ SK_U32 Instance;
++ char Buf[4];
++ int Ret;
++ SK_BOOL prevAutonegValue = SK_TRUE;
++ int prevTxPause = 0;
++ int prevRxPause = 0;
++ unsigned int Len = 1;
++
++ if (port == 0) {
++ Instance = (pAC->RlmtNets == 2) ? 1 : 2;
++ } else {
++ Instance = (pAC->RlmtNets == 2) ? 2 : 3;
++ }
++
++ /*
++ ** we have to determine the current settings to see if
++ ** the operator requested any modification of the flow
++ ** control parameters...
++ */
++ if (pPort->PFlowCtrlMode == SK_FLOW_MODE_LOC_SEND) {
++ prevTxPause = 1;
++ }
++ if ((pPort->PFlowCtrlMode == SK_FLOW_MODE_SYMMETRIC) ||
++ (pPort->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM)) {
++ prevTxPause = 1;
++ prevRxPause = 1;
++ }
++
++ if ((prevRxPause == 0) && (prevTxPause == 0)) {
++ prevAutonegValue = SK_FALSE;
++ }
++
++
++ /*
++ ** perform modifications regarding the changes
++ ** requested by the operator
++ */
++ if (epause->autoneg != prevAutonegValue) {
++ if (epause->autoneg == AUTONEG_DISABLE) {
++ *Buf = (char) SK_FLOW_MODE_NONE;
++ } else {
++ *Buf = (char) SK_FLOW_MODE_SYMMETRIC;
++ }
++ } else {
++ if(epause->rx_pause && epause->tx_pause) {
++ *Buf = (char) SK_FLOW_MODE_SYMMETRIC;
++ } else if (epause->rx_pause && !epause->tx_pause) {
++ *Buf = (char) SK_FLOW_MODE_SYM_OR_REM;
++ } else if(!epause->rx_pause && epause->tx_pause) {
++ *Buf = (char) SK_FLOW_MODE_LOC_SEND;
++ } else {
++ *Buf = (char) SK_FLOW_MODE_NONE;
++ }
++ }
++
++ Ret = SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_FLOWCTRL_MODE,
++ &Buf, &Len, Instance, pNet->NetNr);
++
++ if (Ret != SK_PNMI_ERR_OK) {
++ SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_CTRL,
++ ("ethtool (sk98lin): error changing rx/tx pause (%i)\n", Ret));
++ } else {
++ Len = 1; /* set buffer length to correct value */
++ }
++
++ /*
++ ** It may be that autoneg has been disabled! Therefore
++ ** set the speed to the previously used value...
++ */
++ *Buf = (char) PrevSpeedVal;
++
++ Ret = SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_SPEED_MODE,
++ &Buf, &Len, Instance, pNet->NetNr);
++
++ if (Ret != SK_PNMI_ERR_OK) {
++ SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_CTRL,
++ ("ethtool (sk98lin): error setting speed (%i)\n", Ret));
++ }
++ return 0;
++}
++#endif
++
++#ifdef ETHTOOL_GCOALESCE
++/*****************************************************************************
++ *
++ * getModerationParams - retrieves the IRQ moderation settings
++ *
++ * Description:
++ * All current IRQ moderation settings of a selected adapter are placed
++ * in the passed ethtool_coalesce structure and are returned.
++ *
++ * Returns: N/A
++ *
++ */
++static void getModerationParams(
++SK_AC *pAC, /* pointer to adapter control context */
++int port, /* the port of the selected adapter */
++struct ethtool_coalesce *ecoalesc) /* IRQ moderation struct for results */
++{
++ DIM_INFO *Info = &pAC->DynIrqModInfo;
++ SK_BOOL UseTxIrqModeration = SK_FALSE;
++ SK_BOOL UseRxIrqModeration = SK_FALSE;
++
++ if (Info->IntModTypeSelect != C_INT_MOD_NONE) {
++ if (CHIP_ID_YUKON_2(pAC)) {
++ UseRxIrqModeration = SK_TRUE;
++ UseTxIrqModeration = SK_TRUE;
++ } else {
++ if ((Info->MaskIrqModeration == IRQ_MASK_RX_ONLY) ||
++ (Info->MaskIrqModeration == IRQ_MASK_SP_RX) ||
++ (Info->MaskIrqModeration == IRQ_MASK_RX_TX_SP)) {
++ UseRxIrqModeration = SK_TRUE;
++ }
++ if ((Info->MaskIrqModeration == IRQ_MASK_TX_ONLY) ||
++ (Info->MaskIrqModeration == IRQ_MASK_SP_TX) ||
++ (Info->MaskIrqModeration == IRQ_MASK_RX_TX_SP)) {
++ UseTxIrqModeration = SK_TRUE;
++ }
++ }
++
++ if (UseRxIrqModeration) {
++ ecoalesc->rx_coalesce_usecs = 1000000 / Info->MaxModIntsPerSec;
++ }
++ if (UseTxIrqModeration) {
++ ecoalesc->tx_coalesce_usecs = 1000000 / Info->MaxModIntsPerSec;
++ }
++ if (Info->IntModTypeSelect == C_INT_MOD_DYNAMIC) {
++ ecoalesc->rate_sample_interval = Info->DynIrqModSampleInterval;
++ if (UseRxIrqModeration) {
++ ecoalesc->use_adaptive_rx_coalesce = 1;
++ ecoalesc->rx_coalesce_usecs_low =
++ 1000000 / Info->MaxModIntsPerSecLowerLimit;
++ ecoalesc->rx_coalesce_usecs_high =
++ 1000000 / Info->MaxModIntsPerSecUpperLimit;
++ }
++ if (UseTxIrqModeration) {
++ ecoalesc->use_adaptive_tx_coalesce = 1;
++ ecoalesc->tx_coalesce_usecs_low =
++ 1000000 / Info->MaxModIntsPerSecLowerLimit;
++ ecoalesc->tx_coalesce_usecs_high =
++ 1000000 / Info->MaxModIntsPerSecUpperLimit;
++ }
++ }
++ }
++}
++#endif
++
++#ifdef ETHTOOL_SCOALESCE
++/*****************************************************************************
++ *
++ * setModerationParams - configures the IRQ moderation of an adapter
++ *
++ * Description:
++ * Depending on the desired IRQ moderation parameters, either a) static,
++ * b) dynamic or c) no moderation is configured.
++ *
++ * Returns:
++ * ==0: everything fine, no error
++ * !=0: the return value is the error code of the failure
++ *
++ * Notes:
++ * The supported timeframe for the coalesced interrupts ranges from
++ * 33.333us (30 IntsPerSec) down to 25us (40.000 IntsPerSec).
++ * Any requested value that is not in this range will abort the request!
++ */
++static int setModerationParams(
++SK_AC *pAC, /* pointer to adapter control context */
++int port, /* the port of the selected adapter */
++struct ethtool_coalesce *ecoalesc) /* IRQ moderation struct with params */
++{
++ DIM_INFO *Info = &pAC->DynIrqModInfo;
++ int PrevModeration = Info->IntModTypeSelect;
++
++ Info->IntModTypeSelect = C_INT_MOD_NONE; /* initial default */
++
++ if ((ecoalesc->rx_coalesce_usecs) || (ecoalesc->tx_coalesce_usecs)) {
++ if (ecoalesc->rx_coalesce_usecs) {
++ if ((ecoalesc->rx_coalesce_usecs < 25) ||
++ (ecoalesc->rx_coalesce_usecs > 33333)) {
++ return -EINVAL;
++ }
++ }
++ if (ecoalesc->tx_coalesce_usecs) {
++ if ((ecoalesc->tx_coalesce_usecs < 25) ||
++ (ecoalesc->tx_coalesce_usecs > 33333)) {
++ return -EINVAL;
++ }
++ }
++ if (!CHIP_ID_YUKON_2(pAC)) {
++ if ((Info->MaskIrqModeration == IRQ_MASK_SP_RX) ||
++ (Info->MaskIrqModeration == IRQ_MASK_SP_TX) ||
++ (Info->MaskIrqModeration == IRQ_MASK_RX_TX_SP)) {
++ Info->MaskIrqModeration = IRQ_MASK_SP_ONLY;
++ }
++ }
++ Info->IntModTypeSelect = C_INT_MOD_STATIC;
++ if (ecoalesc->rx_coalesce_usecs) {
++ Info->MaxModIntsPerSec =
++ 1000000 / ecoalesc->rx_coalesce_usecs;
++ if (!CHIP_ID_YUKON_2(pAC)) {
++ if (Info->MaskIrqModeration == IRQ_MASK_TX_ONLY) {
++ Info->MaskIrqModeration = IRQ_MASK_TX_RX;
++ }
++ if (Info->MaskIrqModeration == IRQ_MASK_SP_ONLY) {
++ Info->MaskIrqModeration = IRQ_MASK_SP_RX;
++ }
++ if (Info->MaskIrqModeration == IRQ_MASK_SP_TX) {
++ Info->MaskIrqModeration = IRQ_MASK_RX_TX_SP;
++ }
++ } else {
++ Info->MaskIrqModeration = Y2_IRQ_MASK;
++ }
++ }
++ if (ecoalesc->tx_coalesce_usecs) {
++ Info->MaxModIntsPerSec =
++ 1000000 / ecoalesc->tx_coalesce_usecs;
++ if (!CHIP_ID_YUKON_2(pAC)) {
++ if (Info->MaskIrqModeration == IRQ_MASK_RX_ONLY) {
++ Info->MaskIrqModeration = IRQ_MASK_TX_RX;
++ }
++ if (Info->MaskIrqModeration == IRQ_MASK_SP_ONLY) {
++ Info->MaskIrqModeration = IRQ_MASK_SP_TX;
++ }
++ if (Info->MaskIrqModeration == IRQ_MASK_SP_RX) {
++ Info->MaskIrqModeration = IRQ_MASK_RX_TX_SP;
++ }
++ } else {
++ Info->MaskIrqModeration = Y2_IRQ_MASK;
++ }
++ }
++ }
++ if ((ecoalesc->rate_sample_interval) ||
++ (ecoalesc->rx_coalesce_usecs_low) ||
++ (ecoalesc->tx_coalesce_usecs_low) ||
++ (ecoalesc->rx_coalesce_usecs_high)||
++ (ecoalesc->tx_coalesce_usecs_high)) {
++ if (ecoalesc->rate_sample_interval) {
++ if ((ecoalesc->rate_sample_interval < 1) ||
++ (ecoalesc->rate_sample_interval > 10)) {
++ return -EINVAL;
++ }
++ }
++ if (ecoalesc->rx_coalesce_usecs_low) {
++ if ((ecoalesc->rx_coalesce_usecs_low < 25) ||
++ (ecoalesc->rx_coalesce_usecs_low > 33333)) {
++ return -EINVAL;
++ }
++ }
++ if (ecoalesc->rx_coalesce_usecs_high) {
++ if ((ecoalesc->rx_coalesce_usecs_high < 25) ||
++ (ecoalesc->rx_coalesce_usecs_high > 33333)) {
++ return -EINVAL;
++ }
++ }
++ if (ecoalesc->tx_coalesce_usecs_low) {
++ if ((ecoalesc->tx_coalesce_usecs_low < 25) ||
++ (ecoalesc->tx_coalesce_usecs_low > 33333)) {
++ return -EINVAL;
++ }
++ }
++ if (ecoalesc->tx_coalesce_usecs_high) {
++ if ((ecoalesc->tx_coalesce_usecs_high < 25) ||
++ (ecoalesc->tx_coalesce_usecs_high > 33333)) {
++ return -EINVAL;
++ }
++ }
++
++ Info->IntModTypeSelect = C_INT_MOD_DYNAMIC;
++ if (ecoalesc->rate_sample_interval) {
++ Info->DynIrqModSampleInterval =
++ ecoalesc->rate_sample_interval;
++ }
++ if (ecoalesc->rx_coalesce_usecs_low) {
++ Info->MaxModIntsPerSecLowerLimit =
++ 1000000 / ecoalesc->rx_coalesce_usecs_low;
++ }
++ if (ecoalesc->tx_coalesce_usecs_low) {
++ Info->MaxModIntsPerSecLowerLimit =
++ 1000000 / ecoalesc->tx_coalesce_usecs_low;
++ }
++ if (ecoalesc->rx_coalesce_usecs_high) {
++ Info->MaxModIntsPerSecUpperLimit =
++ 1000000 / ecoalesc->rx_coalesce_usecs_high;
++ }
++ if (ecoalesc->tx_coalesce_usecs_high) {
++ Info->MaxModIntsPerSecUpperLimit =
++ 1000000 / ecoalesc->tx_coalesce_usecs_high;
++ }
++ }
++
++ if ((PrevModeration == C_INT_MOD_NONE) &&
++ (Info->IntModTypeSelect != C_INT_MOD_NONE)) {
++ SkDimEnableModerationIfNeeded(pAC);
++ }
++ if (PrevModeration != C_INT_MOD_NONE) {
++ SkDimDisableModeration(pAC, PrevModeration);
++ if (Info->IntModTypeSelect != C_INT_MOD_NONE) {
++ SkDimEnableModerationIfNeeded(pAC);
++ }
++ }
++
++ return 0;
++}
++#endif
++
++#ifdef ETHTOOL_GWOL
++/*****************************************************************************
++ *
++ * getWOLsettings - retrieves the WOL settings of the selected adapter
++ *
++ * Description:
++ * All current WOL settings of a selected adapter are placed in the
++ * passed ethtool_wolinfo structure and are returned to the caller.
++ *
++ * Returns: N/A
++ *
++ */
++static void getWOLsettings(
++SK_AC *pAC, /* pointer to adapter control context */
++int port, /* the port of the selected adapter */
++struct ethtool_wolinfo *ewol) /* mandatory WOL structure for results */
++{
++ ewol->supported = pAC->WolInfo.SupportedWolOptions;
++ ewol->wolopts = pAC->WolInfo.ConfiguredWolOptions;
++
++ return;
++}
++#endif
++
++#ifdef ETHTOOL_SWOL
++/*****************************************************************************
++ *
++ * setWOLsettings - configures the WOL settings of a selected adapter
++ *
++ * Description:
++ * The WOL settings of a selected adapter are configured regarding
++ * the parameters in the passed ethtool_wolinfo structure.
++ * Note that currently only wake on magic packet is supported!
++ *
++ * Returns:
++ * ==0: everything fine, no error
++ * !=0: the return value is the error code of the failure
++ */
++static int setWOLsettings(
++SK_AC *pAC, /* pointer to adapter control context */
++int port, /* the port of the selected adapter */
++struct ethtool_wolinfo *ewol) /* WOL structure containing settings */
++{
++ if (((ewol->wolopts & WAKE_MAGIC) == WAKE_MAGIC) || (ewol->wolopts == 0)) {
++ pAC->WolInfo.ConfiguredWolOptions = ewol->wolopts;
++ return 0;
++ }
++ return -EFAULT;
++}
++#endif
++
++#ifdef ETHTOOL_GDRVINFO
++/*****************************************************************************
++ *
++ * getDriverInfo - returns generic driver and adapter information
++ *
++ * Description:
++ * Generic driver information is returned via this function, such as
++ * the name of the driver, its version and and firmware version.
++ * In addition to this, the location of the selected adapter is
++ * returned as a bus info string (e.g. '01:05.0').
++ *
++ * Returns: N/A
++ *
++ */
++static void getDriverInfo(
++SK_AC *pAC, /* pointer to adapter control context */
++int port, /* the port of the selected adapter */
++struct ethtool_drvinfo *edrvinfo) /* mandatory info structure for results */
++{
++ char versionString[32];
++
++ snprintf(versionString, 32, "%s (%s)", VER_STRING, PATCHLEVEL);
++ strncpy(edrvinfo->driver, DRIVER_FILE_NAME , 32);
++ strncpy(edrvinfo->version, versionString , 32);
++ strncpy(edrvinfo->fw_version, "N/A", 32);
++ strncpy(edrvinfo->bus_info, pci_name(pAC->PciDev), 32);
++
++#ifdef ETHTOOL_GSTATS
++ edrvinfo->n_stats = SK98LIN_STATS_LEN;
++#endif
++}
++#endif
++
++#ifdef ETHTOOL_PHYS_ID
++/*****************************************************************************
++ *
++ * startLocateNIC - start the locate NIC feature of the elected adapter
++ *
++ * Description:
++ * This function is used if the user want to locate a particular NIC.
++ * All LEDs are regularly switched on and off, so the NIC can easily
++ * be identified.
++ *
++ * Returns:
++ * ==0: everything fine, no error, locateNIC test was started
++ * !=0: one locateNIC test runs already
++ *
++ */
++static int startLocateNIC(
++SK_AC *pAC, /* pointer to adapter control context */
++int port, /* the port of the selected adapter */
++struct ethtool_value *blinkSecs) /* how long the LEDs should blink in seconds */
++{
++ struct SK_NET_DEVICE *pDev = pAC->dev[port];
++ int OtherPort = (port) ? 0 : 1;
++ struct SK_NET_DEVICE *pOtherDev = pAC->dev[OtherPort];
++
++ if (isLocateNICrunning) {
++ return -EFAULT;
++ }
++ isLocateNICrunning = SK_TRUE;
++ currentPortIndex = port;
++ isDualNetCard = (pDev != pOtherDev) ? SK_TRUE : SK_FALSE;
++
++ if (netif_running(pAC->dev[port])) {
++ boardWasDown[0] = SK_FALSE;
++ } else {
++ (*pDev->open)(pDev);
++ boardWasDown[0] = SK_TRUE;
++ }
++
++ if (isDualNetCard) {
++ if (netif_running(pAC->dev[OtherPort])) {
++ boardWasDown[1] = SK_FALSE;
++ } else {
++ (*pOtherDev->open)(pOtherDev);
++ boardWasDown[1] = SK_TRUE;
++ }
++ }
++
++ if ((blinkSecs->data < 1) || (blinkSecs->data > 30)) {
++ blinkSecs->data = 3; /* three seconds default */
++ }
++ nbrBlinkQuarterSeconds = 4*blinkSecs->data;
++
++ init_timer(&locateNICtimer);
++ locateNICtimer.function = toggleLeds;
++ locateNICtimer.data = (unsigned long) pAC;
++ locateNICtimer.expires = jiffies + HZ; /* initially 1sec */
++ add_timer(&locateNICtimer);
++
++ return 0;
++}
++
++/*****************************************************************************
++ *
++ * toggleLeds - Changes the LED state of an adapter
++ *
++ * Description:
++ * This function changes the current state of all LEDs of an adapter so
++ * that it can be located by a user. If the requested time interval for
++ * this test has elapsed, this function cleans up everything that was
++ * temporarily setup during the locate NIC test. This involves of course
++ * also closing or opening any adapter so that the initial board state
++ * is recovered.
++ *
++ * Returns: N/A
++ *
++ */
++static void toggleLeds(
++unsigned long ptr) /* holds the pointer to adapter control context */
++{
++ SK_AC *pAC = (SK_AC *) ptr;
++ int port = currentPortIndex;
++ SK_IOC IoC = pAC->IoBase;
++ struct SK_NET_DEVICE *pDev = pAC->dev[port];
++ int OtherPort = (port) ? 0 : 1;
++ struct SK_NET_DEVICE *pOtherDev = pAC->dev[OtherPort];
++
++ SK_U16 YukLedOn = (PHY_M_LED_MO_DUP(MO_LED_ON) |
++ PHY_M_LED_MO_10(MO_LED_ON) |
++ PHY_M_LED_MO_100(MO_LED_ON) |
++ PHY_M_LED_MO_1000(MO_LED_ON) |
++ PHY_M_LED_MO_RX(MO_LED_ON));
++ SK_U16 YukLedOff = (PHY_M_LED_MO_DUP(MO_LED_OFF) |
++ PHY_M_LED_MO_10(MO_LED_OFF) |
++ PHY_M_LED_MO_100(MO_LED_OFF) |
++ PHY_M_LED_MO_1000(MO_LED_OFF) |
++ PHY_M_LED_MO_RX(MO_LED_OFF));
++
++ nbrBlinkQuarterSeconds--;
++ if (nbrBlinkQuarterSeconds <= 0) {
++ (*pDev->stop)(pDev);
++ if (isDualNetCard) {
++ (*pOtherDev->stop)(pOtherDev);
++ }
++
++ if (!boardWasDown[0]) {
++ (*pDev->open)(pDev);
++ }
++ if (isDualNetCard) {
++ (*pOtherDev->open)(pOtherDev);
++ }
++ isDualNetCard = SK_FALSE;
++ isLocateNICrunning = SK_FALSE;
++ return;
++ }
++
++ doSwitchLEDsOn = (doSwitchLEDsOn) ? SK_FALSE : SK_TRUE;
++ if (doSwitchLEDsOn) {
++ if (pAC->GIni.GIGenesis) {
++ SK_OUT8(IoC,MR_ADDR(port,LNK_LED_REG),(SK_U8)SK_LNK_ON);
++ SkGeYellowLED(pAC,IoC,LED_ON >> 1);
++ SkGeXmitLED(pAC,IoC,MR_ADDR(port,RX_LED_INI),SK_LED_TST);
++ if (pAC->GIni.GP[port].PhyType == SK_PHY_BCOM) {
++ SkXmPhyWrite(pAC,IoC,port,PHY_BCOM_P_EXT_CTRL,PHY_B_PEC_LED_ON);
++ } else if (pAC->GIni.GP[port].PhyType == SK_PHY_LONE) {
++ SkXmPhyWrite(pAC,IoC,port,PHY_LONE_LED_CFG,0x0800);
++ } else {
++ SkGeXmitLED(pAC,IoC,MR_ADDR(port,TX_LED_INI),SK_LED_TST);
++ }
++ } else {
++ SkGmPhyWrite(pAC,IoC,port,PHY_MARV_LED_CTRL,0);
++ SkGmPhyWrite(pAC,IoC,port,PHY_MARV_LED_OVER,YukLedOn);
++ }
++ } else {
++ if (pAC->GIni.GIGenesis) {
++ SK_OUT8(IoC,MR_ADDR(port,LNK_LED_REG),(SK_U8)SK_LNK_OFF);
++ SkGeYellowLED(pAC,IoC,LED_OFF >> 1);
++ SkGeXmitLED(pAC,IoC,MR_ADDR(port,RX_LED_INI),SK_LED_DIS);
++ if (pAC->GIni.GP[port].PhyType == SK_PHY_BCOM) {
++ SkXmPhyWrite(pAC,IoC,port,PHY_BCOM_P_EXT_CTRL,PHY_B_PEC_LED_OFF);
++ } else if (pAC->GIni.GP[port].PhyType == SK_PHY_LONE) {
++ SkXmPhyWrite(pAC,IoC,port,PHY_LONE_LED_CFG,PHY_L_LC_LEDT);
++ } else {
++ SkGeXmitLED(pAC,IoC,MR_ADDR(port,TX_LED_INI),SK_LED_DIS);
++ }
++ } else {
++ SkGmPhyWrite(pAC,IoC,port,PHY_MARV_LED_CTRL,0);
++ SkGmPhyWrite(pAC,IoC,port,PHY_MARV_LED_OVER,YukLedOff);
++ }
++ }
++
++ locateNICtimer.function = toggleLeds;
++ locateNICtimer.data = (unsigned long) pAC;
++ locateNICtimer.expires = jiffies + (HZ/4); /* 250ms */
++ add_timer(&locateNICtimer);
++}
++#endif
++
++/*****************************************************************************
++ *
++ * getPortNumber - evaluates the port number of an interface
++ *
++ * Description:
++ * It may be that the current interface refers to one which is located
++ * on a dual net adapter. Hence, this function will return the correct
++ * port for further use.
++ *
++ * Returns:
++ * the port number that corresponds to the selected adapter
++ *
++ */
++static int getPortNumber(
++struct net_device *netdev, /* the pointer to netdev structure */
++struct ifreq *ifr) /* what interface the request refers to? */
++{
++ DEV_NET *pNet = (DEV_NET*) netdev->priv;
++ SK_AC *pAC = pNet->pAC;
++
++ if (pAC->dev[1] != pAC->dev[0]) {
++ if (!strcmp(pAC->dev[1]->name, ifr->ifr_name)) {
++ return 1; /* port index 1 */
++ }
++ }
++ return 0;
++}
++
++/*******************************************************************************
++ *
++ * End of file
++ *
++ ******************************************************************************/
+diff -ruN linux/drivers/net/sk98lin/skge.c linux-new/drivers/net/sk98lin/skge.c
+--- linux/drivers/net/sk98lin/skge.c 2005-09-26 13:32:48.000000000 +0400
++++ linux-new/drivers/net/sk98lin/skge.c 2005-08-09 17:15:51.000000000 +0400
+@@ -1,32 +1,26 @@
+ /******************************************************************************
+ *
+- * Name: skge.c
+- * Project: GEnesis, PCI Gigabit Ethernet Adapter
+- * Version: $Revision: 1.45 $
+- * Date: $Date: 2004/02/12 14:41:02 $
+- * Purpose: The main driver source module
++ * Name: skge.c
++ * Project: GEnesis, PCI Gigabit Ethernet Adapter
++ * Version: $Revision: 1.60.2.55 $
++ * Date: $Date: 2005/08/09 13:08:34 $
++ * Purpose: The main driver source module
+ *
+ ******************************************************************************/
+
+ /******************************************************************************
+ *
+ * (C)Copyright 1998-2002 SysKonnect GmbH.
+- * (C)Copyright 2002-2003 Marvell.
++ * (C)Copyright 2002-2005 Marvell.
+ *
+ * Driver for Marvell Yukon chipset and SysKonnect Gigabit Ethernet
+ * Server Adapters.
+ *
+- * Created 10-Feb-1999, based on Linux' acenic.c, 3c59x.c and
+- * SysKonnects GEnesis Solaris driver
+- * Author: Christoph Goos (cgoos@syskonnect.de)
+- * Mirko Lindner (mlindner@syskonnect.de)
++ * Author: Mirko Lindner (mlindner@syskonnect.de)
++ * Ralph Roesler (rroesler@syskonnect.de)
+ *
+ * Address all question to: linux@syskonnect.de
+ *
+- * The technical manual for the adapters is available from SysKonnect's
+- * web pages: www.syskonnect.com
+- * Goto "Support" and search Knowledge Base for "manual".
+- *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+@@ -38,71 +32,33 @@
+
+ /******************************************************************************
+ *
+- * Possible compiler options (#define xxx / -Dxxx):
+- *
+- * debugging can be enable by changing SK_DEBUG_CHKMOD and
+- * SK_DEBUG_CHKCAT in makefile (described there).
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+ * Description:
+ *
+- * This is the main module of the Linux GE driver.
+- *
+- * All source files except skge.c, skdrv1st.h, skdrv2nd.h and sktypes.h
+- * are part of SysKonnect's COMMON MODULES for the SK-98xx adapters.
+- * Those are used for drivers on multiple OS', so some thing may seem
+- * unnecessary complicated on Linux. Please do not try to 'clean up'
+- * them without VERY good reasons, because this will make it more
+- * difficult to keep the Linux driver in synchronisation with the
+- * other versions.
+- *
+- * Include file hierarchy:
+- *
+- * <linux/module.h>
+- *
+- * "h/skdrv1st.h"
+- * <linux/types.h>
+- * <linux/kernel.h>
+- * <linux/string.h>
+- * <linux/errno.h>
+- * <linux/ioport.h>
+- * <linux/slab.h>
+- * <linux/interrupt.h>
+- * <linux/pci.h>
+- * <asm/byteorder.h>
+- * <asm/bitops.h>
+- * <asm/io.h>
+- * <linux/netdevice.h>
+- * <linux/etherdevice.h>
+- * <linux/skbuff.h>
+- * those three depending on kernel version used:
+- * <linux/bios32.h>
+- * <linux/init.h>
+- * <asm/uaccess.h>
+- * <net/checksum.h>
+- *
+- * "h/skerror.h"
+- * "h/skdebug.h"
+- * "h/sktypes.h"
+- * "h/lm80.h"
+- * "h/xmac_ii.h"
+- *
+- * "h/skdrv2nd.h"
+- * "h/skqueue.h"
+- * "h/skgehwt.h"
+- * "h/sktimer.h"
+- * "h/ski2c.h"
+- * "h/skgepnmi.h"
+- * "h/skvpd.h"
+- * "h/skgehw.h"
+- * "h/skgeinit.h"
+- * "h/skaddr.h"
+- * "h/skgesirq.h"
+- * "h/skcsum.h"
+- * "h/skrlmt.h"
++ * All source files in this sk98lin directory except of the sk98lin
++ * Linux specific files
++ *
++ * - skdim.c
++ * - skethtool.c
++ * - skge.c
++ * - skproc.c
++ * - sky2.c
++ * - Makefile
++ * - h/skdrv1st.h
++ * - h/skdrv2nd.h
++ * - h/sktypes.h
++ * - h/skversion.h
++ *
++ * are part of SysKonnect's common modules for the SK-9xxx adapters.
++ *
++ * Those common module files which are not Linux specific are used to
++ * build drivers on different OS' (e.g. Windows, MAC OS) so that those
++ * drivers are based on the same set of files
++ *
++ * At a first glance, this seems to complicate things unnescessarily on
++ * Linux, but please do not try to 'clean up' them without VERY good
++ * reasons, because this will make it more difficult to keep the sk98lin
++ * driver for Linux in synchronisation with the other drivers running on
++ * other operating systems.
+ *
+ ******************************************************************************/
+
+@@ -110,6 +66,7 @@
+
+ #include <linux/module.h>
+ #include <linux/init.h>
++#include <linux/ethtool.h>
+
+ #ifdef CONFIG_PROC_FS
+ #include <linux/proc_fs.h>
+@@ -118,6 +75,10 @@
+ #include "h/skdrv1st.h"
+ #include "h/skdrv2nd.h"
+
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9)
++#include <linux/moduleparam.h>
++#endif
++
+ /*******************************************************************************
+ *
+ * Defines
+@@ -127,62 +88,14 @@
+ /* for debuging on x86 only */
+ /* #define BREAKPOINT() asm(" int $3"); */
+
+-/* use the transmit hw checksum driver functionality */
+-#define USE_SK_TX_CHECKSUM
+-
+-/* use the receive hw checksum driver functionality */
+-#define USE_SK_RX_CHECKSUM
+-
+-/* use the scatter-gather functionality with sendfile() */
+-#define SK_ZEROCOPY
+-
+-/* use of a transmit complete interrupt */
+-#define USE_TX_COMPLETE
+-
+-/*
+- * threshold for copying small receive frames
+- * set to 0 to avoid copying, set to 9001 to copy all frames
+- */
+-#define SK_COPY_THRESHOLD 50
+-
+-/* number of adapters that can be configured via command line params */
+-#define SK_MAX_CARD_PARAM 16
+-
+-
+-
+-/*
+- * use those defines for a compile-in version of the driver instead
+- * of command line parameters
+- */
+-// #define LINK_SPEED_A {"Auto", }
+-// #define LINK_SPEED_B {"Auto", }
+-// #define AUTO_NEG_A {"Sense", }
+-// #define AUTO_NEG_B {"Sense", }
+-// #define DUP_CAP_A {"Both", }
+-// #define DUP_CAP_B {"Both", }
+-// #define FLOW_CTRL_A {"SymOrRem", }
+-// #define FLOW_CTRL_B {"SymOrRem", }
+-// #define ROLE_A {"Auto", }
+-// #define ROLE_B {"Auto", }
+-// #define PREF_PORT {"A", }
+-// #define CON_TYPE {"Auto", }
+-// #define RLMT_MODE {"CheckLinkState", }
+-
+-#define DEV_KFREE_SKB(skb) dev_kfree_skb(skb)
+-#define DEV_KFREE_SKB_IRQ(skb) dev_kfree_skb_irq(skb)
+-#define DEV_KFREE_SKB_ANY(skb) dev_kfree_skb_any(skb)
+-
+
+ /* Set blink mode*/
+ #define OEM_CONFIG_VALUE ( SK_ACT_LED_BLINK | \
+ SK_DUP_LED_NORMAL | \
+ SK_LED_LINK100_ON)
+
+-
+-/* Isr return value */
+-#define SkIsrRetVar irqreturn_t
+-#define SkIsrRetNone IRQ_NONE
+-#define SkIsrRetHandled IRQ_HANDLED
++#define CLEAR_AND_START_RX(Port) SK_OUT8(pAC->IoBase, RxQueueAddr[(Port)]+Q_CSR, CSR_START | CSR_IRQ_CL_F)
++#define CLEAR_TX_IRQ(Port,Prio) SK_OUT8(pAC->IoBase, TxQueueAddr[(Port)][(Prio)]+Q_CSR, CSR_IRQ_CL_F)
+
+
+ /*******************************************************************************
+@@ -191,12 +104,25 @@
+ *
+ ******************************************************************************/
+
++static int __devinit sk98lin_init_device(struct pci_dev *pdev, const struct pci_device_id *ent);
++static void sk98lin_remove_device(struct pci_dev *pdev);
++#ifdef CONFIG_PM
++static int sk98lin_suspend(struct pci_dev *pdev, u32 state);
++static int sk98lin_resume(struct pci_dev *pdev);
++static void SkEnableWOMagicPacket(SK_AC *pAC, SK_IOC IoC, SK_MAC_ADDR MacAddr);
++#endif
++#ifdef Y2_RECOVERY
++static void SkGeHandleKernelTimer(unsigned long ptr);
++void SkGeCheckTimer(DEV_NET *pNet);
++static SK_BOOL CheckRXCounters(DEV_NET *pNet);
++static void CheckForRXHang(DEV_NET *pNet);
++#endif
+ static void FreeResources(struct SK_NET_DEVICE *dev);
+ static int SkGeBoardInit(struct SK_NET_DEVICE *dev, SK_AC *pAC);
+ static SK_BOOL BoardAllocMem(SK_AC *pAC);
+ static void BoardFreeMem(SK_AC *pAC);
+ static void BoardInitMem(SK_AC *pAC);
+-static void SetupRing(SK_AC*, void*, uintptr_t, RXD**, RXD**, RXD**, int*, SK_BOOL);
++static void SetupRing(SK_AC*, void*, uintptr_t, RXD**, RXD**, RXD**, int*, int*, SK_BOOL);
+ static SkIsrRetVar SkGeIsr(int irq, void *dev_id, struct pt_regs *ptregs);
+ static SkIsrRetVar SkGeIsrOnePort(int irq, void *dev_id, struct pt_regs *ptregs);
+ static int SkGeOpen(struct SK_NET_DEVICE *dev);
+@@ -212,24 +138,37 @@
+ static void FreeTxDescriptors(SK_AC*pAC, TX_PORT*);
+ static void FillRxRing(SK_AC*, RX_PORT*);
+ static SK_BOOL FillRxDescriptor(SK_AC*, RX_PORT*);
++#ifdef CONFIG_SK98LIN_NAPI
++static int SkGePoll(struct net_device *dev, int *budget);
++static void ReceiveIrq(SK_AC*, RX_PORT*, SK_BOOL, int*, int);
++#else
+ static void ReceiveIrq(SK_AC*, RX_PORT*, SK_BOOL);
+-static void ClearAndStartRx(SK_AC*, int);
+-static void ClearTxIrq(SK_AC*, int, int);
++#endif
++#ifdef SK_POLL_CONTROLLER
++static void SkGeNetPoll(struct SK_NET_DEVICE *dev);
++#endif
+ static void ClearRxRing(SK_AC*, RX_PORT*);
+ static void ClearTxRing(SK_AC*, TX_PORT*);
+ static int SkGeChangeMtu(struct SK_NET_DEVICE *dev, int new_mtu);
+ static void PortReInitBmu(SK_AC*, int);
+ static int SkGeIocMib(DEV_NET*, unsigned int, int);
+ static int SkGeInitPCI(SK_AC *pAC);
+-static void StartDrvCleanupTimer(SK_AC *pAC);
+-static void StopDrvCleanupTimer(SK_AC *pAC);
+-static int XmitFrameSG(SK_AC*, TX_PORT*, struct sk_buff*);
+-
+-#ifdef SK_DIAG_SUPPORT
+ static SK_U32 ParseDeviceNbrFromSlotName(const char *SlotName);
+ static int SkDrvInitAdapter(SK_AC *pAC, int devNbr);
+ static int SkDrvDeInitAdapter(SK_AC *pAC, int devNbr);
+-#endif
++extern void SkLocalEventQueue( SK_AC *pAC,
++ SK_U32 Class,
++ SK_U32 Event,
++ SK_U32 Param1,
++ SK_U32 Param2,
++ SK_BOOL Flag);
++extern void SkLocalEventQueue64( SK_AC *pAC,
++ SK_U32 Class,
++ SK_U32 Event,
++ SK_U64 Param,
++ SK_BOOL Flag);
++
++static int XmitFrameSG(SK_AC*, TX_PORT*, struct sk_buff*);
+
+ /*******************************************************************************
+ *
+@@ -237,17 +176,34 @@
+ *
+ ******************************************************************************/
+
+-#ifdef CONFIG_PROC_FS
+-static const char SK_Root_Dir_entry[] = "sk98lin";
+-static struct proc_dir_entry *pSkRootDir = NULL;
+-extern struct file_operations sk_proc_fops;
++extern SK_BOOL SkY2AllocateResources(SK_AC *pAC);
++extern void SkY2FreeResources(SK_AC *pAC);
++extern void SkY2AllocateRxBuffers(SK_AC *pAC,SK_IOC IoC,int Port);
++extern void SkY2FreeRxBuffers(SK_AC *pAC,SK_IOC IoC,int Port);
++extern void SkY2FreeTxBuffers(SK_AC *pAC,SK_IOC IoC,int Port);
++extern SkIsrRetVar SkY2Isr(int irq,void *dev_id,struct pt_regs *ptregs);
++extern int SkY2Xmit(struct sk_buff *skb,struct SK_NET_DEVICE *dev);
++extern void SkY2PortStop(SK_AC *pAC,SK_IOC IoC,int Port,int Dir,int RstMode);
++extern void SkY2PortStart(SK_AC *pAC,SK_IOC IoC,int Port);
++extern int SkY2RlmtSend(SK_AC *pAC,int PortNr,struct sk_buff *pMessage);
++extern void SkY2RestartStatusUnit(SK_AC *pAC);
++extern void FillReceiveTableYukon2(SK_AC *pAC,SK_IOC IoC,int Port);
++#ifdef CONFIG_SK98LIN_NAPI
++extern int SkY2Poll(struct net_device *dev, int *budget);
+ #endif
+
+ extern void SkDimEnableModerationIfNeeded(SK_AC *pAC);
+-extern void SkDimDisplayModerationSettings(SK_AC *pAC);
+ extern void SkDimStartModerationTimer(SK_AC *pAC);
+ extern void SkDimModerate(SK_AC *pAC);
+
++extern int SkEthIoctl(struct net_device *netdev, struct ifreq *ifr);
++
++#ifdef CONFIG_PROC_FS
++static const char SK_Root_Dir_entry[] = "sk98lin";
++static struct proc_dir_entry *pSkRootDir;
++extern struct file_operations sk_proc_fops;
++#endif
++
+ #ifdef DEBUG
+ static void DumpMsg(struct sk_buff*, char*);
+ static void DumpData(char*, int);
+@@ -257,13 +213,12 @@
+ /* global variables *********************************************************/
+ static const char *BootString = BOOT_STRING;
+ struct SK_NET_DEVICE *SkGeRootDev = NULL;
+-static int probed __initdata = 0;
+ static SK_BOOL DoPrintInterfaceChange = SK_TRUE;
+
+ /* local variables **********************************************************/
+ static uintptr_t TxQueueAddr[SK_MAX_MACS][2] = {{0x680, 0x600},{0x780, 0x700}};
+ static uintptr_t RxQueueAddr[SK_MAX_MACS] = {0x400, 0x480};
+-
++static int sk98lin_max_boards_found = 0;
+
+ #ifdef CONFIG_PROC_FS
+ static struct proc_dir_entry *pSkRootDir;
+@@ -271,285 +226,412 @@
+
+
+
++static struct pci_device_id sk98lin_pci_tbl[] __devinitdata = {
++/* { pci_vendor_id, pci_device_id, * SAMPLE ENTRY! *
++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL }, */
++ { 0x10b7, 0x1700, /* 3Com (10b7), Gigabit Ethernet Adapter */
++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++ { 0x10b7, 0x80eb, /* 3Com (10b7), 3Com 3C940B Gigabit LOM Ethernet Adapter */
++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++ { 0x1148, 0x4300, /* SysKonnect (1148), SK-98xx Gigabit Ethernet Server Adapter */
++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++ { 0x1148, 0x4320, /* SysKonnect (1148), SK-98xx V2.0 Gigabit Ethernet Adapter */
++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++ { 0x1148, 0x9000, /* SysKonnect (1148), SK-9Sxx 10/100/1000Base-T Server Adapter */
++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++ { 0x1148, 0x9E00, /* SysKonnect (1148), SK-9Exx 10/100/1000Base-T Adapter */
++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++ { 0x1186, 0x4b00, /* D-Link (1186), Gigabit Ethernet Adapter */
++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++ { 0x1186, 0x4b01, /* D-Link (1186), Gigabit Ethernet Adapter */
++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++ { 0x1186, 0x4c00, /* D-Link (1186), Gigabit Ethernet Adapter */
++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++ { 0x11ab, 0x4320, /* Marvell (11ab), Gigabit Ethernet Controller */
++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++ { 0x11ab, 0x4340, /* Marvell (11ab), Gigabit Ethernet Controller */
++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++ { 0x11ab, 0x4341, /* Marvell (11ab), Gigabit Ethernet Controller */
++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++ { 0x11ab, 0x4342, /* Marvell (11ab), Gigabit Ethernet Controller */
++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++ { 0x11ab, 0x4343, /* Marvell (11ab), Gigabit Ethernet Controller */
++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++ { 0x11ab, 0x4344, /* Marvell (11ab), Gigabit Ethernet Controller */
++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++ { 0x11ab, 0x4345, /* Marvell (11ab), Gigabit Ethernet Controller */
++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++ { 0x11ab, 0x4346, /* Marvell (11ab), Gigabit Ethernet Controller */
++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++ { 0x11ab, 0x4347, /* Marvell (11ab), Gigabit Ethernet Controller */
++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++ { 0x11ab, 0x4350, /* Marvell (11ab), Fast Ethernet Controller */
++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++ { 0x11ab, 0x4351, /* Marvell (11ab), Fast Ethernet Controller */
++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++ { 0x11ab, 0x4352, /* Marvell (11ab), Gigabit Ethernet Controller */
++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++ { 0x11ab, 0x4360, /* Marvell (11ab), Gigabit Ethernet Controller */
++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++ { 0x11ab, 0x4361, /* Marvell (11ab), Gigabit Ethernet Controller */
++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++ { 0x11ab, 0x4362, /* Marvell (11ab), Gigabit Ethernet Controller */
++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++ { 0x11ab, 0x4363, /* Marvell (11ab), Marvell */
++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++ { 0x11ab, 0x5005, /* Marvell (11ab), Belkin */
++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++ { 0x1371, 0x434e, /* CNet (1371), GigaCard Network Adapter */
++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++ { 0x1737, 0x1032, /* Linksys (1737), Gigabit Network Adapter */
++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++ { 0x1737, 0x1064, /* Linksys (1737), Gigabit Network Adapter */
++ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0UL },
++ { 0, }
++};
++
++MODULE_DEVICE_TABLE(pci, sk98lin_pci_tbl);
++
++static struct pci_driver sk98lin_driver = {
++ .name = DRIVER_FILE_NAME,
++ .id_table = sk98lin_pci_tbl,
++ .probe = sk98lin_init_device,
++ .remove = __devexit_p(sk98lin_remove_device),
++#ifdef CONFIG_PM
++ .suspend = sk98lin_suspend,
++ .resume = sk98lin_resume
++#endif
++};
++
++
+ /*****************************************************************************
+ *
+- * skge_probe - find all SK-98xx adapters
++ * sk98lin_init_device - initialize the adapter
+ *
+ * Description:
+- * This function scans the PCI bus for SK-98xx adapters. Resources for
+- * each adapter are allocated and the adapter is brought into Init 1
++ * This function initializes the adapter. Resources for
++ * the adapter are allocated and the adapter is brought into Init 1
+ * state.
+ *
+ * Returns:
+ * 0, if everything is ok
+ * !=0, on error
+ */
+-static int __init skge_probe (void)
++static int __devinit sk98lin_init_device(struct pci_dev *pdev,
++ const struct pci_device_id *ent)
++
+ {
+- int boards_found = 0;
+- int vendor_flag = SK_FALSE;
++ static SK_BOOL sk98lin_boot_string = SK_FALSE;
++ static SK_BOOL sk98lin_proc_entry = SK_FALSE;
++ static int sk98lin_boards_found = 0;
+ SK_AC *pAC;
+ DEV_NET *pNet = NULL;
+- struct pci_dev *pdev = NULL;
+ struct SK_NET_DEVICE *dev = NULL;
+- SK_BOOL DeviceFound = SK_FALSE;
+- SK_BOOL BootStringCount = SK_FALSE;
+ int retval;
+ #ifdef CONFIG_PROC_FS
+ struct proc_dir_entry *pProcFile;
+ #endif
+
+- if (probed)
+- return -ENODEV;
+- probed++;
++ retval = pci_enable_device(pdev);
++ if (retval) {
++ printk(KERN_ERR "Cannot enable PCI device, "
++ "aborting.\n");
++ return retval;
++ }
+
++ dev = NULL;
++ pNet = NULL;
+
+- while((pdev = pci_find_class(PCI_CLASS_NETWORK_ETHERNET << 8, pdev))) {
+
+- if (pci_enable_device(pdev)) {
+- continue;
+- }
+- dev = NULL;
+- pNet = NULL;
++ /* INSERT * We have to find the power-management capabilities */
++ /* Find power-management capability. */
+
+- /* Don't handle Yukon2 cards at the moment */
+- /* 12-feb-2004 ---- mlindner@syskonnect.de */
+- if (pdev->vendor == 0x11ab) {
+- if ( (pdev->device == 0x4360) || (pdev->device == 0x4361) )
+- continue;
+- }
+
+- SK_PCI_ISCOMPLIANT(vendor_flag, pdev);
+- if (!vendor_flag)
+- continue;
+
+- /* Configure DMA attributes. */
+- if (pci_set_dma_mask(pdev, (u64) 0xffffffffffffffffULL) &&
+- pci_set_dma_mask(pdev, (u64) 0xffffffff))
+- continue;
++ /* Configure DMA attributes. */
++ retval = pci_set_dma_mask(pdev, (u64) 0xffffffffffffffffULL);
++ if (!retval) {
++ retval = pci_set_dma_mask(pdev, (u64) 0xffffffff);
++ if (retval)
++ return retval;
++ } else {
++ return retval;
++ }
+
+
+- if ((dev = alloc_etherdev(sizeof(DEV_NET))) == NULL) {
+- printk(KERN_ERR "Unable to allocate etherdev "
+- "structure!\n");
+- break;
+- }
++ if ((dev = alloc_etherdev(sizeof(DEV_NET))) == NULL) {
++ printk(KERN_ERR "Unable to allocate etherdev "
++ "structure!\n");
++ return -ENODEV;
++ }
+
+- pNet = dev->priv;
+- pNet->pAC = kmalloc(sizeof(SK_AC), GFP_KERNEL);
+- if (pNet->pAC == NULL){
+- free_netdev(dev);
+- printk(KERN_ERR "Unable to allocate adapter "
+- "structure!\n");
+- break;
+- }
++ pNet = dev->priv;
++ pNet->pAC = kmalloc(sizeof(SK_AC), GFP_KERNEL);
++ if (pNet->pAC == NULL){
++ free_netdev(dev);
++ printk(KERN_ERR "Unable to allocate adapter "
++ "structure!\n");
++ return -ENODEV;
++ }
+
+- /* Print message */
+- if (!BootStringCount) {
+- /* set display flag to TRUE so that */
+- /* we only display this string ONCE */
+- BootStringCount = SK_TRUE;
+- printk("%s\n", BootString);
+- }
+
+- memset(pNet->pAC, 0, sizeof(SK_AC));
+- pAC = pNet->pAC;
+- pAC->PciDev = pdev;
+- pAC->PciDevId = pdev->device;
+- pAC->dev[0] = dev;
+- pAC->dev[1] = dev;
+- sprintf(pAC->Name, "SysKonnect SK-98xx");
+- pAC->CheckQueue = SK_FALSE;
++ /* Print message */
++ if (!sk98lin_boot_string) {
++ /* set display flag to TRUE so that */
++ /* we only display this string ONCE */
++ sk98lin_boot_string = SK_TRUE;
++ printk("%s\n", BootString);
++ }
+
+- pNet->Mtu = 1500;
+- pNet->Up = 0;
+- dev->irq = pdev->irq;
+- retval = SkGeInitPCI(pAC);
+- if (retval) {
+- printk("SKGE: PCI setup failed: %i\n", retval);
+- free_netdev(dev);
+- continue;
+- }
++ memset(pNet->pAC, 0, sizeof(SK_AC));
++ pAC = pNet->pAC;
++ pAC->PciDev = pdev;
++ pAC->PciDevId = pdev->device;
++ pAC->dev[0] = dev;
++ pAC->dev[1] = dev;
++ sprintf(pAC->Name, "SysKonnect SK-98xx");
++ pAC->CheckQueue = SK_FALSE;
++
++ dev->irq = pdev->irq;
++ retval = SkGeInitPCI(pAC);
++ if (retval) {
++ printk("SKGE: PCI setup failed: %i\n", retval);
++ free_netdev(dev);
++ return -ENODEV;
++ }
++
++ SET_MODULE_OWNER(dev);
++
++ dev->open = &SkGeOpen;
++ dev->stop = &SkGeClose;
++ dev->get_stats = &SkGeStats;
++ dev->set_multicast_list = &SkGeSetRxMode;
++ dev->set_mac_address = &SkGeSetMacAddr;
++ dev->do_ioctl = &SkGeIoctl;
++ dev->change_mtu = &SkGeChangeMtu;
++ dev->flags &= ~IFF_RUNNING;
++#ifdef SK_POLL_CONTROLLER
++ dev->poll_controller = SkGeNetPoll;
++#endif
++ SET_NETDEV_DEV(dev, &pdev->dev);
+
+- SET_MODULE_OWNER(dev);
+- dev->open = &SkGeOpen;
+- dev->stop = &SkGeClose;
++ pAC->Index = sk98lin_boards_found;
++
++ if (SkGeBoardInit(dev, pAC)) {
++ free_netdev(dev);
++ return -ENODEV;
++ } else {
++ ProductStr(pAC);
++ }
++
++ /* shifter to later moment in time... */
++ if (CHIP_ID_YUKON_2(pAC)) {
++ dev->hard_start_xmit = &SkY2Xmit;
++#ifdef CONFIG_SK98LIN_NAPI
++ dev->poll = &SkY2Poll;
++ dev->weight = 64;
++#endif
++ } else {
+ dev->hard_start_xmit = &SkGeXmit;
+- dev->get_stats = &SkGeStats;
+- dev->last_stats = &SkGeStats;
+- dev->set_multicast_list = &SkGeSetRxMode;
+- dev->set_mac_address = &SkGeSetMacAddr;
+- dev->do_ioctl = &SkGeIoctl;
+- dev->change_mtu = &SkGeChangeMtu;
+- dev->flags &= ~IFF_RUNNING;
+- SET_NETDEV_DEV(dev, &pdev->dev);
++#ifdef CONFIG_SK98LIN_NAPI
++ dev->poll = &SkGePoll;
++ dev->weight = 64;
++#endif
++ }
+
+-#ifdef SK_ZEROCOPY
++#ifdef NETIF_F_TSO
++#ifdef USE_SK_TSO_FEATURE
++ if (CHIP_ID_YUKON_2(pAC)) {
++ dev->features |= NETIF_F_TSO;
++ }
++#endif
++#endif
++#ifdef CONFIG_SK98LIN_ZEROCOPY
++ if (pAC->GIni.GIChipId != CHIP_ID_GENESIS)
++ dev->features |= NETIF_F_SG;
++#endif
+ #ifdef USE_SK_TX_CHECKSUM
+-
+- if (pAC->ChipsetType) {
+- /* Use only if yukon hardware */
+- /* SK and ZEROCOPY - fly baby... */
+- dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
+- }
++ if (pAC->GIni.GIChipId != CHIP_ID_GENESIS)
++ dev->features |= NETIF_F_IP_CSUM;
+ #endif
++#ifdef USE_SK_RX_CHECKSUM
++ pAC->RxPort[0].UseRxCsum = SK_TRUE;
++ if (pAC->GIni.GIMacsFound == 2 ) {
++ pAC->RxPort[1].UseRxCsum = SK_TRUE;
++ }
+ #endif
+
+- pAC->Index = boards_found;
++ /* Save the hardware revision */
++ pAC->HWRevision = (((pAC->GIni.GIPciHwRev >> 4) & 0x0F)*10) +
++ (pAC->GIni.GIPciHwRev & 0x0F);
+
+- if (SkGeBoardInit(dev, pAC)) {
+- free_netdev(dev);
+- continue;
+- }
++ /* Set driver globals */
++ pAC->Pnmi.pDriverFileName = DRIVER_FILE_NAME;
++ pAC->Pnmi.pDriverReleaseDate = DRIVER_REL_DATE;
+
+- /* Register net device */
+- if (register_netdev(dev)) {
+- printk(KERN_ERR "SKGE: Could not register device.\n");
+- FreeResources(dev);
+- free_netdev(dev);
+- continue;
+- }
++ SK_MEMSET(&(pAC->PnmiBackup), 0, sizeof(SK_PNMI_STRUCT_DATA));
++ SK_MEMCPY(&(pAC->PnmiBackup), &(pAC->PnmiStruct),
++ sizeof(SK_PNMI_STRUCT_DATA));
+
+- /* Print adapter specific string from vpd */
+- ProductStr(pAC);
+- printk("%s: %s\n", dev->name, pAC->DeviceStr);
++ /* Register net device */
++ retval = register_netdev(dev);
++ if (retval) {
++ printk(KERN_ERR "SKGE: Could not register device.\n");
++ FreeResources(dev);
++ free_netdev(dev);
++ return retval;
++ }
+
+- /* Print configuration settings */
+- printk(" PrefPort:%c RlmtMode:%s\n",
+- 'A' + pAC->Rlmt.Net[0].Port[pAC->Rlmt.Net[0].PrefPort]->PortNumber,
+- (pAC->RlmtMode==0) ? "Check Link State" :
+- ((pAC->RlmtMode==1) ? "Check Link State" :
+- ((pAC->RlmtMode==3) ? "Check Local Port" :
+- ((pAC->RlmtMode==7) ? "Check Segmentation" :
+- ((pAC->RlmtMode==17) ? "Dual Check Link State" :"Error")))));
++ /* Save initial device name */
++ strcpy(pNet->InitialDevName, dev->name);
+
+- SkGeYellowLED(pAC, pAC->IoBase, 1);
++ /* Set network to off */
++ netif_stop_queue(dev);
++ netif_carrier_off(dev);
+
++ /* Print adapter specific string from vpd and config settings */
++ printk("%s: %s\n", pNet->InitialDevName, pAC->DeviceStr);
++ printk(" PrefPort:%c RlmtMode:%s\n",
++ 'A' + pAC->Rlmt.Net[0].Port[pAC->Rlmt.Net[0].PrefPort]->PortNumber,
++ (pAC->RlmtMode==0) ? "Check Link State" :
++ ((pAC->RlmtMode==1) ? "Check Link State" :
++ ((pAC->RlmtMode==3) ? "Check Local Port" :
++ ((pAC->RlmtMode==7) ? "Check Segmentation" :
++ ((pAC->RlmtMode==17) ? "Dual Check Link State" :"Error")))));
+
+- memcpy((caddr_t) &dev->dev_addr,
+- (caddr_t) &pAC->Addr.Net[0].CurrentMacAddress, 6);
++ SkGeYellowLED(pAC, pAC->IoBase, 1);
+
+- /* First adapter... Create proc and print message */
++ memcpy((caddr_t) &dev->dev_addr,
++ (caddr_t) &pAC->Addr.Net[0].CurrentMacAddress, 6);
++
++ /* First adapter... Create proc and print message */
+ #ifdef CONFIG_PROC_FS
+- if (!DeviceFound) {
+- DeviceFound = SK_TRUE;
+- SK_MEMCPY(&SK_Root_Dir_entry, BootString,
+- sizeof(SK_Root_Dir_entry) - 1);
+-
+- /*Create proc (directory)*/
+- if(!pSkRootDir) {
+- pSkRootDir = proc_mkdir(SK_Root_Dir_entry, proc_net);
+- if (!pSkRootDir) {
+- printk(KERN_WARNING "%s: Unable to create /proc/net/%s",
+- dev->name, SK_Root_Dir_entry);
+- } else {
+- pSkRootDir->owner = THIS_MODULE;
+- }
++ if (!sk98lin_proc_entry) {
++ sk98lin_proc_entry = SK_TRUE;
++ SK_MEMCPY(&SK_Root_Dir_entry, BootString,
++ sizeof(SK_Root_Dir_entry) - 1);
++
++ /*Create proc (directory)*/
++ if(!pSkRootDir) {
++ pSkRootDir = proc_mkdir(SK_Root_Dir_entry, proc_net);
++ if (!pSkRootDir) {
++ printk(KERN_WARNING "%s: Unable to create /proc/net/%s",
++ dev->name, SK_Root_Dir_entry);
++ } else {
++ pSkRootDir->owner = THIS_MODULE;
+ }
+ }
++ }
+
+- /* Create proc file */
+- if (pSkRootDir &&
+- (pProcFile = create_proc_entry(dev->name, S_IRUGO,
+- pSkRootDir))) {
+- pProcFile->proc_fops = &sk_proc_fops;
+- pProcFile->data = dev;
+- }
++ /* Create proc file */
++ if (pSkRootDir &&
++ (pProcFile = create_proc_entry(pNet->InitialDevName, S_IRUGO,
++ pSkRootDir))) {
++ pProcFile->proc_fops = &sk_proc_fops;
++ pProcFile->data = dev;
++ }
+
+ #endif
+
+- pNet->PortNr = 0;
+- pNet->NetNr = 0;
++ pNet->PortNr = 0;
++ pNet->NetNr = 0;
+
+- boards_found++;
++ sk98lin_boards_found++;
++ pci_set_drvdata(pdev, dev);
+
+- /* More then one port found */
+- if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
+- if ((dev = alloc_etherdev(sizeof(DEV_NET))) == 0) {
+- printk(KERN_ERR "Unable to allocate etherdev "
+- "structure!\n");
+- break;
+- }
++ /* More then one port found */
++ if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
++ if ((dev = alloc_etherdev(sizeof(DEV_NET))) == 0) {
++ printk(KERN_ERR "Unable to allocate etherdev "
++ "structure!\n");
++ return -ENODEV;
++ }
+
+- pAC->dev[1] = dev;
+- pNet = dev->priv;
+- pNet->PortNr = 1;
+- pNet->NetNr = 1;
+- pNet->pAC = pAC;
+- pNet->Mtu = 1500;
+- pNet->Up = 0;
+-
+- dev->open = &SkGeOpen;
+- dev->stop = &SkGeClose;
+- dev->hard_start_xmit = &SkGeXmit;
+- dev->get_stats = &SkGeStats;
+- dev->last_stats = &SkGeStats;
+- dev->set_multicast_list = &SkGeSetRxMode;
+- dev->set_mac_address = &SkGeSetMacAddr;
+- dev->do_ioctl = &SkGeIoctl;
+- dev->change_mtu = &SkGeChangeMtu;
+- dev->flags &= ~IFF_RUNNING;
++ pAC->dev[1] = dev;
++ pNet = dev->priv;
++ pNet->PortNr = 1;
++ pNet->NetNr = 1;
++ pNet->pAC = pAC;
++
++ if (CHIP_ID_YUKON_2(pAC)) {
++ dev->hard_start_xmit = &SkY2Xmit;
++#ifdef CONFIG_SK98LIN_NAPI
++ dev->poll = &SkY2Poll;
++ dev->weight = 64;
++#endif
++ } else {
++ dev->hard_start_xmit = &SkGeXmit;
++#ifdef CONFIG_SK98LIN_NAPI
++ dev->poll = &SkGePoll;
++ dev->weight = 64;
++#endif
++ }
++ dev->open = &SkGeOpen;
++ dev->stop = &SkGeClose;
++ dev->get_stats = &SkGeStats;
++ dev->set_multicast_list = &SkGeSetRxMode;
++ dev->set_mac_address = &SkGeSetMacAddr;
++ dev->do_ioctl = &SkGeIoctl;
++ dev->change_mtu = &SkGeChangeMtu;
++ dev->flags &= ~IFF_RUNNING;
++#ifdef SK_POLL_CONTROLLER
++ dev->poll_controller = SkGeNetPoll;
++#endif
+
+-#ifdef SK_ZEROCOPY
+-#ifdef USE_SK_TX_CHECKSUM
+- if (pAC->ChipsetType) {
+- /* SG and ZEROCOPY - fly baby... */
+- dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
+- }
++#ifdef NETIF_F_TSO
++#ifdef USE_SK_TSO_FEATURE
++ if (CHIP_ID_YUKON_2(pAC)) {
++ dev->features |= NETIF_F_TSO;
++ }
++#endif
+ #endif
++#ifdef CONFIG_SK98LIN_ZEROCOPY
++ /* Don't handle if Genesis chipset */
++ if (pAC->GIni.GIChipId != CHIP_ID_GENESIS)
++ dev->features |= NETIF_F_SG;
++#endif
++#ifdef USE_SK_TX_CHECKSUM
++ /* Don't handle if Genesis chipset */
++ if (pAC->GIni.GIChipId != CHIP_ID_GENESIS)
++ dev->features |= NETIF_F_IP_CSUM;
+ #endif
+
+- if (register_netdev(dev)) {
+- printk(KERN_ERR "SKGE: Could not register device.\n");
+- free_netdev(dev);
+- pAC->dev[1] = pAC->dev[0];
+- } else {
++ if (register_netdev(dev)) {
++ printk(KERN_ERR "SKGE: Could not register device.\n");
++ free_netdev(dev);
++ pAC->dev[1] = pAC->dev[0];
++ } else {
++
++ /* Save initial device name */
++ strcpy(pNet->InitialDevName, dev->name);
++
++ /* Set network to off */
++ netif_stop_queue(dev);
++ netif_carrier_off(dev);
++
++
+ #ifdef CONFIG_PROC_FS
+- if (pSkRootDir
+- && (pProcFile = create_proc_entry(dev->name,
+- S_IRUGO, pSkRootDir))) {
+- pProcFile->proc_fops = &sk_proc_fops;
+- pProcFile->data = dev;
+- }
++ if (pSkRootDir
++ && (pProcFile = create_proc_entry(pNet->InitialDevName,
++ S_IRUGO, pSkRootDir))) {
++ pProcFile->proc_fops = &sk_proc_fops;
++ pProcFile->data = dev;
++ }
+ #endif
+
+- memcpy((caddr_t) &dev->dev_addr,
+- (caddr_t) &pAC->Addr.Net[1].CurrentMacAddress, 6);
++ memcpy((caddr_t) &dev->dev_addr,
++ (caddr_t) &pAC->Addr.Net[1].CurrentMacAddress, 6);
+
+- printk("%s: %s\n", dev->name, pAC->DeviceStr);
+- printk(" PrefPort:B RlmtMode:Dual Check Link State\n");
+- }
++ printk("%s: %s\n", pNet->InitialDevName, pAC->DeviceStr);
++ printk(" PrefPort:B RlmtMode:Dual Check Link State\n");
+ }
+-
+- /* Save the hardware revision */
+- pAC->HWRevision = (((pAC->GIni.GIPciHwRev >> 4) & 0x0F)*10) +
+- (pAC->GIni.GIPciHwRev & 0x0F);
+-
+- /* Set driver globals */
+- pAC->Pnmi.pDriverFileName = DRIVER_FILE_NAME;
+- pAC->Pnmi.pDriverReleaseDate = DRIVER_REL_DATE;
+-
+- SK_MEMSET(&(pAC->PnmiBackup), 0, sizeof(SK_PNMI_STRUCT_DATA));
+- SK_MEMCPY(&(pAC->PnmiBackup), &(pAC->PnmiStruct),
+- sizeof(SK_PNMI_STRUCT_DATA));
+-
+- /*
+- * This is bollocks, but we need to tell the net-init
+- * code that it shall go for the next device.
+- */
+-#ifndef MODULE
+- dev->base_addr = 0;
+-#endif
+ }
+
+- /*
+- * If we're at this point we're going through skge_probe() for
+- * the first time. Return success (0) if we've initialized 1
+- * or more boards. Otherwise, return failure (-ENODEV).
+- */
++ pAC->Index = sk98lin_boards_found;
++ sk98lin_max_boards_found = sk98lin_boards_found;
++ return 0;
++}
+
+- return boards_found;
+-} /* skge_probe */
+
+
+ /*****************************************************************************
+@@ -575,7 +657,7 @@
+ dev->mem_start = pci_resource_start (pdev, 0);
+ pci_set_master(pdev);
+
+- if (pci_request_regions(pdev, pAC->Name) != 0) {
++ if (pci_request_regions(pdev, DRIVER_FILE_NAME) != 0) {
+ retval = 2;
+ goto out_disable;
+ }
+@@ -612,6 +694,457 @@
+ return retval;
+ }
+
++#ifdef Y2_RECOVERY
++/*****************************************************************************
++ *
++ * SkGeHandleKernelTimer - Handle the kernel timer requests
++ *
++ * Description:
++ * If the requested time interval for the timer has elapsed,
++ * this function checks the link state.
++ *
++ * Returns: N/A
++ *
++ */
++static void SkGeHandleKernelTimer(
++unsigned long ptr) /* holds the pointer to adapter control context */
++{
++ DEV_NET *pNet = (DEV_NET*) ptr;
++ SkGeCheckTimer(pNet);
++}
++
++/*****************************************************************************
++ *
++ * sk98lin_check_timer - Resume the the card
++ *
++ * Description:
++ * This function checks the kernel timer
++ *
++ * Returns: N/A
++ *
++ */
++void SkGeCheckTimer(
++DEV_NET *pNet) /* holds the pointer to adapter control context */
++{
++ SK_AC *pAC = pNet->pAC;
++ SK_BOOL StartTimer = SK_TRUE;
++
++ if (pNet->InRecover)
++ return;
++ if (pNet->TimerExpired)
++ return;
++ pNet->TimerExpired = SK_TRUE;
++
++#define TXPORT pAC->TxPort[pNet->PortNr][TX_PRIO_LOW]
++#define RXPORT pAC->RxPort[pNet->PortNr]
++
++ if ( (CHIP_ID_YUKON_2(pAC)) &&
++ (netif_running(pAC->dev[pNet->PortNr]))) {
++
++#ifdef Y2_RX_CHECK
++ /* Checks if the RX path hangs */
++ CheckForRXHang(pNet);
++#endif
++
++ /* Checkthe transmitter */
++ if (!(IS_Q_EMPTY(&TXPORT.TxAQ_working))) {
++ if (TXPORT.LastDone != TXPORT.TxALET.Done) {
++ TXPORT.LastDone = TXPORT.TxALET.Done;
++ pNet->TransmitTimeoutTimer = 0;
++ } else {
++ pNet->TransmitTimeoutTimer++;
++ if (pNet->TransmitTimeoutTimer >= 10) {
++ pNet->TransmitTimeoutTimer = 0;
++#ifdef CHECK_TRANSMIT_TIMEOUT
++ StartTimer = SK_FALSE;
++ SkLocalEventQueue(pAC, SKGE_DRV,
++ SK_DRV_RECOVER,pNet->PortNr,-1,SK_FALSE);
++#endif
++ }
++ }
++ }
++
++#ifdef CHECK_TRANSMIT_TIMEOUT
++// if (!timer_pending(&pNet->KernelTimer)) {
++ pNet->KernelTimer.expires = jiffies + (HZ/10); /* 100ms */
++ add_timer(&pNet->KernelTimer);
++ pNet->TimerExpired = SK_FALSE;
++// }
++#endif
++ }
++}
++
++
++/*****************************************************************************
++*
++* CheckRXCounters - Checks the the statistics for RX path hang
++*
++* Description:
++* This function is called periodical by a timer.
++*
++* Notes:
++*
++* Function Parameters:
++*
++* Returns:
++* Traffic status
++*
++*/
++static SK_BOOL CheckRXCounters(
++DEV_NET *pNet) /* holds the pointer to adapter control context */
++{
++ SK_AC *pAC = pNet->pAC;
++ SK_BOOL bStatus = SK_FALSE;
++
++ /* Variable used to store the MAC RX FIFO RP, RPLev*/
++ SK_U32 MACFifoRP = 0;
++ SK_U32 MACFifoRLev = 0;
++
++ /* Variable used to store the PCI RX FIFO RP, RPLev*/
++ SK_U32 RXFifoRP = 0;
++ SK_U8 RXFifoRLev = 0;
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,
++ ("==> CheckRXCounters()\n"));
++
++ /*Check if statistic counters hangs*/
++ if (pNet->LastJiffies == pAC->dev[pNet->PortNr]->last_rx) {
++
++ /*Now read the values of read pointer/level from MAC RX FIFO*/
++ SK_IN32(pAC->IoBase, MR_ADDR(pNet->PortNr, RX_GMF_RP), &MACFifoRP);
++ SK_IN32(pAC->IoBase, MR_ADDR(pNet->PortNr, RX_GMF_RLEV), &MACFifoRLev);
++
++ /*Now read the values of read pointer/level from RX FIFO*/
++ SK_IN8(pAC->IoBase, Q_ADDR(pAC->GIni.GP[pNet->PortNr].PRxQOff, Q_RP), &RXFifoRP);
++ SK_IN8(pAC->IoBase, Q_ADDR(pAC->GIni.GP[pNet->PortNr].PRxQOff, Q_RL), &RXFifoRLev);
++
++ /*Check if the MAC RX hang */
++ if ((MACFifoRP == pNet->PreviousMACFifoRP) &&
++ (MACFifoRLev != 0) &&
++ (MACFifoRLev >= pNet->PreviousMACFifoRLev)){
++ bStatus = SK_TRUE;
++ }
++
++ /*Check if the PCI RX hang */
++ if ((RXFifoRP == pNet->PreviousRXFifoRP) &&
++ (RXFifoRLev != 0) &&
++ (pNet->PreviousRXFifoRLev != 0) &&
++ (RXFifoRLev >= pNet->PreviousRXFifoRLev)){
++
++ /*Set the flag to indicate that the RX FIFO hangs*/
++ bStatus = SK_TRUE;
++ }
++ }
++
++ /* Store now the values of counters for next check */
++ pNet->LastJiffies = pAC->dev[pNet->PortNr]->last_rx;
++
++ /* Store the values of read pointer/level from MAC RX FIFO for next test */
++ pNet->PreviousMACFifoRP = MACFifoRP;
++ pNet->PreviousMACFifoRLev = MACFifoRLev;
++
++ /* Store the values of read pointer/level from RX FIFO for next test */
++ pNet->PreviousRXFifoRP = RXFifoRP;
++ pNet->PreviousRXFifoRLev = RXFifoRLev;
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,
++ ("<== CheckRXCounters()\n"));
++
++ return bStatus;
++}
++
++/*****************************************************************************
++*
++* CheckForRXHang - Checks if the RX path hangs
++*
++* Description:
++* This function is called periodical by a timer.
++*
++* Notes:
++*
++* Function Parameters:
++*
++* Returns:
++* None.
++*
++*/
++static void CheckForRXHang(
++DEV_NET *pNet) /* holds the pointer to adapter control context */
++{
++ unsigned long Flags; /* for the spin locks */
++ /* Initialize the pAC structure.*/
++ SK_AC *pAC = pNet->pAC;
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,
++ ("==> CheckRXCounters()\n"));
++
++ /*If the statistics are not changed then could be an RX hang*/
++ if (CheckRXCounters(pNet)){
++ /*
++ * So here we don't know yet which RX Hang occured.
++ * First we try the simple solution by resetting the Level Timer
++ */
++
++ /* Stop Level Timer of Status BMU */
++ SK_OUT8(pAC->IoBase, STAT_LEV_TIMER_CTRL, TIM_STOP);
++
++ /* Start Level Timer of Status BMU */
++ SK_OUT8(pAC->IoBase, STAT_LEV_TIMER_CTRL, TIM_START);
++
++ if (!CheckRXCounters(pNet)) {
++ return;
++ }
++
++ spin_lock_irqsave(&pAC->SlowPathLock, Flags);
++ SkLocalEventQueue(pAC, SKGE_DRV,
++ SK_DRV_RECOVER,pNet->PortNr,-1,SK_TRUE);
++
++ /* Reset the fifo counters */
++ pNet->PreviousMACFifoRP = 0;
++ pNet->PreviousMACFifoRLev = 0;
++ pNet->PreviousRXFifoRP = 0;
++ pNet->PreviousRXFifoRLev = 0;
++
++ spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
++ }
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,
++ ("<== CheckForRXHang()\n"));
++}
++
++
++
++#endif
++
++
++#ifdef CONFIG_PM
++/*****************************************************************************
++ *
++ * sk98lin_resume - Resume the the card
++ *
++ * Description:
++ * This function resumes the card into the D0 state
++ *
++ * Returns: N/A
++ *
++ */
++static int sk98lin_resume(
++struct pci_dev *pdev) /* the device that is to resume */
++{
++ struct net_device *dev = pci_get_drvdata(pdev);
++ DEV_NET *pNet = (DEV_NET*) dev->priv;
++ SK_AC *pAC = pNet->pAC;
++ SK_U16 PmCtlSts;
++
++ /* Set the power state to D0 */
++ pci_set_power_state(pdev, 0);
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9)
++ pci_restore_state(pdev);
++#else
++ pci_restore_state(pdev, pAC->PciState);
++#endif
++
++ /* Set the adapter power state to D0 */
++ SkPciReadCfgWord(pAC, PCI_PM_CTL_STS, &PmCtlSts);
++ PmCtlSts &= ~(PCI_PM_STATE_D3); /* reset all DState bits */
++ PmCtlSts |= PCI_PM_STATE_D0;
++ SkPciWriteCfgWord(pAC, PCI_PM_CTL_STS, PmCtlSts);
++
++ /* Reinit the adapter and start the port again */
++ pAC->BoardLevel = SK_INIT_DATA;
++ SkDrvLeaveDiagMode(pAC);
++
++ netif_device_attach(dev);
++ netif_start_queue(dev);
++ return 0;
++}
++
++/*****************************************************************************
++ *
++ * sk98lin_suspend - Suspend the card
++ *
++ * Description:
++ * This function suspends the card into a defined state
++ *
++ * Returns: N/A
++ *
++ */
++static int sk98lin_suspend(
++struct pci_dev *pdev, /* pointer to the device that is to suspend */
++u32 state) /* what power state is desired by Linux? */
++{
++ struct net_device *dev = pci_get_drvdata(pdev);
++ DEV_NET *pNet = (DEV_NET*) dev->priv;
++ SK_AC *pAC = pNet->pAC;
++ SK_U16 PciPMControlStatus;
++ SK_U16 PciPMCapabilities;
++ SK_MAC_ADDR MacAddr;
++ int i;
++
++ /* GEnesis and first yukon revs do not support power management */
++ if (pAC->GIni.GIChipId == CHIP_ID_YUKON) {
++ if (pAC->GIni.GIChipRev == 0) {
++ return 0; /* power management not supported */
++ }
++ }
++
++ if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
++ return 0; /* not supported for this chipset */
++ }
++
++ if (pAC->WolInfo.ConfiguredWolOptions == 0) {
++ return 0; /* WOL possible, but disabled via ethtool */
++ }
++
++ if(netif_running(dev)) {
++ netif_stop_queue(dev); /* stop device if running */
++ }
++
++ netif_device_detach(dev);
++
++ /* read the PM control/status register from the PCI config space */
++ SK_IN16(pAC->IoBase, PCI_C(pAC, PCI_PM_CTL_STS), &PciPMControlStatus);
++
++ /* read the power management capabilities from the config space */
++ SK_IN16(pAC->IoBase, PCI_C(pAC, PCI_PM_CAP_REG), &PciPMCapabilities);
++
++ /* Enable WakeUp with Magic Packet - get MAC address from adapter */
++ for (i = 0; i < SK_MAC_ADDR_LEN; i++) {
++ /* virtual address: will be used for data */
++ SK_IN8(pAC->IoBase, (B2_MAC_1 + i), &MacAddr.a[i]);
++ }
++
++ SkDrvEnterDiagMode(pAC);
++ SkEnableWOMagicPacket(pAC, pAC->IoBase, MacAddr);
++
++ pci_enable_wake(pdev, 3, 1);
++ pci_enable_wake(pdev, 4, 1); /* 4 == D3 cold */
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9)
++ pci_save_state(pdev);
++#else
++ pci_save_state(pdev, pAC->PciState);
++#endif
++ pci_set_power_state(pdev, state); /* set the state */
++
++ return 0;
++}
++
++
++/******************************************************************************
++ *
++ * SkEnableWOMagicPacket - Enable Wake on Magic Packet on the adapter
++ *
++ * Context:
++ * init, pageable
++ * the adapter should be de-initialized before calling this function
++ *
++ * Returns:
++ * nothing
++ */
++
++static void SkEnableWOMagicPacket(
++SK_AC *pAC, /* Adapter Control Context */
++SK_IOC IoC, /* I/O control context */
++SK_MAC_ADDR MacAddr) /* MacAddr expected in magic packet */
++{
++ SK_U16 Word;
++ SK_U32 DWord;
++ int i;
++ int HwPortIndex;
++ int Port = 0;
++
++ /* use Port 0 as long as we do not have any dual port cards which support WOL */
++ HwPortIndex = 0;
++ DWord = 0;
++
++ SK_OUT16(IoC, 0x0004, 0x0002); /* clear S/W Reset */
++ SK_OUT16(IoC, 0x0f10, 0x0002); /* clear Link Reset */
++
++ /*
++ * PHY Configuration:
++ * Autonegotioation is enalbed, advertise 10 HD, 10 FD,
++ * 100 HD, and 100 FD.
++ */
++ if ((pAC->GIni.GIChipId == CHIP_ID_YUKON_EC) ||
++ (pAC->GIni.GIChipId == CHIP_ID_YUKON) ||
++ (pAC->GIni.GIChipId == CHIP_ID_YUKON_LITE)) {
++
++ SK_OUT16(IoC, 0x0004, 0x0800); /* enable CLK_RUN */
++ SK_OUT8(IoC, 0x0007, 0xa9); /* enable VAUX */
++
++ /* WA code for COMA mode */
++ /* Only for yukon plus based chipsets rev A3 */
++ if (pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) {
++ SK_IN32(IoC, B2_GP_IO, &DWord);
++ DWord |= GP_DIR_9; /* set to output */
++ DWord &= ~GP_IO_9; /* clear PHY reset (active high) */
++ SK_OUT32(IoC, B2_GP_IO, DWord); /* clear PHY reset */
++ }
++
++ if ((pAC->GIni.GIChipId == CHIP_ID_YUKON_LITE) ||
++ (pAC->GIni.GIChipId == CHIP_ID_YUKON)) {
++ SK_OUT32(IoC, 0x0f04, 0x01f04001); /* set PHY reset */
++ SK_OUT32(IoC, 0x0f04, 0x01f04002); /* clear PHY reset */
++ } else {
++ SK_OUT8(IoC, 0x0f04, 0x02); /* clear PHY reset */
++ }
++
++ SK_OUT8(IoC, 0x0f00, 0x02); /* clear MAC reset */
++ SkGmPhyWrite(pAC, IoC, Port, 4, 0x01e1); /* advertise 10/100 HD/FD */
++ SkGmPhyWrite(pAC, IoC, Port, 9, 0x0000); /* do not advertise 1000 HD/FD */
++ SkGmPhyWrite(pAC, IoC, Port, 00, 0xB300); /* 100 MBit, disable Autoneg */
++ } else if (pAC->GIni.GIChipId == CHIP_ID_YUKON_FE) {
++ SK_OUT8(IoC, 0x0007, 0xa9); /* enable VAUX */
++ SK_OUT8(IoC, 0x0f04, 0x02); /* clear PHY reset */
++ SK_OUT8(IoC, 0x0f00, 0x02); /* clear MAC reset */
++ SkGmPhyWrite(pAC, IoC, Port, 16, 0x0130); /* Enable Automatic Crossover */
++ SkGmPhyWrite(pAC, IoC, Port, 00, 0xB300); /* 100 MBit, disable Autoneg */
++ }
++
++
++ /*
++ * MAC Configuration:
++ * Set the MAC to 100 HD and enable the auto update features
++ * for Speed, Flow Control and Duplex Mode.
++ * If autonegotiation completes successfully the
++ * MAC takes the link parameters from the PHY.
++ * If the link partner doesn't support autonegotiation
++ * the MAC can receive magic packets if the link partner
++ * uses 100 HD.
++ */
++ SK_OUT16(IoC, 0x2804, 0x3832);
++
++
++ /*
++ * Set Up Magic Packet parameters
++ */
++ for (i = 0; i < 6; i+=2) { /* set up magic packet MAC address */
++ SK_IN16(IoC, 0x100 + i, &Word);
++ SK_OUT16(IoC, 0xf24 + i, Word);
++ }
++
++ SK_OUT16(IoC, 0x0f20, 0x0208); /* enable PME on magic packet */
++ /* and on wake up frame */
++
++ /*
++ * Set up PME generation
++ */
++ /* set PME legacy mode */
++ /* Only for PCI express based chipsets */
++ if ((pAC->GIni.GIChipId == CHIP_ID_YUKON_EC) ||
++ (pAC->GIni.GIChipId == CHIP_ID_YUKON_FE)) {
++ SkPciReadCfgDWord(pAC, 0x40, &DWord);
++ DWord |= 0x8000;
++ SkPciWriteCfgDWord(pAC, 0x40, DWord);
++ }
++
++ /* clear PME status and switch adapter to DState */
++ SkPciReadCfgWord(pAC, 0x4c, &Word);
++ Word |= 0x103;
++ SkPciWriteCfgWord(pAC, 0x4c, Word);
++} /* SkEnableWOMagicPacket */
++#endif
++
+
+ /*****************************************************************************
+ *
+@@ -643,7 +1176,9 @@
+ if (pAC->IoBase) {
+ iounmap(pAC->IoBase);
+ }
+- if (pAC->pDescrMem) {
++ if (CHIP_ID_YUKON_2(pAC)) {
++ SkY2FreeResources(pAC);
++ } else {
+ BoardFreeMem(pAC);
+ }
+ }
+@@ -653,28 +1188,6 @@
+ MODULE_AUTHOR("Mirko Lindner <mlindner@syskonnect.de>");
+ MODULE_DESCRIPTION("SysKonnect SK-NET Gigabit Ethernet SK-98xx driver");
+ MODULE_LICENSE("GPL");
+-MODULE_PARM(Speed_A, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
+-MODULE_PARM(Speed_B, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
+-MODULE_PARM(AutoNeg_A, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
+-MODULE_PARM(AutoNeg_B, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
+-MODULE_PARM(DupCap_A, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
+-MODULE_PARM(DupCap_B, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
+-MODULE_PARM(FlowCtrl_A, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
+-MODULE_PARM(FlowCtrl_B, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
+-MODULE_PARM(Role_A, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
+-MODULE_PARM(Role_B, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
+-MODULE_PARM(ConType, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
+-MODULE_PARM(PrefPort, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
+-MODULE_PARM(RlmtMode, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
+-/* not used, just there because every driver should have them: */
+-MODULE_PARM(options, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "i");
+-MODULE_PARM(debug, "i");
+-/* used for interrupt moderation */
+-MODULE_PARM(IntsPerSec, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "i");
+-MODULE_PARM(Moderation, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
+-MODULE_PARM(Stats, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
+-MODULE_PARM(ModerationMask, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
+-MODULE_PARM(AutoSizing, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
+
+
+ #ifdef LINK_SPEED_A
+@@ -755,47 +1268,55 @@
+ static char *RlmtMode[SK_MAX_CARD_PARAM] = {"", };
+ #endif
+
+-static int debug = 0; /* not used */
+-static int options[SK_MAX_CARD_PARAM] = {0, }; /* not used */
+-
+ static int IntsPerSec[SK_MAX_CARD_PARAM];
+ static char *Moderation[SK_MAX_CARD_PARAM];
+ static char *ModerationMask[SK_MAX_CARD_PARAM];
+-static char *AutoSizing[SK_MAX_CARD_PARAM];
+-static char *Stats[SK_MAX_CARD_PARAM];
+-
+-
+-/*****************************************************************************
+- *
+- * skge_init_module - module initialization function
+- *
+- * Description:
+- * Very simple, only call skge_probe and return approriate result.
+- *
+- * Returns:
+- * 0, if everything is ok
+- * !=0, on error
+- */
+-static int __init skge_init_module(void)
+-{
+- int cards;
+- SkGeRootDev = NULL;
+-
+- /* just to avoid warnings ... */
+- debug = 0;
+- options[0] = 0;
+
+- cards = skge_probe();
+- if (cards == 0) {
+- printk("sk98lin: No adapter found.\n");
+- }
+- return cards ? 0 : -ENODEV;
+-} /* skge_init_module */
++static char *LowLatency[SK_MAX_CARD_PARAM];
++
++#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,9)
++module_param_array(Speed_A, charp, NULL, 0);
++module_param_array(Speed_B, charp, NULL, 0);
++module_param_array(AutoNeg_A, charp, NULL, 0);
++module_param_array(AutoNeg_B, charp, NULL, 0);
++module_param_array(DupCap_A, charp, NULL, 0);
++module_param_array(DupCap_B, charp, NULL, 0);
++module_param_array(FlowCtrl_A, charp, NULL, 0);
++module_param_array(FlowCtrl_B, charp, NULL, 0);
++module_param_array(Role_A, charp, NULL, 0);
++module_param_array(Role_B, charp, NULL, 0);
++module_param_array(ConType, charp, NULL, 0);
++module_param_array(PrefPort, charp, NULL, 0);
++module_param_array(RlmtMode, charp, NULL, 0);
++/* used for interrupt moderation */
++module_param_array(IntsPerSec, int, NULL, 0);
++module_param_array(Moderation, charp, NULL, 0);
++module_param_array(ModerationMask, charp, NULL, 0);
++module_param_array(LowLatency, charp, NULL, 0);
++#else
++MODULE_PARM(Speed_A, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
++MODULE_PARM(Speed_B, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
++MODULE_PARM(AutoNeg_A, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
++MODULE_PARM(AutoNeg_B, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
++MODULE_PARM(DupCap_A, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
++MODULE_PARM(DupCap_B, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
++MODULE_PARM(FlowCtrl_A, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
++MODULE_PARM(FlowCtrl_B, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
++MODULE_PARM(Role_A, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
++MODULE_PARM(Role_B, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
++MODULE_PARM(ConType, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
++MODULE_PARM(PrefPort, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
++MODULE_PARM(RlmtMode, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
++MODULE_PARM(IntsPerSec, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "i");
++MODULE_PARM(Moderation, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
++MODULE_PARM(ModerationMask, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
++MODULE_PARM(LowLatency, "1-" __MODULE_STRING(SK_MAX_CARD_PARAM) "s");
++#endif
+
+
+ /*****************************************************************************
+ *
+- * skge_cleanup_module - module unload function
++ * sk98lin_remove_device - device deinit function
+ *
+ * Description:
+ * Disable adapter if it is still running, free resources,
+@@ -803,73 +1324,83 @@
+ *
+ * Returns: N/A
+ */
+-static void __exit skge_cleanup_module(void)
++
++static void sk98lin_remove_device(struct pci_dev *pdev)
+ {
+ DEV_NET *pNet;
+ SK_AC *pAC;
+ struct SK_NET_DEVICE *next;
+ unsigned long Flags;
+-SK_EVPARA EvPara;
++struct net_device *dev = pci_get_drvdata(pdev);
+
+- while (SkGeRootDev) {
+- pNet = (DEV_NET*) SkGeRootDev->priv;
+- pAC = pNet->pAC;
+- next = pAC->Next;
+
+- netif_stop_queue(SkGeRootDev);
+- SkGeYellowLED(pAC, pAC->IoBase, 0);
++ /* Device not available. Return. */
++ if (!dev)
++ return;
++
++ pNet = (DEV_NET*) dev->priv;
++ pAC = pNet->pAC;
++ next = pAC->Next;
+
+- if(pAC->BoardLevel == SK_INIT_RUN) {
+- /* board is still alive */
+- spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+- EvPara.Para32[0] = 0;
+- EvPara.Para32[1] = -1;
+- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
+- EvPara.Para32[0] = 1;
+- EvPara.Para32[1] = -1;
+- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
+- SkEventDispatcher(pAC, pAC->IoBase);
+- /* disable interrupts */
+- SK_OUT32(pAC->IoBase, B0_IMSK, 0);
+- SkGeDeInit(pAC, pAC->IoBase);
+- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+- pAC->BoardLevel = SK_INIT_DATA;
+- /* We do NOT check here, if IRQ was pending, of course*/
+- }
+-
+- if(pAC->BoardLevel == SK_INIT_IO) {
+- /* board is still alive */
+- SkGeDeInit(pAC, pAC->IoBase);
+- pAC->BoardLevel = SK_INIT_DATA;
+- }
+-
+- if ((pAC->GIni.GIMacsFound == 2) && pAC->RlmtNets == 2){
+- unregister_netdev(pAC->dev[1]);
+- free_netdev(pAC->dev[1]);
+- }
++ netif_stop_queue(dev);
++ SkGeYellowLED(pAC, pAC->IoBase, 0);
+
+- FreeResources(SkGeRootDev);
++ if(pAC->BoardLevel == SK_INIT_RUN) {
++ /* board is still alive */
++ spin_lock_irqsave(&pAC->SlowPathLock, Flags);
++ SkLocalEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP,
++ 0, -1, SK_FALSE);
++ SkLocalEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP,
++ 1, -1, SK_TRUE);
+
+- SkGeRootDev->get_stats = NULL;
+- /*
+- * otherwise unregister_netdev calls get_stats with
+- * invalid IO ... :-(
+- */
+- unregister_netdev(SkGeRootDev);
+- free_netdev(SkGeRootDev);
+- kfree(pAC);
+- SkGeRootDev = next;
++ /* disable interrupts */
++ SK_OUT32(pAC->IoBase, B0_IMSK, 0);
++ SkGeDeInit(pAC, pAC->IoBase);
++ spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
++ pAC->BoardLevel = SK_INIT_DATA;
++ /* We do NOT check here, if IRQ was pending, of course*/
++ }
++
++ if(pAC->BoardLevel == SK_INIT_IO) {
++ /* board is still alive */
++ SkGeDeInit(pAC, pAC->IoBase);
++ pAC->BoardLevel = SK_INIT_DATA;
++ }
++
++ if ((pAC->GIni.GIMacsFound == 2) && pAC->RlmtNets == 2){
++ unregister_netdev(pAC->dev[1]);
++ free_netdev(pAC->dev[1]);
+ }
+
++ FreeResources(dev);
++
+ #ifdef CONFIG_PROC_FS
+- /* clear proc-dir */
+- remove_proc_entry(pSkRootDir->name, proc_net);
++ /* Remove the sk98lin procfs device entries */
++ if ((pAC->GIni.GIMacsFound == 2) && pAC->RlmtNets == 2){
++ remove_proc_entry(pAC->dev[1]->name, pSkRootDir);
++ }
++ remove_proc_entry(pNet->InitialDevName, pSkRootDir);
+ #endif
+
+-} /* skge_cleanup_module */
++ dev->get_stats = NULL;
++ /*
++ * otherwise unregister_netdev calls get_stats with
++ * invalid IO ... :-(
++ */
++ unregister_netdev(dev);
++ free_netdev(dev);
++ kfree(pAC);
++ sk98lin_max_boards_found--;
++
++#ifdef CONFIG_PROC_FS
++ /* Remove all Proc entries if last device */
++ if (sk98lin_max_boards_found == 0) {
++ /* clear proc-dir */
++ remove_proc_entry(pSkRootDir->name, proc_net);
++ }
++#endif
+
+-module_init(skge_init_module);
+-module_exit(skge_cleanup_module);
++}
+
+
+ /*****************************************************************************
+@@ -908,7 +1439,10 @@
+ spin_lock_init(&pAC->TxPort[i][0].TxDesRingLock);
+ spin_lock_init(&pAC->RxPort[i].RxDesRingLock);
+ }
++
+ spin_lock_init(&pAC->SlowPathLock);
++ spin_lock_init(&pAC->TxQueueLock); /* for Yukon2 chipsets */
++ spin_lock_init(&pAC->SetPutIndexLock); /* for Yukon2 chipsets */
+
+ /* level 0 init common modules here */
+
+@@ -927,15 +1461,13 @@
+ SkTimerInit(pAC, pAC->IoBase, SK_INIT_DATA);
+
+ pAC->BoardLevel = SK_INIT_DATA;
+- pAC->RxBufSize = ETH_BUF_SIZE;
++ pAC->RxPort[0].RxBufSize = ETH_BUF_SIZE;
++ pAC->RxPort[1].RxBufSize = ETH_BUF_SIZE;
+
+ SK_PNMI_SET_DRIVER_DESCR(pAC, DescrString);
+ SK_PNMI_SET_DRIVER_VER(pAC, VerStr);
+
+- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+-
+ /* level 1 init common modules here (HW init) */
+- spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+ if (SkGeInit(pAC, pAC->IoBase, SK_INIT_IO) != 0) {
+ printk("sk98lin: HWInit (1) failed.\n");
+ spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+@@ -947,51 +1479,93 @@
+ SkAddrInit( pAC, pAC->IoBase, SK_INIT_IO);
+ SkRlmtInit( pAC, pAC->IoBase, SK_INIT_IO);
+ SkTimerInit(pAC, pAC->IoBase, SK_INIT_IO);
++#ifdef Y2_RECOVERY
++ /* mark entries invalid */
++ pAC->LastPort = 3;
++ pAC->LastOpc = 0xFF;
++#endif
+
+ /* Set chipset type support */
+- pAC->ChipsetType = 0;
+ if ((pAC->GIni.GIChipId == CHIP_ID_YUKON) ||
+- (pAC->GIni.GIChipId == CHIP_ID_YUKON_LITE)) {
+- pAC->ChipsetType = 1;
++ (pAC->GIni.GIChipId == CHIP_ID_YUKON_LITE) ||
++ (pAC->GIni.GIChipId == CHIP_ID_YUKON_LP)) {
++ pAC->ChipsetType = 1; /* Yukon chipset (descriptor logic) */
++ } else if (CHIP_ID_YUKON_2(pAC)) {
++ pAC->ChipsetType = 2; /* Yukon2 chipset (list logic) */
++ } else {
++ pAC->ChipsetType = 0; /* Genesis chipset (descriptor logic) */
++ }
++
++ /* wake on lan support */
++ pAC->WolInfo.SupportedWolOptions = 0;
++#if defined (ETHTOOL_GWOL) && defined (ETHTOOL_SWOL)
++ if (pAC->GIni.GIChipId != CHIP_ID_GENESIS) {
++ pAC->WolInfo.SupportedWolOptions = WAKE_MAGIC;
++ if (pAC->GIni.GIChipId == CHIP_ID_YUKON) {
++ if (pAC->GIni.GIChipRev == 0) {
++ pAC->WolInfo.SupportedWolOptions = 0;
++ }
++ }
+ }
++#endif
++ pAC->WolInfo.ConfiguredWolOptions = pAC->WolInfo.SupportedWolOptions;
+
+ GetConfiguration(pAC);
+ if (pAC->RlmtNets == 2) {
+- pAC->GIni.GIPortUsage = SK_MUL_LINK;
++ pAC->GIni.GP[0].PPortUsage = SK_MUL_LINK;
++ pAC->GIni.GP[1].PPortUsage = SK_MUL_LINK;
+ }
+
+ pAC->BoardLevel = SK_INIT_IO;
+ spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+
+- if (pAC->GIni.GIMacsFound == 2) {
+- Ret = request_irq(dev->irq, SkGeIsr, SA_SHIRQ, pAC->Name, dev);
+- } else if (pAC->GIni.GIMacsFound == 1) {
+- Ret = request_irq(dev->irq, SkGeIsrOnePort, SA_SHIRQ,
+- pAC->Name, dev);
+- } else {
+- printk(KERN_WARNING "sk98lin: Illegal number of ports: %d\n",
+- pAC->GIni.GIMacsFound);
+- return -EAGAIN;
++ if (!CHIP_ID_YUKON_2(pAC)) {
++ if (pAC->GIni.GIMacsFound == 2) {
++ Ret = request_irq(dev->irq, SkGeIsr, SA_SHIRQ, dev->name, dev);
++ } else if (pAC->GIni.GIMacsFound == 1) {
++ Ret = request_irq(dev->irq, SkGeIsrOnePort, SA_SHIRQ, dev->name, dev);
++ } else {
++ printk(KERN_WARNING "sk98lin: Illegal number of ports: %d\n",
++ pAC->GIni.GIMacsFound);
++ return -EAGAIN;
++ }
++ }
++ else {
++ Ret = request_irq(dev->irq, SkY2Isr, SA_SHIRQ, dev->name, dev);
+ }
+
+ if (Ret) {
+ printk(KERN_WARNING "sk98lin: Requested IRQ %d is busy.\n",
+- dev->irq);
++ dev->irq);
+ return -EAGAIN;
+ }
+ pAC->AllocFlag |= SK_ALLOC_IRQ;
+
+- /* Alloc memory for this board (Mem for RxD/TxD) : */
+- if(!BoardAllocMem(pAC)) {
+- printk("No memory for descriptor rings.\n");
+- return(-EAGAIN);
++ /*
++ ** Alloc descriptor/LETable memory for this board (both RxD/TxD)
++ */
++ if (CHIP_ID_YUKON_2(pAC)) {
++ if (!SkY2AllocateResources(pAC)) {
++ printk("No memory for Yukon2 settings\n");
++ return(-EAGAIN);
++ }
++ } else {
++ if(!BoardAllocMem(pAC)) {
++ printk("No memory for descriptor rings.\n");
++ return(-EAGAIN);
++ }
+ }
+
++#ifdef SK_USE_CSUM
+ SkCsSetReceiveFlags(pAC,
+ SKCS_PROTO_IP | SKCS_PROTO_TCP | SKCS_PROTO_UDP,
+ &pAC->CsOfs1, &pAC->CsOfs2, 0);
+ pAC->CsOfs = (pAC->CsOfs2 << 16) | pAC->CsOfs1;
++#endif
+
++ /*
++ ** Function BoardInitMem() for Yukon dependent settings...
++ */
+ BoardInitMem(pAC);
+ /* tschilling: New common function with minimum size check. */
+ DualNet = SK_FALSE;
+@@ -1003,7 +1577,12 @@
+ pAC,
+ pAC->ActivePort,
+ DualNet)) {
+- BoardFreeMem(pAC);
++ if (CHIP_ID_YUKON_2(pAC)) {
++ SkY2FreeResources(pAC);
++ } else {
++ BoardFreeMem(pAC);
++ }
++
+ printk("sk98lin: SkGeInitAssignRamToQueues failed.\n");
+ return(-EAGAIN);
+ }
+@@ -1103,16 +1682,20 @@
+
+ SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+ ("BoardFreeMem\n"));
++
++ if (pAC->pDescrMem) {
++
+ #if (BITS_PER_LONG == 32)
+- AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound + 8;
++ AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound + 8;
+ #else
+- AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound
+- + RX_RING_SIZE + 8;
++ AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound
++ + RX_RING_SIZE + 8;
+ #endif
+
+- pci_free_consistent(pAC->PciDev, AllocLength,
++ pci_free_consistent(pAC->PciDev, AllocLength,
+ pAC->pDescrMem, pAC->pDescrMemDMA);
+- pAC->pDescrMem = NULL;
++ pAC->pDescrMem = NULL;
++ }
+ } /* BoardFreeMem */
+
+
+@@ -1121,7 +1704,7 @@
+ * BoardInitMem - initiate the descriptor rings
+ *
+ * Description:
+- * This function sets the descriptor rings up in memory.
++ * This function sets the descriptor rings or LETables up in memory.
+ * The adapter is initialized with the descriptor start addresses.
+ *
+ * Returns: N/A
+@@ -1136,34 +1719,37 @@
+ SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+ ("BoardInitMem\n"));
+
+- RxDescrSize = (((sizeof(RXD) - 1) / DESCR_ALIGN) + 1) * DESCR_ALIGN;
+- pAC->RxDescrPerRing = RX_RING_SIZE / RxDescrSize;
+- TxDescrSize = (((sizeof(TXD) - 1) / DESCR_ALIGN) + 1) * DESCR_ALIGN;
+- pAC->TxDescrPerRing = TX_RING_SIZE / RxDescrSize;
++ if (!pAC->GIni.GIYukon2) {
++ RxDescrSize = (((sizeof(RXD) - 1) / DESCR_ALIGN) + 1) * DESCR_ALIGN;
++ pAC->RxDescrPerRing = RX_RING_SIZE / RxDescrSize;
++ TxDescrSize = (((sizeof(TXD) - 1) / DESCR_ALIGN) + 1) * DESCR_ALIGN;
++ pAC->TxDescrPerRing = TX_RING_SIZE / RxDescrSize;
+
+- for (i=0; i<pAC->GIni.GIMacsFound; i++) {
+- SetupRing(
+- pAC,
+- pAC->TxPort[i][0].pTxDescrRing,
+- pAC->TxPort[i][0].VTxDescrRing,
+- (RXD**)&pAC->TxPort[i][0].pTxdRingHead,
+- (RXD**)&pAC->TxPort[i][0].pTxdRingTail,
+- (RXD**)&pAC->TxPort[i][0].pTxdRingPrev,
+- &pAC->TxPort[i][0].TxdRingFree,
+- SK_TRUE);
+- SetupRing(
+- pAC,
+- pAC->RxPort[i].pRxDescrRing,
+- pAC->RxPort[i].VRxDescrRing,
+- &pAC->RxPort[i].pRxdRingHead,
+- &pAC->RxPort[i].pRxdRingTail,
+- &pAC->RxPort[i].pRxdRingPrev,
+- &pAC->RxPort[i].RxdRingFree,
+- SK_FALSE);
++ for (i=0; i<pAC->GIni.GIMacsFound; i++) {
++ SetupRing(
++ pAC,
++ pAC->TxPort[i][0].pTxDescrRing,
++ pAC->TxPort[i][0].VTxDescrRing,
++ (RXD**)&pAC->TxPort[i][0].pTxdRingHead,
++ (RXD**)&pAC->TxPort[i][0].pTxdRingTail,
++ (RXD**)&pAC->TxPort[i][0].pTxdRingPrev,
++ &pAC->TxPort[i][0].TxdRingFree,
++ &pAC->TxPort[i][0].TxdRingPrevFree,
++ SK_TRUE);
++ SetupRing(
++ pAC,
++ pAC->RxPort[i].pRxDescrRing,
++ pAC->RxPort[i].VRxDescrRing,
++ &pAC->RxPort[i].pRxdRingHead,
++ &pAC->RxPort[i].pRxdRingTail,
++ &pAC->RxPort[i].pRxdRingPrev,
++ &pAC->RxPort[i].RxdRingFree,
++ &pAC->RxPort[i].RxdRingFree,
++ SK_FALSE);
++ }
+ }
+ } /* BoardInitMem */
+
+-
+ /*****************************************************************************
+ *
+ * SetupRing - create one descriptor ring
+@@ -1183,6 +1769,7 @@
+ RXD **ppRingTail, /* address where the tail should be written */
+ RXD **ppRingPrev, /* address where the tail should be written */
+ int *pRingFree, /* address where the # of free descr. goes */
++int *pRingPrevFree, /* address where the # of free descr. goes */
+ SK_BOOL IsTx) /* flag: is this a tx ring */
+ {
+ int i; /* loop counter */
+@@ -1225,11 +1812,12 @@
+ }
+ pPrevDescr->pNextRxd = (RXD*) pMemArea;
+ pPrevDescr->VNextRxd = VMemArea;
+- pDescr = (RXD*) pMemArea;
+- *ppRingHead = (RXD*) pMemArea;
+- *ppRingTail = *ppRingHead;
+- *ppRingPrev = pPrevDescr;
+- *pRingFree = DescrNum;
++ pDescr = (RXD*) pMemArea;
++ *ppRingHead = (RXD*) pMemArea;
++ *ppRingTail = *ppRingHead;
++ *ppRingPrev = pPrevDescr;
++ *pRingFree = DescrNum;
++ *pRingPrevFree = DescrNum;
+ } /* SetupRing */
+
+
+@@ -1301,10 +1889,28 @@
+ * Check and process if its our interrupt
+ */
+ SK_IN32(pAC->IoBase, B0_SP_ISRC, &IntSrc);
+- if (IntSrc == 0) {
++ if ((IntSrc == 0) && (!pNet->NetConsoleMode)) {
+ return SkIsrRetNone;
+ }
+
++#ifdef CONFIG_SK98LIN_NAPI
++ if (netif_rx_schedule_prep(dev)) {
++ pAC->GIni.GIValIrqMask &= ~(NAPI_DRV_IRQS);
++ SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask);
++ __netif_rx_schedule(dev);
++ }
++
++#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
++ if (IntSrc & IS_XA1_F) {
++ CLEAR_TX_IRQ(0, TX_PRIO_LOW);
++ }
++ if (IntSrc & IS_XA2_F) {
++ CLEAR_TX_IRQ(1, TX_PRIO_LOW);
++ }
++#endif
++
++
++#else
+ while (((IntSrc & IRQ_MASK) & ~SPECIAL_IRQS) != 0) {
+ #if 0 /* software irq currently not used */
+ if (IntSrc & IS_IRQ_SW) {
+@@ -1318,6 +1924,7 @@
+ SK_DBGCAT_DRV_INT_SRC,
+ ("EOF RX1 IRQ\n"));
+ ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE);
++ CLEAR_AND_START_RX(0);
+ SK_PNMI_CNT_RX_INTR(pAC, 0);
+ }
+ if (IntSrc & IS_R2_F) {
+@@ -1325,6 +1932,7 @@
+ SK_DBGCAT_DRV_INT_SRC,
+ ("EOF RX2 IRQ\n"));
+ ReceiveIrq(pAC, &pAC->RxPort[1], SK_TRUE);
++ CLEAR_AND_START_RX(1);
+ SK_PNMI_CNT_RX_INTR(pAC, 1);
+ }
+ #ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
+@@ -1332,6 +1940,7 @@
+ SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+ SK_DBGCAT_DRV_INT_SRC,
+ ("EOF AS TX1 IRQ\n"));
++ CLEAR_TX_IRQ(0, TX_PRIO_LOW);
+ SK_PNMI_CNT_TX_INTR(pAC, 0);
+ spin_lock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
+ FreeTxDescriptors(pAC, &pAC->TxPort[0][TX_PRIO_LOW]);
+@@ -1341,6 +1950,7 @@
+ SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+ SK_DBGCAT_DRV_INT_SRC,
+ ("EOF AS TX2 IRQ\n"));
++ CLEAR_TX_IRQ(1, TX_PRIO_LOW);
+ SK_PNMI_CNT_TX_INTR(pAC, 1);
+ spin_lock(&pAC->TxPort[1][TX_PRIO_LOW].TxDesRingLock);
+ FreeTxDescriptors(pAC, &pAC->TxPort[1][TX_PRIO_LOW]);
+@@ -1351,38 +1961,28 @@
+ SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+ SK_DBGCAT_DRV_INT_SRC,
+ ("EOF SY TX1 IRQ\n"));
++ CLEAR_TX_IRQ(0, TX_PRIO_HIGH);
+ SK_PNMI_CNT_TX_INTR(pAC, 1);
+ spin_lock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
+ FreeTxDescriptors(pAC, 0, TX_PRIO_HIGH);
+ spin_unlock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
+- ClearTxIrq(pAC, 0, TX_PRIO_HIGH);
+ }
+ if (IntSrc & IS_XS2_F) {
+ SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+ SK_DBGCAT_DRV_INT_SRC,
+ ("EOF SY TX2 IRQ\n"));
++ CLEAR_TX_IRQ(1, TX_PRIO_HIGH);
+ SK_PNMI_CNT_TX_INTR(pAC, 1);
+ spin_lock(&pAC->TxPort[1][TX_PRIO_HIGH].TxDesRingLock);
+ FreeTxDescriptors(pAC, 1, TX_PRIO_HIGH);
+ spin_unlock(&pAC->TxPort[1][TX_PRIO_HIGH].TxDesRingLock);
+- ClearTxIrq(pAC, 1, TX_PRIO_HIGH);
+ }
+ #endif
+ #endif
+
+- /* do all IO at once */
+- if (IntSrc & IS_R1_F)
+- ClearAndStartRx(pAC, 0);
+- if (IntSrc & IS_R2_F)
+- ClearAndStartRx(pAC, 1);
+-#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
+- if (IntSrc & IS_XA1_F)
+- ClearTxIrq(pAC, 0, TX_PRIO_LOW);
+- if (IntSrc & IS_XA2_F)
+- ClearTxIrq(pAC, 1, TX_PRIO_LOW);
+-#endif
+ SK_IN32(pAC->IoBase, B0_ISRC, &IntSrc);
+ } /* while (IntSrc & IRQ_MASK != 0) */
++#endif
+
+ IntSrc &= pAC->GIni.GIValIrqMask;
+ if ((IntSrc & SPECIAL_IRQS) || pAC->CheckQueue) {
+@@ -1396,18 +1996,12 @@
+ SkEventDispatcher(pAC, pAC->IoBase);
+ spin_unlock(&pAC->SlowPathLock);
+ }
+- /*
+- * do it all again is case we cleared an interrupt that
+- * came in after handling the ring (OUTs may be delayed
+- * in hardware buffers, but are through after IN)
+- *
+- * rroesler: has been commented out and shifted to
+- * SkGeDrvEvent(), because it is timer
+- * guarded now
+- *
++
++#ifndef CONFIG_SK98LIN_NAPI
++ /* Handle interrupts */
+ ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE);
+ ReceiveIrq(pAC, &pAC->RxPort[1], SK_TRUE);
+- */
++#endif
+
+ if (pAC->CheckQueue) {
+ pAC->CheckQueue = SK_FALSE;
+@@ -1450,10 +2044,25 @@
+ * Check and process if its our interrupt
+ */
+ SK_IN32(pAC->IoBase, B0_SP_ISRC, &IntSrc);
+- if (IntSrc == 0) {
++ if ((IntSrc == 0) && (!pNet->NetConsoleMode)) {
+ return SkIsrRetNone;
+ }
+
++#ifdef CONFIG_SK98LIN_NAPI
++ if (netif_rx_schedule_prep(dev)) {
++ // CLEAR_AND_START_RX(0);
++ // CLEAR_TX_IRQ(0, TX_PRIO_LOW);
++ pAC->GIni.GIValIrqMask &= ~(NAPI_DRV_IRQS);
++ SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask);
++ __netif_rx_schedule(dev);
++ }
++
++#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
++ if (IntSrc & IS_XA1_F) {
++ CLEAR_TX_IRQ(0, TX_PRIO_LOW);
++ }
++#endif
++#else
+ while (((IntSrc & IRQ_MASK) & ~SPECIAL_IRQS) != 0) {
+ #if 0 /* software irq currently not used */
+ if (IntSrc & IS_IRQ_SW) {
+@@ -1467,6 +2076,7 @@
+ SK_DBGCAT_DRV_INT_SRC,
+ ("EOF RX1 IRQ\n"));
+ ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE);
++ CLEAR_AND_START_RX(0);
+ SK_PNMI_CNT_RX_INTR(pAC, 0);
+ }
+ #ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
+@@ -1474,6 +2084,7 @@
+ SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+ SK_DBGCAT_DRV_INT_SRC,
+ ("EOF AS TX1 IRQ\n"));
++ CLEAR_TX_IRQ(0, TX_PRIO_LOW);
+ SK_PNMI_CNT_TX_INTR(pAC, 0);
+ spin_lock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
+ FreeTxDescriptors(pAC, &pAC->TxPort[0][TX_PRIO_LOW]);
+@@ -1484,24 +2095,18 @@
+ SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+ SK_DBGCAT_DRV_INT_SRC,
+ ("EOF SY TX1 IRQ\n"));
++ CLEAR_TX_IRQ(0, TX_PRIO_HIGH);
+ SK_PNMI_CNT_TX_INTR(pAC, 0);
+ spin_lock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
+ FreeTxDescriptors(pAC, 0, TX_PRIO_HIGH);
+ spin_unlock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock);
+- ClearTxIrq(pAC, 0, TX_PRIO_HIGH);
+ }
+ #endif
+ #endif
+
+- /* do all IO at once */
+- if (IntSrc & IS_R1_F)
+- ClearAndStartRx(pAC, 0);
+-#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */
+- if (IntSrc & IS_XA1_F)
+- ClearTxIrq(pAC, 0, TX_PRIO_LOW);
+-#endif
+ SK_IN32(pAC->IoBase, B0_ISRC, &IntSrc);
+ } /* while (IntSrc & IRQ_MASK != 0) */
++#endif
+
+ IntSrc &= pAC->GIni.GIValIrqMask;
+ if ((IntSrc & SPECIAL_IRQS) || pAC->CheckQueue) {
+@@ -1515,17 +2120,10 @@
+ SkEventDispatcher(pAC, pAC->IoBase);
+ spin_unlock(&pAC->SlowPathLock);
+ }
+- /*
+- * do it all again is case we cleared an interrupt that
+- * came in after handling the ring (OUTs may be delayed
+- * in hardware buffers, but are through after IN)
+- *
+- * rroesler: has been commented out and shifted to
+- * SkGeDrvEvent(), because it is timer
+- * guarded now
+- *
++
++#ifndef CONFIG_SK98LIN_NAPI
+ ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE);
+- */
++#endif
+
+ /* IRQ is processed - Enable IRQs again*/
+ SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask);
+@@ -1533,7 +2131,6 @@
+ return SkIsrRetHandled;
+ } /* SkGeIsrOnePort */
+
+-
+ /****************************************************************************
+ *
+ * SkGeOpen - handle start of initialized adapter
+@@ -1551,27 +2148,21 @@
+ * != 0 on error
+ */
+ static int SkGeOpen(
+-struct SK_NET_DEVICE *dev)
++struct SK_NET_DEVICE *dev) /* the device that is to be opened */
+ {
+- DEV_NET *pNet;
+- SK_AC *pAC;
+- unsigned long Flags; /* for spin lock */
+- int i;
+- SK_EVPARA EvPara; /* an event parameter union */
++ DEV_NET *pNet = (DEV_NET*) dev->priv;
++ SK_AC *pAC = pNet->pAC;
++ unsigned long Flags; /* for the spin locks */
++ int CurrMac; /* loop ctr for ports */
+
+- pNet = (DEV_NET*) dev->priv;
+- pAC = pNet->pAC;
+-
+ SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+ ("SkGeOpen: pAC=0x%lX:\n", (unsigned long)pAC));
+
+-#ifdef SK_DIAG_SUPPORT
+ if (pAC->DiagModeActive == DIAG_ACTIVE) {
+ if (pAC->Pnmi.DiagAttached == SK_DIAG_RUNNING) {
+ return (-1); /* still in use by diag; deny actions */
+ }
+ }
+-#endif
+
+ if (!try_module_get(THIS_MODULE)) {
+ return (-1); /* increase of usage count not possible */
+@@ -1595,6 +2186,11 @@
+ SkRlmtInit (pAC, pAC->IoBase, SK_INIT_IO);
+ SkTimerInit (pAC, pAC->IoBase, SK_INIT_IO);
+ pAC->BoardLevel = SK_INIT_IO;
++#ifdef Y2_RECOVERY
++ /* mark entries invalid */
++ pAC->LastPort = 3;
++ pAC->LastOpc = 0xFF;
++#endif
+ }
+
+ if (pAC->BoardLevel != SK_INIT_RUN) {
+@@ -1613,45 +2209,61 @@
+ pAC->BoardLevel = SK_INIT_RUN;
+ }
+
+- for (i=0; i<pAC->GIni.GIMacsFound; i++) {
+- /* Enable transmit descriptor polling. */
+- SkGePollTxD(pAC, pAC->IoBase, i, SK_TRUE);
+- FillRxRing(pAC, &pAC->RxPort[i]);
++ for (CurrMac=0; CurrMac<pAC->GIni.GIMacsFound; CurrMac++) {
++ if (!CHIP_ID_YUKON_2(pAC)) {
++ /* Enable transmit descriptor polling. */
++ SkGePollTxD(pAC, pAC->IoBase, CurrMac, SK_TRUE);
++ FillRxRing(pAC, &pAC->RxPort[CurrMac]);
++ SkMacRxTxEnable(pAC, pAC->IoBase, pNet->PortNr);
++ }
+ }
+- SkGeYellowLED(pAC, pAC->IoBase, 1);
+
+- StartDrvCleanupTimer(pAC);
++ SkGeYellowLED(pAC, pAC->IoBase, 1);
+ SkDimEnableModerationIfNeeded(pAC);
+- SkDimDisplayModerationSettings(pAC);
+
+- pAC->GIni.GIValIrqMask &= IRQ_MASK;
+-
+- /* enable Interrupts */
+- SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask);
+- SK_OUT32(pAC->IoBase, B0_HWE_IMSK, IRQ_HWE_MASK);
++ if (!CHIP_ID_YUKON_2(pAC)) {
++ /*
++ ** Has been setup already at SkGeInit(SK_INIT_IO),
++ ** but additional masking added for Genesis & Yukon
++ ** chipsets -> modify it...
++ */
++ pAC->GIni.GIValIrqMask &= IRQ_MASK;
++#ifndef USE_TX_COMPLETE
++ pAC->GIni.GIValIrqMask &= ~(TX_COMPL_IRQS);
++#endif
++ }
+
+ spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+
+ if ((pAC->RlmtMode != 0) && (pAC->MaxPorts == 0)) {
+- EvPara.Para32[0] = pAC->RlmtNets;
+- EvPara.Para32[1] = -1;
+- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_SET_NETS,
+- EvPara);
+- EvPara.Para32[0] = pAC->RlmtMode;
+- EvPara.Para32[1] = 0;
+- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_MODE_CHANGE,
+- EvPara);
++ SkLocalEventQueue(pAC, SKGE_RLMT, SK_RLMT_SET_NETS,
++ pAC->RlmtNets, -1, SK_FALSE);
++ SkLocalEventQueue(pAC, SKGE_RLMT, SK_RLMT_MODE_CHANGE,
++ pAC->RlmtMode, 0, SK_FALSE);
+ }
+
+- EvPara.Para32[0] = pNet->NetNr;
+- EvPara.Para32[1] = -1;
+- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
+- SkEventDispatcher(pAC, pAC->IoBase);
++ SkLocalEventQueue(pAC, SKGE_RLMT, SK_RLMT_START,
++ pNet->NetNr, -1, SK_TRUE);
+ spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+
+- pAC->MaxPorts++;
+- pNet->Up = 1;
++#ifdef Y2_RECOVERY
++ pNet->TimerExpired = SK_FALSE;
++ pNet->InRecover = SK_FALSE;
++ pNet->NetConsoleMode = SK_FALSE;
++
++ /* Initialize the kernel timer */
++ init_timer(&pNet->KernelTimer);
++ pNet->KernelTimer.function = SkGeHandleKernelTimer;
++ pNet->KernelTimer.data = (unsigned long) pNet;
++ pNet->KernelTimer.expires = jiffies + (HZ/4); /* initially 250ms */
++ add_timer(&pNet->KernelTimer);
++#endif
++
++ /* enable Interrupts */
++ SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask);
++ SK_OUT32(pAC->IoBase, B0_HWE_IMSK, IRQ_HWE_MASK);
+
++ pAC->MaxPorts++;
+
+ SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+ ("SkGeOpen suceeded\n"));
+@@ -1672,24 +2284,26 @@
+ * error code - on error
+ */
+ static int SkGeClose(
+-struct SK_NET_DEVICE *dev)
++struct SK_NET_DEVICE *dev) /* the device that is to be closed */
+ {
+- DEV_NET *pNet;
+- DEV_NET *newPtrNet;
+- SK_AC *pAC;
+-
+- unsigned long Flags; /* for spin lock */
+- int i;
+- int PortIdx;
+- SK_EVPARA EvPara;
+-
++ DEV_NET *pNet = (DEV_NET*) dev->priv;
++ SK_AC *pAC = pNet->pAC;
++ DEV_NET *newPtrNet;
++ unsigned long Flags; /* for the spin locks */
++ int CurrMac; /* loop ctr for the current MAC */
++ int PortIdx;
++#ifdef CONFIG_SK98LIN_NAPI
++ int WorkToDo = 1; /* min(*budget, dev->quota); */
++ int WorkDone = 0;
++#endif
+ SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+ ("SkGeClose: pAC=0x%lX ", (unsigned long)pAC));
+
+- pNet = (DEV_NET*) dev->priv;
+- pAC = pNet->pAC;
++#ifdef Y2_RECOVERY
++ pNet->InRecover = SK_TRUE;
++ del_timer(&pNet->KernelTimer);
++#endif
+
+-#ifdef SK_DIAG_SUPPORT
+ if (pAC->DiagModeActive == DIAG_ACTIVE) {
+ if (pAC->DiagFlowCtrl == SK_FALSE) {
+ module_put(THIS_MODULE);
+@@ -1709,7 +2323,6 @@
+ pAC->DiagFlowCtrl = SK_FALSE;
+ }
+ }
+-#endif
+
+ netif_stop_queue(dev);
+
+@@ -1718,8 +2331,6 @@
+ else
+ PortIdx = pNet->NetNr;
+
+- StopDrvCleanupTimer(pAC);
+-
+ /*
+ * Clear multicast table, promiscuous mode ....
+ */
+@@ -1731,46 +2342,101 @@
+ spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+ /* disable interrupts */
+ SK_OUT32(pAC->IoBase, B0_IMSK, 0);
+- EvPara.Para32[0] = pNet->NetNr;
+- EvPara.Para32[1] = -1;
+- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
+- SkEventDispatcher(pAC, pAC->IoBase);
++ SkLocalEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP,
++ pNet->NetNr, -1, SK_TRUE);
+ SK_OUT32(pAC->IoBase, B0_IMSK, 0);
+ /* stop the hardware */
+- SkGeDeInit(pAC, pAC->IoBase);
+- pAC->BoardLevel = SK_INIT_DATA;
++
++
++ if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 1)) {
++ /* RLMT check link state mode */
++ for (CurrMac=0; CurrMac<pAC->GIni.GIMacsFound; CurrMac++) {
++ if (CHIP_ID_YUKON_2(pAC))
++ SkY2PortStop( pAC,
++ pAC->IoBase,
++ CurrMac,
++ SK_STOP_ALL,
++ SK_HARD_RST);
++ else
++ SkGeStopPort( pAC,
++ pAC->IoBase,
++ CurrMac,
++ SK_STOP_ALL,
++ SK_HARD_RST);
++ } /* for */
++ } else {
++ /* Single link or single port */
++ if (CHIP_ID_YUKON_2(pAC))
++ SkY2PortStop( pAC,
++ pAC->IoBase,
++ PortIdx,
++ SK_STOP_ALL,
++ SK_HARD_RST);
++ else
++ SkGeStopPort( pAC,
++ pAC->IoBase,
++ PortIdx,
++ SK_STOP_ALL,
++ SK_HARD_RST);
++ }
+ spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+ } else {
+-
+ spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+- EvPara.Para32[0] = pNet->NetNr;
+- EvPara.Para32[1] = -1;
+- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
+- SkPnmiEvent(pAC, pAC->IoBase, SK_PNMI_EVT_XMAC_RESET, EvPara);
+- SkEventDispatcher(pAC, pAC->IoBase);
++ SkLocalEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP,
++ pNet->NetNr, -1, SK_FALSE);
++ SkLocalEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_XMAC_RESET,
++ pNet->NetNr, -1, SK_TRUE);
+ spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+
+ /* Stop port */
+ spin_lock_irqsave(&pAC->TxPort[pNet->PortNr]
+ [TX_PRIO_LOW].TxDesRingLock, Flags);
+- SkGeStopPort(pAC, pAC->IoBase, pNet->PortNr,
+- SK_STOP_ALL, SK_HARD_RST);
++ if (CHIP_ID_YUKON_2(pAC)) {
++ SkY2PortStop(pAC, pAC->IoBase, pNet->PortNr,
++ SK_STOP_ALL, SK_HARD_RST);
++ }
++ else {
++ SkGeStopPort(pAC, pAC->IoBase, pNet->PortNr,
++ SK_STOP_ALL, SK_HARD_RST);
++ }
+ spin_unlock_irqrestore(&pAC->TxPort[pNet->PortNr]
+ [TX_PRIO_LOW].TxDesRingLock, Flags);
+ }
+
+ if (pAC->RlmtNets == 1) {
+ /* clear all descriptor rings */
+- for (i=0; i<pAC->GIni.GIMacsFound; i++) {
+- ReceiveIrq(pAC, &pAC->RxPort[i], SK_TRUE);
+- ClearRxRing(pAC, &pAC->RxPort[i]);
+- ClearTxRing(pAC, &pAC->TxPort[i][TX_PRIO_LOW]);
++ for (CurrMac=0; CurrMac<pAC->GIni.GIMacsFound; CurrMac++) {
++ if (!CHIP_ID_YUKON_2(pAC)) {
++#ifdef CONFIG_SK98LIN_NAPI
++ WorkToDo = 1;
++ ReceiveIrq(pAC,&pAC->RxPort[CurrMac],
++ SK_TRUE,&WorkDone,WorkToDo);
++#else
++ ReceiveIrq(pAC,&pAC->RxPort[CurrMac],SK_TRUE);
++#endif
++ ClearRxRing(pAC, &pAC->RxPort[CurrMac]);
++ ClearTxRing(pAC, &pAC->TxPort[CurrMac][TX_PRIO_LOW]);
++ } else {
++ SkY2FreeRxBuffers(pAC, pAC->IoBase, CurrMac);
++ SkY2FreeTxBuffers(pAC, pAC->IoBase, CurrMac);
++ }
+ }
+ } else {
+ /* clear port descriptor rings */
+- ReceiveIrq(pAC, &pAC->RxPort[pNet->PortNr], SK_TRUE);
+- ClearRxRing(pAC, &pAC->RxPort[pNet->PortNr]);
+- ClearTxRing(pAC, &pAC->TxPort[pNet->PortNr][TX_PRIO_LOW]);
++ if (!CHIP_ID_YUKON_2(pAC)) {
++#ifdef CONFIG_SK98LIN_NAPI
++ WorkToDo = 1;
++ ReceiveIrq(pAC, &pAC->RxPort[pNet->PortNr], SK_TRUE, &WorkDone, WorkToDo);
++#else
++ ReceiveIrq(pAC, &pAC->RxPort[pNet->PortNr], SK_TRUE);
++#endif
++ ClearRxRing(pAC, &pAC->RxPort[pNet->PortNr]);
++ ClearTxRing(pAC, &pAC->TxPort[pNet->PortNr][TX_PRIO_LOW]);
++ }
++ else {
++ SkY2FreeRxBuffers(pAC, pAC->IoBase, pNet->PortNr);
++ SkY2FreeTxBuffers(pAC, pAC->IoBase, pNet->PortNr);
++ }
+ }
+
+ SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+@@ -1781,9 +2447,12 @@
+ sizeof(SK_PNMI_STRUCT_DATA));
+
+ pAC->MaxPorts--;
+- pNet->Up = 0;
+-
+ module_put(THIS_MODULE);
++
++#ifdef Y2_RECOVERY
++ pNet->InRecover = SK_FALSE;
++#endif
++
+ return (0);
+ } /* SkGeClose */
+
+@@ -1841,9 +2510,11 @@
+ }
+
+ /* Transmitter out of resources? */
++#ifdef USE_TX_COMPLETE
+ if (Rc <= 0) {
+ netif_stop_queue(dev);
+ }
++#endif
+
+ /* If not taken, give buffer ownership back to the
+ * queueing layer.
+@@ -1855,6 +2526,94 @@
+ return (0);
+ } /* SkGeXmit */
+
++#ifdef CONFIG_SK98LIN_NAPI
++/*****************************************************************************
++ *
++ * SkGePoll - NAPI Rx polling callback for GEnesis and Yukon chipsets
++ *
++ * Description:
++ * Called by the Linux system in case NAPI polling is activated
++ *
++ * Returns:
++ * The number of work data still to be handled
++ */
++static int SkGePoll(struct net_device *dev, int *budget)
++{
++SK_AC *pAC = ((DEV_NET*)(dev->priv))->pAC; /* pointer to adapter context */
++int WorkToDo = min(*budget, dev->quota);
++int WorkDone = 0;
++
++ if (pAC->dev[0] != pAC->dev[1]) {
++#ifdef USE_TX_COMPLETE
++ spin_lock(&pAC->TxPort[1][TX_PRIO_LOW].TxDesRingLock);
++ FreeTxDescriptors(pAC, &pAC->TxPort[1][TX_PRIO_LOW]);
++ spin_unlock(&pAC->TxPort[1][TX_PRIO_LOW].TxDesRingLock);
++#endif
++ ReceiveIrq(pAC, &pAC->RxPort[1], SK_TRUE, &WorkDone, WorkToDo);
++ CLEAR_AND_START_RX(1);
++ }
++#ifdef USE_TX_COMPLETE
++ spin_lock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
++ FreeTxDescriptors(pAC, &pAC->TxPort[0][TX_PRIO_LOW]);
++ spin_unlock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock);
++#endif
++ ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE, &WorkDone, WorkToDo);
++ CLEAR_AND_START_RX(0);
++
++ *budget -= WorkDone;
++ dev->quota -= WorkDone;
++
++ if(WorkDone < WorkToDo) {
++ netif_rx_complete(dev);
++ /* enable interrupts again */
++ pAC->GIni.GIValIrqMask |= (NAPI_DRV_IRQS);
++#ifndef USE_TX_COMPLETE
++ pAC->GIni.GIValIrqMask &= ~(TX_COMPL_IRQS);
++#endif
++ SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask);
++ }
++ return (WorkDone >= WorkToDo);
++} /* SkGePoll */
++#endif
++
++#ifdef SK_POLL_CONTROLLER
++/*****************************************************************************
++ *
++ * SkGeNetPoll - Polling "interrupt"
++ *
++ * Description:
++ * Polling 'interrupt' - used by things like netconsole and netdump
++ * to send skbs without having to re-enable interrupts.
++ * It's not called while the interrupt routine is executing.
++ */
++static void SkGeNetPoll(
++struct SK_NET_DEVICE *dev)
++{
++DEV_NET *pNet;
++SK_AC *pAC;
++
++ pNet = (DEV_NET*) dev->priv;
++ pAC = pNet->pAC;
++ pNet->NetConsoleMode = SK_TRUE;
++
++ /* Prevent any reconfiguration while handling
++ the 'interrupt' */
++ SK_OUT32(pAC->IoBase, B0_IMSK, 0);
++
++ if (!CHIP_ID_YUKON_2(pAC)) {
++ /* Handle the GENESIS Isr */
++ if (pAC->GIni.GIMacsFound == 2)
++ SkGeIsr(dev->irq, dev, NULL);
++ else
++ SkGeIsrOnePort(dev->irq, dev, NULL);
++ } else {
++ /* Handle the Yukon2 Isr */
++ SkY2Isr(dev->irq, dev, NULL);
++ }
++
++}
++#endif
++
+
+ /*****************************************************************************
+ *
+@@ -1879,7 +2638,7 @@
+ * < 0 - on failure: other problems ( -> return failure to upper layers)
+ */
+ static int XmitFrame(
+-SK_AC *pAC, /* pointer to adapter context */
++SK_AC *pAC, /* pointer to adapter context */
+ TX_PORT *pTxPort, /* pointer to struct of port to send to */
+ struct sk_buff *pMessage) /* pointer to send-message */
+ {
+@@ -1895,11 +2654,14 @@
+
+ spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags);
+ #ifndef USE_TX_COMPLETE
+- FreeTxDescriptors(pAC, pTxPort);
++ if ((pTxPort->TxdRingPrevFree - pTxPort->TxdRingFree) > 6) {
++ FreeTxDescriptors(pAC, pTxPort);
++ pTxPort->TxdRingPrevFree = pTxPort->TxdRingFree;
++ }
+ #endif
+ if (pTxPort->TxdRingFree == 0) {
+ /*
+- ** no enough free descriptors in ring at the moment.
++ ** not enough free descriptors in ring at the moment.
+ ** Maybe free'ing some old one help?
+ */
+ FreeTxDescriptors(pAC, pTxPort);
+@@ -1985,7 +2747,7 @@
+ BMU_IRQ_EOF |
+ #endif
+ pMessage->len;
+- } else {
++ } else {
+ pTxd->TBControl = BMU_OWN | BMU_STF | BMU_CHECK |
+ BMU_SW | BMU_EOF |
+ #ifdef USE_TX_COMPLETE
+@@ -2321,7 +3083,7 @@
+ SK_U16 Length; /* data fragment length */
+ SK_U64 PhysAddr; /* physical address of a rx buffer */
+
+- pMsgBlock = alloc_skb(pAC->RxBufSize, GFP_ATOMIC);
++ pMsgBlock = alloc_skb(pRxPort->RxBufSize, GFP_ATOMIC);
+ if (pMsgBlock == NULL) {
+ SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+ SK_DBGCAT_DRV_ENTRY,
+@@ -2335,12 +3097,12 @@
+ pRxd = pRxPort->pRxdRingTail;
+ pRxPort->pRxdRingTail = pRxd->pNextRxd;
+ pRxPort->RxdRingFree--;
+- Length = pAC->RxBufSize;
++ Length = pRxPort->RxBufSize;
+ PhysAddr = (SK_U64) pci_map_page(pAC->PciDev,
+ virt_to_page(pMsgBlock->data),
+ ((unsigned long) pMsgBlock->data &
+ ~PAGE_MASK),
+- pAC->RxBufSize - 2,
++ pRxPort->RxBufSize - 2,
+ PCI_DMA_FROMDEVICE);
+
+ pRxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff);
+@@ -2380,7 +3142,7 @@
+ pRxd = pRxPort->pRxdRingTail;
+ pRxPort->pRxdRingTail = pRxd->pNextRxd;
+ pRxPort->RxdRingFree--;
+- Length = pAC->RxBufSize;
++ Length = pRxPort->RxBufSize;
+
+ pRxd->VDataLow = PhysLow;
+ pRxd->VDataHigh = PhysHigh;
+@@ -2405,33 +3167,40 @@
+ * Returns: N/A
+ */
+ static void ReceiveIrq(
+- SK_AC *pAC, /* pointer to adapter context */
+- RX_PORT *pRxPort, /* pointer to receive port struct */
+- SK_BOOL SlowPathLock) /* indicates if SlowPathLock is needed */
+-{
+-RXD *pRxd; /* pointer to receive descriptors */
+-SK_U32 Control; /* control field of descriptor */
+-struct sk_buff *pMsg; /* pointer to message holding frame */
+-struct sk_buff *pNewMsg; /* pointer to a new message for copying frame */
+-int FrameLength; /* total length of received frame */
+-int IpFrameLength;
+-SK_MBUF *pRlmtMbuf; /* ptr to a buffer for giving a frame to rlmt */
+-SK_EVPARA EvPara; /* an event parameter union */
+-unsigned long Flags; /* for spin lock */
+-int PortIndex = pRxPort->PortIndex;
+-unsigned int Offset;
+-unsigned int NumBytes;
+-unsigned int ForRlmt;
+-SK_BOOL IsBc;
+-SK_BOOL IsMc;
+-SK_BOOL IsBadFrame; /* Bad frame */
+-
+-SK_U32 FrameStat;
+-unsigned short Csum1;
+-unsigned short Csum2;
+-unsigned short Type;
+-int Result;
+-SK_U64 PhysAddr;
++#ifdef CONFIG_SK98LIN_NAPI
++SK_AC *pAC, /* pointer to adapter context */
++RX_PORT *pRxPort, /* pointer to receive port struct */
++SK_BOOL SlowPathLock, /* indicates if SlowPathLock is needed */
++int *WorkDone,
++int WorkToDo)
++#else
++SK_AC *pAC, /* pointer to adapter context */
++RX_PORT *pRxPort, /* pointer to receive port struct */
++SK_BOOL SlowPathLock) /* indicates if SlowPathLock is needed */
++#endif
++{
++ RXD *pRxd; /* pointer to receive descriptors */
++ struct sk_buff *pMsg; /* pointer to message holding frame */
++ struct sk_buff *pNewMsg; /* pointer to new message for frame copy */
++ SK_MBUF *pRlmtMbuf; /* ptr to buffer for giving frame to RLMT */
++ SK_EVPARA EvPara; /* an event parameter union */
++ SK_U32 Control; /* control field of descriptor */
++ unsigned long Flags; /* for spin lock handling */
++ int PortIndex = pRxPort->PortIndex;
++ int FrameLength; /* total length of received frame */
++ int IpFrameLength; /* IP length of the received frame */
++ unsigned int Offset;
++ unsigned int NumBytes;
++ unsigned int RlmtNotifier;
++ SK_BOOL IsBc; /* we received a broadcast packet */
++ SK_BOOL IsMc; /* we received a multicast packet */
++ SK_BOOL IsBadFrame; /* the frame received is bad! */
++ SK_U32 FrameStat;
++ unsigned short Csum1;
++ unsigned short Csum2;
++ unsigned short Type;
++ int Result;
++ SK_U64 PhysAddr;
+
+ rx_start:
+ /* do forever; exit if BMU_OWN found */
+@@ -2453,6 +3222,13 @@
+
+ Control = pRxd->RBControl;
+
++#ifdef CONFIG_SK98LIN_NAPI
++ if (*WorkDone >= WorkToDo) {
++ break;
++ }
++ (*WorkDone)++;
++#endif
++
+ /* check if this descriptor is ready */
+ if ((Control & BMU_OWN) != 0) {
+ /* this descriptor is not yet ready */
+@@ -2461,11 +3237,10 @@
+ FillRxRing(pAC, pRxPort);
+ return;
+ }
+- pAC->DynIrqModInfo.NbrProcessedDescr++;
+
+ /* get length of frame and check it */
+ FrameLength = Control & BMU_BBC;
+- if (FrameLength > pAC->RxBufSize) {
++ if (FrameLength > pRxPort->RxBufSize) {
+ goto rx_failed;
+ }
+
+@@ -2480,8 +3255,8 @@
+ FrameStat = pRxd->FrameStat;
+
+ /* check for frame length mismatch */
+-#define XMR_FS_LEN_SHIFT 18
+-#define GMR_FS_LEN_SHIFT 16
++#define XMR_FS_LEN_SHIFT 18
++#define GMR_FS_LEN_SHIFT 16
+ if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
+ if (FrameLength != (SK_U32) (FrameStat >> XMR_FS_LEN_SHIFT)) {
+ SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+@@ -2491,8 +3266,7 @@
+ (SK_U32) (FrameStat >> XMR_FS_LEN_SHIFT)));
+ goto rx_failed;
+ }
+- }
+- else {
++ } else {
+ if (FrameLength != (SK_U32) (FrameStat >> GMR_FS_LEN_SHIFT)) {
+ SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+ SK_DBGCAT_DRV_RX_PROGRESS,
+@@ -2525,9 +3299,6 @@
+ /* DumpMsg(pMsg, "Rx"); */
+
+ if ((Control & BMU_STAT_VAL) != BMU_STAT_VAL || (IsBadFrame)) {
+-#if 0
+- (FrameStat & (XMR_FS_ANY_ERR | XMR_FS_2L_VLAN)) != 0) {
+-#endif
+ /* there is a receive error in this frame */
+ SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+ SK_DBGCAT_DRV_RX_PROGRESS,
+@@ -2535,6 +3306,20 @@
+ "Control: %x\nRxStat: %x\n",
+ Control, FrameStat));
+
++ PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;
++ PhysAddr |= (SK_U64) pRxd->VDataLow;
++
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5)
++ pci_dma_sync_single(pAC->PciDev,
++ (dma_addr_t) PhysAddr,
++ FrameLength,
++ PCI_DMA_FROMDEVICE);
++#else
++ pci_dma_sync_single_for_cpu(pAC->PciDev,
++ (dma_addr_t) PhysAddr,
++ FrameLength,
++ PCI_DMA_FROMDEVICE);
++#endif
+ ReQueueRxBuffer(pAC, pRxPort, pMsg,
+ pRxd->VDataHigh, pRxd->VDataLow);
+
+@@ -2554,150 +3339,107 @@
+ skb_put(pNewMsg, FrameLength);
+ PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;
+ PhysAddr |= (SK_U64) pRxd->VDataLow;
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5)
++ pci_dma_sync_single(pAC->PciDev,
++ (dma_addr_t) PhysAddr,
++ FrameLength,
++ PCI_DMA_FROMDEVICE);
++#else
++ pci_dma_sync_single_for_device(pAC->PciDev,
++ (dma_addr_t) PhysAddr,
++ FrameLength,
++ PCI_DMA_FROMDEVICE);
++#endif
+
+- pci_dma_sync_single_for_cpu(pAC->PciDev,
+- (dma_addr_t) PhysAddr,
+- FrameLength,
+- PCI_DMA_FROMDEVICE);
+ eth_copy_and_sum(pNewMsg, pMsg->data,
+ FrameLength, 0);
+- pci_dma_sync_single_for_device(pAC->PciDev,
+- (dma_addr_t) PhysAddr,
+- FrameLength,
+- PCI_DMA_FROMDEVICE);
+ ReQueueRxBuffer(pAC, pRxPort, pMsg,
+ pRxd->VDataHigh, pRxd->VDataLow);
+
+ pMsg = pNewMsg;
+
+- }
+- else {
++ } else {
+ /*
+ * if large frame, or SKB allocation failed, pass
+ * the SKB directly to the networking
+ */
+-
+ PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32;
+ PhysAddr |= (SK_U64) pRxd->VDataLow;
+
+ /* release the DMA mapping */
+ pci_unmap_single(pAC->PciDev,
+ PhysAddr,
+- pAC->RxBufSize - 2,
++ pRxPort->RxBufSize - 2,
+ PCI_DMA_FROMDEVICE);
++ skb_put(pMsg, FrameLength); /* set message len */
++ pMsg->ip_summed = CHECKSUM_NONE; /* initial default */
+
+- /* set length in message */
+- skb_put(pMsg, FrameLength);
+- /* hardware checksum */
+- Type = ntohs(*((short*)&pMsg->data[12]));
+-
+-#ifdef USE_SK_RX_CHECKSUM
+- if (Type == 0x800) {
+- Csum1=le16_to_cpu(pRxd->TcpSums & 0xffff);
+- Csum2=le16_to_cpu((pRxd->TcpSums >> 16) & 0xffff);
+- IpFrameLength = (int) ntohs((unsigned short)
+- ((unsigned short *) pMsg->data)[8]);
+-
+- /*
+- * Test: If frame is padded, a check is not possible!
+- * Frame not padded? Length difference must be 14 (0xe)!
+- */
+- if ((FrameLength - IpFrameLength) != 0xe) {
+- /* Frame padded => TCP offload not possible! */
+- pMsg->ip_summed = CHECKSUM_NONE;
+- } else {
+- /* Frame not padded => TCP offload! */
+- if ((((Csum1 & 0xfffe) && (Csum2 & 0xfffe)) &&
+- (pAC->GIni.GIChipId == CHIP_ID_GENESIS)) ||
+- (pAC->ChipsetType)) {
+- Result = SkCsGetReceiveInfo(pAC,
+- &pMsg->data[14],
+- Csum1, Csum2, pRxPort->PortIndex);
+- if (Result ==
+- SKCS_STATUS_IP_FRAGMENT ||
+- Result ==
+- SKCS_STATUS_IP_CSUM_OK ||
+- Result ==
+- SKCS_STATUS_TCP_CSUM_OK ||
+- Result ==
+- SKCS_STATUS_UDP_CSUM_OK) {
+- pMsg->ip_summed =
+- CHECKSUM_UNNECESSARY;
+- }
+- else if (Result ==
+- SKCS_STATUS_TCP_CSUM_ERROR ||
+- Result ==
+- SKCS_STATUS_UDP_CSUM_ERROR ||
+- Result ==
+- SKCS_STATUS_IP_CSUM_ERROR_UDP ||
+- Result ==
+- SKCS_STATUS_IP_CSUM_ERROR_TCP ||
+- Result ==
+- SKCS_STATUS_IP_CSUM_ERROR ) {
+- /* HW Checksum error */
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+- SK_DBGCAT_DRV_RX_PROGRESS,
+- ("skge: CRC error. Frame dropped!\n"));
+- goto rx_failed;
+- } else {
+- pMsg->ip_summed =
+- CHECKSUM_NONE;
+- }
+- }/* checksumControl calculation valid */
+- } /* Frame length check */
+- } /* IP frame */
+-#else
+- pMsg->ip_summed = CHECKSUM_NONE;
+-#endif
++ if (pRxPort->UseRxCsum) {
++ Type = ntohs(*((short*)&pMsg->data[12]));
++ if (Type == 0x800) {
++ IpFrameLength = (int) ntohs((unsigned short)
++ ((unsigned short *) pMsg->data)[8]);
++ if ((FrameLength - IpFrameLength) == 0xe) {
++ Csum1=le16_to_cpu(pRxd->TcpSums & 0xffff);
++ Csum2=le16_to_cpu((pRxd->TcpSums >> 16) & 0xffff);
++ if ((((Csum1 & 0xfffe) && (Csum2 & 0xfffe)) &&
++ (pAC->GIni.GIChipId == CHIP_ID_GENESIS)) ||
++ (pAC->ChipsetType)) {
++ Result = SkCsGetReceiveInfo(pAC, &pMsg->data[14],
++ Csum1, Csum2, PortIndex);
++ if ((Result == SKCS_STATUS_IP_FRAGMENT) ||
++ (Result == SKCS_STATUS_IP_CSUM_OK) ||
++ (Result == SKCS_STATUS_TCP_CSUM_OK) ||
++ (Result == SKCS_STATUS_UDP_CSUM_OK)) {
++ pMsg->ip_summed = CHECKSUM_UNNECESSARY;
++ } else if ((Result == SKCS_STATUS_TCP_CSUM_ERROR) ||
++ (Result == SKCS_STATUS_UDP_CSUM_ERROR) ||
++ (Result == SKCS_STATUS_IP_CSUM_ERROR_UDP) ||
++ (Result == SKCS_STATUS_IP_CSUM_ERROR_TCP) ||
++ (Result == SKCS_STATUS_IP_CSUM_ERROR)) {
++ /* HW Checksum error */
++ SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
++ SK_DBGCAT_DRV_RX_PROGRESS,
++ ("skge: CRC error. Frame dropped!\n"));
++ goto rx_failed;
++ } else {
++ pMsg->ip_summed = CHECKSUM_NONE;
++ }
++ }/* checksumControl calculation valid */
++ } /* Frame length check */
++ } /* IP frame */
++ } /* pRxPort->UseRxCsum */
+ } /* frame > SK_COPY_TRESHOLD */
+
+ SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 1,("V"));
+- ForRlmt = SK_RLMT_RX_PROTOCOL;
+-#if 0
+- IsBc = (FrameStat & XMR_FS_BC)==XMR_FS_BC;
+-#endif
++ RlmtNotifier = SK_RLMT_RX_PROTOCOL;
+ SK_RLMT_PRE_LOOKAHEAD(pAC, PortIndex, FrameLength,
+- IsBc, &Offset, &NumBytes);
++ IsBc, &Offset, &NumBytes);
+ if (NumBytes != 0) {
+-#if 0
+- IsMc = (FrameStat & XMR_FS_MC)==XMR_FS_MC;
+-#endif
+- SK_RLMT_LOOKAHEAD(pAC, PortIndex,
+- &pMsg->data[Offset],
+- IsBc, IsMc, &ForRlmt);
++ SK_RLMT_LOOKAHEAD(pAC,PortIndex,&pMsg->data[Offset],
++ IsBc,IsMc,&RlmtNotifier);
+ }
+- if (ForRlmt == SK_RLMT_RX_PROTOCOL) {
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 1,("W"));
++ if (RlmtNotifier == SK_RLMT_RX_PROTOCOL) {
++ SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 1,("W"));
+ /* send up only frames from active port */
+- if ((PortIndex == pAC->ActivePort) ||
+- (pAC->RlmtNets == 2)) {
+- /* frame for upper layer */
++ if ((PortIndex == pAC->ActivePort)||(pAC->RlmtNets == 2)) {
+ SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 1,("U"));
+ #ifdef xDEBUG
+ DumpMsg(pMsg, "Rx");
+ #endif
+- SK_PNMI_CNT_RX_OCTETS_DELIVERED(pAC,
+- FrameLength, pRxPort->PortIndex);
+-
+- pMsg->dev = pAC->dev[pRxPort->PortIndex];
+- pMsg->protocol = eth_type_trans(pMsg,
+- pAC->dev[pRxPort->PortIndex]);
+- netif_rx(pMsg);
+- pAC->dev[pRxPort->PortIndex]->last_rx = jiffies;
+- }
+- else {
+- /* drop frame */
++ SK_PNMI_CNT_RX_OCTETS_DELIVERED(pAC,FrameLength,PortIndex);
++ pMsg->dev = pAC->dev[PortIndex];
++ pMsg->protocol = eth_type_trans(pMsg,pAC->dev[PortIndex]);
++ netif_rx(pMsg); /* frame for upper layer */
++ pAC->dev[PortIndex]->last_rx = jiffies;
++ } else {
+ SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+- SK_DBGCAT_DRV_RX_PROGRESS,
+- ("D"));
+- DEV_KFREE_SKB(pMsg);
++ SK_DBGCAT_DRV_RX_PROGRESS,("D"));
++ DEV_KFREE_SKB(pMsg); /* drop frame */
+ }
+-
+- } /* if not for rlmt */
+- else {
+- /* packet for rlmt */
++ } else { /* packet for RLMT stack */
+ SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+- SK_DBGCAT_DRV_RX_PROGRESS, ("R"));
++ SK_DBGCAT_DRV_RX_PROGRESS,("R"));
+ pRlmtMbuf = SkDrvAllocRlmtMbuf(pAC,
+ pAC->IoBase, FrameLength);
+ if (pRlmtMbuf != NULL) {
+@@ -2725,32 +3467,22 @@
+ }
+
+ SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
+- SK_DBGCAT_DRV_RX_PROGRESS,
+- ("Q"));
++ SK_DBGCAT_DRV_RX_PROGRESS,("Q"));
+ }
+- if ((pAC->dev[pRxPort->PortIndex]->flags &
+- (IFF_PROMISC | IFF_ALLMULTI)) != 0 ||
+- (ForRlmt & SK_RLMT_RX_PROTOCOL) ==
+- SK_RLMT_RX_PROTOCOL) {
+- pMsg->dev = pAC->dev[pRxPort->PortIndex];
+- pMsg->protocol = eth_type_trans(pMsg,
+- pAC->dev[pRxPort->PortIndex]);
++ if ((pAC->dev[PortIndex]->flags & (IFF_PROMISC | IFF_ALLMULTI)) ||
++ (RlmtNotifier & SK_RLMT_RX_PROTOCOL)) {
++ pMsg->dev = pAC->dev[PortIndex];
++ pMsg->protocol = eth_type_trans(pMsg,pAC->dev[PortIndex]);
+ netif_rx(pMsg);
+- pAC->dev[pRxPort->PortIndex]->last_rx = jiffies;
+- }
+- else {
++ pAC->dev[PortIndex]->last_rx = jiffies;
++ } else {
+ DEV_KFREE_SKB(pMsg);
+ }
+-
+- } /* if packet for rlmt */
++ } /* if packet for RLMT stack */
+ } /* for ... scanning the RXD ring */
+
+ /* RXD ring is empty -> fill and restart */
+ FillRxRing(pAC, pRxPort);
+- /* do not start if called from Close */
+- if (pAC->BoardLevel > SK_INIT_DATA) {
+- ClearAndStartRx(pAC, PortIndex);
+- }
+ return;
+
+ rx_failed:
+@@ -2764,7 +3496,7 @@
+ PhysAddr |= (SK_U64) pRxd->VDataLow;
+ pci_unmap_page(pAC->PciDev,
+ PhysAddr,
+- pAC->RxBufSize - 2,
++ pRxPort->RxBufSize - 2,
+ PCI_DMA_FROMDEVICE);
+ DEV_KFREE_SKB_IRQ(pRxd->pMBuf);
+ pRxd->pMBuf = NULL;
+@@ -2774,49 +3506,6 @@
+
+ } /* ReceiveIrq */
+
+-
+-/*****************************************************************************
+- *
+- * ClearAndStartRx - give a start receive command to BMU, clear IRQ
+- *
+- * Description:
+- * This function sends a start command and a clear interrupt
+- * command for one receive queue to the BMU.
+- *
+- * Returns: N/A
+- * none
+- */
+-static void ClearAndStartRx(
+-SK_AC *pAC, /* pointer to the adapter context */
+-int PortIndex) /* index of the receive port (XMAC) */
+-{
+- SK_OUT8(pAC->IoBase,
+- RxQueueAddr[PortIndex]+Q_CSR,
+- CSR_START | CSR_IRQ_CL_F);
+-} /* ClearAndStartRx */
+-
+-
+-/*****************************************************************************
+- *
+- * ClearTxIrq - give a clear transmit IRQ command to BMU
+- *
+- * Description:
+- * This function sends a clear tx IRQ command for one
+- * transmit queue to the BMU.
+- *
+- * Returns: N/A
+- */
+-static void ClearTxIrq(
+-SK_AC *pAC, /* pointer to the adapter context */
+-int PortIndex, /* index of the transmit port (XMAC) */
+-int Prio) /* priority or normal queue */
+-{
+- SK_OUT8(pAC->IoBase,
+- TxQueueAddr[PortIndex][Prio]+Q_CSR,
+- CSR_IRQ_CL_F);
+-} /* ClearTxIrq */
+-
+-
+ /*****************************************************************************
+ *
+ * ClearRxRing - remove all buffers from the receive ring
+@@ -2847,7 +3536,7 @@
+ PhysAddr |= (SK_U64) pRxd->VDataLow;
+ pci_unmap_page(pAC->PciDev,
+ PhysAddr,
+- pAC->RxBufSize - 2,
++ pRxPort->RxBufSize - 2,
+ PCI_DMA_FROMDEVICE);
+ DEV_KFREE_SKB(pRxd->pMBuf);
+ pRxd->pMBuf = NULL;
+@@ -2907,29 +3596,30 @@
+
+ DEV_NET *pNet = (DEV_NET*) dev->priv;
+ SK_AC *pAC = pNet->pAC;
++int Ret;
+
+ struct sockaddr *addr = p;
+ unsigned long Flags;
+
+ SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+ ("SkGeSetMacAddr starts now...\n"));
+- if(netif_running(dev))
+- return -EBUSY;
+
+ memcpy(dev->dev_addr, addr->sa_data,dev->addr_len);
+
+ spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+
+ if (pAC->RlmtNets == 2)
+- SkAddrOverride(pAC, pAC->IoBase, pNet->NetNr,
++ Ret = SkAddrOverride(pAC, pAC->IoBase, pNet->NetNr,
+ (SK_MAC_ADDR*)dev->dev_addr, SK_ADDR_VIRTUAL_ADDRESS);
+ else
+- SkAddrOverride(pAC, pAC->IoBase, pAC->ActivePort,
++ Ret = SkAddrOverride(pAC, pAC->IoBase, pAC->ActivePort,
+ (SK_MAC_ADDR*)dev->dev_addr, SK_ADDR_VIRTUAL_ADDRESS);
+-
+-
+
+ spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
++
++ if (Ret != SK_ADDR_OVERRIDE_SUCCESS)
++ return -EBUSY;
++
+ return 0;
+ } /* SkGeSetMacAddr */
+
+@@ -3011,6 +3701,45 @@
+
+ /*****************************************************************************
+ *
++ * SkSetMtuBufferSize - set the MTU buffer to another value
++ *
++ * Description:
++ * This function sets the new buffers and is called whenever the MTU
++ * size is changed
++ *
++ * Returns:
++ * N/A
++ */
++
++static void SkSetMtuBufferSize(
++SK_AC *pAC, /* pointer to adapter context */
++int PortNr, /* Port number */
++int Mtu) /* pointer to tx prt struct */
++{
++ pAC->RxPort[PortNr].RxBufSize = Mtu + 32;
++
++ /* RxBufSize must be a multiple of 8 */
++ while (pAC->RxPort[PortNr].RxBufSize % 8) {
++ pAC->RxPort[PortNr].RxBufSize =
++ pAC->RxPort[PortNr].RxBufSize + 1;
++ }
++
++ if (Mtu > 1500) {
++ pAC->GIni.GP[PortNr].PPortUsage = SK_JUMBO_LINK;
++ } else {
++ if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
++ pAC->GIni.GP[PortNr].PPortUsage = SK_MUL_LINK;
++ } else {
++ pAC->GIni.GP[PortNr].PPortUsage = SK_RED_LINK;
++ }
++ }
++
++ return;
++}
++
++
++/*****************************************************************************
++ *
+ * SkGeChangeMtu - set the MTU to another value
+ *
+ * Description:
+@@ -3024,12 +3753,13 @@
+ */
+ static int SkGeChangeMtu(struct SK_NET_DEVICE *dev, int NewMtu)
+ {
+-DEV_NET *pNet;
+-DEV_NET *pOtherNet;
+-SK_AC *pAC;
+-unsigned long Flags;
+-int i;
+-SK_EVPARA EvPara;
++DEV_NET *pNet;
++SK_AC *pAC;
++unsigned long Flags;
++#ifdef CONFIG_SK98LIN_NAPI
++int WorkToDo = 1; // min(*budget, dev->quota);
++int WorkDone = 0;
++#endif
+
+ SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+ ("SkGeChangeMtu starts now...\n"));
+@@ -3037,15 +3767,12 @@
+ pNet = (DEV_NET*) dev->priv;
+ pAC = pNet->pAC;
+
++ /* MTU size outside the spec */
+ if ((NewMtu < 68) || (NewMtu > SK_JUMBO_MTU)) {
+ return -EINVAL;
+ }
+
+- if(pAC->BoardLevel != SK_INIT_RUN) {
+- return -EINVAL;
+- }
+-
+-#ifdef SK_DIAG_SUPPORT
++ /* Diag access active */
+ if (pAC->DiagModeActive == DIAG_ACTIVE) {
+ if (pAC->DiagFlowCtrl == SK_FALSE) {
+ return -1; /* still in use, deny any actions of MTU */
+@@ -3053,201 +3780,74 @@
+ pAC->DiagFlowCtrl = SK_FALSE;
+ }
+ }
+-#endif
+-
+- pNet->Mtu = NewMtu;
+- pOtherNet = (DEV_NET*)pAC->dev[1 - pNet->NetNr]->priv;
+- if ((pOtherNet->Mtu>1500) && (NewMtu<=1500) && (pOtherNet->Up==1)) {
+- return(0);
+- }
+
+- pAC->RxBufSize = NewMtu + 32;
+ dev->mtu = NewMtu;
++ SkSetMtuBufferSize(pAC, pNet->PortNr, NewMtu);
+
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+- ("New MTU: %d\n", NewMtu));
++ if(!netif_running(dev)) {
++ /* Preset MTU size if device not ready/running */
++ return 0;
++ }
+
+- /*
+- ** Prevent any reconfiguration while changing the MTU
+- ** by disabling any interrupts
+- */
++ /* Prevent any reconfiguration while changing the MTU
++ by disabling any interrupts */
+ SK_OUT32(pAC->IoBase, B0_IMSK, 0);
+ spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+
+- /*
+- ** Notify RLMT that any ports are to be stopped
+- */
+- EvPara.Para32[0] = 0;
+- EvPara.Para32[1] = -1;
+- if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
+- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
+- EvPara.Para32[0] = 1;
+- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
+- } else {
+- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara);
+- }
+-
+- /*
+- ** After calling the SkEventDispatcher(), RLMT is aware about
+- ** the stopped ports -> configuration can take place!
+- */
+- SkEventDispatcher(pAC, pAC->IoBase);
+-
+- for (i=0; i<pAC->GIni.GIMacsFound; i++) {
+- spin_lock_irqsave(
+- &pAC->TxPort[i][TX_PRIO_LOW].TxDesRingLock, Flags);
+- netif_stop_queue(pAC->dev[i]);
++ /* Notify RLMT that the port has to be stopped */
++ netif_stop_queue(dev);
++ SkLocalEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP,
++ pNet->PortNr, -1, SK_TRUE);
++ spin_lock(&pAC->TxPort[pNet->PortNr][TX_PRIO_LOW].TxDesRingLock);
+
+- }
+
+- /*
+- ** Depending on the desired MTU size change, a different number of
+- ** RX buffers need to be allocated
+- */
+- if (NewMtu > 1500) {
+- /*
+- ** Use less rx buffers
+- */
+- for (i=0; i<pAC->GIni.GIMacsFound; i++) {
+- if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
+- pAC->RxPort[i].RxFillLimit = pAC->RxDescrPerRing -
+- (pAC->RxDescrPerRing / 4);
+- } else {
+- if (i == pAC->ActivePort) {
+- pAC->RxPort[i].RxFillLimit = pAC->RxDescrPerRing -
+- (pAC->RxDescrPerRing / 4);
+- } else {
+- pAC->RxPort[i].RxFillLimit = pAC->RxDescrPerRing -
+- (pAC->RxDescrPerRing / 10);
+- }
+- }
+- }
++ /* Change RxFillLimit to 1 */
++ if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
++ pAC->RxPort[pNet->PortNr].RxFillLimit = 1;
+ } else {
+- /*
+- ** Use the normal amount of rx buffers
+- */
+- for (i=0; i<pAC->GIni.GIMacsFound; i++) {
+- if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
+- pAC->RxPort[i].RxFillLimit = 1;
+- } else {
+- if (i == pAC->ActivePort) {
+- pAC->RxPort[i].RxFillLimit = 1;
+- } else {
+- pAC->RxPort[i].RxFillLimit = pAC->RxDescrPerRing -
+- (pAC->RxDescrPerRing / 4);
+- }
+- }
+- }
++ pAC->RxPort[1 - pNet->PortNr].RxFillLimit = 1;
++ pAC->RxPort[pNet->PortNr].RxFillLimit = pAC->RxDescrPerRing -
++ (pAC->RxDescrPerRing / 4);
+ }
+-
+- SkGeDeInit(pAC, pAC->IoBase);
+
+- /*
+- ** enable/disable hardware support for long frames
+- */
+- if (NewMtu > 1500) {
+-// pAC->JumboActivated = SK_TRUE; /* is never set back !!! */
+- pAC->GIni.GIPortUsage = SK_JUMBO_LINK;
++ /* clear and reinit the rx rings here, because of new MTU size */
++ if (CHIP_ID_YUKON_2(pAC)) {
++ SkY2PortStop(pAC, pAC->IoBase, pNet->PortNr, SK_STOP_ALL, SK_SOFT_RST);
++ SkY2AllocateRxBuffers(pAC, pAC->IoBase, pNet->PortNr);
++ SkY2PortStart(pAC, pAC->IoBase, pNet->PortNr);
+ } else {
+- if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
+- pAC->GIni.GIPortUsage = SK_MUL_LINK;
+- } else {
+- pAC->GIni.GIPortUsage = SK_RED_LINK;
+- }
+- }
++// SkGeStopPort(pAC, pAC->IoBase, pNet->PortNr, SK_STOP_ALL, SK_SOFT_RST);
++#ifdef CONFIG_SK98LIN_NAPI
++ WorkToDo = 1;
++ ReceiveIrq(pAC, &pAC->RxPort[pNet->PortNr], SK_TRUE, &WorkDone, WorkToDo);
++#else
++ ReceiveIrq(pAC, &pAC->RxPort[pNet->PortNr], SK_TRUE);
++#endif
++ ClearRxRing(pAC, &pAC->RxPort[pNet->PortNr]);
++ FillRxRing(pAC, &pAC->RxPort[pNet->PortNr]);
+
+- SkGeInit( pAC, pAC->IoBase, SK_INIT_IO);
+- SkI2cInit( pAC, pAC->IoBase, SK_INIT_IO);
+- SkEventInit(pAC, pAC->IoBase, SK_INIT_IO);
+- SkPnmiInit( pAC, pAC->IoBase, SK_INIT_IO);
+- SkAddrInit( pAC, pAC->IoBase, SK_INIT_IO);
+- SkRlmtInit( pAC, pAC->IoBase, SK_INIT_IO);
+- SkTimerInit(pAC, pAC->IoBase, SK_INIT_IO);
+-
+- /*
+- ** tschilling:
+- ** Speed and others are set back to default in level 1 init!
+- */
+- GetConfiguration(pAC);
+-
+- SkGeInit( pAC, pAC->IoBase, SK_INIT_RUN);
+- SkI2cInit( pAC, pAC->IoBase, SK_INIT_RUN);
+- SkEventInit(pAC, pAC->IoBase, SK_INIT_RUN);
+- SkPnmiInit( pAC, pAC->IoBase, SK_INIT_RUN);
+- SkAddrInit( pAC, pAC->IoBase, SK_INIT_RUN);
+- SkRlmtInit( pAC, pAC->IoBase, SK_INIT_RUN);
+- SkTimerInit(pAC, pAC->IoBase, SK_INIT_RUN);
++ /* Enable transmit descriptor polling */
++ SkGePollTxD(pAC, pAC->IoBase, pNet->PortNr, SK_TRUE);
++ FillRxRing(pAC, &pAC->RxPort[pNet->PortNr]);
++ }
+
+- /*
+- ** clear and reinit the rx rings here
+- */
+- for (i=0; i<pAC->GIni.GIMacsFound; i++) {
+- ReceiveIrq(pAC, &pAC->RxPort[i], SK_TRUE);
+- ClearRxRing(pAC, &pAC->RxPort[i]);
+- FillRxRing(pAC, &pAC->RxPort[i]);
++ netif_start_queue(pAC->dev[pNet->PortNr]);
+
+- /*
+- ** Enable transmit descriptor polling
+- */
+- SkGePollTxD(pAC, pAC->IoBase, i, SK_TRUE);
+- FillRxRing(pAC, &pAC->RxPort[i]);
+- };
++ spin_unlock(&pAC->TxPort[pNet->PortNr][TX_PRIO_LOW].TxDesRingLock);
+
+- SkGeYellowLED(pAC, pAC->IoBase, 1);
+- SkDimEnableModerationIfNeeded(pAC);
+- SkDimDisplayModerationSettings(pAC);
+
+- netif_start_queue(pAC->dev[pNet->PortNr]);
+- for (i=pAC->GIni.GIMacsFound-1; i>=0; i--) {
+- spin_unlock(&pAC->TxPort[i][TX_PRIO_LOW].TxDesRingLock);
+- }
++ /* Notify RLMT about the changing and restarting one (or more) ports */
++ SkLocalEventQueue(pAC, SKGE_RLMT, SK_RLMT_START,
++ pNet->PortNr, -1, SK_TRUE);
+
+- /*
+- ** Enable Interrupts again
+- */
++ /* Enable Interrupts again */
+ SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask);
+ SK_OUT32(pAC->IoBase, B0_HWE_IMSK, IRQ_HWE_MASK);
+
+- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
+- SkEventDispatcher(pAC, pAC->IoBase);
+-
+- /*
+- ** Notify RLMT about the changing and restarting one (or more) ports
+- */
+- if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) {
+- EvPara.Para32[0] = pAC->RlmtNets;
+- EvPara.Para32[1] = -1;
+- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_SET_NETS, EvPara);
+- EvPara.Para32[0] = pNet->PortNr;
+- EvPara.Para32[1] = -1;
+- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
+-
+- if (pOtherNet->Up) {
+- EvPara.Para32[0] = pOtherNet->PortNr;
+- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
+- }
+- } else {
+- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara);
+- }
+-
+- SkEventDispatcher(pAC, pAC->IoBase);
+ spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+-
+- /*
+- ** While testing this driver with latest kernel 2.5 (2.5.70), it
+- ** seems as if upper layers have a problem to handle a successful
+- ** return value of '0'. If such a zero is returned, the complete
+- ** system hangs for several minutes (!), which is in acceptable.
+- **
+- ** Currently it is not clear, what the exact reason for this problem
+- ** is. The implemented workaround for 2.5 is to return the desired
+- ** new MTU size if all needed changes for the new MTU size where
+- ** performed. In kernels 2.2 and 2.4, a zero value is returned,
+- ** which indicates the successful change of the mtu-size.
+- */
+- return NewMtu;
++ return 0;
+
+-} /* SkGeChangeMtu */
++}
+
+
+ /*****************************************************************************
+@@ -3265,42 +3865,38 @@
+ {
+ DEV_NET *pNet = (DEV_NET*) dev->priv;
+ SK_AC *pAC = pNet->pAC;
+-SK_PNMI_STRUCT_DATA *pPnmiStruct; /* structure for all Pnmi-Data */
+-SK_PNMI_STAT *pPnmiStat; /* pointer to virtual XMAC stat. data */
+-SK_PNMI_CONF *pPnmiConf; /* pointer to virtual link config. */
+-unsigned int Size; /* size of pnmi struct */
++SK_PNMI_STRUCT_DATA *pPnmiStruct; /* structure for all Pnmi-Data */
++SK_PNMI_STAT *pPnmiStat; /* pointer to virtual XMAC stat. data */
++SK_PNMI_CONF *pPnmiConf; /* pointer to virtual link config. */
++unsigned int Size; /* size of pnmi struct */
+ unsigned long Flags; /* for spin lock */
+
+ SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+ ("SkGeStats starts now...\n"));
+ pPnmiStruct = &pAC->PnmiStruct;
+
+-#ifdef SK_DIAG_SUPPORT
+- if ((pAC->DiagModeActive == DIAG_NOTACTIVE) &&
+- (pAC->BoardLevel == SK_INIT_RUN)) {
+-#endif
+- SK_MEMSET(pPnmiStruct, 0, sizeof(SK_PNMI_STRUCT_DATA));
+- spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+- Size = SK_PNMI_STRUCT_SIZE;
+- SkPnmiGetStruct(pAC, pAC->IoBase, pPnmiStruct, &Size, pNet->NetNr);
+- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+-#ifdef SK_DIAG_SUPPORT
++ if ((pAC->DiagModeActive == DIAG_NOTACTIVE) &&
++ (pAC->BoardLevel == SK_INIT_RUN)) {
++ SK_MEMSET(pPnmiStruct, 0, sizeof(SK_PNMI_STRUCT_DATA));
++ spin_lock_irqsave(&pAC->SlowPathLock, Flags);
++ Size = SK_PNMI_STRUCT_SIZE;
++ SkPnmiGetStruct(pAC, pAC->IoBase, pPnmiStruct, &Size, pNet->NetNr);
++ spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+ }
+-#endif
+
+- pPnmiStat = &pPnmiStruct->Stat[0];
+- pPnmiConf = &pPnmiStruct->Conf[0];
++ pPnmiStat = &pPnmiStruct->Stat[0];
++ pPnmiConf = &pPnmiStruct->Conf[0];
+
+ pAC->stats.rx_packets = (SK_U32) pPnmiStruct->RxDeliveredCts & 0xFFFFFFFF;
+ pAC->stats.tx_packets = (SK_U32) pPnmiStat->StatTxOkCts & 0xFFFFFFFF;
+ pAC->stats.rx_bytes = (SK_U32) pPnmiStruct->RxOctetsDeliveredCts;
+ pAC->stats.tx_bytes = (SK_U32) pPnmiStat->StatTxOctetsOkCts;
+
+- if (pNet->Mtu <= 1500) {
+- pAC->stats.rx_errors = (SK_U32) pPnmiStruct->InErrorsCts & 0xFFFFFFFF;
+- } else {
+- pAC->stats.rx_errors = (SK_U32) ((pPnmiStruct->InErrorsCts -
+- pPnmiStat->StatRxTooLongCts) & 0xFFFFFFFF);
++ if (dev->mtu <= 1500) {
++ pAC->stats.rx_errors = (SK_U32) pPnmiStruct->InErrorsCts & 0xFFFFFFFF;
++ } else {
++ pAC->stats.rx_errors = (SK_U32) ((pPnmiStruct->InErrorsCts -
++ pPnmiStat->StatRxTooLongCts) & 0xFFFFFFFF);
+ }
+
+
+@@ -3345,32 +3941,35 @@
+ * 0, if everything is ok
+ * !=0, on error
+ */
+-static int SkGeIoctl(struct SK_NET_DEVICE *dev, struct ifreq *rq, int cmd)
+-{
+-DEV_NET *pNet;
+-SK_AC *pAC;
+-void *pMemBuf;
+-struct pci_dev *pdev = NULL;
+-SK_GE_IOCTL Ioctl;
+-unsigned int Err = 0;
+-int Size = 0;
+-int Ret = 0;
+-unsigned int Length = 0;
+-int HeaderLength = sizeof(SK_U32) + sizeof(SK_U32);
++static int SkGeIoctl(
++struct SK_NET_DEVICE *dev, /* the device the IOCTL is to be performed on */
++struct ifreq *rq, /* additional request structure containing data */
++int cmd) /* requested IOCTL command number */
++{
++ DEV_NET *pNet = (DEV_NET*) dev->priv;
++ SK_AC *pAC = pNet->pAC;
++ struct pci_dev *pdev = NULL;
++ void *pMemBuf;
++ SK_GE_IOCTL Ioctl;
++ unsigned long Flags; /* for spin lock */
++ unsigned int Err = 0;
++ unsigned int Length = 0;
++ int HeaderLength = sizeof(SK_U32) + sizeof(SK_U32);
++ int Size = 0;
++ int Ret = 0;
+
+ SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+ ("SkGeIoctl starts now...\n"));
+
+- pNet = (DEV_NET*) dev->priv;
+- pAC = pNet->pAC;
+-
+ if(copy_from_user(&Ioctl, rq->ifr_data, sizeof(SK_GE_IOCTL))) {
+ return -EFAULT;
+ }
+
+ switch(cmd) {
+- case SK_IOCTL_SETMIB:
+- case SK_IOCTL_PRESETMIB:
++ case SIOCETHTOOL:
++ return SkEthIoctl(dev, rq);
++ case SK_IOCTL_SETMIB: /* FALL THRU */
++ case SK_IOCTL_PRESETMIB: /* FALL THRU (if capable!) */
+ if (!capable(CAP_NET_ADMIN)) return -EPERM;
+ case SK_IOCTL_GETMIB:
+ if(copy_from_user(&pAC->PnmiStruct, Ioctl.pData,
+@@ -3397,6 +3996,7 @@
+ if (NULL == (pMemBuf = kmalloc(Length, GFP_KERNEL))) {
+ return -ENOMEM;
+ }
++ spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+ if(copy_from_user(pMemBuf, Ioctl.pData, Length)) {
+ Err = -EFAULT;
+ goto fault_gen;
+@@ -3415,10 +4015,10 @@
+ goto fault_gen;
+ }
+ fault_gen:
++ spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+ kfree(pMemBuf); /* cleanup everything */
+ break;
+-#ifdef SK_DIAG_SUPPORT
+- case SK_IOCTL_DIAG:
++ case SK_IOCTL_DIAG:
+ if (!capable(CAP_NET_ADMIN)) return -EPERM;
+ if (Ioctl.Len < (sizeof(pAC->PnmiStruct) + HeaderLength)) {
+ Length = Ioctl.Len;
+@@ -3442,7 +4042,7 @@
+ */
+ * ((SK_U32 *)pMemBuf) = 0;
+ * ((SK_U32 *)pMemBuf + 1) = pdev->bus->number;
+- * ((SK_U32 *)pMemBuf + 2) = ParseDeviceNbrFromSlotName(pdev->slot_name);
++ * ((SK_U32 *)pMemBuf + 2) = ParseDeviceNbrFromSlotName(pci_name(pdev));
+ if(copy_to_user(Ioctl.pData, pMemBuf, Length) ) {
+ Err = -EFAULT;
+ goto fault_diag;
+@@ -3455,7 +4055,6 @@
+ fault_diag:
+ kfree(pMemBuf); /* cleanup everything */
+ break;
+-#endif
+ default:
+ Err = -EOPNOTSUPP;
+ }
+@@ -3487,12 +4086,12 @@
+ unsigned int Size, /* length of ioctl data */
+ int mode) /* flag for set/preset */
+ {
+-unsigned long Flags; /* for spin lock */
+-SK_AC *pAC;
++ SK_AC *pAC = pNet->pAC;
++ unsigned long Flags; /* for spin lock */
+
+ SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY,
+ ("SkGeIocMib starts now...\n"));
+- pAC = pNet->pAC;
++
+ /* access MIB */
+ spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+ switch(mode) {
+@@ -3535,17 +4134,18 @@
+ SK_I32 Port; /* preferred port */
+ SK_BOOL AutoSet;
+ SK_BOOL DupSet;
+-int LinkSpeed = SK_LSPEED_AUTO; /* Link speed */
+-int AutoNeg = 1; /* autoneg off (0) or on (1) */
+-int DuplexCap = 0; /* 0=both,1=full,2=half */
+-int FlowCtrl = SK_FLOW_MODE_SYM_OR_REM; /* FlowControl */
+-int MSMode = SK_MS_MODE_AUTO; /* master/slave mode */
+-
+-SK_BOOL IsConTypeDefined = SK_TRUE;
+-SK_BOOL IsLinkSpeedDefined = SK_TRUE;
+-SK_BOOL IsFlowCtrlDefined = SK_TRUE;
+-SK_BOOL IsRoleDefined = SK_TRUE;
+-SK_BOOL IsModeDefined = SK_TRUE;
++int LinkSpeed = SK_LSPEED_AUTO; /* Link speed */
++int AutoNeg = 1; /* autoneg off (0) or on (1) */
++int DuplexCap = 0; /* 0=both,1=full,2=half */
++int FlowCtrl = SK_FLOW_MODE_SYM_OR_REM; /* FlowControl */
++int MSMode = SK_MS_MODE_AUTO; /* master/slave mode */
++int IrqModMaskOffset = 6; /* all ints moderated=default */
++
++SK_BOOL IsConTypeDefined = SK_TRUE;
++SK_BOOL IsLinkSpeedDefined = SK_TRUE;
++SK_BOOL IsFlowCtrlDefined = SK_TRUE;
++SK_BOOL IsRoleDefined = SK_TRUE;
++SK_BOOL IsModeDefined = SK_TRUE;
+ /*
+ * The two parameters AutoNeg. and DuplexCap. map to one configuration
+ * parameter. The mapping is described by this table:
+@@ -3563,6 +4163,15 @@
+ {SK_LMODE_AUTOBOTH , SK_LMODE_AUTOFULL , SK_LMODE_AUTOHALF },
+ {SK_LMODE_AUTOSENSE, SK_LMODE_AUTOSENSE, SK_LMODE_AUTOSENSE} };
+
++SK_U32 IrqModMask[7][2] =
++ { { IRQ_MASK_RX_ONLY , Y2_DRIVER_IRQS },
++ { IRQ_MASK_TX_ONLY , Y2_DRIVER_IRQS },
++ { IRQ_MASK_SP_ONLY , Y2_SPECIAL_IRQS },
++ { IRQ_MASK_SP_RX , Y2_IRQ_MASK },
++ { IRQ_MASK_TX_RX , Y2_DRIVER_IRQS },
++ { IRQ_MASK_SP_TX , Y2_IRQ_MASK },
++ { IRQ_MASK_RX_TX_SP, Y2_IRQ_MASK } };
++
+ #define DC_BOTH 0
+ #define DC_FULL 1
+ #define DC_HALF 2
+@@ -3602,7 +4211,7 @@
+ **
+ ** This ConType parameter is used for all ports of the adapter!
+ */
+- if ( (ConType != NULL) &&
++ if ( (ConType != NULL) &&
+ (pAC->Index < SK_MAX_CARD_PARAM) &&
+ (ConType[pAC->Index] != NULL) ) {
+
+@@ -3628,40 +4237,40 @@
+ M_CurrPort.PMSMode = SK_MS_MODE_AUTO;
+ M_CurrPort.PLinkSpeed = SK_LSPEED_AUTO;
+ }
+- } else if (strcmp(ConType[pAC->Index],"100FD")==0) {
++ } else if (strcmp(ConType[pAC->Index],"100FD")==0) {
+ for (Port = 0; Port < SK_MAX_MACS; Port++) {
+ M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_FULL];
+ M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE;
+ M_CurrPort.PMSMode = SK_MS_MODE_AUTO;
+ M_CurrPort.PLinkSpeed = SK_LSPEED_100MBPS;
+ }
+- } else if (strcmp(ConType[pAC->Index],"100HD")==0) {
++ } else if (strcmp(ConType[pAC->Index],"100HD")==0) {
+ for (Port = 0; Port < SK_MAX_MACS; Port++) {
+ M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_HALF];
+ M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE;
+ M_CurrPort.PMSMode = SK_MS_MODE_AUTO;
+ M_CurrPort.PLinkSpeed = SK_LSPEED_100MBPS;
+ }
+- } else if (strcmp(ConType[pAC->Index],"10FD")==0) {
++ } else if (strcmp(ConType[pAC->Index],"10FD")==0) {
+ for (Port = 0; Port < SK_MAX_MACS; Port++) {
+ M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_FULL];
+ M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE;
+ M_CurrPort.PMSMode = SK_MS_MODE_AUTO;
+ M_CurrPort.PLinkSpeed = SK_LSPEED_10MBPS;
+ }
+- } else if (strcmp(ConType[pAC->Index],"10HD")==0) {
++ } else if (strcmp(ConType[pAC->Index],"10HD")==0) {
+ for (Port = 0; Port < SK_MAX_MACS; Port++) {
+ M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_HALF];
+ M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE;
+ M_CurrPort.PMSMode = SK_MS_MODE_AUTO;
+ M_CurrPort.PLinkSpeed = SK_LSPEED_10MBPS;
+ }
+- } else {
++ } else {
+ printk("sk98lin: Illegal value \"%s\" for ConType\n",
+ ConType[pAC->Index]);
+ IsConTypeDefined = SK_FALSE; /* Wrong ConType defined */
+ }
+- } else {
++ } else {
+ IsConTypeDefined = SK_FALSE; /* No ConType defined */
+ }
+
+@@ -3680,14 +4289,30 @@
+ } else if (strcmp(Speed_A[pAC->Index],"100")==0) {
+ LinkSpeed = SK_LSPEED_100MBPS;
+ } else if (strcmp(Speed_A[pAC->Index],"1000")==0) {
+- LinkSpeed = SK_LSPEED_1000MBPS;
++ if ((pAC->PciDev->vendor == 0x11ab ) &&
++ (pAC->PciDev->device == 0x4350)) {
++ LinkSpeed = SK_LSPEED_100MBPS;
++ printk("sk98lin: Illegal value \"%s\" for Speed_A.\n"
++ "Gigabit speed not possible with this chip revision!",
++ Speed_A[pAC->Index]);
++ } else {
++ LinkSpeed = SK_LSPEED_1000MBPS;
++ }
+ } else {
+ printk("sk98lin: Illegal value \"%s\" for Speed_A\n",
+ Speed_A[pAC->Index]);
+ IsLinkSpeedDefined = SK_FALSE;
+ }
+ } else {
+- IsLinkSpeedDefined = SK_FALSE;
++ if ((pAC->PciDev->vendor == 0x11ab ) &&
++ (pAC->PciDev->device == 0x4350)) {
++ /* Gigabit speed not supported
++ * Swith to speed 100
++ */
++ LinkSpeed = SK_LSPEED_100MBPS;
++ } else {
++ IsLinkSpeedDefined = SK_FALSE;
++ }
+ }
+
+ /*
+@@ -3782,9 +4407,6 @@
+ }
+
+ if (!AutoSet && DupSet) {
+- printk("sk98lin: Port A: Duplex setting not"
+- " possible in\n default AutoNegotiation mode"
+- " (Sense).\n Using AutoNegotiation On\n");
+ AutoNeg = AN_ON;
+ }
+
+@@ -3812,7 +4434,7 @@
+ FlowCtrl = SK_FLOW_MODE_NONE;
+ } else {
+ printk("sk98lin: Illegal value \"%s\" for FlowCtrl_A\n",
+- FlowCtrl_A[pAC->Index]);
++ FlowCtrl_A[pAC->Index]);
+ IsFlowCtrlDefined = SK_FALSE;
+ }
+ } else {
+@@ -3904,7 +4526,7 @@
+ ** Decide whether to set new config value if somethig valid has
+ ** been received.
+ */
+- if (IsLinkSpeedDefined) {
++ if (IsLinkSpeedDefined) {
+ pAC->GIni.GP[1].PLinkSpeed = LinkSpeed;
+ }
+
+@@ -3980,9 +4602,6 @@
+ }
+
+ if (!AutoSet && DupSet) {
+- printk("sk98lin: Port B: Duplex setting not"
+- " possible in\n default AutoNegotiation mode"
+- " (Sense).\n Using AutoNegotiation On\n");
+ AutoNeg = AN_ON;
+ }
+
+@@ -4095,11 +4714,15 @@
+ }
+
+ pAC->RlmtNets = 1;
++ pAC->RlmtMode = 0;
+
+ if (RlmtMode != NULL && pAC->Index<SK_MAX_CARD_PARAM &&
+ RlmtMode[pAC->Index] != NULL) {
+ if (strcmp(RlmtMode[pAC->Index], "") == 0) {
+- pAC->RlmtMode = 0;
++ if (pAC->GIni.GIMacsFound == 2) {
++ pAC->RlmtMode = SK_RLMT_CHECK_LINK;
++ pAC->RlmtNets = 2;
++ }
+ } else if (strcmp(RlmtMode[pAC->Index], "CheckLinkState") == 0) {
+ pAC->RlmtMode = SK_RLMT_CHECK_LINK;
+ } else if (strcmp(RlmtMode[pAC->Index], "CheckLocalPort") == 0) {
+@@ -4120,12 +4743,37 @@
+ pAC->RlmtMode = 0;
+ }
+ } else {
+- pAC->RlmtMode = 0;
++ if (pAC->GIni.GIMacsFound == 2) {
++ pAC->RlmtMode = SK_RLMT_CHECK_LINK;
++ pAC->RlmtNets = 2;
++ }
+ }
+-
++
++#ifdef SK_YUKON2
++ /*
++ ** use dualnet config per default
++ *
++ pAC->RlmtMode = SK_RLMT_CHECK_LINK;
++ pAC->RlmtNets = 2;
++ */
++#endif
++
++
++ /*
++ ** Check the LowLatance parameters
++ */
++ pAC->LowLatency = SK_FALSE;
++ if (LowLatency[pAC->Index] != NULL) {
++ if (strcmp(LowLatency[pAC->Index], "On") == 0) {
++ pAC->LowLatency = SK_TRUE;
++ }
++ }
++
++
+ /*
+ ** Check the interrupt moderation parameters
+ */
++ pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE;
+ if (Moderation[pAC->Index] != NULL) {
+ if (strcmp(Moderation[pAC->Index], "") == 0) {
+ pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE;
+@@ -4139,70 +4787,49 @@
+ printk("sk98lin: Illegal value \"%s\" for Moderation.\n"
+ " Disable interrupt moderation.\n",
+ Moderation[pAC->Index]);
+- pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE;
+- }
+- } else {
+- pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE;
+- }
+-
+- if (Stats[pAC->Index] != NULL) {
+- if (strcmp(Stats[pAC->Index], "Yes") == 0) {
+- pAC->DynIrqModInfo.DisplayStats = SK_TRUE;
+- } else {
+- pAC->DynIrqModInfo.DisplayStats = SK_FALSE;
+ }
+ } else {
+- pAC->DynIrqModInfo.DisplayStats = SK_FALSE;
++/* Set interrupt moderation if wished */
++#ifdef CONFIG_SK98LIN_STATINT
++ pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_STATIC;
++#endif
+ }
+
+ if (ModerationMask[pAC->Index] != NULL) {
+ if (strcmp(ModerationMask[pAC->Index], "Rx") == 0) {
+- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_ONLY;
++ IrqModMaskOffset = 0;
+ } else if (strcmp(ModerationMask[pAC->Index], "Tx") == 0) {
+- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_TX_ONLY;
++ IrqModMaskOffset = 1;
+ } else if (strcmp(ModerationMask[pAC->Index], "Sp") == 0) {
+- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_ONLY;
++ IrqModMaskOffset = 2;
+ } else if (strcmp(ModerationMask[pAC->Index], "RxSp") == 0) {
+- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_RX;
++ IrqModMaskOffset = 3;
+ } else if (strcmp(ModerationMask[pAC->Index], "SpRx") == 0) {
+- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_RX;
++ IrqModMaskOffset = 3;
+ } else if (strcmp(ModerationMask[pAC->Index], "RxTx") == 0) {
+- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_TX_RX;
++ IrqModMaskOffset = 4;
+ } else if (strcmp(ModerationMask[pAC->Index], "TxRx") == 0) {
+- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_TX_RX;
++ IrqModMaskOffset = 4;
+ } else if (strcmp(ModerationMask[pAC->Index], "TxSp") == 0) {
+- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_TX;
++ IrqModMaskOffset = 5;
+ } else if (strcmp(ModerationMask[pAC->Index], "SpTx") == 0) {
+- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_TX;
+- } else if (strcmp(ModerationMask[pAC->Index], "RxTxSp") == 0) {
+- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
+- } else if (strcmp(ModerationMask[pAC->Index], "RxSpTx") == 0) {
+- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
+- } else if (strcmp(ModerationMask[pAC->Index], "TxRxSp") == 0) {
+- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
+- } else if (strcmp(ModerationMask[pAC->Index], "TxSpRx") == 0) {
+- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
+- } else if (strcmp(ModerationMask[pAC->Index], "SpTxRx") == 0) {
+- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
+- } else if (strcmp(ModerationMask[pAC->Index], "SpRxTx") == 0) {
+- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP;
+- } else { /* some rubbish */
+- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_ONLY;
+- }
+- } else { /* operator has stated nothing */
+- pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_TX_RX;
+- }
+-
+- if (AutoSizing[pAC->Index] != NULL) {
+- if (strcmp(AutoSizing[pAC->Index], "On") == 0) {
+- pAC->DynIrqModInfo.AutoSizing = SK_FALSE;
+- } else {
+- pAC->DynIrqModInfo.AutoSizing = SK_FALSE;
++ IrqModMaskOffset = 5;
++ } else { /* some rubbish stated */
++ // IrqModMaskOffset = 6; ->has been initialized
++ // already at the begin of this function...
+ }
+- } else { /* operator has stated nothing */
+- pAC->DynIrqModInfo.AutoSizing = SK_FALSE;
++ }
++ if (!CHIP_ID_YUKON_2(pAC)) {
++ pAC->DynIrqModInfo.MaskIrqModeration = IrqModMask[IrqModMaskOffset][0];
++ } else {
++ pAC->DynIrqModInfo.MaskIrqModeration = IrqModMask[IrqModMaskOffset][1];
+ }
+
++ if (!CHIP_ID_YUKON_2(pAC)) {
++ pAC->DynIrqModInfo.MaxModIntsPerSec = C_INTS_PER_SEC_DEFAULT;
++ } else {
++ pAC->DynIrqModInfo.MaxModIntsPerSec = C_Y2_INTS_PER_SEC_DEFAULT;
++ }
+ if (IntsPerSec[pAC->Index] != 0) {
+ if ((IntsPerSec[pAC->Index]< C_INT_MOD_IPS_LOWER_RANGE) ||
+ (IntsPerSec[pAC->Index] > C_INT_MOD_IPS_UPPER_RANGE)) {
+@@ -4211,28 +4838,25 @@
+ IntsPerSec[pAC->Index],
+ C_INT_MOD_IPS_LOWER_RANGE,
+ C_INT_MOD_IPS_UPPER_RANGE,
+- C_INTS_PER_SEC_DEFAULT);
+- pAC->DynIrqModInfo.MaxModIntsPerSec = C_INTS_PER_SEC_DEFAULT;
++ pAC->DynIrqModInfo.MaxModIntsPerSec);
+ } else {
+ pAC->DynIrqModInfo.MaxModIntsPerSec = IntsPerSec[pAC->Index];
+ }
+- } else {
+- pAC->DynIrqModInfo.MaxModIntsPerSec = C_INTS_PER_SEC_DEFAULT;
+- }
++ }
+
+ /*
+ ** Evaluate upper and lower moderation threshold
+ */
+ pAC->DynIrqModInfo.MaxModIntsPerSecUpperLimit =
+ pAC->DynIrqModInfo.MaxModIntsPerSec +
+- (pAC->DynIrqModInfo.MaxModIntsPerSec / 2);
++ (pAC->DynIrqModInfo.MaxModIntsPerSec / 5);
+
+ pAC->DynIrqModInfo.MaxModIntsPerSecLowerLimit =
+ pAC->DynIrqModInfo.MaxModIntsPerSec -
+- (pAC->DynIrqModInfo.MaxModIntsPerSec / 2);
+-
+- pAC->DynIrqModInfo.PrevTimeVal = jiffies; /* initial value */
++ (pAC->DynIrqModInfo.MaxModIntsPerSec / 5);
+
++ pAC->DynIrqModInfo.DynIrqModSampleInterval =
++ SK_DRV_MODERATION_TIMER_LENGTH;
+
+ } /* GetConfiguration */
+
+@@ -4247,66 +4871,22 @@
+ *
+ * Returns: N/A
+ */
+-static void ProductStr(
+-SK_AC *pAC /* pointer to adapter context */
+-)
+-{
+-int StrLen = 80; /* length of the string, defined in SK_AC */
+-char Keyword[] = VPD_NAME; /* vpd productname identifier */
+-int ReturnCode; /* return code from vpd_read */
+-unsigned long Flags;
++static void ProductStr(SK_AC *pAC)
++{
++ char Default[] = "Generic Marvell Yukon chipset Ethernet device";
++ char Key[] = VPD_NAME; /* VPD productname key */
++ int StrLen = 80; /* stringlen */
++ unsigned long Flags;
+
+ spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+- ReturnCode = VpdRead(pAC, pAC->IoBase, Keyword, pAC->DeviceStr,
+- &StrLen);
+- spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+- if (ReturnCode != 0) {
+- /* there was an error reading the vpd data */
++ if (VpdRead(pAC, pAC->IoBase, Key, pAC->DeviceStr, &StrLen)) {
+ SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ERROR,
+ ("Error reading VPD data: %d\n", ReturnCode));
+- pAC->DeviceStr[0] = '\0';
++ strcpy(pAC->DeviceStr, Default);
+ }
++ spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+ } /* ProductStr */
+
+-/*****************************************************************************
+- *
+- * StartDrvCleanupTimer - Start timer to check for descriptors which
+- * might be placed in descriptor ring, but
+- * havent been handled up to now
+- *
+- * Description:
+- * This function requests a HW-timer fo the Yukon card. The actions to
+- * perform when this timer expires, are located in the SkDrvEvent().
+- *
+- * Returns: N/A
+- */
+-static void
+-StartDrvCleanupTimer(SK_AC *pAC) {
+- SK_EVPARA EventParam; /* Event struct for timer event */
+-
+- SK_MEMSET((char *) &EventParam, 0, sizeof(EventParam));
+- EventParam.Para32[0] = SK_DRV_RX_CLEANUP_TIMER;
+- SkTimerStart(pAC, pAC->IoBase, &pAC->DrvCleanupTimer,
+- SK_DRV_RX_CLEANUP_TIMER_LENGTH,
+- SKGE_DRV, SK_DRV_TIMER, EventParam);
+-}
+-
+-/*****************************************************************************
+- *
+- * StopDrvCleanupTimer - Stop timer to check for descriptors
+- *
+- * Description:
+- * This function requests a HW-timer fo the Yukon card. The actions to
+- * perform when this timer expires, are located in the SkDrvEvent().
+- *
+- * Returns: N/A
+- */
+-static void
+-StopDrvCleanupTimer(SK_AC *pAC) {
+- SkTimerStop(pAC, pAC->IoBase, &pAC->DrvCleanupTimer);
+- SK_MEMSET((char *) &pAC->DrvCleanupTimer, 0, sizeof(SK_TIMER));
+-}
+-
+ /****************************************************************************/
+ /* functions for common modules *********************************************/
+ /****************************************************************************/
+@@ -4395,7 +4975,9 @@
+ SK_U64 SkOsGetTime(SK_AC *pAC)
+ {
+ SK_U64 PrivateJiffies;
++
+ SkOsGetTimeCurrent(pAC, &PrivateJiffies);
++
+ return PrivateJiffies;
+ } /* SkOsGetTime */
+
+@@ -4550,29 +5132,26 @@
+ *
+ */
+ int SkDrvEvent(
+-SK_AC *pAC, /* pointer to adapter context */
+-SK_IOC IoC, /* io-context */
+-SK_U32 Event, /* event-id */
+-SK_EVPARA Param) /* event-parameter */
+-{
+-SK_MBUF *pRlmtMbuf; /* pointer to a rlmt-mbuf structure */
+-struct sk_buff *pMsg; /* pointer to a message block */
+-int FromPort; /* the port from which we switch away */
+-int ToPort; /* the port we switch to */
+-SK_EVPARA NewPara; /* parameter for further events */
+-int Stat;
+-unsigned long Flags;
+-SK_BOOL DualNet;
++SK_AC *pAC, /* pointer to adapter context */
++SK_IOC IoC, /* IO control context */
++SK_U32 Event, /* event-id */
++SK_EVPARA Param) /* event-parameter */
++{
++ SK_MBUF *pRlmtMbuf; /* pointer to a rlmt-mbuf structure */
++ struct sk_buff *pMsg; /* pointer to a message block */
++ SK_BOOL DualNet;
++ SK_U32 Reason;
++ unsigned long Flags;
++ int FromPort; /* the port from which we switch away */
++ int ToPort; /* the port we switch to */
++ int Stat;
++ DEV_NET *pNet = NULL;
++#ifdef CONFIG_SK98LIN_NAPI
++ int WorkToDo = 1; /* min(*budget, dev->quota); */
++ int WorkDone = 0;
++#endif
+
+ switch (Event) {
+- case SK_DRV_ADAP_FAIL:
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
+- ("ADAPTER FAIL EVENT\n"));
+- printk("%s: Adapter failed.\n", pAC->dev[0]->name);
+- /* disable interrupts */
+- SK_OUT32(pAC->IoBase, B0_IMSK, 0);
+- /* cgoos */
+- break;
+ case SK_DRV_PORT_FAIL:
+ FromPort = Param.Para32[0];
+ SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
+@@ -4582,222 +5161,294 @@
+ } else {
+ printk("%s: Port B failed.\n", pAC->dev[1]->name);
+ }
+- /* cgoos */
+ break;
+- case SK_DRV_PORT_RESET: /* SK_U32 PortIdx */
+- /* action list 4 */
++ case SK_DRV_PORT_RESET:
+ FromPort = Param.Para32[0];
+ SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
+ ("PORT RESET EVENT, Port: %d ", FromPort));
+- NewPara.Para64 = FromPort;
+- SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_XMAC_RESET, NewPara);
++ SkLocalEventQueue64(pAC, SKGE_PNMI, SK_PNMI_EVT_XMAC_RESET,
++ FromPort, SK_FALSE);
+ spin_lock_irqsave(
+ &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
+ Flags);
+-
+- SkGeStopPort(pAC, IoC, FromPort, SK_STOP_ALL, SK_HARD_RST);
++ if (CHIP_ID_YUKON_2(pAC)) {
++ SkY2PortStop(pAC, IoC, FromPort, SK_STOP_ALL, SK_HARD_RST);
++ } else {
++ SkGeStopPort(pAC, IoC, FromPort, SK_STOP_ALL, SK_HARD_RST);
++ }
+ pAC->dev[Param.Para32[0]]->flags &= ~IFF_RUNNING;
+ spin_unlock_irqrestore(
+ &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
+ Flags);
+
+- /* clear rx ring from received frames */
+- ReceiveIrq(pAC, &pAC->RxPort[FromPort], SK_FALSE);
+-
+- ClearTxRing(pAC, &pAC->TxPort[FromPort][TX_PRIO_LOW]);
++ if (!CHIP_ID_YUKON_2(pAC)) {
++#ifdef CONFIG_SK98LIN_NAPI
++ WorkToDo = 1;
++ ReceiveIrq(pAC, &pAC->RxPort[FromPort], SK_FALSE, &WorkDone, WorkToDo);
++#else
++ ReceiveIrq(pAC, &pAC->RxPort[FromPort], SK_FALSE);
++#endif
++ ClearTxRing(pAC, &pAC->TxPort[FromPort][TX_PRIO_LOW]);
++ }
+ spin_lock_irqsave(
+ &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
+ Flags);
+-
+- /* tschilling: Handling of return value inserted. */
+- if (SkGeInitPort(pAC, IoC, FromPort)) {
+- if (FromPort == 0) {
+- printk("%s: SkGeInitPort A failed.\n", pAC->dev[0]->name);
++
++#ifdef USE_TIST_FOR_RESET
++ if (pAC->GIni.GIYukon2) {
++#ifdef Y2_RECOVERY
++ /* for Yukon II we want to have tist enabled all the time */
++ if (!SK_ADAPTER_WAITING_FOR_TIST(pAC)) {
++ Y2_ENABLE_TIST(pAC->IoBase);
++ }
++#else
++ /* make sure that we do not accept any status LEs from now on */
++ if (SK_ADAPTER_WAITING_FOR_TIST(pAC)) {
++#endif
++ /* port already waiting for tist */
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DUMP,
++ ("Port %c is now waiting for specific Tist\n",
++ 'A' + FromPort));
++ SK_SET_WAIT_BIT_FOR_PORT(
++ pAC,
++ SK_PSTATE_WAITING_FOR_SPECIFIC_TIST,
++ FromPort);
++ /* get current timestamp */
++ Y2_GET_TIST_LOW_VAL(pAC->IoBase, &pAC->MinTistLo);
++ pAC->MinTistHi = pAC->GIni.GITimeStampCnt;
++#ifndef Y2_RECOVERY
+ } else {
+- printk("%s: SkGeInitPort B failed.\n", pAC->dev[1]->name);
++ /* nobody is waiting yet */
++ SK_SET_WAIT_BIT_FOR_PORT(
++ pAC,
++ SK_PSTATE_WAITING_FOR_ANY_TIST,
++ FromPort);
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DUMP,
++ ("Port %c is now waiting for any Tist (0x%X)\n",
++ 'A' + FromPort, pAC->AdapterResetState));
++ /* start tist */
++ Y2_ENABLE_TIST(pAC-IoBase);
++ }
++#endif
++ }
++#endif
++
++#ifdef Y2_LE_CHECK
++ /* mark entries invalid */
++ pAC->LastPort = 3;
++ pAC->LastOpc = 0xFF;
++#endif
++ if (CHIP_ID_YUKON_2(pAC)) {
++ SkY2PortStart(pAC, IoC, FromPort);
++ } else {
++ /* tschilling: Handling of return value inserted. */
++ if (SkGeInitPort(pAC, IoC, FromPort)) {
++ if (FromPort == 0) {
++ printk("%s: SkGeInitPort A failed.\n", pAC->dev[0]->name);
++ } else {
++ printk("%s: SkGeInitPort B failed.\n", pAC->dev[1]->name);
++ }
+ }
++ SkAddrMcUpdate(pAC,IoC, FromPort);
++ PortReInitBmu(pAC, FromPort);
++ SkGePollTxD(pAC, IoC, FromPort, SK_TRUE);
++ CLEAR_AND_START_RX(FromPort);
+ }
+- SkAddrMcUpdate(pAC,IoC, FromPort);
+- PortReInitBmu(pAC, FromPort);
+- SkGePollTxD(pAC, IoC, FromPort, SK_TRUE);
+- ClearAndStartRx(pAC, FromPort);
+ spin_unlock_irqrestore(
+ &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
+ Flags);
+ break;
+- case SK_DRV_NET_UP: /* SK_U32 PortIdx */
+- /* action list 5 */
++ case SK_DRV_NET_UP:
+ FromPort = Param.Para32[0];
+ SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
+- ("NET UP EVENT, Port: %d ", Param.Para32[0]));
+- /* Mac update */
+- SkAddrMcUpdate(pAC,IoC, FromPort);
+-
++ ("NET UP EVENT, Port: %d ", FromPort));
++ SkAddrMcUpdate(pAC,IoC, FromPort); /* Mac update */
+ if (DoPrintInterfaceChange) {
+- printk("%s: network connection up using"
+- " port %c\n", pAC->dev[Param.Para32[0]]->name, 'A'+Param.Para32[0]);
++ printk("%s: network connection up using port %c\n",
++ pAC->dev[FromPort]->name, 'A'+FromPort);
+
+- /* tschilling: Values changed according to LinkSpeedUsed. */
+- Stat = pAC->GIni.GP[FromPort].PLinkSpeedUsed;
+- if (Stat == SK_LSPEED_STAT_10MBPS) {
+- printk(" speed: 10\n");
+- } else if (Stat == SK_LSPEED_STAT_100MBPS) {
+- printk(" speed: 100\n");
+- } else if (Stat == SK_LSPEED_STAT_1000MBPS) {
+- printk(" speed: 1000\n");
+- } else {
+- printk(" speed: unknown\n");
+- }
++ /* tschilling: Values changed according to LinkSpeedUsed. */
++ Stat = pAC->GIni.GP[FromPort].PLinkSpeedUsed;
++ if (Stat == SK_LSPEED_STAT_10MBPS) {
++ printk(" speed: 10\n");
++ } else if (Stat == SK_LSPEED_STAT_100MBPS) {
++ printk(" speed: 100\n");
++ } else if (Stat == SK_LSPEED_STAT_1000MBPS) {
++ printk(" speed: 1000\n");
++ } else {
++ printk(" speed: unknown\n");
++ }
+
++ Stat = pAC->GIni.GP[FromPort].PLinkModeStatus;
++ if ((Stat == SK_LMODE_STAT_AUTOHALF) ||
++ (Stat == SK_LMODE_STAT_AUTOFULL)) {
++ printk(" autonegotiation: yes\n");
++ } else {
++ printk(" autonegotiation: no\n");
++ }
+
+- Stat = pAC->GIni.GP[FromPort].PLinkModeStatus;
+- if (Stat == SK_LMODE_STAT_AUTOHALF ||
+- Stat == SK_LMODE_STAT_AUTOFULL) {
+- printk(" autonegotiation: yes\n");
+- }
+- else {
+- printk(" autonegotiation: no\n");
+- }
+- if (Stat == SK_LMODE_STAT_AUTOHALF ||
+- Stat == SK_LMODE_STAT_HALF) {
+- printk(" duplex mode: half\n");
+- }
+- else {
+- printk(" duplex mode: full\n");
+- }
+- Stat = pAC->GIni.GP[FromPort].PFlowCtrlStatus;
+- if (Stat == SK_FLOW_STAT_REM_SEND ) {
+- printk(" flowctrl: remote send\n");
+- }
+- else if (Stat == SK_FLOW_STAT_LOC_SEND ){
+- printk(" flowctrl: local send\n");
+- }
+- else if (Stat == SK_FLOW_STAT_SYMMETRIC ){
+- printk(" flowctrl: symmetric\n");
+- }
+- else {
+- printk(" flowctrl: none\n");
+- }
+-
+- /* tschilling: Check against CopperType now. */
+- if ((pAC->GIni.GICopperType == SK_TRUE) &&
+- (pAC->GIni.GP[FromPort].PLinkSpeedUsed ==
+- SK_LSPEED_STAT_1000MBPS)) {
+- Stat = pAC->GIni.GP[FromPort].PMSStatus;
+- if (Stat == SK_MS_STAT_MASTER ) {
+- printk(" role: master\n");
++ if ((Stat == SK_LMODE_STAT_AUTOHALF) ||
++ (Stat == SK_LMODE_STAT_HALF)) {
++ printk(" duplex mode: half\n");
++ } else {
++ printk(" duplex mode: full\n");
+ }
+- else if (Stat == SK_MS_STAT_SLAVE ) {
+- printk(" role: slave\n");
++
++ Stat = pAC->GIni.GP[FromPort].PFlowCtrlStatus;
++ if (Stat == SK_FLOW_STAT_REM_SEND ) {
++ printk(" flowctrl: remote send\n");
++ } else if (Stat == SK_FLOW_STAT_LOC_SEND ) {
++ printk(" flowctrl: local send\n");
++ } else if (Stat == SK_FLOW_STAT_SYMMETRIC ) {
++ printk(" flowctrl: symmetric\n");
++ } else {
++ printk(" flowctrl: none\n");
+ }
+- else {
+- printk(" role: ???\n");
++
++ /* tschilling: Check against CopperType now. */
++ if ((pAC->GIni.GICopperType == SK_TRUE) &&
++ (pAC->GIni.GP[FromPort].PLinkSpeedUsed ==
++ SK_LSPEED_STAT_1000MBPS)) {
++ Stat = pAC->GIni.GP[FromPort].PMSStatus;
++ if (Stat == SK_MS_STAT_MASTER ) {
++ printk(" role: master\n");
++ } else if (Stat == SK_MS_STAT_SLAVE ) {
++ printk(" role: slave\n");
++ } else {
++ printk(" role: ???\n");
++ }
+ }
+- }
+
+- /*
+- Display dim (dynamic interrupt moderation)
+- informations
+- */
+- if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_STATIC)
+- printk(" irq moderation: static (%d ints/sec)\n",
++ /* Display interrupt moderation informations */
++ if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_STATIC) {
++ printk(" irq moderation: static (%d ints/sec)\n",
+ pAC->DynIrqModInfo.MaxModIntsPerSec);
+- else if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_DYNAMIC)
+- printk(" irq moderation: dynamic (%d ints/sec)\n",
++ } else if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_DYNAMIC) {
++ printk(" irq moderation: dynamic (%d ints/sec)\n",
+ pAC->DynIrqModInfo.MaxModIntsPerSec);
+- else
+- printk(" irq moderation: disabled\n");
++ } else {
++ printk(" irq moderation: disabled\n");
++ }
++
++#ifdef NETIF_F_TSO
++ if (CHIP_ID_YUKON_2(pAC)) {
++ if (pAC->dev[FromPort]->features & NETIF_F_TSO) {
++ printk(" tcp offload: enabled\n");
++ } else {
++ printk(" tcp offload: disabled\n");
++ }
++ }
++#endif
+
++ if (pAC->dev[FromPort]->features & NETIF_F_SG) {
++ printk(" scatter-gather: enabled\n");
++ } else {
++ printk(" scatter-gather: disabled\n");
++ }
+
+-#ifdef SK_ZEROCOPY
+- if (pAC->ChipsetType)
+-#ifdef USE_SK_TX_CHECKSUM
+- printk(" scatter-gather: enabled\n");
+-#else
+- printk(" tx-checksum: disabled\n");
+-#endif
+- else
+- printk(" scatter-gather: disabled\n");
+-#else
+- printk(" scatter-gather: disabled\n");
+-#endif
++ if (pAC->dev[FromPort]->features & NETIF_F_IP_CSUM) {
++ printk(" tx-checksum: enabled\n");
++ } else {
++ printk(" tx-checksum: disabled\n");
++ }
+
+-#ifndef USE_SK_RX_CHECKSUM
+- printk(" rx-checksum: disabled\n");
++ if (pAC->RxPort[FromPort].UseRxCsum) {
++ printk(" rx-checksum: enabled\n");
++ } else {
++ printk(" rx-checksum: disabled\n");
++ }
++#ifdef CONFIG_SK98LIN_NAPI
++ printk(" rx-polling: enabled\n");
+ #endif
+-
++ if (pAC->LowLatency) {
++ printk(" low latency: enabled\n");
++ }
+ } else {
+- DoPrintInterfaceChange = SK_TRUE;
+- }
++ DoPrintInterfaceChange = SK_TRUE;
++ }
+
+- if ((Param.Para32[0] != pAC->ActivePort) &&
+- (pAC->RlmtNets == 1)) {
+- NewPara.Para32[0] = pAC->ActivePort;
+- NewPara.Para32[1] = Param.Para32[0];
+- SkEventQueue(pAC, SKGE_DRV, SK_DRV_SWITCH_INTERN,
+- NewPara);
++ if ((FromPort != pAC->ActivePort)&&(pAC->RlmtNets == 1)) {
++ SkLocalEventQueue(pAC, SKGE_DRV, SK_DRV_SWITCH_INTERN,
++ pAC->ActivePort, FromPort, SK_FALSE);
+ }
+
+ /* Inform the world that link protocol is up. */
+- pAC->dev[Param.Para32[0]]->flags |= IFF_RUNNING;
+-
++ netif_wake_queue(pAC->dev[FromPort]);
++ netif_carrier_on(pAC->dev[FromPort]);
++ pAC->dev[FromPort]->flags |= IFF_RUNNING;
+ break;
+- case SK_DRV_NET_DOWN: /* SK_U32 Reason */
+- /* action list 7 */
++ case SK_DRV_NET_DOWN:
++ Reason = Param.Para32[0];
++ FromPort = Param.Para32[1];
+ SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
+ ("NET DOWN EVENT "));
++
++ /* Stop queue and carrier */
++ netif_stop_queue(pAC->dev[FromPort]);
++ netif_carrier_off(pAC->dev[FromPort]);
++
++ /* Print link change */
+ if (DoPrintInterfaceChange) {
+- printk("%s: network connection down\n",
+- pAC->dev[Param.Para32[1]]->name);
++ if (pAC->dev[FromPort]->flags & IFF_RUNNING) {
++ printk("%s: network connection down\n",
++ pAC->dev[FromPort]->name);
++ }
+ } else {
+ DoPrintInterfaceChange = SK_TRUE;
+ }
+- pAC->dev[Param.Para32[1]]->flags &= ~IFF_RUNNING;
++ pAC->dev[FromPort]->flags &= ~IFF_RUNNING;
+ break;
+- case SK_DRV_SWITCH_HARD: /* SK_U32 FromPortIdx SK_U32 ToPortIdx */
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
+- ("PORT SWITCH HARD "));
+- case SK_DRV_SWITCH_SOFT: /* SK_U32 FromPortIdx SK_U32 ToPortIdx */
+- /* action list 6 */
+- printk("%s: switching to port %c\n", pAC->dev[0]->name,
+- 'A'+Param.Para32[1]);
+- case SK_DRV_SWITCH_INTERN: /* SK_U32 FromPortIdx SK_U32 ToPortIdx */
++ case SK_DRV_SWITCH_HARD: /* FALL THRU */
++ case SK_DRV_SWITCH_SOFT: /* FALL THRU */
++ case SK_DRV_SWITCH_INTERN:
+ FromPort = Param.Para32[0];
+- ToPort = Param.Para32[1];
++ ToPort = Param.Para32[1];
++ printk("%s: switching from port %c to port %c\n",
++ pAC->dev[0]->name, 'A'+FromPort, 'A'+ToPort);
+ SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
+ ("PORT SWITCH EVENT, From: %d To: %d (Pref %d) ",
+ FromPort, ToPort, pAC->Rlmt.Net[0].PrefPort));
+- NewPara.Para64 = FromPort;
+- SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_XMAC_RESET, NewPara);
+- NewPara.Para64 = ToPort;
+- SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_XMAC_RESET, NewPara);
++ SkLocalEventQueue64(pAC, SKGE_PNMI, SK_PNMI_EVT_XMAC_RESET,
++ FromPort, SK_FALSE);
++ SkLocalEventQueue64(pAC, SKGE_PNMI, SK_PNMI_EVT_XMAC_RESET,
++ ToPort, SK_FALSE);
+ spin_lock_irqsave(
+ &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
+ Flags);
+- spin_lock_irqsave(
+- &pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock, Flags);
+- SkGeStopPort(pAC, IoC, FromPort, SK_STOP_ALL, SK_SOFT_RST);
+- SkGeStopPort(pAC, IoC, ToPort, SK_STOP_ALL, SK_SOFT_RST);
+- spin_unlock_irqrestore(
+- &pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock, Flags);
++ spin_lock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
++ if (CHIP_ID_YUKON_2(pAC)) {
++ SkY2PortStop(pAC, IoC, FromPort, SK_STOP_ALL, SK_SOFT_RST);
++ SkY2PortStop(pAC, IoC, ToPort, SK_STOP_ALL, SK_SOFT_RST);
++ }
++ else {
++ SkGeStopPort(pAC, IoC, FromPort, SK_STOP_ALL, SK_SOFT_RST);
++ SkGeStopPort(pAC, IoC, ToPort, SK_STOP_ALL, SK_SOFT_RST);
++ }
++ spin_unlock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
+ spin_unlock_irqrestore(
+ &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
+ Flags);
+
+- ReceiveIrq(pAC, &pAC->RxPort[FromPort], SK_FALSE); /* clears rx ring */
+- ReceiveIrq(pAC, &pAC->RxPort[ToPort], SK_FALSE); /* clears rx ring */
+
+- ClearTxRing(pAC, &pAC->TxPort[FromPort][TX_PRIO_LOW]);
+- ClearTxRing(pAC, &pAC->TxPort[ToPort][TX_PRIO_LOW]);
++ if (!CHIP_ID_YUKON_2(pAC)) {
++#ifdef CONFIG_SK98LIN_NAPI
++ WorkToDo = 1;
++ ReceiveIrq(pAC, &pAC->RxPort[FromPort], SK_FALSE, &WorkDone, WorkToDo);
++ ReceiveIrq(pAC, &pAC->RxPort[ToPort], SK_FALSE, &WorkDone, WorkToDo);
++#else
++ ReceiveIrq(pAC, &pAC->RxPort[FromPort], SK_FALSE); /* clears rx ring */
++ ReceiveIrq(pAC, &pAC->RxPort[ToPort], SK_FALSE); /* clears rx ring */
++#endif
++ ClearTxRing(pAC, &pAC->TxPort[FromPort][TX_PRIO_LOW]);
++ ClearTxRing(pAC, &pAC->TxPort[ToPort][TX_PRIO_LOW]);
++ }
++
+ spin_lock_irqsave(
+ &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
+ Flags);
+- spin_lock_irqsave(
+- &pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock, Flags);
++ spin_lock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
+ pAC->ActivePort = ToPort;
+-#if 0
+- SetQueueSizes(pAC);
+-#else
++
+ /* tschilling: New common function with minimum size check. */
+ DualNet = SK_FALSE;
+ if (pAC->RlmtNets == 2) {
+@@ -4808,85 +5459,345 @@
+ pAC,
+ pAC->ActivePort,
+ DualNet)) {
+- spin_unlock_irqrestore(
+- &pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock, Flags);
++ spin_unlock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
+ spin_unlock_irqrestore(
+ &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
+ Flags);
+ printk("SkGeInitAssignRamToQueues failed.\n");
+ break;
+ }
+-#endif
+- /* tschilling: Handling of return values inserted. */
+- if (SkGeInitPort(pAC, IoC, FromPort) ||
+- SkGeInitPort(pAC, IoC, ToPort)) {
+- printk("%s: SkGeInitPort failed.\n", pAC->dev[0]->name);
++
++ if (!CHIP_ID_YUKON_2(pAC)) {
++ /* tschilling: Handling of return values inserted. */
++ if (SkGeInitPort(pAC, IoC, FromPort) ||
++ SkGeInitPort(pAC, IoC, ToPort)) {
++ printk("%s: SkGeInitPort failed.\n", pAC->dev[0]->name);
++ }
+ }
+- if (Event == SK_DRV_SWITCH_SOFT) {
+- SkMacRxTxEnable(pAC, IoC, FromPort);
++ if (!CHIP_ID_YUKON_2(pAC)) {
++ if (Event == SK_DRV_SWITCH_SOFT) {
++ SkMacRxTxEnable(pAC, IoC, FromPort);
++ }
++ SkMacRxTxEnable(pAC, IoC, ToPort);
+ }
+- SkMacRxTxEnable(pAC, IoC, ToPort);
++
+ SkAddrSwap(pAC, IoC, FromPort, ToPort);
+ SkAddrMcUpdate(pAC, IoC, FromPort);
+ SkAddrMcUpdate(pAC, IoC, ToPort);
+- PortReInitBmu(pAC, FromPort);
+- PortReInitBmu(pAC, ToPort);
+- SkGePollTxD(pAC, IoC, FromPort, SK_TRUE);
+- SkGePollTxD(pAC, IoC, ToPort, SK_TRUE);
+- ClearAndStartRx(pAC, FromPort);
+- ClearAndStartRx(pAC, ToPort);
+- spin_unlock_irqrestore(
+- &pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock, Flags);
++
++#ifdef USE_TIST_FOR_RESET
++ if (pAC->GIni.GIYukon2) {
++ /* make sure that we do not accept any status LEs from now on */
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DUMP,
++ ("both Ports now waiting for specific Tist\n"));
++ SK_SET_WAIT_BIT_FOR_PORT(
++ pAC,
++ SK_PSTATE_WAITING_FOR_ANY_TIST,
++ 0);
++ SK_SET_WAIT_BIT_FOR_PORT(
++ pAC,
++ SK_PSTATE_WAITING_FOR_ANY_TIST,
++ 1);
++
++ /* start tist */
++ Y2_ENABLE_TIST(pAC->IoBase);
++ }
++#endif
++ if (!CHIP_ID_YUKON_2(pAC)) {
++ PortReInitBmu(pAC, FromPort);
++ PortReInitBmu(pAC, ToPort);
++ SkGePollTxD(pAC, IoC, FromPort, SK_TRUE);
++ SkGePollTxD(pAC, IoC, ToPort, SK_TRUE);
++ CLEAR_AND_START_RX(FromPort);
++ CLEAR_AND_START_RX(ToPort);
++ } else {
++ SkY2PortStart(pAC, IoC, FromPort);
++ SkY2PortStart(pAC, IoC, ToPort);
++#ifdef SK_YUKON2
++ /* in yukon-II always port 0 has to be started first */
++ // SkY2PortStart(pAC, IoC, 0);
++ // SkY2PortStart(pAC, IoC, 1);
++#endif
++ }
++ spin_unlock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock);
+ spin_unlock_irqrestore(
+ &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
+ Flags);
+ break;
+ case SK_DRV_RLMT_SEND: /* SK_MBUF *pMb */
+- SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
+- ("RLS "));
++ SK_DBG_MSG(NULL,SK_DBGMOD_DRV,SK_DBGCAT_DRV_EVENT,("RLS "));
+ pRlmtMbuf = (SK_MBUF*) Param.pParaPtr;
+ pMsg = (struct sk_buff*) pRlmtMbuf->pOs;
+ skb_put(pMsg, pRlmtMbuf->Length);
+- if (XmitFrame(pAC, &pAC->TxPort[pRlmtMbuf->PortIdx][TX_PRIO_LOW],
+- pMsg) < 0)
+-
+- DEV_KFREE_SKB_ANY(pMsg);
++ if (!CHIP_ID_YUKON_2(pAC)) {
++ if (XmitFrame(pAC, &pAC->TxPort[pRlmtMbuf->PortIdx][TX_PRIO_LOW],
++ pMsg) < 0) {
++ DEV_KFREE_SKB_ANY(pMsg);
++ }
++ } else {
++ if (SkY2RlmtSend(pAC, pRlmtMbuf->PortIdx, pMsg) < 0) {
++ DEV_KFREE_SKB_ANY(pMsg);
++ }
++ }
+ break;
+ case SK_DRV_TIMER:
+ if (Param.Para32[0] == SK_DRV_MODERATION_TIMER) {
+- /*
+- ** expiration of the moderation timer implies that
+- ** dynamic moderation is to be applied
+- */
++ /* check what IRQs are to be moderated */
+ SkDimStartModerationTimer(pAC);
+ SkDimModerate(pAC);
+- if (pAC->DynIrqModInfo.DisplayStats) {
+- SkDimDisplayModerationSettings(pAC);
+- }
+- } else if (Param.Para32[0] == SK_DRV_RX_CLEANUP_TIMER) {
+- /*
+- ** check if we need to check for descriptors which
+- ** haven't been handled the last millisecs
+- */
+- StartDrvCleanupTimer(pAC);
+- if (pAC->GIni.GIMacsFound == 2) {
+- ReceiveIrq(pAC, &pAC->RxPort[1], SK_FALSE);
+- }
+- ReceiveIrq(pAC, &pAC->RxPort[0], SK_FALSE);
+ } else {
+ printk("Expiration of unknown timer\n");
+ }
+ break;
++ case SK_DRV_ADAP_FAIL:
++#if (!defined (Y2_RECOVERY) && !defined (Y2_LE_CHECK))
++ SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
++ ("ADAPTER FAIL EVENT\n"));
++ printk("%s: Adapter failed.\n", pAC->dev[0]->name);
++ SK_OUT32(pAC->IoBase, B0_IMSK, 0); /* disable interrupts */
++ break;
++#endif
++
++#if (defined (Y2_RECOVERY) || defined (Y2_LE_CHECK))
++ case SK_DRV_RECOVER:
++ pNet = (DEV_NET *) pAC->dev[0]->priv;
++
++ /* Recover already in progress */
++ if (pNet->InRecover) {
++ break;
++ }
++
++ netif_stop_queue(pAC->dev[0]); /* stop device if running */
++ pNet->InRecover = SK_TRUE;
++
++ FromPort = Param.Para32[0];
++ SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
++ ("PORT RESET EVENT, Port: %d ", FromPort));
++
++ /* Disable interrupts */
++ SK_OUT32(pAC->IoBase, B0_IMSK, 0);
++ SK_OUT32(pAC->IoBase, B0_HWE_IMSK, 0);
++
++ SkLocalEventQueue64(pAC, SKGE_PNMI, SK_PNMI_EVT_XMAC_RESET,
++ FromPort, SK_FALSE);
++ spin_lock_irqsave(
++ &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
++ Flags);
++ if (CHIP_ID_YUKON_2(pAC)) {
++ if (pAC->GIni.GIMacsFound > 1) {
++ SkY2PortStop(pAC, IoC, 0, SK_STOP_ALL, SK_SOFT_RST);
++ SkY2PortStop(pAC, IoC, 1, SK_STOP_ALL, SK_SOFT_RST);
++ } else {
++ SkY2PortStop(pAC, IoC, FromPort, SK_STOP_ALL, SK_SOFT_RST);
++ }
++ } else {
++ SkGeStopPort(pAC, IoC, FromPort, SK_STOP_ALL, SK_SOFT_RST);
++ }
++ pAC->dev[Param.Para32[0]]->flags &= ~IFF_RUNNING;
++ spin_unlock_irqrestore(
++ &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
++ Flags);
++
++ if (!CHIP_ID_YUKON_2(pAC)) {
++#ifdef CONFIG_SK98LIN_NAPI
++ WorkToDo = 1;
++ ReceiveIrq(pAC, &pAC->RxPort[FromPort], SK_FALSE, &WorkDone, WorkToDo);
++#else
++ ReceiveIrq(pAC, &pAC->RxPort[FromPort], SK_FALSE);
++#endif
++ ClearTxRing(pAC, &pAC->TxPort[FromPort][TX_PRIO_LOW]);
++ }
++ spin_lock_irqsave(
++ &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
++ Flags);
++
++#ifdef USE_TIST_FOR_RESET
++ if (pAC->GIni.GIYukon2) {
++#if 0
++ /* make sure that we do not accept any status LEs from now on */
++ Y2_ENABLE_TIST(pAC->IoBase);
++
++ /* get current timestamp */
++ Y2_GET_TIST_LOW_VAL(pAC->IoBase, &pAC->MinTistLo);
++ pAC->MinTistHi = pAC->GIni.GITimeStampCnt;
++
++ SK_SET_WAIT_BIT_FOR_PORT(
++ pAC,
++ SK_PSTATE_WAITING_FOR_SPECIFIC_TIST,
++ FromPort);
++#endif
++ if (pAC->GIni.GIMacsFound > 1) {
++ SK_SET_WAIT_BIT_FOR_PORT(
++ pAC,
++ SK_PSTATE_WAITING_FOR_ANY_TIST,
++ 0);
++ SK_SET_WAIT_BIT_FOR_PORT(
++ pAC,
++ SK_PSTATE_WAITING_FOR_ANY_TIST,
++ 1);
++ } else {
++ SK_SET_WAIT_BIT_FOR_PORT(
++ pAC,
++ SK_PSTATE_WAITING_FOR_ANY_TIST,
++ FromPort);
++ }
++
++ /* start tist */
++ Y2_ENABLE_TIST(pAC->IoBase);
++ }
++#endif
++
++ /* Restart Receive BMU on Yukon-2 */
++ if (SkYuk2RestartRxBmu(pAC, IoC, FromPort)) {
++ printk("%s: SkYuk2RestartRxBmu failed.\n", pAC->dev[0]->name);
++ }
++
++
++#ifdef Y2_LE_CHECK
++ /* mark entries invalid */
++ pAC->LastPort = 3;
++ pAC->LastOpc = 0xFF;
++#endif
++
++#endif
++ /* Restart ports but do not initialize PHY. */
++ if (CHIP_ID_YUKON_2(pAC)) {
++ if (pAC->GIni.GIMacsFound > 1) {
++ SkY2PortStart(pAC, IoC, 0);
++ SkY2PortStart(pAC, IoC, 1);
++ } else {
++ SkY2PortStart(pAC, IoC, FromPort);
++ }
++ } else {
++ /* tschilling: Handling of return value inserted. */
++ if (SkGeInitPort(pAC, IoC, FromPort)) {
++ if (FromPort == 0) {
++ printk("%s: SkGeInitPort A failed.\n", pAC->dev[0]->name);
++ } else {
++ printk("%s: SkGeInitPort B failed.\n", pAC->dev[1]->name);
++ }
++ }
++ SkAddrMcUpdate(pAC,IoC, FromPort);
++ PortReInitBmu(pAC, FromPort);
++ SkGePollTxD(pAC, IoC, FromPort, SK_TRUE);
++ CLEAR_AND_START_RX(FromPort);
++ }
++ spin_unlock_irqrestore(
++ &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock,
++ Flags);
++
++ /* Map any waiting RX buffers to HW */
++ FillReceiveTableYukon2(pAC, pAC->IoBase, FromPort);
++
++ pNet->InRecover = SK_FALSE;
++ /* enable Interrupts */
++ SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask);
++ SK_OUT32(pAC->IoBase, B0_HWE_IMSK, IRQ_HWE_MASK);
++ netif_wake_queue(pAC->dev[0]);
++ break;
+ default:
+ break;
+ }
+ SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT,
+ ("END EVENT "));
+-
++
+ return (0);
+ } /* SkDrvEvent */
+
+
++/******************************************************************************
++ *
++ * SkLocalEventQueue() - add event to queue
++ *
++ * Description:
++ * This function adds an event to the event queue and run the
++ * SkEventDispatcher. At least Init Level 1 is required to queue events,
++ * but will be scheduled add Init Level 2.
++ *
++ * returns:
++ * nothing
++ */
++void SkLocalEventQueue(
++SK_AC *pAC, /* Adapters context */
++SK_U32 Class, /* Event Class */
++SK_U32 Event, /* Event to be queued */
++SK_U32 Param1, /* Event parameter 1 */
++SK_U32 Param2, /* Event parameter 2 */
++SK_BOOL Dispatcher) /* Dispatcher flag:
++ * TRUE == Call SkEventDispatcher
++ * FALSE == Don't execute SkEventDispatcher
++ */
++{
++ SK_EVPARA EvPara;
++ EvPara.Para32[0] = Param1;
++ EvPara.Para32[1] = Param2;
++
++
++ if (Class == SKGE_PNMI) {
++ SkPnmiEvent( pAC,
++ pAC->IoBase,
++ Event,
++ EvPara);
++ } else {
++ SkEventQueue( pAC,
++ Class,
++ Event,
++ EvPara);
++ }
++
++ /* Run the dispatcher */
++ if (Dispatcher) {
++ SkEventDispatcher(pAC, pAC->IoBase);
++ }
++
++}
++
++/******************************************************************************
++ *
++ * SkLocalEventQueue64() - add event to queue (64bit version)
++ *
++ * Description:
++ * This function adds an event to the event queue and run the
++ * SkEventDispatcher. At least Init Level 1 is required to queue events,
++ * but will be scheduled add Init Level 2.
++ *
++ * returns:
++ * nothing
++ */
++void SkLocalEventQueue64(
++SK_AC *pAC, /* Adapters context */
++SK_U32 Class, /* Event Class */
++SK_U32 Event, /* Event to be queued */
++SK_U64 Param, /* Event parameter */
++SK_BOOL Dispatcher) /* Dispatcher flag:
++ * TRUE == Call SkEventDispatcher
++ * FALSE == Don't execute SkEventDispatcher
++ */
++{
++ SK_EVPARA EvPara;
++ EvPara.Para64 = Param;
++
++
++ if (Class == SKGE_PNMI) {
++ SkPnmiEvent( pAC,
++ pAC->IoBase,
++ Event,
++ EvPara);
++ } else {
++ SkEventQueue( pAC,
++ Class,
++ Event,
++ EvPara);
++ }
++
++ /* Run the dispatcher */
++ if (Dispatcher) {
++ SkEventDispatcher(pAC, pAC->IoBase);
++ }
++
++}
++
++
+ /*****************************************************************************
+ *
+ * SkErrorLog - log errors
+@@ -4936,8 +5847,6 @@
+
+ } /* SkErrorLog */
+
+-#ifdef SK_DIAG_SUPPORT
+-
+ /*****************************************************************************
+ *
+ * SkDrvEnterDiagMode - handles DIAG attach request
+@@ -4963,7 +5872,7 @@
+
+ pAC->DiagModeActive = DIAG_ACTIVE;
+ if (pAC->BoardLevel > SK_INIT_DATA) {
+- if (pNet->Up) {
++ if (netif_running(pAC->dev[0])) {
+ pAC->WasIfUp[0] = SK_TRUE;
+ pAC->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */
+ DoPrintInterfaceChange = SK_FALSE;
+@@ -4971,9 +5880,10 @@
+ } else {
+ pAC->WasIfUp[0] = SK_FALSE;
+ }
++
+ if (pNet != (DEV_NET *) pAc->dev[1]->priv) {
+ pNet = (DEV_NET *) pAc->dev[1]->priv;
+- if (pNet->Up) {
++ if (netif_running(pAC->dev[1])) {
+ pAC->WasIfUp[1] = SK_TRUE;
+ pAC->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */
+ DoPrintInterfaceChange = SK_FALSE;
+@@ -5005,16 +5915,16 @@
+ sizeof(SK_PNMI_STRUCT_DATA));
+ pAc->DiagModeActive = DIAG_NOTACTIVE;
+ pAc->Pnmi.DiagAttached = SK_DIAG_IDLE;
+- if (pAc->WasIfUp[0] == SK_TRUE) {
+- pAc->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */
++ if (pAc->WasIfUp[0] == SK_TRUE) {
++ pAc->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */
+ DoPrintInterfaceChange = SK_FALSE;
+- SkDrvInitAdapter(pAc, 0); /* first device */
+- }
+- if (pAc->WasIfUp[1] == SK_TRUE) {
+- pAc->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */
++ SkDrvInitAdapter(pAc, 0); /* first device */
++ }
++ if (pAc->WasIfUp[1] == SK_TRUE) {
++ pAc->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */
+ DoPrintInterfaceChange = SK_FALSE;
+- SkDrvInitAdapter(pAc, 1); /* second device */
+- }
++ SkDrvInitAdapter(pAc, 1); /* second device */
++ }
+ return(0);
+ }
+
+@@ -5159,14 +6069,25 @@
+
+ } /* SkDrvInitAdapter */
+
+-#endif
++static int __init sk98lin_init(void)
++{
++ return pci_module_init(&sk98lin_driver);
++}
++
++static void __exit sk98lin_cleanup(void)
++{
++ pci_unregister_driver(&sk98lin_driver);
++}
++
++module_init(sk98lin_init);
++module_exit(sk98lin_cleanup);
++
+
+ #ifdef DEBUG
+ /****************************************************************************/
+ /* "debug only" section *****************************************************/
+ /****************************************************************************/
+
+-
+ /*****************************************************************************
+ *
+ * DumpMsg - print a frame
+@@ -5177,9 +6098,11 @@
+ * Returns: N/A
+ *
+ */
+-static void DumpMsg(struct sk_buff *skb, char *str)
++static void DumpMsg(
++struct sk_buff *skb, /* linux' socket buffer */
++char *str) /* additional msg string */
+ {
+- int msglen;
++ int msglen = (skb->len > 64) ? 64 : skb->len;
+
+ if (skb == NULL) {
+ printk("DumpMsg(): NULL-Message\n");
+@@ -5191,19 +6114,14 @@
+ return;
+ }
+
+- msglen = skb->len;
+- if (msglen > 64)
+- msglen = 64;
+-
+- printk("--- Begin of message from %s , len %d (from %d) ----\n", str, msglen, skb->len);
+-
++ printk("DumpMsg: PhysPage: %p\n",
++ page_address(virt_to_page(skb->data)));
++ printk("--- Begin of message from %s , len %d (from %d) ----\n",
++ str, msglen, skb->len);
+ DumpData((char *)skb->data, msglen);
+-
+ printk("------- End of message ---------\n");
+ } /* DumpMsg */
+
+-
+-
+ /*****************************************************************************
+ *
+ * DumpData - print a data area
+@@ -5215,23 +6133,22 @@
+ * Returns: N/A
+ *
+ */
+-static void DumpData(char *p, int size)
+-{
+-register int i;
+-int haddr, addr;
+-char hex_buffer[180];
+-char asc_buffer[180];
+-char HEXCHAR[] = "0123456789ABCDEF";
+-
+- addr = 0;
+- haddr = 0;
+- hex_buffer[0] = 0;
+- asc_buffer[0] = 0;
++static void DumpData(
++char *p, /* pointer to area containing the data */
++int size) /* the size of that data area in bytes */
++{
++ register int i;
++ int haddr = 0, addr = 0;
++ char hex_buffer[180] = { '\0' };
++ char asc_buffer[180] = { '\0' };
++ char HEXCHAR[] = "0123456789ABCDEF";
++
+ for (i=0; i < size; ) {
+- if (*p >= '0' && *p <='z')
++ if (*p >= '0' && *p <='z') {
+ asc_buffer[addr] = *p;
+- else
++ } else {
+ asc_buffer[addr] = '.';
++ }
+ addr++;
+ asc_buffer[addr] = 0;
+ hex_buffer[haddr] = HEXCHAR[(*p & 0xf0) >> 4];
+@@ -5257,27 +6174,24 @@
+ * DumpLong - print a data area as long values
+ *
+ * Description:
+- * This function prints a area of data to the system logfile/to the
++ * This function prints a long variable to the system logfile/to the
+ * console.
+ *
+ * Returns: N/A
+ *
+ */
+-static void DumpLong(char *pc, int size)
+-{
+-register int i;
+-int haddr, addr;
+-char hex_buffer[180];
+-char asc_buffer[180];
+-char HEXCHAR[] = "0123456789ABCDEF";
+-long *p;
+-int l;
+-
+- addr = 0;
+- haddr = 0;
+- hex_buffer[0] = 0;
+- asc_buffer[0] = 0;
+- p = (long*) pc;
++static void DumpLong(
++char *pc, /* location of the variable to print */
++int size) /* how large is the variable? */
++{
++ register int i;
++ int haddr = 0, addr = 0;
++ char hex_buffer[180] = { '\0' };
++ char asc_buffer[180] = { '\0' };
++ char HEXCHAR[] = "0123456789ABCDEF";
++ long *p = (long*) pc;
++ int l;
++
+ for (i=0; i < size; ) {
+ l = (long) *p;
+ hex_buffer[haddr] = HEXCHAR[(l >> 28) & 0xf];
+@@ -5316,3 +6230,4 @@
+ * End of file
+ *
+ ******************************************************************************/
++
+diff -ruN linux/drivers/net/sk98lin/skgehwt.c linux-new/drivers/net/sk98lin/skgehwt.c
+--- linux/drivers/net/sk98lin/skgehwt.c 2005-09-26 13:32:48.000000000 +0400
++++ linux-new/drivers/net/sk98lin/skgehwt.c 2005-08-09 17:15:51.000000000 +0400
+@@ -2,8 +2,8 @@
+ *
+ * Name: skgehwt.c
+ * Project: Gigabit Ethernet Adapters, Event Scheduler Module
+- * Version: $Revision: 1.15 $
+- * Date: $Date: 2003/09/16 13:41:23 $
++ * Version: $Revision: 2.2 $
++ * Date: $Date: 2004/05/28 13:39:04 $
+ * Purpose: Hardware Timer
+ *
+ ******************************************************************************/
+@@ -11,7 +11,7 @@
+ /******************************************************************************
+ *
+ * (C)Copyright 1998-2002 SysKonnect GmbH.
+- * (C)Copyright 2002-2003 Marvell.
++ * (C)Copyright 2002-2004 Marvell.
+ *
+ * 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
+@@ -27,7 +27,7 @@
+ */
+ #if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
+ static const char SysKonnectFileId[] =
+- "@(#) $Id: skgehwt.c,v 1.15 2003/09/16 13:41:23 rschmidt Exp $ (C) Marvell.";
++ "@(#) $Id: skgehwt.c,v 2.2 2004/05/28 13:39:04 rschmidt Exp $ (C) Marvell.";
+ #endif
+
+ #include "h/skdrv1st.h" /* Driver Specific Definitions */
+@@ -44,10 +44,10 @@
+ /*
+ * Prototypes of local functions.
+ */
+-#define SK_HWT_MAX (65000)
++#define SK_HWT_MAX 65000UL * 160 /* ca. 10 sec. */
+
+ /* correction factor */
+-#define SK_HWT_FAC (1000 * (SK_U32)pAC->GIni.GIHstClkFact / 100)
++#define SK_HWT_FAC (10 * (SK_U32)pAC->GIni.GIHstClkFact / 16)
+
+ /*
+ * Initialize hardware timer.
+@@ -73,29 +73,21 @@
+ void SkHwtStart(
+ SK_AC *pAC, /* Adapters context */
+ SK_IOC Ioc, /* IoContext */
+-SK_U32 Time) /* Time in units of 16us to load the timer with. */
++SK_U32 Time) /* Time in usec to load the timer */
+ {
+- SK_U32 Cnt;
+-
+ if (Time > SK_HWT_MAX)
+ Time = SK_HWT_MAX;
+
+ pAC->Hwt.TStart = Time;
+ pAC->Hwt.TStop = 0L;
+
+- Cnt = Time;
+-
+- /*
+- * if time < 16 us
+- * time = 16 us
+- */
+- if (!Cnt) {
+- Cnt++;
++ if (!Time) {
++ Time = 1L;
+ }
+
+- SK_OUT32(Ioc, B2_TI_INI, Cnt * SK_HWT_FAC);
+-
+- SK_OUT16(Ioc, B2_TI_CTRL, TIM_START); /* Start timer. */
++ SK_OUT32(Ioc, B2_TI_INI, Time * SK_HWT_FAC);
++
++ SK_OUT16(Ioc, B2_TI_CTRL, TIM_START); /* Start timer */
+
+ pAC->Hwt.TActive = SK_TRUE;
+ }
+@@ -109,13 +101,12 @@
+ SK_IOC Ioc) /* IoContext */
+ {
+ SK_OUT16(Ioc, B2_TI_CTRL, TIM_STOP);
+-
++
+ SK_OUT16(Ioc, B2_TI_CTRL, TIM_CLR_IRQ);
+
+ pAC->Hwt.TActive = SK_FALSE;
+ }
+
+-
+ /*
+ * Stop hardware timer and read time elapsed since last start.
+ *
+@@ -129,6 +120,9 @@
+ {
+ SK_U32 TRead;
+ SK_U32 IStatus;
++ SK_U32 TimerInt;
++
++ TimerInt = CHIP_ID_YUKON_2(pAC) ? Y2_IS_TIMINT : IS_TIMINT;
+
+ if (pAC->Hwt.TActive) {
+
+@@ -139,15 +133,15 @@
+
+ SK_IN32(Ioc, B0_ISRC, &IStatus);
+
+- /* Check if timer expired (or wraped around) */
+- if ((TRead > pAC->Hwt.TStart) || (IStatus & IS_TIMINT)) {
+-
++ /* Check if timer expired (or wrapped around) */
++ if ((TRead > pAC->Hwt.TStart) || ((IStatus & TimerInt) != 0)) {
++
+ SkHwtStop(pAC, Ioc);
+-
++
+ pAC->Hwt.TStop = pAC->Hwt.TStart;
+ }
+ else {
+-
++
+ pAC->Hwt.TStop = pAC->Hwt.TStart - TRead;
+ }
+ }
+@@ -162,9 +156,9 @@
+ SK_IOC Ioc) /* IoContext */
+ {
+ SkHwtStop(pAC, Ioc);
+-
++
+ pAC->Hwt.TStop = pAC->Hwt.TStart;
+-
++
+ SkTimerDone(pAC, Ioc);
+ }
+
+diff -ruN linux/drivers/net/sk98lin/skgeinit.c linux-new/drivers/net/sk98lin/skgeinit.c
+--- linux/drivers/net/sk98lin/skgeinit.c 2005-09-26 13:32:48.000000000 +0400
++++ linux-new/drivers/net/sk98lin/skgeinit.c 2005-08-09 17:15:51.000000000 +0400
+@@ -2,8 +2,8 @@
+ *
+ * Name: skgeinit.c
+ * Project: Gigabit Ethernet Adapters, Common Modules
+- * Version: $Revision: 1.97 $
+- * Date: $Date: 2003/10/02 16:45:31 $
++ * Version: $Revision: 2.77 $
++ * Date: $Date: 2005/07/19 15:38:26 $
+ * Purpose: Contains functions to initialize the adapter
+ *
+ ******************************************************************************/
+@@ -11,13 +11,12 @@
+ /******************************************************************************
+ *
+ * (C)Copyright 1998-2002 SysKonnect.
+- * (C)Copyright 2002-2003 Marvell.
++ * (C)Copyright 2002-2005 Marvell.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+- *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+@@ -31,7 +30,7 @@
+
+ #if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
+ static const char SysKonnectFileId[] =
+- "@(#) $Id: skgeinit.c,v 1.97 2003/10/02 16:45:31 rschmidt Exp $ (C) Marvell.";
++ "@(#) $Id: skgeinit.c,v 2.77 2005/07/19 15:38:26 rschmidt Exp $ (C) Marvell.";
+ #endif
+
+ struct s_QOffTab {
+@@ -59,6 +58,96 @@
+
+ /******************************************************************************
+ *
++ * SkGePortVlan() - Enable / Disable VLAN support
++ *
++ * Description:
++ * Enable or disable the VLAN support of the selected port.
++ * The new configuration is *not* saved over any SkGeStopPort() and
++ * SkGeInitPort() calls.
++ * Currently this function is only supported on Yukon-2/EC adapters.
++ *
++ * Returns:
++ * nothing
++ */
++void SkGePortVlan(
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
++int Port, /* Port number */
++SK_BOOL Enable) /* Flag */
++{
++ SK_U32 RxCtrl;
++ SK_U32 TxCtrl;
++
++ if (CHIP_ID_YUKON_2(pAC)) {
++ if (Enable) {
++ RxCtrl = RX_VLAN_STRIP_ON;
++ TxCtrl = TX_VLAN_TAG_ON;
++ }
++ else {
++ RxCtrl = RX_VLAN_STRIP_OFF;
++ TxCtrl = TX_VLAN_TAG_OFF;
++ }
++
++ SK_OUT32(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), RX_VLAN_STRIP_ON);
++ SK_OUT32(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), TX_VLAN_TAG_ON);
++ }
++} /* SkGePortVlan */
++
++
++/******************************************************************************
++ *
++ * SkGeRxRss() - Enable / Disable RSS Hash Calculation
++ *
++ * Description:
++ * Enable or disable the RSS hash calculation of the selected port.
++ * The new configuration is *not* saved over any SkGeStopPort() and
++ * SkGeInitPort() calls.
++ * Currently this function is only supported on Yukon-2/EC adapters.
++ *
++ * Returns:
++ * nothing
++ */
++void SkGeRxRss(
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
++int Port, /* Port number */
++SK_BOOL Enable) /* Flag */
++{
++ if (CHIP_ID_YUKON_2(pAC)) {
++ SK_OUT32(IoC, Q_ADDR(pAC->GIni.GP[Port].PRxQOff, Q_CSR),
++ Enable ? BMU_ENA_RX_RSS_HASH : BMU_DIS_RX_RSS_HASH);
++ }
++} /* SkGeRxRss */
++
++
++/******************************************************************************
++ *
++ * SkGeRxCsum() - Enable / Disable Receive Checksum
++ *
++ * Description:
++ * Enable or disable the checksum of the selected port.
++ * The new configuration is *not* saved over any SkGeStopPort() and
++ * SkGeInitPort() calls.
++ * Currently this function is only supported on Yukon-2/EC adapters.
++ *
++ * Returns:
++ * nothing
++ */
++void SkGeRxCsum(
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
++int Port, /* Port number */
++SK_BOOL Enable) /* Flag */
++{
++ if (CHIP_ID_YUKON_2(pAC)) {
++ SK_OUT32(IoC, Q_ADDR(pAC->GIni.GP[Port].PRxQOff, Q_CSR),
++ Enable ? BMU_ENA_RX_CHKSUM : BMU_DIS_RX_CHKSUM);
++ }
++} /* SkGeRxCsum */
++
++
++/******************************************************************************
++ *
+ * SkGePollRxD() - Enable / Disable Descriptor Polling of RxD Ring
+ *
+ * Description:
+@@ -71,8 +160,8 @@
+ * nothing
+ */
+ void SkGePollRxD(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ int Port, /* Port Index (MAC_1 + n) */
+ SK_BOOL PollRxD) /* SK_TRUE (enable pol.), SK_FALSE (disable pol.) */
+ {
+@@ -80,8 +169,8 @@
+
+ pPrt = &pAC->GIni.GP[Port];
+
+- SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), (PollRxD) ?
+- CSR_ENA_POL : CSR_DIS_POL);
++ SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), (SK_U32)((PollRxD) ?
++ CSR_ENA_POL : CSR_DIS_POL));
+ } /* SkGePollRxD */
+
+
+@@ -99,8 +188,8 @@
+ * nothing
+ */
+ void SkGePollTxD(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ int Port, /* Port Index (MAC_1 + n) */
+ SK_BOOL PollTxD) /* SK_TRUE (enable pol.), SK_FALSE (disable pol.) */
+ {
+@@ -114,7 +203,7 @@
+ if (pPrt->PXSQSize != 0) {
+ SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), DWord);
+ }
+-
++
+ if (pPrt->PXAQSize != 0) {
+ SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), DWord);
+ }
+@@ -135,17 +224,27 @@
+ * nothing
+ */
+ void SkGeYellowLED(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ int State) /* yellow LED state, 0 = OFF, 0 != ON */
+ {
++ int LedReg;
++
++ if (CHIP_ID_YUKON_2(pAC)) {
++ /* different mapping on Yukon-2 */
++ LedReg = B0_CTST + 1;
++ }
++ else {
++ LedReg = B0_LED;
++ }
++
+ if (State == 0) {
+- /* Switch yellow LED OFF */
+- SK_OUT8(IoC, B0_LED, LED_STAT_OFF);
++ /* Switch state LED OFF */
++ SK_OUT8(IoC, LedReg, LED_STAT_OFF);
+ }
+ else {
+- /* Switch yellow LED ON */
+- SK_OUT8(IoC, B0_LED, LED_STAT_ON);
++ /* Switch state LED ON */
++ SK_OUT8(IoC, LedReg, LED_STAT_ON);
+ }
+ } /* SkGeYellowLED */
+
+@@ -169,8 +268,8 @@
+ * nothing
+ */
+ void SkGeXmitLED(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ int Led, /* offset to the LED Init Value register */
+ int Mode) /* Mode may be SK_LED_DIS, SK_LED_ENA, SK_LED_TST */
+ {
+@@ -195,15 +294,14 @@
+ */
+ SK_OUT32(IoC, Led + XMIT_LED_CNT, 0);
+ SK_OUT8(IoC, Led + XMIT_LED_TST, LED_T_OFF);
+- break;
+ }
+-
++
+ /*
+- * 1000BT: The Transmit LED is driven by the PHY.
++ * 1000BT: the Transmit LED is driven by the PHY.
+ * But the default LED configuration is used for
+ * Level One and Broadcom PHYs.
+- * (Broadcom: It may be that PHY_B_PEC_EN_LTR has to be set.)
+- * (In this case it has to be added here. But we will see. XXX)
++ * (Broadcom: It may be that PHY_B_PEC_EN_LTR has to be set.
++ * In this case it has to be added here.)
+ */
+ } /* SkGeXmitLED */
+ #endif /* !SK_SLIM || GENESIS */
+@@ -227,7 +325,7 @@
+ * 1: configuration error
+ */
+ static int DoCalcAddr(
+-SK_AC *pAC, /* adapter context */
++SK_AC *pAC, /* Adapter Context */
+ SK_GEPORT SK_FAR *pPrt, /* port index */
+ int QuSize, /* size of the queue to configure in kB */
+ SK_U32 SK_FAR *StartVal, /* start value for address calculation */
+@@ -264,12 +362,35 @@
+
+ /******************************************************************************
+ *
++ * SkGeRoundQueueSize() - Round the given queue size to the adpaters QZ units
++ *
++ * Description:
++ * This function rounds the given queue size in kBs to adapter specific
++ * queue size units (Genesis and Yukon: 8 kB, Yukon-2/EC: 1 kB).
++ *
++ * Returns:
++ * the rounded queue size in kB
++ */
++static int SkGeRoundQueueSize(
++SK_AC *pAC, /* Adapter Context */
++int QueueSizeKB) /* Queue size in kB */
++{
++ int QueueSizeSteps;
++
++ QueueSizeSteps = (CHIP_ID_YUKON_2(pAC)) ? QZ_STEP_Y2 : QZ_STEP;
++
++ return((QueueSizeKB + QueueSizeSteps - 1) & ~(QueueSizeSteps - 1));
++} /* SkGeRoundQueueSize */
++
++
++/******************************************************************************
++ *
+ * SkGeInitAssignRamToQueues() - allocate default queue sizes
+ *
+ * Description:
+ * This function assigns the memory to the different queues and ports.
+ * When DualNet is set to SK_TRUE all ports get the same amount of memory.
+- * Otherwise the first port gets most of the memory and all the
++ * Otherwise the first port gets most of the memory and all the
+ * other ports just the required minimum.
+ * This function can only be called when pAC->GIni.GIRamSize and
+ * pAC->GIni.GIMacsFound have been initialized, usually this happens
+@@ -282,102 +403,141 @@
+ */
+
+ int SkGeInitAssignRamToQueues(
+-SK_AC *pAC, /* Adapter context */
++SK_AC *pAC, /* Adapter Context */
+ int ActivePort, /* Active Port in RLMT mode */
+-SK_BOOL DualNet) /* adapter context */
++SK_BOOL DualNet) /* Dual Net active */
+ {
+ int i;
+ int UsedKilobytes; /* memory already assigned */
+ int ActivePortKilobytes; /* memory available for active port */
+- SK_GEPORT *pGePort;
+-
+- UsedKilobytes = 0;
++ int MinQueueSize; /* min. memory for queues */
++ int TotalRamSize; /* total memory for queues */
++ SK_BOOL DualPortYukon2;
++ SK_GEPORT *pPrt;
+
+ if (ActivePort >= pAC->GIni.GIMacsFound) {
++
+ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
+ ("SkGeInitAssignRamToQueues: ActivePort (%d) invalid\n",
+ ActivePort));
+ return(1);
+ }
+- if (((pAC->GIni.GIMacsFound * (SK_MIN_RXQ_SIZE + SK_MIN_TXQ_SIZE)) +
+- ((RAM_QUOTA_SYNC == 0) ? 0 : SK_MIN_TXQ_SIZE)) > pAC->GIni.GIRamSize) {
++
++ DualPortYukon2 = (CHIP_ID_YUKON_2(pAC) && pAC->GIni.GIMacsFound == 2);
++
++ TotalRamSize = pAC->GIni.GIRamSize;
++
++ if (DualPortYukon2) {
++ TotalRamSize *= 2;
++ }
++
++ MinQueueSize = SK_MIN_RXQ_SIZE + SK_MIN_TXQ_SIZE;
++
++ if (MinQueueSize > pAC->GIni.GIRamSize) {
++ MinQueueSize = pAC->GIni.GIRamSize;
++ }
++
++ if ((pAC->GIni.GIMacsFound * MinQueueSize +
++ RAM_QUOTA_SYNC * SK_MIN_TXQ_SIZE) > TotalRamSize) {
++
+ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
+ ("SkGeInitAssignRamToQueues: Not enough memory (%d)\n",
+- pAC->GIni.GIRamSize));
++ TotalRamSize));
+ return(2);
+ }
+
+ if (DualNet) {
+ /* every port gets the same amount of memory */
+- ActivePortKilobytes = pAC->GIni.GIRamSize / pAC->GIni.GIMacsFound;
++ ActivePortKilobytes = TotalRamSize / pAC->GIni.GIMacsFound;
++
+ for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
+
+- pGePort = &pAC->GIni.GP[i];
+-
++ pPrt = &pAC->GIni.GP[i];
++
++ if (DualPortYukon2) {
++ ActivePortKilobytes = pAC->GIni.GIRamSize;
++ }
+ /* take away the minimum memory for active queues */
+- ActivePortKilobytes -= (SK_MIN_RXQ_SIZE + SK_MIN_TXQ_SIZE);
++ ActivePortKilobytes -= MinQueueSize;
+
+ /* receive queue gets the minimum + 80% of the rest */
+- pGePort->PRxQSize = (int) (ROUND_QUEUE_SIZE_KB((
+- ActivePortKilobytes * (unsigned long) RAM_QUOTA_RX) / 100))
++ pPrt->PRxQSize = SkGeRoundQueueSize(pAC,
++ (int)((long)ActivePortKilobytes * RAM_QUOTA_RX) / 100)
+ + SK_MIN_RXQ_SIZE;
+
+- ActivePortKilobytes -= (pGePort->PRxQSize - SK_MIN_RXQ_SIZE);
++ ActivePortKilobytes -= (pPrt->PRxQSize - SK_MIN_RXQ_SIZE);
+
+ /* synchronous transmit queue */
+- pGePort->PXSQSize = 0;
++ pPrt->PXSQSize = 0;
+
+ /* asynchronous transmit queue */
+- pGePort->PXAQSize = (int) ROUND_QUEUE_SIZE_KB(ActivePortKilobytes +
+- SK_MIN_TXQ_SIZE);
++ pPrt->PXAQSize = SkGeRoundQueueSize(pAC,
++ ActivePortKilobytes + SK_MIN_TXQ_SIZE);
+ }
+ }
+- else {
+- /* Rlmt Mode or single link adapter */
++ else { /* RLMT Mode or single link adapter */
+
+- /* Set standby queue size defaults for all standby ports */
++ UsedKilobytes = 0;
++
++ /* set standby queue size defaults for all standby ports */
+ for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
+
+ if (i != ActivePort) {
+- pGePort = &pAC->GIni.GP[i];
++ pPrt = &pAC->GIni.GP[i];
+
+- pGePort->PRxQSize = SK_MIN_RXQ_SIZE;
+- pGePort->PXAQSize = SK_MIN_TXQ_SIZE;
+- pGePort->PXSQSize = 0;
++ if (DualPortYukon2) {
++ pPrt->PRxQSize = SkGeRoundQueueSize(pAC,
++ (int)((long)pAC->GIni.GIRamSize * RAM_QUOTA_RX) / 100);
++ pPrt->PXAQSize = pAC->GIni.GIRamSize - pPrt->PRxQSize;
++ }
++ else {
++ pPrt->PRxQSize = SK_MIN_RXQ_SIZE;
++ pPrt->PXAQSize = SK_MIN_TXQ_SIZE;
++ }
++ pPrt->PXSQSize = 0;
+
+ /* Count used RAM */
+- UsedKilobytes += pGePort->PRxQSize + pGePort->PXAQSize;
++ UsedKilobytes += pPrt->PRxQSize + pPrt->PXAQSize;
+ }
+ }
+ /* what's left? */
+- ActivePortKilobytes = pAC->GIni.GIRamSize - UsedKilobytes;
++ ActivePortKilobytes = TotalRamSize - UsedKilobytes;
+
+ /* assign it to the active port */
+ /* first take away the minimum memory */
+- ActivePortKilobytes -= (SK_MIN_RXQ_SIZE + SK_MIN_TXQ_SIZE);
+- pGePort = &pAC->GIni.GP[ActivePort];
++ ActivePortKilobytes -= MinQueueSize;
++ pPrt = &pAC->GIni.GP[ActivePort];
+
+ /* receive queue get's the minimum + 80% of the rest */
+- pGePort->PRxQSize = (int) (ROUND_QUEUE_SIZE_KB((ActivePortKilobytes *
+- (unsigned long) RAM_QUOTA_RX) / 100)) + SK_MIN_RXQ_SIZE;
++ pPrt->PRxQSize = SkGeRoundQueueSize(pAC,
++ (int)((long)ActivePortKilobytes * RAM_QUOTA_RX) / 100) +
++ MinQueueSize/2;
+
+- ActivePortKilobytes -= (pGePort->PRxQSize - SK_MIN_RXQ_SIZE);
++ ActivePortKilobytes -= (pPrt->PRxQSize - MinQueueSize/2);
+
+ /* synchronous transmit queue */
+- pGePort->PXSQSize = 0;
++ pPrt->PXSQSize = 0;
+
+ /* asynchronous transmit queue */
+- pGePort->PXAQSize = (int) ROUND_QUEUE_SIZE_KB(ActivePortKilobytes) +
+- SK_MIN_TXQ_SIZE;
++ pPrt->PXAQSize = SkGeRoundQueueSize(pAC, ActivePortKilobytes) +
++ MinQueueSize/2;
+ }
+-#ifdef VCPU
+- VCPUprintf(0, "PRxQSize=%u, PXSQSize=%u, PXAQSize=%u\n",
+- pGePort->PRxQSize, pGePort->PXSQSize, pGePort->PXAQSize);
+-#endif /* VCPU */
++
++#ifdef DEBUG
++ for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
++
++ pPrt = &pAC->GIni.GP[i];
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
++ ("Port %d: RxQSize=%u, TxAQSize=%u, TxSQSize=%u\n",
++ i, pPrt->PRxQSize, pPrt->PXAQSize, pPrt->PXSQSize));
++ }
++#endif /* DEBUG */
+
+ return(0);
+ } /* SkGeInitAssignRamToQueues */
+
++
+ /******************************************************************************
+ *
+ * SkGeCheckQSize() - Checks the Adapters Queue Size Configuration
+@@ -388,12 +548,12 @@
+ * used ports.
+ * This requirements must be fullfilled to have a valid configuration:
+ * - The size of all queues must not exceed GIRamSize.
+- * - The queue sizes must be specified in units of 8 kB.
++ * - The queue sizes must be specified in units of 8 kB (Genesis & Yukon).
+ * - The size of Rx queues of available ports must not be
+- * smaller than 16 kB.
++ * smaller than 16 kB (Genesis & Yukon) resp. 10 kB (Yukon-2).
+ * - The size of at least one Tx queue (synch. or asynch.)
+- * of available ports must not be smaller than 16 kB
+- * when Jumbo Frames are used.
++ * of available ports must not be smaller than 16 kB (Genesis & Yukon),
++ * resp. 10 kB (Yukon-2) when Jumbo Frames are used.
+ * - The RAM start and end addresses must not be changed
+ * for ports which are already initialized.
+ * Furthermore SkGeCheckQSize() defines the Start and End Addresses
+@@ -404,7 +564,7 @@
+ * 1: Queue Size Configuration invalid
+ */
+ static int SkGeCheckQSize(
+-SK_AC *pAC, /* adapter context */
++SK_AC *pAC, /* Adapter Context */
+ int Port) /* port index */
+ {
+ SK_GEPORT *pPrt;
+@@ -414,55 +574,68 @@
+ SK_U32 StartAddr;
+ #ifndef SK_SLIM
+ int UsedMem; /* total memory used (max. found ports) */
+-#endif
++#endif
+
+ Rtv = 0;
+-
++
+ #ifndef SK_SLIM
+
+ UsedMem = 0;
++ Rtv = 0;
+ for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
+ pPrt = &pAC->GIni.GP[i];
+
+- if ((pPrt->PRxQSize & QZ_UNITS) != 0 ||
+- (pPrt->PXSQSize & QZ_UNITS) != 0 ||
+- (pPrt->PXAQSize & QZ_UNITS) != 0) {
++ if (CHIP_ID_YUKON_2(pAC)) {
++ UsedMem = 0;
++ }
++ else if (((pPrt->PRxQSize & QZ_UNITS) != 0 ||
++ (pPrt->PXSQSize & QZ_UNITS) != 0 ||
++ (pPrt->PXAQSize & QZ_UNITS) != 0)) {
+
+ SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E012, SKERR_HWI_E012MSG);
+ return(1);
+ }
+
+- if (i == Port && pPrt->PRxQSize < SK_MIN_RXQ_SIZE) {
++#ifndef SK_DIAG
++ if (i == Port && pAC->GIni.GIRamSize > SK_MIN_RXQ_SIZE &&
++ pPrt->PRxQSize < SK_MIN_RXQ_SIZE) {
+ SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E011, SKERR_HWI_E011MSG);
+ return(1);
+ }
+-
++
+ /*
+ * the size of at least one Tx queue (synch. or asynch.) has to be > 0.
+ * if Jumbo Frames are used, this size has to be >= 16 kB.
+ */
+ if ((i == Port && pPrt->PXSQSize == 0 && pPrt->PXAQSize == 0) ||
+- (pAC->GIni.GIPortUsage == SK_JUMBO_LINK &&
+- ((pPrt->PXSQSize > 0 && pPrt->PXSQSize < SK_MIN_TXQ_SIZE) ||
++ (pPrt->PPortUsage == SK_JUMBO_LINK &&
++ ((pPrt->PXSQSize > 0 && pPrt->PXSQSize < SK_MIN_TXQ_SIZE) ||
+ (pPrt->PXAQSize > 0 && pPrt->PXAQSize < SK_MIN_TXQ_SIZE)))) {
+ SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E023, SKERR_HWI_E023MSG);
+ return(1);
+ }
+-
++#endif /* !SK_DIAG */
++
+ UsedMem += pPrt->PRxQSize + pPrt->PXSQSize + pPrt->PXAQSize;
++
++ if (UsedMem > pAC->GIni.GIRamSize) {
++ SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E012, SKERR_HWI_E012MSG);
++ return(1);
++ }
+ }
+-
+- if (UsedMem > pAC->GIni.GIRamSize) {
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E012, SKERR_HWI_E012MSG);
+- return(1);
+- }
++
+ #endif /* !SK_SLIM */
+
+ /* Now start address calculation */
+ StartAddr = pAC->GIni.GIRamOffs;
+ for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
++
+ pPrt = &pAC->GIni.GP[i];
+
++ if (CHIP_ID_YUKON_2(pAC)) {
++ StartAddr = 0;
++ }
++
+ /* Calculate/Check values for the receive queue */
+ Rtv2 = DoCalcAddr(pAC, pPrt, pPrt->PRxQSize, &StartAddr,
+ &pPrt->PRxQRamStart, &pPrt->PRxQRamEnd);
+@@ -502,8 +675,8 @@
+ * nothing
+ */
+ static void SkGeInitMacArb(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC) /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC) /* I/O Context */
+ {
+ /* release local reset */
+ SK_OUT16(IoC, B3_MA_TO_CTRL, MA_RST_CLR);
+@@ -542,8 +715,8 @@
+ * nothing
+ */
+ static void SkGeInitPktArb(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC) /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC) /* I/O Context */
+ {
+ /* release local reset */
+ SK_OUT16(IoC, B3_PA_CTRL, PA_RST_CLR);
+@@ -559,7 +732,8 @@
+ * NOTE: the packet arbiter timeout interrupt is needed for
+ * half duplex hangup workaround
+ */
+- if (pAC->GIni.GIPortUsage != SK_JUMBO_LINK) {
++ if (pAC->GIni.GP[MAC_1].PPortUsage != SK_JUMBO_LINK &&
++ pAC->GIni.GP[MAC_2].PPortUsage != SK_JUMBO_LINK) {
+ if (pAC->GIni.GIMacsFound == 1) {
+ SK_OUT16(IoC, B3_PA_CTRL, PA_ENA_TO_TX1);
+ }
+@@ -582,14 +756,11 @@
+ * nothing
+ */
+ static void SkGeInitMacFifo(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ int Port) /* Port Index (MAC_1 + n) */
+ {
+ SK_U16 Word;
+-#ifdef VCPU
+- SK_U32 DWord;
+-#endif /* VCPU */
+ /*
+ * For each FIFO:
+ * - release local reset
+@@ -597,31 +768,29 @@
+ * - setup defaults for the control register
+ * - enable the FIFO
+ */
+-
++
+ #ifdef GENESIS
+ if (pAC->GIni.GIGenesis) {
+- /* Configure Rx MAC FIFO */
++ /* configure Rx MAC FIFO */
+ SK_OUT8(IoC, MR_ADDR(Port, RX_MFF_CTRL2), MFF_RST_CLR);
+ SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_RX_CTRL_DEF);
+ SK_OUT8(IoC, MR_ADDR(Port, RX_MFF_CTRL2), MFF_ENA_OP_MD);
+-
++
+ /* Configure Tx MAC FIFO */
+ SK_OUT8(IoC, MR_ADDR(Port, TX_MFF_CTRL2), MFF_RST_CLR);
+ SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_TX_CTRL_DEF);
+ SK_OUT8(IoC, MR_ADDR(Port, TX_MFF_CTRL2), MFF_ENA_OP_MD);
+-
+- /* Enable frame flushing if jumbo frames used */
+- if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
++
++ /* enable frame flushing if jumbo frames used */
++ if (pAC->GIni.GP[Port].PPortUsage == SK_JUMBO_LINK) {
+ SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_ENA_FLUSH);
+ }
+ }
+ #endif /* GENESIS */
+-
++
+ #ifdef YUKON
+ if (pAC->GIni.GIYukon) {
+- /* set Rx GMAC FIFO Flush Mask */
+- SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_FL_MSK), (SK_U16)RX_FF_FL_DEF_MSK);
+-
++
+ Word = (SK_U16)GMF_RX_CTRL_DEF;
+
+ /* disable Rx GMAC FIFO Flush for YUKON-Lite Rev. A0 only */
+@@ -629,23 +798,52 @@
+
+ Word &= ~GMF_RX_F_FL_ON;
+ }
+-
+- /* Configure Rx MAC FIFO */
++
++ /* Configure Rx GMAC FIFO */
+ SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_RST_CLR);
+ SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), Word);
+-
+- /* set Rx GMAC FIFO Flush Threshold (default: 0x0a -> 56 bytes) */
+- SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_FL_THR), RX_GMF_FL_THR_DEF);
+-
+- /* Configure Tx MAC FIFO */
++
++ Word = RX_FF_FL_DEF_MSK;
++
++#ifndef SK_DIAG
++ if (HW_FEATURE(pAC, HWF_WA_DEV_4115)) {
++ /*
++ * Flushing must be enabled (needed for ASF see dev. #4.29),
++ * but the flushing mask should be disabled (see dev. #4.115)
++ */
++ Word = 0;
++ }
++#endif /* !SK_DIAG */
++
++ /* set Rx GMAC FIFO Flush Mask (after clearing reset) */
++ SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_FL_MSK), Word);
++
++ /* default: 0x0a -> 56 bytes on Yukon-1 and 64 bytes on Yukon-2 */
++ Word = (SK_U16)RX_GMF_FL_THR_DEF;
++
++ if (CHIP_ID_YUKON_2(pAC)) {
++ if (pAC->GIni.GIChipId == CHIP_ID_YUKON_EC &&
++ pAC->GIni.GIAsfEnabled) {
++ /* WA for dev. #4.30 (reduce to 0x08 -> 48 bytes) */
++ Word -= 2;
++ }
++ }
++ else {
++ /*
++ * because Pause Packet Truncation in GMAC is not working
++ * we have to increase the Flush Threshold to 64 bytes
++ * in order to flush pause packets in Rx FIFO on Yukon-1
++ */
++ Word++;
++ }
++
++ /* set Rx GMAC FIFO Flush Threshold (after clearing reset) */
++ SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_FL_THR), Word);
++
++ /* Configure Tx GMAC FIFO */
+ SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_RST_CLR);
+ SK_OUT16(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U16)GMF_TX_CTRL_DEF);
+-
+-#ifdef VCPU
+- SK_IN32(IoC, MR_ADDR(Port, RX_GMF_AF_THR), &DWord);
+- SK_IN32(IoC, MR_ADDR(Port, TX_GMF_AE_THR), &DWord);
+-#endif /* VCPU */
+-
++
+ /* set Tx GMAC FIFO Almost Empty Threshold */
+ /* SK_OUT32(IoC, MR_ADDR(Port, TX_GMF_AE_THR), 0); */
+ }
+@@ -653,7 +851,7 @@
+
+ } /* SkGeInitMacFifo */
+
+-#ifdef SK_LNK_SYNC_CNT
++#ifdef SK_LNK_SYNC_CNT
+ /******************************************************************************
+ *
+ * SkGeLoadLnkSyncCnt() - Load the Link Sync Counter and starts counting
+@@ -674,8 +872,8 @@
+ * nothing
+ */
+ void SkGeLoadLnkSyncCnt(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ int Port, /* Port Index (MAC_1 + n) */
+ SK_U32 CntVal) /* Counter value */
+ {
+@@ -685,7 +883,7 @@
+ SK_BOOL IrqPend;
+
+ /* stop counter */
+- SK_OUT8(IoC, MR_ADDR(Port, LNK_SYNC_CTRL), LED_STOP);
++ SK_OUT8(IoC, MR_ADDR(Port, LNK_SYNC_CTRL), LNK_STOP);
+
+ /*
+ * ASIC problem:
+@@ -698,6 +896,7 @@
+ IrqPend = SK_FALSE;
+ SK_IN32(IoC, B0_ISRC, &ISrc);
+ SK_IN32(IoC, B0_IMSK, &OrgIMsk);
++
+ if (Port == MAC_1) {
+ NewIMsk = OrgIMsk & ~IS_LNK_SYNC_M1;
+ if ((ISrc & IS_LNK_SYNC_M1) != 0) {
+@@ -710,6 +909,7 @@
+ IrqPend = SK_TRUE;
+ }
+ }
++
+ if (!IrqPend) {
+ SK_OUT32(IoC, B0_IMSK, NewIMsk);
+ }
+@@ -718,15 +918,17 @@
+ SK_OUT32(IoC, MR_ADDR(Port, LNK_SYNC_INI), CntVal);
+
+ /* start counter */
+- SK_OUT8(IoC, MR_ADDR(Port, LNK_SYNC_CTRL), LED_START);
++ SK_OUT8(IoC, MR_ADDR(Port, LNK_SYNC_CTRL), LNK_START);
+
+ if (!IrqPend) {
+- /* clear the unexpected IRQ, and restore the interrupt mask */
+- SK_OUT8(IoC, MR_ADDR(Port, LNK_SYNC_CTRL), LED_CLR_IRQ);
++ /* clear the unexpected IRQ */
++ SK_OUT8(IoC, MR_ADDR(Port, LNK_SYNC_CTRL), LNK_CLR_IRQ);
++
++ /* restore the interrupt mask */
+ SK_OUT32(IoC, B0_IMSK, OrgIMsk);
+ }
+ } /* SkGeLoadLnkSyncCnt*/
+-#endif /* SK_LNK_SYNC_CNT */
++#endif /* SK_LNK_SYNC_CNT */
+
+ #if defined(SK_DIAG) || defined(SK_CFG_SYNC)
+ /******************************************************************************
+@@ -758,8 +960,8 @@
+ * synchronous queue is configured
+ */
+ int SkGeCfgSync(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ int Port, /* Port Index (MAC_1 + n) */
+ SK_U32 IntTime, /* Interval Timer Value in units of 8ns */
+ SK_U32 LimCount, /* Number of bytes to transfer during IntTime */
+@@ -777,16 +979,16 @@
+ SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E010, SKERR_HWI_E010MSG);
+ return(1);
+ }
+-
++
+ if (pAC->GIni.GP[Port].PXSQSize == 0) {
+ SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E009, SKERR_HWI_E009MSG);
+ return(2);
+ }
+-
++
+ /* calculate register values */
+ IntTime = (IntTime / 2) * pAC->GIni.GIHstClkFact / 100;
+ LimCount = LimCount / 8;
+-
++
+ if (IntTime > TXA_MAX_VAL || LimCount > TXA_MAX_VAL) {
+ SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E010, SKERR_HWI_E010MSG);
+ return(1);
+@@ -804,13 +1006,13 @@
+ */
+ SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL),
+ TXA_ENA_FSYNC | TXA_DIS_ALLOC | TXA_STOP_RC);
+-
++
+ SK_OUT32(IoC, MR_ADDR(Port, TXA_ITI_INI), IntTime);
+ SK_OUT32(IoC, MR_ADDR(Port, TXA_LIM_INI), LimCount);
+-
++
+ SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL),
+ (SK_U8)(SyncMode & (TXA_ENA_ALLOC | TXA_DIS_ALLOC)));
+-
++
+ if (IntTime != 0 || LimCount != 0) {
+ SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL), TXA_DIS_FSYNC | TXA_START_RC);
+ }
+@@ -831,10 +1033,10 @@
+ * Returns:
+ * nothing
+ */
+-static void DoInitRamQueue(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int QuIoOffs, /* Queue IO Address Offset */
++void DoInitRamQueue(
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
++int QuIoOffs, /* Queue I/O Address Offset */
+ SK_U32 QuStartAddr, /* Queue Start Address */
+ SK_U32 QuEndAddr, /* Queue End Address */
+ int QuType) /* Queue Type (SK_RX_SRAM_Q|SK_RX_BRAM_Q|SK_TX_RAM_Q) */
+@@ -867,8 +1069,7 @@
+
+ /* continue with SK_RX_BRAM_Q */
+ case SK_RX_BRAM_Q:
+- /* write threshold for Rx Queue */
+-
++ /* write threshold for Rx Queue (Pause packets) */
+ SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_RX_UTPP), RxUpThresVal);
+ SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_RX_LTPP), RxLoThresVal);
+
+@@ -882,7 +1083,8 @@
+ * or YUKON is used ((GMAC Tx FIFO is only 1 kB)
+ * we NEED Store & Forward of the RAM buffer.
+ */
+- if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK ||
++ if (pAC->GIni.GP[MAC_1].PPortUsage == SK_JUMBO_LINK ||
++ pAC->GIni.GP[MAC_2].PPortUsage == SK_JUMBO_LINK ||
+ pAC->GIni.GIYukon) {
+ /* enable Store & Forward Mode for the Tx Side */
+ SK_OUT8(IoC, RB_ADDR(QuIoOffs, RB_CTRL), RB_ENA_STFWD);
+@@ -911,8 +1113,8 @@
+ * nothing
+ */
+ static void SkGeInitRamBufs(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ int Port) /* Port Index (MAC_1 + n) */
+ {
+ SK_GEPORT *pPrt;
+@@ -920,8 +1122,8 @@
+
+ pPrt = &pAC->GIni.GP[Port];
+
+- if (pPrt->PRxQSize == SK_MIN_RXQ_SIZE) {
+- RxQType = SK_RX_SRAM_Q; /* small Rx Queue */
++ if (pPrt->PRxQSize <= SK_MIN_RXQ_SIZE) {
++ RxQType = SK_RX_SRAM_Q; /* small Rx Queue */
+ }
+ else {
+ RxQType = SK_RX_BRAM_Q; /* big Rx Queue */
+@@ -929,10 +1131,10 @@
+
+ DoInitRamQueue(pAC, IoC, pPrt->PRxQOff, pPrt->PRxQRamStart,
+ pPrt->PRxQRamEnd, RxQType);
+-
++
+ DoInitRamQueue(pAC, IoC, pPrt->PXsQOff, pPrt->PXsQRamStart,
+ pPrt->PXsQRamEnd, SK_TX_RAM_Q);
+-
++
+ DoInitRamQueue(pAC, IoC, pPrt->PXaQOff, pPrt->PXaQRamStart,
+ pPrt->PXaQRamEnd, SK_TX_RAM_Q);
+
+@@ -953,26 +1155,37 @@
+ * nothing
+ */
+ void SkGeInitRamIface(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC) /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC) /* I/O Context */
+ {
+- /* release local reset */
+- SK_OUT16(IoC, B3_RI_CTRL, RI_RST_CLR);
++ int i;
++ int RamBuffers;
+
+- /* configure timeout values */
+- SK_OUT8(IoC, B3_RI_WTO_R1, SK_RI_TO_53);
+- SK_OUT8(IoC, B3_RI_WTO_XA1, SK_RI_TO_53);
+- SK_OUT8(IoC, B3_RI_WTO_XS1, SK_RI_TO_53);
+- SK_OUT8(IoC, B3_RI_RTO_R1, SK_RI_TO_53);
+- SK_OUT8(IoC, B3_RI_RTO_XA1, SK_RI_TO_53);
+- SK_OUT8(IoC, B3_RI_RTO_XS1, SK_RI_TO_53);
+- SK_OUT8(IoC, B3_RI_WTO_R2, SK_RI_TO_53);
+- SK_OUT8(IoC, B3_RI_WTO_XA2, SK_RI_TO_53);
+- SK_OUT8(IoC, B3_RI_WTO_XS2, SK_RI_TO_53);
+- SK_OUT8(IoC, B3_RI_RTO_R2, SK_RI_TO_53);
+- SK_OUT8(IoC, B3_RI_RTO_XA2, SK_RI_TO_53);
+- SK_OUT8(IoC, B3_RI_RTO_XS2, SK_RI_TO_53);
++ if (CHIP_ID_YUKON_2(pAC)) {
++ RamBuffers = pAC->GIni.GIMacsFound;
++ }
++ else {
++ RamBuffers = 1;
++ }
++
++ for (i = 0; i < RamBuffers; i++) {
++ /* release local reset */
++ SK_OUT8(IoC, SELECT_RAM_BUFFER(i, B3_RI_CTRL), (SK_U8)RI_RST_CLR);
+
++ /* configure timeout values */
++ SK_OUT8(IoC, SELECT_RAM_BUFFER(i, B3_RI_WTO_R1), SK_RI_TO_53);
++ SK_OUT8(IoC, SELECT_RAM_BUFFER(i, B3_RI_WTO_XA1), SK_RI_TO_53);
++ SK_OUT8(IoC, SELECT_RAM_BUFFER(i, B3_RI_WTO_XS1), SK_RI_TO_53);
++ SK_OUT8(IoC, SELECT_RAM_BUFFER(i, B3_RI_RTO_R1), SK_RI_TO_53);
++ SK_OUT8(IoC, SELECT_RAM_BUFFER(i, B3_RI_RTO_XA1), SK_RI_TO_53);
++ SK_OUT8(IoC, SELECT_RAM_BUFFER(i, B3_RI_RTO_XS1), SK_RI_TO_53);
++ SK_OUT8(IoC, SELECT_RAM_BUFFER(i, B3_RI_WTO_R2), SK_RI_TO_53);
++ SK_OUT8(IoC, SELECT_RAM_BUFFER(i, B3_RI_WTO_XA2), SK_RI_TO_53);
++ SK_OUT8(IoC, SELECT_RAM_BUFFER(i, B3_RI_WTO_XS2), SK_RI_TO_53);
++ SK_OUT8(IoC, SELECT_RAM_BUFFER(i, B3_RI_RTO_R2), SK_RI_TO_53);
++ SK_OUT8(IoC, SELECT_RAM_BUFFER(i, B3_RI_RTO_XA2), SK_RI_TO_53);
++ SK_OUT8(IoC, SELECT_RAM_BUFFER(i, B3_RI_RTO_XS2), SK_RI_TO_53);
++ }
+ } /* SkGeInitRamIface */
+
+
+@@ -987,8 +1200,8 @@
+ * nothing
+ */
+ static void SkGeInitBmu(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ int Port) /* Port Index (MAC_1 + n) */
+ {
+ SK_GEPORT *pPrt;
+@@ -999,29 +1212,63 @@
+
+ RxWm = SK_BMU_RX_WM;
+ TxWm = SK_BMU_TX_WM;
+-
+- if (!pAC->GIni.GIPciSlot64 && !pAC->GIni.GIPciClock66) {
+- /* for better performance */
+- RxWm /= 2;
+- TxWm /= 2;
+- }
+
+- /* Rx Queue: Release all local resets and set the watermark */
+- SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), CSR_CLR_RESET);
+- SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_F), RxWm);
++ if (CHIP_ID_YUKON_2(pAC)) {
+
+- /*
+- * Tx Queue: Release all local resets if the queue is used !
+- * set watermark
+- */
+- if (pPrt->PXSQSize != 0) {
+- SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_CLR_RESET);
+- SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_F), TxWm);
++ if (pAC->GIni.GIPciBus == SK_PEX_BUS) {
++ /* for better performance set it to 128 */
++ RxWm = SK_BMU_RX_WM_PEX;
++ }
++
++ /* Rx Queue: Release all local resets and set the watermark */
++ SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), BMU_CLR_RESET);
++ SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), BMU_OPER_INIT);
++ SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), BMU_FIFO_OP_ON);
++ SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_WM), RxWm);
++
++ /*
++ * Tx Queue: Release all local resets if the queue is used !
++ * set watermark
++ */
++ if (pPrt->PXSQSize != 0 && HW_SYNC_TX_SUPPORTED(pAC)) {
++ /* Yukon-EC doesn't have a synchronous Tx queue */
++ SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), BMU_CLR_RESET);
++ SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), BMU_OPER_INIT);
++ SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), BMU_FIFO_OP_ON);
++ SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_WM), TxWm);
++ }
++
++ if (pPrt->PXAQSize != 0) {
++ SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), BMU_CLR_RESET);
++ SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), BMU_OPER_INIT);
++ SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), BMU_FIFO_OP_ON);
++ SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_WM), TxWm);
++ }
+ }
+-
+- if (pPrt->PXAQSize != 0) {
+- SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_CLR_RESET);
+- SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_F), TxWm);
++ else {
++ if (!pAC->GIni.GIPciSlot64 && !pAC->GIni.GIPciClock66) {
++ /* for better performance */
++ RxWm /= 2;
++ TxWm /= 2;
++ }
++
++ /* Rx Queue: Release all local resets and set the watermark */
++ SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), CSR_CLR_RESET);
++ SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_F), RxWm);
++
++ /*
++ * Tx Queue: Release all local resets if the queue is used !
++ * set watermark
++ */
++ if (pPrt->PXSQSize != 0) {
++ SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_CLR_RESET);
++ SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_F), TxWm);
++ }
++
++ if (pPrt->PXAQSize != 0) {
++ SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_CLR_RESET);
++ SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_F), TxWm);
++ }
+ }
+ /*
+ * Do NOT enable the descriptor poll timers here, because
+@@ -1045,20 +1292,29 @@
+ */
+ static SK_U32 TestStopBit(
+ SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* IO Context */
+-int QuIoOffs) /* Queue IO Address Offset */
++SK_IOC IoC, /* I/O Context */
++int QuIoOffs) /* Queue I/O Address Offset */
+ {
+ SK_U32 QuCsr; /* CSR contents */
+
+ SK_IN32(IoC, Q_ADDR(QuIoOffs, Q_CSR), &QuCsr);
+-
+- if ((QuCsr & (CSR_STOP | CSR_SV_IDLE)) == 0) {
+- /* Stop Descriptor overridden by start command */
+- SK_OUT32(IoC, Q_ADDR(QuIoOffs, Q_CSR), CSR_STOP);
+
+- SK_IN32(IoC, Q_ADDR(QuIoOffs, Q_CSR), &QuCsr);
++ if (CHIP_ID_YUKON_2(pAC)) {
++ if ((QuCsr & (BMU_STOP | BMU_IDLE)) == 0) {
++ /* Stop Descriptor overridden by start command */
++ SK_OUT32(IoC, Q_ADDR(QuIoOffs, Q_CSR), BMU_STOP);
++
++ SK_IN32(IoC, Q_ADDR(QuIoOffs, Q_CSR), &QuCsr);
++ }
++ }
++ else {
++ if ((QuCsr & (CSR_STOP | CSR_SV_IDLE)) == 0) {
++ /* Stop Descriptor overridden by start command */
++ SK_OUT32(IoC, Q_ADDR(QuIoOffs, Q_CSR), CSR_STOP);
++
++ SK_IN32(IoC, Q_ADDR(QuIoOffs, Q_CSR), &QuCsr);
++ }
+ }
+-
+ return(QuCsr);
+ } /* TestStopBit */
+
+@@ -1082,8 +1338,8 @@
+ * has to be stopped once before.
+ * SK_STOP_ALL SK_STOP_TX + SK_STOP_RX
+ *
+- * RstMode = SK_SOFT_RST Resets the MAC. The PHY is still alive.
+- * SK_HARD_RST Resets the MAC and the PHY.
++ * RstMode = SK_SOFT_RST Resets the MAC, the PHY is still alive.
++ * SK_HARD_RST Resets the MAC and the PHY.
+ *
+ * Example:
+ * 1) A Link Down event was signaled for a port. Therefore the activity
+@@ -1142,56 +1398,82 @@
+ * SWITCH_PORT.
+ */
+ void SkGeStopPort(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* I/O context */
+-int Port, /* port to stop (MAC_1 + n) */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
++int Port, /* Port to stop (MAC_1 + n) */
+ int Dir, /* Direction to Stop (SK_STOP_RX, SK_STOP_TX, SK_STOP_ALL) */
+ int RstMode)/* Reset Mode (SK_SOFT_RST, SK_HARD_RST) */
+ {
+-#ifndef SK_DIAG
+- SK_EVPARA Para;
+-#endif /* !SK_DIAG */
+ SK_GEPORT *pPrt;
+- SK_U32 DWord;
++ SK_U32 RxCsr;
+ SK_U32 XsCsr;
+ SK_U32 XaCsr;
+ SK_U64 ToutStart;
++ SK_U32 CsrStart;
++ SK_U32 CsrStop;
++ SK_U32 CsrIdle;
++ SK_U32 CsrTest;
++ SK_U8 rsl; /* FIFO read shadow level */
++ SK_U8 rl; /* FIFO read level */
+ int i;
+ int ToutCnt;
+
+ pPrt = &pAC->GIni.GP[Port];
+
++ /* set the proper values of Q_CSR register layout depending on the chip */
++ if (CHIP_ID_YUKON_2(pAC)) {
++ CsrStart = BMU_START;
++ CsrStop = BMU_STOP;
++ CsrIdle = BMU_IDLE;
++ CsrTest = BMU_IDLE;
++ }
++ else {
++ CsrStart = CSR_START;
++ CsrStop = CSR_STOP;
++ CsrIdle = CSR_SV_IDLE;
++ CsrTest = CSR_SV_IDLE | CSR_STOP;
++ }
++
+ if ((Dir & SK_STOP_TX) != 0) {
+- /* disable receiver and transmitter */
+- SkMacRxTxDisable(pAC, IoC, Port);
+-
++
++ if (!pAC->GIni.GIAsfEnabled) {
++ /* disable receiver and transmitter */
++ SkMacRxTxDisable(pAC, IoC, Port);
++ }
++
+ /* stop both transmit queues */
++ SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CsrStop);
++ SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CsrStop);
+ /*
+ * If the BMU is in the reset state CSR_STOP will terminate
+ * immediately.
+ */
+- SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_STOP);
+- SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_STOP);
+
+ ToutStart = SkOsGetTime(pAC);
+ ToutCnt = 0;
+ do {
+- /*
+- * Clear packet arbiter timeout to make sure
+- * this loop will terminate.
+- */
+- SK_OUT16(IoC, B3_PA_CTRL, (SK_U16)((Port == MAC_1) ?
+- PA_CLR_TO_TX1 : PA_CLR_TO_TX2));
+-
+- /*
+- * If the transfer stucks at the MAC the STOP command will not
+- * terminate if we don't flush the XMAC's transmit FIFO !
+- */
+- SkMacFlushTxFifo(pAC, IoC, Port);
++#ifdef GENESIS
++ if (pAC->GIni.GIGenesis) {
++ /* clear Tx packet arbiter timeout IRQ */
++ SK_OUT16(IoC, B3_PA_CTRL, (SK_U16)((Port == MAC_1) ?
++ PA_CLR_TO_TX1 : PA_CLR_TO_TX2));
++ /*
++ * If the transfer stucks at the XMAC the STOP command will not
++ * terminate if we don't flush the XMAC's transmit FIFO !
++ */
++ SkMacFlushTxFifo(pAC, IoC, Port);
++ }
++#endif /* GENESIS */
+
+- XsCsr = TestStopBit(pAC, IoC, pPrt->PXsQOff);
+ XaCsr = TestStopBit(pAC, IoC, pPrt->PXaQOff);
+
++ if (HW_SYNC_TX_SUPPORTED(pAC)) {
++ XsCsr = TestStopBit(pAC, IoC, pPrt->PXsQOff);
++ }
++ else {
++ XsCsr = XaCsr;
++ }
++
+ if (SkOsGetTime(pAC) - ToutStart > (SK_TICKS_PER_SEC / 18)) {
+ /*
+ * Timeout of 1/18 second reached.
+@@ -1199,67 +1481,111 @@
+ */
+ ToutCnt++;
+ if (ToutCnt > 1) {
+- /* Might be a problem when the driver event handler
+- * calls StopPort again. XXX.
++ /*
++ * If BMU stop doesn't terminate, we assume that
++ * we have a stable state and can reset the BMU,
++ * the Prefetch Unit, and RAM buffer now.
+ */
+-
+- /* Fatal Error, Loop aborted */
+- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E018,
+- SKERR_HWI_E018MSG);
+-#ifndef SK_DIAG
+- Para.Para64 = Port;
+- SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
+-#endif /* !SK_DIAG */
+- return;
++ break; /* ===> leave do/while loop here */
+ }
+ /*
+- * Cache incoherency workaround: Assume a start command
++ * Cache incoherency workaround: assume a start command
+ * has been lost while sending the frame.
+ */
+ ToutStart = SkOsGetTime(pAC);
+
+- if ((XsCsr & CSR_STOP) != 0) {
+- SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_START);
++ if ((XsCsr & CsrStop) != 0) {
++ SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CsrStart);
+ }
+- if ((XaCsr & CSR_STOP) != 0) {
+- SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_START);
++
++ if ((XaCsr & CsrStop) != 0) {
++ SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CsrStart);
+ }
+- }
+
++ /*
++ * After the previous operations the X(s|a)Csr does no
++ * longer contain the proper values
++ */
++ XaCsr = TestStopBit(pAC, IoC, pPrt->PXaQOff);
++
++ if (HW_SYNC_TX_SUPPORTED(pAC)) {
++ XsCsr = TestStopBit(pAC, IoC, pPrt->PXsQOff);
++ }
++ else {
++ XsCsr = XaCsr;
++ }
++ }
+ /*
+ * Because of the ASIC problem report entry from 21.08.1998 it is
+ * required to wait until CSR_STOP is reset and CSR_SV_IDLE is set.
++ * (valid for GENESIS only)
+ */
+- } while ((XsCsr & (CSR_STOP | CSR_SV_IDLE)) != CSR_SV_IDLE ||
+- (XaCsr & (CSR_STOP | CSR_SV_IDLE)) != CSR_SV_IDLE);
++ } while (((XsCsr & CsrTest) != CsrIdle ||
++ (XaCsr & CsrTest) != CsrIdle));
++
++ if (pAC->GIni.GIAsfEnabled) {
+
+- /* Reset the MAC depending on the RstMode */
+- if (RstMode == SK_SOFT_RST) {
+- SkMacSoftRst(pAC, IoC, Port);
++ pPrt->PState = (RstMode == SK_SOFT_RST) ? SK_PRT_STOP :
++ SK_PRT_RESET;
+ }
+ else {
+- SkMacHardRst(pAC, IoC, Port);
++ /* Reset the MAC depending on the RstMode */
++ if (RstMode == SK_SOFT_RST) {
++
++ SkMacSoftRst(pAC, IoC, Port);
++ }
++ else {
++ if (HW_FEATURE(pAC, HWF_WA_DEV_472) && Port == MAC_1 &&
++ pAC->GIni.GP[MAC_2].PState == SK_PRT_RUN) {
++
++ pAC->GIni.GP[MAC_1].PState = SK_PRT_RESET;
++
++ /* set GPHY Control reset */
++ SK_OUT8(IoC, MR_ADDR(MAC_1, GPHY_CTRL), (SK_U8)GPC_RST_SET);
++ }
++ else {
++
++ SkMacHardRst(pAC, IoC, Port);
++ }
++ }
+ }
+-
+- /* Disable Force Sync bit and Enable Alloc bit */
++
++ /* disable Force Sync bit and Enable Alloc bit */
+ SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL),
+ TXA_DIS_FSYNC | TXA_DIS_ALLOC | TXA_STOP_RC);
+-
++
+ /* Stop Interval Timer and Limit Counter of Tx Arbiter */
+ SK_OUT32(IoC, MR_ADDR(Port, TXA_ITI_INI), 0L);
+ SK_OUT32(IoC, MR_ADDR(Port, TXA_LIM_INI), 0L);
+
+ /* Perform a local reset of the port's Tx path */
++ if (CHIP_ID_YUKON_2(pAC)) {
++ /* Reset the PCI FIFO of the async Tx queue */
++ SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR),
++ BMU_RST_SET | BMU_FIFO_RST);
++
++ /* Reset the PCI FIFO of the sync Tx queue */
++ SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR),
++ BMU_RST_SET | BMU_FIFO_RST);
++
++ /* Reset the Tx prefetch units */
++ SK_OUT32(IoC, Y2_PREF_Q_ADDR(pPrt->PXaQOff, PREF_UNIT_CTRL_REG),
++ PREF_UNIT_RST_SET);
++ SK_OUT32(IoC, Y2_PREF_Q_ADDR(pPrt->PXsQOff, PREF_UNIT_CTRL_REG),
++ PREF_UNIT_RST_SET);
++ }
++ else {
++ /* Reset the PCI FIFO of the async Tx queue */
++ SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_SET_RESET);
++ /* Reset the PCI FIFO of the sync Tx queue */
++ SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_SET_RESET);
++ }
+
+- /* Reset the PCI FIFO of the async Tx queue */
+- SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_SET_RESET);
+- /* Reset the PCI FIFO of the sync Tx queue */
+- SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_SET_RESET);
+ /* Reset the RAM Buffer async Tx queue */
+ SK_OUT8(IoC, RB_ADDR(pPrt->PXaQOff, RB_CTRL), RB_RST_SET);
+ /* Reset the RAM Buffer sync Tx queue */
+ SK_OUT8(IoC, RB_ADDR(pPrt->PXsQOff, RB_CTRL), RB_RST_SET);
+-
++
+ /* Reset Tx MAC FIFO */
+ #ifdef GENESIS
+ if (pAC->GIni.GIGenesis) {
+@@ -1271,71 +1597,116 @@
+ SkGeXmitLED(pAC, IoC, MR_ADDR(Port, TX_LED_INI), SK_LED_DIS);
+ }
+ #endif /* GENESIS */
+-
++
+ #ifdef YUKON
+ if (pAC->GIni.GIYukon) {
+- /* Reset TX MAC FIFO */
+- SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_RST_SET);
++ /* do the reset only if ASF is not enabled */
++ if (!pAC->GIni.GIAsfEnabled) {
++ /* Reset Tx MAC FIFO */
++ SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_RST_SET);
++ }
++
++ /* set Pause Off */
++ SK_OUT8(IoC, MR_ADDR(Port, GMAC_CTRL), (SK_U8)GMC_PAUSE_OFF);
+ }
+ #endif /* YUKON */
+ }
+
+ if ((Dir & SK_STOP_RX) != 0) {
+- /*
+- * The RX Stop Command will not terminate if no buffers
+- * are queued in the RxD ring. But it will always reach
+- * the Idle state. Therefore we can use this feature to
+- * stop the transfer of received packets.
+- */
+- /* stop the port's receive queue */
+- SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), CSR_STOP);
+-
+- i = 100;
+- do {
++
++ if (CHIP_ID_YUKON_2(pAC)) {
+ /*
+- * Clear packet arbiter timeout to make sure
+- * this loop will terminate
++ * The RX Stop command will not work for Yukon-2 if the BMU does not
++ * reach the end of packet and since we can't make sure that we have
++ * incoming data, we must reset the BMU while it is not during a DMA
++ * transfer. Since it is possible that the RX path is still active,
++ * the RX RAM buffer will be stopped first, so any possible incoming
++ * data will not trigger a DMA. After the RAM buffer is stopped, the
++ * BMU is polled until any DMA in progress is ended and only then it
++ * will be reset.
+ */
+- SK_OUT16(IoC, B3_PA_CTRL, (SK_U16)((Port == MAC_1) ?
+- PA_CLR_TO_RX1 : PA_CLR_TO_RX2));
+
+- DWord = TestStopBit(pAC, IoC, pPrt->PRxQOff);
++ /* disable the RAM Buffer receive queue */
++ SK_OUT8(IoC, RB_ADDR(pPrt->PRxQOff, RB_CTRL), RB_DIS_OP_MD);
+
+- /* timeout if i==0 (bug fix for #10748) */
+- if (--i == 0) {
+- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E024,
+- SKERR_HWI_E024MSG);
+- break;
++ i = 0xffff;
++ while (--i) {
++ SK_IN8(IoC, RB_ADDR(pPrt->PRxQOff, Q_RSL), &rsl);
++ SK_IN8(IoC, RB_ADDR(pPrt->PRxQOff, Q_RL), &rl);
++
++ if (rsl == rl) {
++ break;
++ }
+ }
++
++ /*
++ * If the Rx side is blocked, the above loop cannot terminate.
++ * But, if there was any traffic it should be terminated, now.
++ * However, stop the Rx BMU and the Prefetch Unit !
++ */
++ SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR),
++ BMU_RST_SET | BMU_FIFO_RST);
++ /* reset the Rx prefetch unit */
++ SK_OUT32(IoC, Y2_PREF_Q_ADDR(pPrt->PRxQOff, PREF_UNIT_CTRL_REG),
++ PREF_UNIT_RST_SET);
++ }
++ else {
+ /*
+- * because of the ASIC problem report entry from 21.08.98
+- * it is required to wait until CSR_STOP is reset and
+- * CSR_SV_IDLE is set.
++ * The RX Stop Command will not terminate if no buffers
++ * are queued in the RxD ring. But it will always reach
++ * the Idle state. Therefore we can use this feature to
++ * stop the transfer of received packets.
+ */
+- } while ((DWord & (CSR_STOP | CSR_SV_IDLE)) != CSR_SV_IDLE);
++ /* stop the port's receive queue */
++ SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), CsrStop);
++
++ i = 100;
++ do {
++#ifdef GENESIS
++ if (pAC->GIni.GIGenesis) {
++ /* clear Rx packet arbiter timeout IRQ */
++ SK_OUT16(IoC, B3_PA_CTRL, (SK_U16)((Port == MAC_1) ?
++ PA_CLR_TO_RX1 : PA_CLR_TO_RX2));
++ }
++#endif /* GENESIS */
+
+- /* The path data transfer activity is fully stopped now */
++ RxCsr = TestStopBit(pAC, IoC, pPrt->PRxQOff);
+
+- /* Perform a local reset of the port's Rx path */
++ /* timeout if i==0 (bug fix for #10748) */
++ if (--i == 0) {
++ SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E024,
++ SKERR_HWI_E024MSG);
++ break;
++ }
++ /*
++ * Because of the ASIC problem report entry from 21.08.1998 it is
++ * required to wait until CSR_STOP is reset and CSR_SV_IDLE is set.
++ * (valid for GENESIS only)
++ */
++ } while ((RxCsr & CsrTest) != CsrIdle);
++ /* The path data transfer activity is fully stopped now */
++
++ /* Perform a local reset of the port's Rx path */
++ /* Reset the PCI FIFO of the Rx queue */
++ SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), CSR_SET_RESET);
++ }
+
+- /* Reset the PCI FIFO of the Rx queue */
+- SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), CSR_SET_RESET);
+ /* Reset the RAM Buffer receive queue */
+ SK_OUT8(IoC, RB_ADDR(pPrt->PRxQOff, RB_CTRL), RB_RST_SET);
+
+ /* Reset Rx MAC FIFO */
+ #ifdef GENESIS
+ if (pAC->GIni.GIGenesis) {
+-
++
+ SK_OUT8(IoC, MR_ADDR(Port, RX_MFF_CTRL2), MFF_RST_SET);
+
+ /* switch Rx LED off, stop the LED counter */
+ SkGeXmitLED(pAC, IoC, MR_ADDR(Port, RX_LED_INI), SK_LED_DIS);
+ }
+ #endif /* GENESIS */
+-
++
+ #ifdef YUKON
+- if (pAC->GIni.GIYukon) {
++ if (pAC->GIni.GIYukon && !pAC->GIni.GIAsfEnabled) {
+ /* Reset Rx MAC FIFO */
+ SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_RST_SET);
+ }
+@@ -1355,8 +1726,8 @@
+ * nothing
+ */
+ static void SkGeInit0(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC) /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC) /* I/O Context */
+ {
+ int i;
+ SK_GEPORT *pPrt;
+@@ -1365,6 +1736,7 @@
+ pPrt = &pAC->GIni.GP[i];
+
+ pPrt->PState = SK_PRT_RESET;
++ pPrt->PPortUsage = SK_RED_LINK;
+ pPrt->PRxQOff = QOffTab[i].RxQOff;
+ pPrt->PXsQOff = QOffTab[i].XsQOff;
+ pPrt->PXaQOff = QOffTab[i].XaQOff;
+@@ -1393,24 +1765,30 @@
+ pPrt->PLipaAutoNeg = (SK_U8)SK_LIPA_UNKNOWN;
+ pPrt->PAutoNegFail = SK_FALSE;
+ pPrt->PHWLinkUp = SK_FALSE;
+- pPrt->PLinkBroken = SK_TRUE; /* See WA code */
++ pPrt->PLinkBroken = SK_TRUE; /* See WA code */
+ pPrt->PPhyPowerState = PHY_PM_OPERATIONAL_MODE;
+ pPrt->PMacColThres = TX_COL_DEF;
+ pPrt->PMacJamLen = TX_JAM_LEN_DEF;
+ pPrt->PMacJamIpgVal = TX_JAM_IPG_DEF;
+ pPrt->PMacJamIpgData = TX_IPG_JAM_DEF;
++ pPrt->PMacBackOffLim = TX_BOF_LIM_DEF;
++ pPrt->PMacDataBlind = DATA_BLIND_DEF;
+ pPrt->PMacIpgData = IPG_DATA_DEF;
+ pPrt->PMacLimit4 = SK_FALSE;
+ }
+
+- pAC->GIni.GIPortUsage = SK_RED_LINK;
+ pAC->GIni.GILedBlinkCtrl = (SK_U16)OemConfig.Value;
+- pAC->GIni.GIValIrqMask = IS_ALL_MSK;
++ pAC->GIni.GIChipCap = 0;
++
++ for (i = 0; i < 4; i++) {
++ pAC->GIni.HwF.Features[i]= 0x00000000;
++ pAC->GIni.HwF.OnMask[i] = 0x00000000;
++ pAC->GIni.HwF.OffMask[i] = 0x00000000;
++ }
+
+ } /* SkGeInit0*/
+
+ #ifdef SK_PCI_RESET
+-
+ /******************************************************************************
+ *
+ * SkGePciReset() - Reset PCI interface
+@@ -1426,8 +1804,8 @@
+ * 1: Power state could not be changed to 3.
+ */
+ static int SkGePciReset(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC) /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC) /* I/O Context */
+ {
+ int i;
+ SK_U16 PmCtlSts;
+@@ -1450,7 +1828,7 @@
+ /* We know the RAM Interface Arbiter is enabled. */
+ SkPciWriteCfgWord(pAC, PCI_PM_CTL_STS, PCI_PM_STATE_D3);
+ SkPciReadCfgWord(pAC, PCI_PM_CTL_STS, &PmCtlSts);
+-
++
+ if ((PmCtlSts & PCI_PM_STATE_MSK) != PCI_PM_STATE_D3) {
+ return(1);
+ }
+@@ -1460,7 +1838,7 @@
+
+ /* Check for D0 state. */
+ SkPciReadCfgWord(pAC, PCI_PM_CTL_STS, &PmCtlSts);
+-
++
+ if ((PmCtlSts & PCI_PM_STATE_MSK) != PCI_PM_STATE_D0) {
+ return(1);
+ }
+@@ -1469,11 +1847,24 @@
+ SkPciReadCfgWord(pAC, PCI_COMMAND, &PciCmd);
+ SkPciReadCfgByte(pAC, PCI_CACHE_LSZ, &Cls);
+ SkPciReadCfgDWord(pAC, PCI_BASE_1ST, &Bp1);
+- SkPciReadCfgDWord(pAC, PCI_BASE_2ND, &Bp2);
++
++ /*
++ * Compute the location in PCI config space of BAR2
++ * relativ to the location of BAR1
++ */
++ if ((Bp1 & PCI_MEM_TYP_MSK) == PCI_MEM64BIT) {
++ /* BAR1 is 64 bits wide */
++ i = 8;
++ }
++ else {
++ i = 4;
++ }
++
++ SkPciReadCfgDWord(pAC, PCI_BASE_1ST + i, &Bp2);
+ SkPciReadCfgByte(pAC, PCI_LAT_TIM, &Lat);
+-
+- if (PciCmd != 0 || Cls != (SK_U8)0 || Lat != (SK_U8)0 ||
+- (Bp1 & 0xfffffff0L) != 0 || Bp2 != 1) {
++
++ if (PciCmd != 0 || Cls != 0 || (Bp1 & 0xfffffff0L) != 0 || Bp2 != 1 ||
++ Lat != 0) {
+ return(1);
+ }
+
+@@ -1484,9 +1875,80 @@
+
+ return(0);
+ } /* SkGePciReset */
+-
+ #endif /* SK_PCI_RESET */
+
++
++/******************************************************************************
++ *
++ * SkGeSetUpSupFeatures() - Collect Feature List for HW_FEATURE Macro
++ *
++ * Description:
++ * This function collects the available features and required
++ * deviation services of the Adapter and provides these
++ * information in the GIHwF struct. This information is used as
++ * default value and may be overritten by the driver using the
++ * SET_HW_FEATURE_MASK() macro in its Init0 phase.
++ *
++ * Notice:
++ * Using the On and Off mask: Never switch on the same bit in both
++ * masks simultaneously. However, if doing the Off mask will win.
++ *
++ * Returns:
++ * nothing
++ */
++static void SkGeSetUpSupFeatures(
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC) /* I/O Context */
++{
++ int i;
++
++ switch (pAC->GIni.GIChipId) {
++ case CHIP_ID_YUKON_EC:
++ if (pAC->GIni.GIChipRev == CHIP_REV_YU_EC_A1) {
++ /* A0/A1 */
++ pAC->GIni.HwF.Features[HW_DEV_LIST] =
++ HWF_WA_DEV_42 | HWF_WA_DEV_46 | HWF_WA_DEV_43_418 |
++ HWF_WA_DEV_420 | HWF_WA_DEV_423 |
++ HWF_WA_DEV_424 | HWF_WA_DEV_425 | HWF_WA_DEV_427 |
++ HWF_WA_DEV_428 | HWF_WA_DEV_483 | HWF_WA_DEV_4109;
++ }
++ else {
++ /* A2/A3 */
++ pAC->GIni.HwF.Features[HW_DEV_LIST] =
++ HWF_WA_DEV_424 | HWF_WA_DEV_425 | HWF_WA_DEV_427 |
++ HWF_WA_DEV_428 | HWF_WA_DEV_483 | HWF_WA_DEV_4109;
++ }
++ break;
++ case CHIP_ID_YUKON_FE:
++ pAC->GIni.HwF.Features[HW_DEV_LIST] = HWF_WA_DEV_427 | HWF_WA_DEV_4109;
++ break;
++ case CHIP_ID_YUKON_XL:
++ /* still needed for Diag */
++ if (pAC->GIni.GIChipRev == 0) {
++ pAC->GIni.HwF.Features[HW_DEV_LIST] =
++ HWF_WA_DEV_427 | HWF_WA_DEV_463 | HWF_WA_DEV_472 |
++ HWF_WA_DEV_479 | HWF_WA_DEV_483 | HWF_WA_DEV_4115;
++ }
++ else if (pAC->GIni.GIChipRev == 1) {
++ pAC->GIni.HwF.Features[HW_DEV_LIST] =
++ HWF_WA_DEV_427 | HWF_WA_DEV_483 | HWF_WA_DEV_4109 |
++ HWF_WA_DEV_4115;
++ }
++ else {
++ pAC->GIni.HwF.Features[HW_DEV_LIST] =
++ HWF_WA_DEV_427 | HWF_WA_DEV_483 | HWF_WA_DEV_4109;
++ }
++ break;
++ }
++
++ for (i = 0; i < 4; i++) {
++ pAC->GIni.HwF.Features[i] =
++ (pAC->GIni.HwF.Features[i] | pAC->GIni.HwF.OnMask[i]) &
++ ~pAC->GIni.HwF.OffMask[i];
++ }
++} /* SkGeSetUpSupFeatures */
++
++
+ /******************************************************************************
+ *
+ * SkGeInit1() - Level 1 Initialization
+@@ -1509,80 +1971,223 @@
+ * 6: HW self test failed
+ */
+ static int SkGeInit1(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC) /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC) /* I/O Context */
+ {
+ SK_U8 Byte;
+ SK_U16 Word;
+- SK_U16 CtrlStat;
++ SK_U32 CtrlStat;
++ SK_U32 VauxAvail;
+ SK_U32 DWord;
++ SK_U32 PowerDownBit;
++ SK_GEPORT *pPrt;
+ int RetVal;
+- int i;
++ int i, j;
+
+ RetVal = 0;
+
+- /* save CLK_RUN bits (YUKON-Lite) */
+- SK_IN16(IoC, B0_CTST, &CtrlStat);
++ /* save CLK_RUN & ASF_ENABLE bits (YUKON-Lite, YUKON-EC) */
++ SK_IN32(IoC, B0_CTST, &CtrlStat);
+
+ #ifdef SK_PCI_RESET
+ (void)SkGePciReset(pAC, IoC);
+ #endif /* SK_PCI_RESET */
+
+- /* do the SW-reset */
+- SK_OUT8(IoC, B0_CTST, CS_RST_SET);
+-
+ /* release the SW-reset */
++ /* Important: SW-reset has to be cleared here, to ensure
++ * the CHIP_ID can be read IO-mapped based, too -
++ * remember the RAP register can only be written if
++ * SW-reset is cleared.
++ */
+ SK_OUT8(IoC, B0_CTST, CS_RST_CLR);
+
++ /* read Chip Identification Number */
++ SK_IN8(IoC, B2_CHIP_ID, &Byte);
++ pAC->GIni.GIChipId = Byte;
++
++ pAC->GIni.GIAsfEnabled = SK_FALSE;
++
++ /* ASF support only for Yukon-2 */
++ if ((pAC->GIni.GIChipId >= CHIP_ID_YUKON_XL) &&
++ (pAC->GIni.GIChipId <= CHIP_ID_YUKON_EC)) {
++#ifdef SK_ASF
++ if ((CtrlStat & Y2_ASF_ENABLE) != 0) {
++ /* do the SW-reset only if ASF is not enabled */
++ pAC->GIni.GIAsfEnabled = SK_TRUE;
++ }
++#else /* !SK_ASF */
++
++ SK_IN8(IoC, B28_Y2_ASF_STAT_CMD, &Byte);
++
++ pAC->GIni.GIAsfRunning = Byte & Y2_ASF_RUNNING;
++
++ /* put ASF system in reset state */
++ SK_OUT8(IoC, B28_Y2_ASF_STAT_CMD, Y2_ASF_RESET);
++
++ /* disable ASF Unit */
++ SK_OUT16(IoC, B0_CTST, Y2_ASF_DISABLE);
++#endif /* !SK_ASF */
++ }
++
++ if (!pAC->GIni.GIAsfEnabled) {
++ /* Yukon-2: required for Diag and Power Management */
++ /* set the SW-reset */
++ SK_OUT8(IoC, B0_CTST, CS_RST_SET);
++
++ /* release the SW-reset */
++ SK_OUT8(IoC, B0_CTST, CS_RST_CLR);
++ }
++
+ /* reset all error bits in the PCI STATUS register */
+ /*
+ * Note: PCI Cfg cycles cannot be used, because they are not
+ * available on some platforms after 'boot time'.
+ */
+- SK_IN16(IoC, PCI_C(PCI_STATUS), &Word);
+-
++ SK_IN16(IoC, PCI_C(pAC, PCI_STATUS), &Word);
++
+ SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON);
+- SK_OUT16(IoC, PCI_C(PCI_STATUS), (SK_U16)(Word | PCI_ERRBITS));
+- SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
++
++ SK_OUT16(IoC, PCI_C(pAC, PCI_STATUS), Word | (SK_U16)PCI_ERRBITS);
+
+ /* release Master Reset */
+ SK_OUT8(IoC, B0_CTST, CS_MRST_CLR);
+
+ #ifdef CLK_RUN
+ CtrlStat |= CS_CLK_RUN_ENA;
+-#endif /* CLK_RUN */
+
+ /* restore CLK_RUN bits */
+ SK_OUT16(IoC, B0_CTST, (SK_U16)(CtrlStat &
+ (CS_CLK_RUN_HOT | CS_CLK_RUN_RST | CS_CLK_RUN_ENA)));
++#endif /* CLK_RUN */
++
++ if ((pAC->GIni.GIChipId >= CHIP_ID_YUKON_XL) &&
++ (pAC->GIni.GIChipId <= CHIP_ID_YUKON_FE)) {
++
++ pAC->GIni.GIYukon2 = SK_TRUE;
++ pAC->GIni.GIValIrqMask = Y2_IS_ALL_MSK;
++ pAC->GIni.GIValHwIrqMask = Y2_HWE_ALL_MSK;
++
++ VauxAvail = Y2_VAUX_AVAIL;
++
++ SK_IN32(IoC, PCI_C(pAC, PCI_OUR_STATUS), &DWord);
++
++ if ((DWord & PCI_OS_PCI_X) != 0) {
++ /* this is a PCI / PCI-X bus */
++ if ((DWord & PCI_OS_PCIX) != 0) {
++ /* this is a PCI-X bus */
++ pAC->GIni.GIPciBus = SK_PCIX_BUS;
++
++ /* PCI-X is always 64-bit wide */
++ pAC->GIni.GIPciSlot64 = SK_TRUE;
++
++ pAC->GIni.GIPciMode = (SK_U8)(PCI_OS_SPEED(DWord));
++ }
++ else {
++ /* this is a conventional PCI bus */
++ pAC->GIni.GIPciBus = SK_PCI_BUS;
++
++ SK_IN16(IoC, PCI_C(pAC, PCI_OUR_REG_2), &Word);
++
++ /* check if 64-bit width is used */
++ pAC->GIni.GIPciSlot64 = (SK_BOOL)
++ (((DWord & PCI_OS_PCI64B) != 0) &&
++ ((Word & PCI_USEDATA64) != 0));
++
++ /* check if 66 MHz PCI Clock is active */
++ pAC->GIni.GIPciClock66 = (SK_BOOL)((DWord & PCI_OS_PCI66M) != 0);
++ }
++ }
++ else {
++ /* this is a PEX bus */
++ pAC->GIni.GIPciBus = SK_PEX_BUS;
++
++ /* clear any PEX errors */
++ SK_OUT32(IoC, PCI_C(pAC, PEX_UNC_ERR_STAT), 0xffffffffUL);
++
++ SK_IN16(IoC, PCI_C(pAC, PEX_LNK_STAT), &Word);
++
++ pAC->GIni.GIPexWidth = (SK_U8)((Word & PEX_LS_LINK_WI_MSK) >> 4);
++ }
++ /*
++ * Yukon-2 chips family has a different way of providing
++ * the number of MACs available
++ */
++ pAC->GIni.GIMacsFound = 1;
++
++ SK_IN8(IoC, B2_Y2_HW_RES, &Byte);
++
++ if (CHIP_ID_YUKON_2(pAC)) {
++ /*
++ * OEM config value is overwritten and should not
++ * be used for Yukon-2
++ */
++ pAC->GIni.GILedBlinkCtrl |= SK_ACT_LED_BLINK;
++
++ if (CFG_LED_MODE(Byte) == CFG_LED_DUAL_ACT_LNK) {
++
++ pAC->GIni.GILedBlinkCtrl |= SK_DUAL_LED_ACT_LNK;
++ }
++ }
++
++ if ((Byte & CFG_DUAL_MAC_MSK) == CFG_DUAL_MAC_MSK) {
++
++ SK_IN8(IoC, B2_Y2_CLK_GATE, &Byte);
++
++ if (!(Byte & Y2_STATUS_LNK2_INAC)) {
++ /* Link 2 activ */
++ pAC->GIni.GIMacsFound++;
++ }
++ }
++
++#ifdef VCPU
++ if (pAC->GIni.GIChipId == CHIP_ID_YUKON_XL) {
++ /* temporary WA for reported number of links */
++ pAC->GIni.GIMacsFound = 2;
++ }
++#endif /* VCPU */
++
++ /* read Chip Revision */
++ SK_IN8(IoC, B2_MAC_CFG, &Byte);
++
++ pAC->GIni.GIChipCap = Byte & 0x0f;
++ }
++ else {
++ pAC->GIni.GIYukon2 = SK_FALSE;
++ pAC->GIni.GIValIrqMask = IS_ALL_MSK;
++ pAC->GIni.GIValHwIrqMask = 0; /* not activated */
++
++ VauxAvail = CS_VAUX_AVAIL;
++
++ /* read number of MACs and Chip Revision */
++ SK_IN8(IoC, B2_MAC_CFG, &Byte);
++
++ pAC->GIni.GIMacsFound = (Byte & CFG_SNG_MAC) ? 1 : 2;
++ }
+
+- /* read Chip Identification Number */
+- SK_IN8(IoC, B2_CHIP_ID, &Byte);
+- pAC->GIni.GIChipId = Byte;
+-
+- /* read number of MACs */
+- SK_IN8(IoC, B2_MAC_CFG, &Byte);
+- pAC->GIni.GIMacsFound = (Byte & CFG_SNG_MAC) ? 1 : 2;
+-
+ /* get Chip Revision Number */
+ pAC->GIni.GIChipRev = (SK_U8)((Byte & CFG_CHIP_R_MSK) >> 4);
+
+- /* get diff. PCI parameters */
+- SK_IN16(IoC, B0_CTST, &CtrlStat);
+-
++#ifndef SK_DIAG
++ if (pAC->GIni.GIChipId == CHIP_ID_YUKON_XL && pAC->GIni.GIChipRev == 0) {
++ /* Yukon-2 Chip Rev. A0 */
++ return(6);
++ }
++#endif /* !SK_DIAG */
++
+ /* read the adapters RAM size */
+ SK_IN8(IoC, B2_E_0, &Byte);
+-
++
+ pAC->GIni.GIGenesis = SK_FALSE;
+ pAC->GIni.GIYukon = SK_FALSE;
+ pAC->GIni.GIYukonLite = SK_FALSE;
++ pAC->GIni.GIVauxAvail = SK_FALSE;
+
+ #ifdef GENESIS
+ if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) {
+
+ pAC->GIni.GIGenesis = SK_TRUE;
+
+- if (Byte == (SK_U8)3) {
++ if (Byte == (SK_U8)3) {
+ /* special case: 4 x 64k x 36, offset = 0x80000 */
+ pAC->GIni.GIRamSize = 1024;
+ pAC->GIni.GIRamOffs = (SK_U32)512 * 1024;
+@@ -1591,57 +2196,77 @@
+ pAC->GIni.GIRamSize = (int)Byte * 512;
+ pAC->GIni.GIRamOffs = 0;
+ }
+- /* all GE adapters work with 53.125 MHz host clock */
++ /* all GENESIS adapters work with 53.125 MHz host clock */
+ pAC->GIni.GIHstClkFact = SK_FACT_53;
+-
++
+ /* set Descr. Poll Timer Init Value to 250 ms */
+ pAC->GIni.GIPollTimerVal =
+ SK_DPOLL_DEF * (SK_U32)pAC->GIni.GIHstClkFact / 100;
+ }
+ #endif /* GENESIS */
+-
++
+ #ifdef YUKON
+ if (pAC->GIni.GIChipId != CHIP_ID_GENESIS) {
+-
++
+ pAC->GIni.GIYukon = SK_TRUE;
+-
++
+ pAC->GIni.GIRamSize = (Byte == (SK_U8)0) ? 128 : (int)Byte * 4;
+-
++
+ pAC->GIni.GIRamOffs = 0;
+-
+- /* WA for chip Rev. A */
++
++ /* WA for Yukon chip Rev. A */
+ pAC->GIni.GIWolOffs = (pAC->GIni.GIChipId == CHIP_ID_YUKON &&
+ pAC->GIni.GIChipRev == 0) ? WOL_REG_OFFS : 0;
+-
++
+ /* get PM Capabilities of PCI config space */
+- SK_IN16(IoC, PCI_C(PCI_PM_CAP_REG), &Word);
++ SK_IN16(IoC, PCI_C(pAC, PCI_PM_CAP_REG), &Word);
+
+ /* check if VAUX is available */
+- if (((CtrlStat & CS_VAUX_AVAIL) != 0) &&
++ if (((CtrlStat & VauxAvail) != 0) &&
+ /* check also if PME from D3cold is set */
+ ((Word & PCI_PME_D3C_SUP) != 0)) {
+ /* set entry in GE init struct */
+ pAC->GIni.GIVauxAvail = SK_TRUE;
+ }
+-
+- if (pAC->GIni.GIChipId == CHIP_ID_YUKON_LITE) {
+- /* this is Rev. A1 */
+- pAC->GIni.GIYukonLite = SK_TRUE;
+- }
+- else {
+- /* save Flash-Address Register */
+- SK_IN32(IoC, B2_FAR, &DWord);
+
+- /* test Flash-Address Register */
+- SK_OUT8(IoC, B2_FAR + 3, 0xff);
+- SK_IN8(IoC, B2_FAR + 3, &Byte);
++ if (!CHIP_ID_YUKON_2(pAC)) {
+
+- if (Byte != 0) {
+- /* this is Rev. A0 */
++ if (pAC->GIni.GIChipId == CHIP_ID_YUKON_LITE) {
++ /* this is Rev. A1 */
+ pAC->GIni.GIYukonLite = SK_TRUE;
++ }
++ else {
++ /* save Flash-Address Register */
++ SK_IN32(IoC, B2_FAR, &DWord);
+
+- /* restore Flash-Address Register */
+- SK_OUT32(IoC, B2_FAR, DWord);
++ /* test Flash-Address Register */
++ SK_OUT8(IoC, B2_FAR + 3, 0xff);
++ SK_IN8(IoC, B2_FAR + 3, &Byte);
++
++ if (Byte != 0) {
++ /* this is Rev. A0 */
++ pAC->GIni.GIYukonLite = SK_TRUE;
++
++ /* restore Flash-Address Register */
++ SK_OUT32(IoC, B2_FAR, DWord);
++ }
++ }
++ }
++ else {
++ /* Check for CLS = 0 (dev. #4.55) */
++ if (pAC->GIni.GIPciBus != SK_PEX_BUS) {
++ /* PCI and PCI-X */
++ SK_IN8(IoC, PCI_C(pAC, PCI_CACHE_LSZ), &Byte);
++ if (Byte == 0) {
++ /* set CLS to 2 if configured to 0 */
++ SK_OUT8(IoC, PCI_C(pAC, PCI_CACHE_LSZ), 2);
++ }
++ if (pAC->GIni.GIPciBus == SK_PCIX_BUS) {
++ /* set Cache Line Size opt. */
++ SK_IN32(IoC, PCI_C(pAC, PCI_OUR_REG_1), &DWord);
++ DWord |= PCI_CLS_OPT;
++ SK_OUT32(IoC, PCI_C(pAC, PCI_OUR_REG_1), DWord);
++ }
+ }
+ }
+
+@@ -1649,138 +2274,258 @@
+ SK_OUT8(IoC, B0_POWER_CTRL, (SK_U8)(PC_VAUX_ENA | PC_VCC_ENA |
+ PC_VAUX_OFF | PC_VCC_ON));
+
+- /* read the Interrupt source */
+- SK_IN32(IoC, B0_ISRC, &DWord);
+-
+- if ((DWord & IS_HW_ERR) != 0) {
+- /* read the HW Error Interrupt source */
+- SK_IN32(IoC, B0_HWE_ISRC, &DWord);
+-
+- if ((DWord & IS_IRQ_SENSOR) != 0) {
+- /* disable HW Error IRQ */
+- pAC->GIni.GIValIrqMask &= ~IS_HW_ERR;
++ Byte = 0;
++
++ if (CHIP_ID_YUKON_2(pAC)) {
++ switch (pAC->GIni.GIChipId) {
++ /* PEX adapters work with different host clock */
++ case CHIP_ID_YUKON_EC:
++ case CHIP_ID_YUKON_EC_U:
++ /* Yukon-EC works with 125 MHz host clock */
++ pAC->GIni.GIHstClkFact = SK_FACT_125;
++ break;
++ case CHIP_ID_YUKON_FE:
++ /* Yukon-FE works with 100 MHz host clock */
++ pAC->GIni.GIHstClkFact = SK_FACT_100;
++ break;
++ case CHIP_ID_YUKON_XL:
++ /* all Yukon-2 adapters work with 156 MHz host clock */
++ pAC->GIni.GIHstClkFact = 2 * SK_FACT_78;
++
++ if (pAC->GIni.GIChipRev > 1) {
++ /* enable bits are inverted */
++ Byte = (SK_U8)(Y2_PCI_CLK_LNK1_DIS | Y2_COR_CLK_LNK1_DIS |
++ Y2_CLK_GAT_LNK1_DIS | Y2_PCI_CLK_LNK2_DIS |
++ Y2_COR_CLK_LNK2_DIS | Y2_CLK_GAT_LNK2_DIS);
++ }
++ break;
++ default:
++ SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E006,
++ SKERR_HWI_E006MSG);
+ }
++
++ pAC->GIni.GIPollTimerVal =
++ SK_DPOLL_DEF_Y2 * (SK_U32)pAC->GIni.GIHstClkFact / 100;
++
++ /* set power down bit */
++ PowerDownBit = PCI_Y2_PHY1_POWD | PCI_Y2_PHY2_POWD;
++
++ /* disable Core Clock Division, set Clock Select to 0 (Yukon-2) */
++ SK_OUT32(IoC, B2_Y2_CLK_CTRL, Y2_CLK_DIV_DIS);
++
++ /* enable MAC/PHY, PCI and Core Clock for both Links */
++ SK_OUT8(IoC, B2_Y2_CLK_GATE, Byte);
+ }
+-
+- for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
+- /* set GMAC Link Control reset */
+- SK_OUT16(IoC, MR_ADDR(i, GMAC_LINK_CTRL), GMLC_RST_SET);
++ else {
++ /* YUKON adapters work with 78 MHz host clock */
++ pAC->GIni.GIHstClkFact = SK_FACT_78;
++
++ pAC->GIni.GIPollTimerVal = SK_DPOLL_MAX; /* 215 ms */
++
++ /* read the Interrupt source */
++ SK_IN32(IoC, B0_ISRC, &DWord);
++
++ if ((DWord & IS_HW_ERR) != 0) {
++ /* read the HW Error Interrupt source */
++ SK_IN32(IoC, B0_HWE_ISRC, &DWord);
+
+- /* clear GMAC Link Control reset */
+- SK_OUT16(IoC, MR_ADDR(i, GMAC_LINK_CTRL), GMLC_RST_CLR);
++ if ((DWord & IS_IRQ_SENSOR) != 0) {
++ /* disable HW Error IRQ */
++ pAC->GIni.GIValIrqMask &= ~IS_HW_ERR;
++ }
++ }
++ /* set power down bit */
++ PowerDownBit = PCI_PHY_COMA;
++ }
++
++ SK_IN32(IoC, PCI_C(pAC, PCI_OUR_REG_1), &DWord);
++
++ DWord &= ~PowerDownBit;
++
++ if (pAC->GIni.GIChipId == CHIP_ID_YUKON_XL && pAC->GIni.GIChipRev > 1) {
++ /* deassert Low Power for 1st PHY */
++ DWord |= PCI_Y2_PHY1_COMA;
++
++ if (pAC->GIni.GIMacsFound > 1) {
++ /* deassert Low Power for 2nd PHY */
++ DWord |= PCI_Y2_PHY2_COMA;
++ }
++ }
++
++ /* Release PHY from PowerDown/COMA Mode */
++ SK_OUT32(IoC, PCI_C(pAC, PCI_OUR_REG_1), DWord);
++
++ if (!pAC->GIni.GIAsfEnabled) {
++
++ for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
++ /* set GMAC Link Control reset */
++ SK_OUT8(IoC, MR_ADDR(i, GMAC_LINK_CTRL), (SK_U8)GMLC_RST_SET);
++
++ /* clear GMAC Link Control reset */
++ SK_OUT8(IoC, MR_ADDR(i, GMAC_LINK_CTRL), (SK_U8)GMLC_RST_CLR);
++ }
+ }
+- /* all YU chips work with 78.125 MHz host clock */
+- pAC->GIni.GIHstClkFact = SK_FACT_78;
+-
+- pAC->GIni.GIPollTimerVal = SK_DPOLL_MAX; /* 215 ms */
+ }
+ #endif /* YUKON */
+
+- /* check if 64-bit PCI Slot is present */
+- pAC->GIni.GIPciSlot64 = (SK_BOOL)((CtrlStat & CS_BUS_SLOT_SZ) != 0);
+-
+- /* check if 66 MHz PCI Clock is active */
+- pAC->GIni.GIPciClock66 = (SK_BOOL)((CtrlStat & CS_BUS_CLOCK) != 0);
++ SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
++
++ if (!CHIP_ID_YUKON_2(pAC)) {
++ /* this is a conventional PCI bus */
++ pAC->GIni.GIPciBus = SK_PCI_BUS;
++
++ /* check if 64-bit PCI Slot is present */
++ pAC->GIni.GIPciSlot64 = (SK_BOOL)((CtrlStat & CS_BUS_SLOT_SZ) != 0);
++
++ /* check if 66 MHz PCI Clock is active */
++ pAC->GIni.GIPciClock66 = (SK_BOOL)((CtrlStat & CS_BUS_CLOCK) != 0);
++ }
+
+ /* read PCI HW Revision Id. */
+- SK_IN8(IoC, PCI_C(PCI_REV_ID), &Byte);
++ SK_IN8(IoC, PCI_C(pAC, PCI_REV_ID), &Byte);
+ pAC->GIni.GIPciHwRev = Byte;
+
++ /* read connector type */
++ SK_IN8(IoC, B2_CONN_TYP, &pAC->GIni.GIConTyp);
++
+ /* read the PMD type */
+ SK_IN8(IoC, B2_PMD_TYP, &Byte);
+- pAC->GIni.GICopperType = (SK_U8)(Byte == 'T');
+
+- /* read the PHY type */
++ pAC->GIni.GIPmdTyp = Byte;
++
++ pAC->GIni.GICopperType = (SK_BOOL)(Byte == 'T' || Byte == '1' ||
++ (pAC->GIni.GIYukon2 && !(Byte == 'L' || Byte == 'S')));
++
++ /* read the PHY type (Yukon and Genesis) */
+ SK_IN8(IoC, B2_E_1, &Byte);
+
+ Byte &= 0x0f; /* the PHY type is stored in the lower nibble */
+ for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
+-
++
++ pPrt = &pAC->GIni.GP[i];
++
++ /* get the MAC addresses */
++ for (j = 0; j < 3; j++) {
++ SK_IN16(IoC, B2_MAC_1 + i * 8 + j * 2, &pPrt->PMacAddr[j]);
++ }
++
+ #ifdef GENESIS
+ if (pAC->GIni.GIGenesis) {
+ switch (Byte) {
+ case SK_PHY_XMAC:
+- pAC->GIni.GP[i].PhyAddr = PHY_ADDR_XMAC;
++ pPrt->PhyAddr = PHY_ADDR_XMAC;
+ break;
+ case SK_PHY_BCOM:
+- pAC->GIni.GP[i].PhyAddr = PHY_ADDR_BCOM;
+- pAC->GIni.GP[i].PMSCap = (SK_U8)(SK_MS_CAP_AUTO |
++ pPrt->PhyAddr = PHY_ADDR_BCOM;
++ pPrt->PMSCap = (SK_U8)(SK_MS_CAP_AUTO |
+ SK_MS_CAP_MASTER | SK_MS_CAP_SLAVE);
+ break;
+ #ifdef OTHER_PHY
+ case SK_PHY_LONE:
+- pAC->GIni.GP[i].PhyAddr = PHY_ADDR_LONE;
++ pPrt->PhyAddr = PHY_ADDR_LONE;
+ break;
+ case SK_PHY_NAT:
+- pAC->GIni.GP[i].PhyAddr = PHY_ADDR_NAT;
++ pPrt->PhyAddr = PHY_ADDR_NAT;
+ break;
+ #endif /* OTHER_PHY */
+ default:
+ /* ERROR: unexpected PHY type detected */
+ RetVal = 5;
+- break;
+ }
+ }
+ #endif /* GENESIS */
+-
++
+ #ifdef YUKON
+ if (pAC->GIni.GIYukon) {
+-
+- if (Byte < (SK_U8)SK_PHY_MARV_COPPER) {
++
++ if (((Byte < (SK_U8)SK_PHY_MARV_COPPER) || pAC->GIni.GIYukon2) &&
++ pAC->GIni.GIPmdTyp != 'L' && pAC->GIni.GIPmdTyp != 'S') {
+ /* if this field is not initialized */
+ Byte = (SK_U8)SK_PHY_MARV_COPPER;
+-
++
+ pAC->GIni.GICopperType = SK_TRUE;
+ }
+-
+- pAC->GIni.GP[i].PhyAddr = PHY_ADDR_MARV;
+-
++
++ pPrt->PhyAddr = PHY_ADDR_MARV;
++
+ if (pAC->GIni.GICopperType) {
+
+- pAC->GIni.GP[i].PLinkSpeedCap = (SK_U8)(SK_LSPEED_CAP_AUTO |
+- SK_LSPEED_CAP_10MBPS | SK_LSPEED_CAP_100MBPS |
+- SK_LSPEED_CAP_1000MBPS);
+-
+- pAC->GIni.GP[i].PLinkSpeed = (SK_U8)SK_LSPEED_AUTO;
+-
+- pAC->GIni.GP[i].PMSCap = (SK_U8)(SK_MS_CAP_AUTO |
++ if (pAC->GIni.GIChipId == CHIP_ID_YUKON_FE ||
++ (pAC->GIni.GIChipId == CHIP_ID_YUKON_EC &&
++ pAC->GIni.GIChipCap == 2)) {
++
++ pPrt->PLinkSpeedCap = (SK_U8)(SK_LSPEED_CAP_100MBPS |
++ SK_LSPEED_CAP_10MBPS);
++
++ pAC->GIni.GIRamSize = 4;
++ }
++ else {
++ pPrt->PLinkSpeedCap = (SK_U8)(SK_LSPEED_CAP_1000MBPS |
++ SK_LSPEED_CAP_100MBPS | SK_LSPEED_CAP_10MBPS |
++ SK_LSPEED_CAP_AUTO);
++ }
++
++ pPrt->PLinkSpeed = (SK_U8)SK_LSPEED_AUTO;
++
++ pPrt->PMSCap = (SK_U8)(SK_MS_CAP_AUTO |
+ SK_MS_CAP_MASTER | SK_MS_CAP_SLAVE);
+ }
+ else {
+ Byte = (SK_U8)SK_PHY_MARV_FIBER;
+ }
+ }
++
++ /* clear TWSI IRQ */
++ SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ);
++
+ #endif /* YUKON */
+-
+- pAC->GIni.GP[i].PhyType = (int)Byte;
+-
++
++ pPrt->PhyType = (int)Byte;
++
+ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
+- ("PHY type: %d PHY addr: %04x\n", Byte,
+- pAC->GIni.GP[i].PhyAddr));
++ ("PHY type: %d PHY addr: %04x\n",
++ Byte, pPrt->PhyAddr));
+ }
+-
++
+ /* get MAC Type & set function pointers dependent on */
+ #ifdef GENESIS
+ if (pAC->GIni.GIGenesis) {
+-
++
+ pAC->GIni.GIMacType = SK_MAC_XMAC;
+
+ pAC->GIni.GIFunc.pFnMacUpdateStats = SkXmUpdateStats;
+ pAC->GIni.GIFunc.pFnMacStatistic = SkXmMacStatistic;
+ pAC->GIni.GIFunc.pFnMacResetCounter = SkXmResetCounter;
+ pAC->GIni.GIFunc.pFnMacOverflow = SkXmOverflowStatus;
++#ifdef SK_DIAG
++ pAC->GIni.GIFunc.pFnMacPhyRead = SkXmPhyRead;
++ pAC->GIni.GIFunc.pFnMacPhyWrite = SkXmPhyWrite;
++#else /* SK_DIAG */
++ pAC->GIni.GIFunc.pSkGeSirqIsr = SkGeYuSirqIsr;
++#endif /* !SK_DIAG */
+ }
+ #endif /* GENESIS */
+-
++
+ #ifdef YUKON
+ if (pAC->GIni.GIYukon) {
+-
++
+ pAC->GIni.GIMacType = SK_MAC_GMAC;
+
+ pAC->GIni.GIFunc.pFnMacUpdateStats = SkGmUpdateStats;
+ pAC->GIni.GIFunc.pFnMacStatistic = SkGmMacStatistic;
+ pAC->GIni.GIFunc.pFnMacResetCounter = SkGmResetCounter;
+ pAC->GIni.GIFunc.pFnMacOverflow = SkGmOverflowStatus;
++#ifdef SK_DIAG
++ pAC->GIni.GIFunc.pFnMacPhyRead = SkGmPhyRead;
++ pAC->GIni.GIFunc.pFnMacPhyWrite = SkGmPhyWrite;
++#else /* SK_DIAG */
++ if (CHIP_ID_YUKON_2(pAC)) {
++ pAC->GIni.GIFunc.pSkGeSirqIsr = SkYuk2SirqIsr;
++ }
++ else {
++ pAC->GIni.GIFunc.pSkGeSirqIsr = SkGeYuSirqIsr;
++ }
++#endif /* !SK_DIAG */
+
+ #ifdef SPECIAL_HANDLING
+ if (pAC->GIni.GIChipId == CHIP_ID_YUKON) {
+@@ -1793,7 +2538,9 @@
+ #endif
+ }
+ #endif /* YUKON */
+-
++
++ SkGeSetUpSupFeatures(pAC, IoC);
++
+ return(RetVal);
+ } /* SkGeInit1 */
+
+@@ -1814,9 +2561,12 @@
+ * nothing
+ */
+ static void SkGeInit2(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC) /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC) /* I/O Context */
+ {
++#ifdef YUKON
++ SK_U16 Word;
++#endif /* YUKON */
+ #ifdef GENESIS
+ SK_U32 DWord;
+ #endif /* GENESIS */
+@@ -1850,13 +2600,13 @@
+ SkGeInitPktArb(pAC, IoC);
+ }
+ #endif /* GENESIS */
+-
+-#ifdef YUKON
++
++#ifdef xSK_DIAG
+ if (pAC->GIni.GIYukon) {
+ /* start Time Stamp Timer */
+ SK_OUT8(IoC, GMAC_TI_ST_CTRL, (SK_U8)GMT_ST_START);
+ }
+-#endif /* YUKON */
++#endif /* SK_DIAG */
+
+ /* enable the Tx Arbiters */
+ for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
+@@ -1866,8 +2616,34 @@
+ /* enable the RAM Interface Arbiter */
+ SkGeInitRamIface(pAC, IoC);
+
++#ifdef YUKON
++ if (CHIP_ID_YUKON_2(pAC)) {
++
++ if (pAC->GIni.GIPciBus == SK_PEX_BUS) {
++
++ SK_IN16(IoC, PCI_C(pAC, PEX_DEV_CTRL), &Word);
++
++ /* change Max. Read Request Size to 2048 bytes */
++ Word &= ~PEX_DC_MAX_RRS_MSK;
++ Word |= PEX_DC_MAX_RD_RQ_SIZE(4);
++
++ SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON);
++
++ SK_OUT16(IoC, PCI_C(pAC, PEX_DEV_CTRL), Word);
++
++ SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
++ }
++
++ /*
++ * Writing the HW Error Mask Reg. will not generate an IRQ
++ * as long as the B0_IMSK is not set by the driver.
++ */
++ SK_OUT32(IoC, B0_HWE_IMSK, pAC->GIni.GIValHwIrqMask);
++ }
++#endif /* YUKON */
+ } /* SkGeInit2 */
+
++
+ /******************************************************************************
+ *
+ * SkGeInit() - Initialize the GE Adapter with the specified level.
+@@ -1889,7 +2665,7 @@
+ * if Number of MACs > SK_MAX_MACS
+ *
+ * After returning from Level 0 the adapter
+- * may be accessed with IO operations.
++ * may be accessed with I/O operations.
+ *
+ * Level 2: start the Blink Source Counter
+ *
+@@ -1898,14 +2674,14 @@
+ * 1: Number of MACs exceeds SK_MAX_MACS (after level 1)
+ * 2: Adapter not present or not accessible
+ * 3: Illegal initialization level
+- * 4: Initialization Level 1 Call missing
++ * 4: Initialization level 1 call missing
+ * 5: Unexpected PHY type detected
+ * 6: HW self test failed
+ */
+ int SkGeInit(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Level) /* initialization level */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
++int Level) /* Initialization Level */
+ {
+ int RetVal; /* return value */
+ SK_U32 DWord;
+@@ -1920,7 +2696,7 @@
+ SkGeInit0(pAC, IoC);
+ pAC->GIni.GILevel = SK_INIT_DATA;
+ break;
+-
++
+ case SK_INIT_IO:
+ /* Initialization Level 1 */
+ RetVal = SkGeInit1(pAC, IoC);
+@@ -1932,22 +2708,24 @@
+ SK_OUT32(IoC, B2_IRQM_INI, SK_TEST_VAL);
+ SK_IN32(IoC, B2_IRQM_INI, &DWord);
+ SK_OUT32(IoC, B2_IRQM_INI, 0L);
+-
++
+ if (DWord != SK_TEST_VAL) {
+ RetVal = 2;
+ break;
+ }
+
++#ifdef DEBUG
+ /* check if the number of GIMacsFound matches SK_MAX_MACS */
+ if (pAC->GIni.GIMacsFound > SK_MAX_MACS) {
+ RetVal = 1;
+ break;
+ }
++#endif /* DEBUG */
+
+ /* Level 1 successfully passed */
+ pAC->GIni.GILevel = SK_INIT_IO;
+ break;
+-
++
+ case SK_INIT_RUN:
+ /* Initialization Level 2 */
+ if (pAC->GIni.GILevel != SK_INIT_IO) {
+@@ -1957,12 +2735,13 @@
+ RetVal = 4;
+ break;
+ }
++
+ SkGeInit2(pAC, IoC);
+
+ /* Level 2 successfully passed */
+ pAC->GIni.GILevel = SK_INIT_RUN;
+ break;
+-
++
+ default:
+ SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E003, SKERR_HWI_E003MSG);
+ RetVal = 3;
+@@ -1985,77 +2764,79 @@
+ * nothing
+ */
+ void SkGeDeInit(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC) /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC) /* I/O Context */
+ {
+ int i;
+ SK_U16 Word;
+
+-#ifdef SK_PHY_LP_MODE
+- SK_U8 Byte;
++#ifdef SK_PHY_LP_MODE_DEEP_SLEEP
+ SK_U16 PmCtlSts;
+-#endif /* SK_PHY_LP_MODE */
++#endif
+
+ #if (!defined(SK_SLIM) && !defined(VCPU))
+ /* ensure I2C is ready */
+ SkI2cWaitIrq(pAC, IoC);
+-#endif
+-
+- /* stop all current transfer activity */
+- for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
+- if (pAC->GIni.GP[i].PState != SK_PRT_STOP &&
+- pAC->GIni.GP[i].PState != SK_PRT_RESET) {
+-
+- SkGeStopPort(pAC, IoC, i, SK_STOP_ALL, SK_HARD_RST);
+- }
+- }
++#endif
+
+-#ifdef SK_PHY_LP_MODE
+- /*
++#ifdef SK_PHY_LP_MODE_DEEP_SLEEP
++ /*
+ * for power saving purposes within mobile environments
+- * we set the PHY to coma mode and switch to D3 power state.
++ * we set the PHY to coma mode.
+ */
+- if (pAC->GIni.GIYukonLite &&
+- pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) {
++#ifdef XXX
++ if (pAC->GIni.GIVauxAvail) {
++ /* switch power to VAUX */
++ SK_OUT8(IoC, B0_POWER_CTRL, (SK_U8)(PC_VAUX_ENA | PC_VCC_ENA |
++ PC_VAUX_ON | PC_VCC_OFF));
++ }
++#endif /* XXX */
++
++ if (CHIP_ID_YUKON_2(pAC) && /* pAC->GIni.GIMacsFound == 1 && */
++ !pAC->GIni.GIAsfEnabled
++#ifdef XXX
++ || (pAC->GIni.GIYukonLite && pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3)
++#endif /* XXX */
++ ) {
+
+ /* for all ports switch PHY to coma mode */
+ for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
+-
+- SkGmEnterLowPowerMode(pAC, IoC, i, PHY_PM_DEEP_SLEEP);
+- }
+
+- if (pAC->GIni.GIVauxAvail) {
+- /* switch power to VAUX */
+- Byte = PC_VAUX_ENA | PC_VCC_ENA | PC_VAUX_ON | PC_VCC_OFF;
+-
+- SK_OUT8(IoC, B0_POWER_CTRL, Byte);
++ (void)SkGmEnterLowPowerMode(pAC, IoC, i, PHY_PM_DEEP_SLEEP);
+ }
+-
+- /* switch to D3 state */
+- SK_IN16(IoC, PCI_C(PCI_PM_CTL_STS), &PmCtlSts);
+-
+- PmCtlSts |= PCI_PM_STATE_D3;
++ }
++#else /* !SK_PHY_LP_MODE_DEEP_SLEEP */
+
+- SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON);
++ if (!pAC->GIni.GIAsfEnabled) {
++ /* stop all current transfer activity */
++ for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
++ if (pAC->GIni.GP[i].PState != SK_PRT_STOP &&
++ pAC->GIni.GP[i].PState != SK_PRT_RESET) {
+
+- SK_OUT16(IoC, PCI_C(PCI_PM_CTL_STS), PmCtlSts);
++ SkGeStopPort(pAC, IoC, i, SK_STOP_ALL, SK_HARD_RST);
++ }
++ }
+ }
+-#endif /* SK_PHY_LP_MODE */
+
+- /* Reset all bits in the PCI STATUS register */
++ /* reset all bits in the PCI STATUS register */
+ /*
+ * Note: PCI Cfg cycles cannot be used, because they are not
+ * available on some platforms after 'boot time'.
+ */
+- SK_IN16(IoC, PCI_C(PCI_STATUS), &Word);
+-
++ SK_IN16(IoC, PCI_C(pAC, PCI_STATUS), &Word);
++
+ SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON);
+- SK_OUT16(IoC, PCI_C(PCI_STATUS), (SK_U16)(Word | PCI_ERRBITS));
++
++ SK_OUT16(IoC, PCI_C(pAC, PCI_STATUS), Word | (SK_U16)PCI_ERRBITS);
++
+ SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
+
+- /* do the reset, all LEDs are switched off now */
+- SK_OUT8(IoC, B0_CTST, CS_RST_SET);
+-
++ if (!pAC->GIni.GIAsfEnabled) {
++ /* set the SW-reset */
++ SK_OUT8(IoC, B0_CTST, CS_RST_SET);
++ }
++#endif /* !SK_PHY_LP_MODE_DEEP_SLEEP */
++
+ pAC->GIni.GILevel = SK_INIT_DATA;
+ } /* SkGeDeInit */
+
+@@ -2089,8 +2870,8 @@
+ * 2: The port has to be stopped before it can be initialized again.
+ */
+ int SkGeInitPort(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ int Port) /* Port to configure */
+ {
+ SK_GEPORT *pPrt;
+@@ -2101,8 +2882,8 @@
+ SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E004, SKERR_HWI_E004MSG);
+ return(1);
+ }
+-
+- if (pPrt->PState == SK_PRT_INIT || pPrt->PState == SK_PRT_RUN) {
++
++ if (pPrt->PState >= SK_PRT_INIT) {
+ SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E005, SKERR_HWI_E005MSG);
+ return(2);
+ }
+@@ -2119,29 +2900,29 @@
+ SkGeXmitLED(pAC, IoC, MR_ADDR(Port, TX_LED_INI), SK_LED_ENA);
+ SkGeXmitLED(pAC, IoC, MR_ADDR(Port, RX_LED_INI), SK_LED_ENA);
+ /* The Link LED is initialized by RLMT or Diagnostics itself */
+-
++
+ SkXmInitMac(pAC, IoC, Port);
+ }
+ #endif /* GENESIS */
+-
++
+ #ifdef YUKON
+ if (pAC->GIni.GIYukon) {
+
+ SkGmInitMac(pAC, IoC, Port);
+ }
+ #endif /* YUKON */
+-
++
+ /* do NOT initialize the Link Sync Counter */
+
+ SkGeInitMacFifo(pAC, IoC, Port);
+-
++
+ SkGeInitRamBufs(pAC, IoC, Port);
+-
++
+ if (pPrt->PXSQSize != 0) {
+ /* enable Force Sync bit if synchronous queue available */
+ SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL), TXA_ENA_FSYNC);
+ }
+-
++
+ SkGeInitBmu(pAC, IoC, Port);
+
+ /* mark port as initialized */
+@@ -2149,3 +2930,194 @@
+
+ return(0);
+ } /* SkGeInitPort */
++
++
++#ifdef YUK2
++/******************************************************************************
++ *
++ * RamWrite() - Writes One quadword to RAM
++ *
++ * Returns:
++ * 0
++ */
++static void RamWrite(
++SK_IOC IoC, /* I/O Context */
++SK_U32 Addr, /* Address to be written to (in quadwords) */
++SK_U32 LowDword, /* Lower Dword to be written */
++SK_U32 HighDword, /* Upper Dword to be written */
++int Port) /* Select RAM buffer (Yukon-2 has 2 RAM buffers) */
++{
++ SK_OUT32(IoC, SELECT_RAM_BUFFER(Port, B3_RAM_ADDR), Addr);
++
++ /* Write Access is initiated by writing the upper Dword */
++ SK_OUT32(IoC, SELECT_RAM_BUFFER(Port, B3_RAM_DATA_LO), LowDword);
++ SK_OUT32(IoC, SELECT_RAM_BUFFER(Port, B3_RAM_DATA_HI), HighDword);
++}
++
++
++/******************************************************************************
++ *
++ * SkYuk2RestartRxBmu() - Restart Receive BMU on Yukon-2
++ *
++ * return:
++ * 0 o.k.
++ * 1 timeout
++ */
++int SkYuk2RestartRxBmu(
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
++int Port) /* Port Index (MAC_1 + n) */
++{
++ SK_U16 Word;
++ SK_U16 MacCtrl;
++ SK_U16 RxCtrl;
++ SK_U16 FlushMask;
++ SK_U16 FlushTrsh;
++ SK_U32 RamAdr;
++ SK_U32 DWord;
++ SK_U32 StartTime;
++ SK_U32 CurrTime;
++ SK_U32 Delta;
++ SK_U32 TimeOut;
++ SK_GEPORT *pPrt; /* GIni Port struct pointer */
++ int i;
++ int Rtv;
++
++ Rtv = 0;
++
++ pPrt = &pAC->GIni.GP[Port];
++
++/*
++ 1. save Rx MAC FIFO Flush Mask and Rx MAC FIFO Flush Threshold
++ 2. save GMAC Rx Control Register
++ 3. re-initialize MAC Rx FIFO, Rx RAM Buffer Queue, PCI Rx FIFO,
++ Rx BMU and Rx Prefetch Unit of the link.
++ 4. set Rx MAC FIFO Flush Mask to 0xffff
++ set Rx MAC FIFO Flush Threshold to a high value, e.g. 0x20
++ 5. set GMAC to loopback mode and switch GMAC back to Rx/Tx enable
++ 6. clear Rx/Tx Frame Complete IRQ in Rx/T MAC FIFO Control Register
++ 7. send one packet with a size of 64bytes (size below flush threshold)
++ from TXA RAM Buffer Queue to set the rx_sop flop:
++ - set TxAQ Write Pointer to (packet size in qwords + 2)
++ - set TxAQ Level to (packet size in qwords + 2)
++ - write Internal Status Word 1 and 2 to TxAQ RAM Buffer Queue QWord 0,1
++ according to figure 61 on page 330 of Yukon-2 Spec.
++ - write MAC header with Destination Address = own MAC address to
++ TxAQ RAM Buffer Queue QWords 2 and 3
++ - set TxAQ Packet Counter to 1 -> packet is transmitted immediately
++ 8. poll GMAC IRQ Source Register for IRQ Rx/Tx Frame Complete
++ 9. restore GMAC Rx Control Register
++10. restore Rx MAC FIFO Flush Mask and Rx MAC FIFO Flush Threshold
++11. set GMAC back to GMII mode
++*/
++
++ /* save Rx GMAC FIFO Flush Mask */
++ SK_IN16(IoC, MR_ADDR(Port, RX_GMF_FL_MSK), &FlushMask);
++
++ /* save Rx GMAC FIFO Flush Threshold */
++ SK_IN16(IoC, MR_ADDR(Port, RX_GMF_FL_THR), &FlushTrsh);
++
++ /* save GMAC Rx Control Register */
++ GM_IN16(IoC, Port, GM_RX_CTRL, &RxCtrl);
++
++ /* configure Tx GMAC FIFO */
++ SkGeInitMacFifo(pAC, IoC, Port);
++
++ SkGeInitRamBufs(pAC, IoC, Port);
++
++ SkGeInitBmu(pAC, IoC, Port);
++
++ /* configure Rx GMAC FIFO */
++ SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), GMF_RX_CTRL_DEF);
++
++ /* set Rx GMAC FIFO Flush Mask */
++ SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_FL_MSK), 0xffff);
++
++ /* set Rx GMAC FIFO Flush Threshold */
++ SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_FL_THR), 0x20);
++
++ /* set to promiscuous mode */
++ Word = RxCtrl & ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
++
++ /* set GMAC Rx Control Register */
++ GM_OUT16(IoC, Port, GM_RX_CTRL, Word);
++
++ /* get General Purpose Control */
++ GM_IN16(IoC, Port, GM_GP_CTRL, &MacCtrl);
++
++ /* enable MAC Loopback Mode*/
++ GM_OUT16(IoC, Port, GM_GP_CTRL, MacCtrl | GM_GPCR_LOOP_ENA);
++
++ /* enable MAC Loopback Mode and Rx/Tx */
++ GM_OUT16(IoC, Port, GM_GP_CTRL, MacCtrl | GM_GPCR_LOOP_ENA |
++ GM_GPCR_RX_ENA | GM_GPCR_TX_ENA);
++
++ /* clear GMAC IRQ Rx Frame Complete */
++ SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_CLI_RX_FC);
++
++ /* clear GMAC IRQ Tx Frame Complete */
++ SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_CLI_TX_FC);
++
++ /* send one packet with a size of 64bytes from RAM buffer*/
++
++ RamAdr = pPrt->PXaQRamStart / 8;
++
++ SK_OUT32(IoC, RB_ADDR(pPrt->PXaQOff, RB_WP), RamAdr + 10);
++
++ SK_OUT32(IoC, RB_ADDR(pPrt->PXaQOff, RB_LEV), 10);
++
++ /* write 1st status quad word (packet end address in RAM, packet length */
++ RamWrite(IoC, RamAdr, (RamAdr + 9) << 16, 64, Port);
++
++ /* write 2nd status quad word */
++ RamWrite(IoC, RamAdr + 1, 0, 0, Port);
++
++ /* write DA to MAC header */
++ RamWrite(IoC, RamAdr + 2, *(SK_U32 *)&pPrt->PMacAddr[0],
++ *(SK_U32 *)&pPrt->PMacAddr[2], Port);
++
++ SK_OUT32(IoC, RB_ADDR(pPrt->PXaQOff, RB_PC), 1);
++
++ SK_IN32(IoC, GMAC_TI_ST_VAL, &StartTime);
++
++ /* set timeout to 1 ms */
++ TimeOut = HW_MS_TO_TICKS(pAC, 1);
++
++ do {
++ SK_IN32(IoC, GMAC_TI_ST_VAL, &CurrTime);
++
++ if (CurrTime >= StartTime) {
++ Delta = CurrTime - StartTime;
++ }
++ else {
++ Delta = CurrTime + ~StartTime + 1;
++ }
++
++ if (Delta > TimeOut) {
++ Rtv = 1;
++ break;
++ }
++
++ /* read the GMAC Interrupt source register */
++ SK_IN16(IoC, MR_ADDR(Port, GMAC_IRQ_SRC), &Word);
++
++ } while ((Word & (GM_IS_TX_COMPL | GM_IS_RX_COMPL)) !=
++ (GM_IS_TX_COMPL | GM_IS_RX_COMPL));
++
++ /* disable MAC Loopback Mode and Rx/Tx */
++ GM_OUT16(IoC, Port, GM_GP_CTRL, MacCtrl);
++
++ /* restore GMAC Rx Control Register */
++ GM_OUT16(IoC, Port, GM_RX_CTRL, RxCtrl);
++
++ /* restore Rx GMAC FIFO Flush Mask */
++ SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_FL_MSK), FlushMask);
++
++ /* restore Rx GMAC FIFO Flush Threshold */
++ SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_FL_THR), FlushTrsh);
++
++ return(Rtv);
++
++} /* SkYuk2RestartRxBmu */
++#endif /* YUK2 */
++
+diff -ruN linux/drivers/net/sk98lin/skgemib.c linux-new/drivers/net/sk98lin/skgemib.c
+--- linux/drivers/net/sk98lin/skgemib.c 2005-09-26 13:32:47.000000000 +0400
++++ linux-new/drivers/net/sk98lin/skgemib.c 2005-08-09 17:15:51.000000000 +0400
+@@ -2,8 +2,8 @@
+ *
+ * Name: skgemib.c
+ * Project: GEnesis, PCI Gigabit Ethernet Adapter
+- * Version: $Revision: 1.11 $
+- * Date: $Date: 2003/09/15 13:38:12 $
++ * Version: $Revision: 2.7 $
++ * Date: $Date: 2004/10/26 12:42:18 $
+ * Purpose: Private Network Management Interface Management Database
+ *
+ ****************************************************************************/
+@@ -251,6 +251,183 @@
+ 0,
+ SK_PNMI_RW, DiagActions, 0},
+ #endif /* SK_DIAG_SUPPORT */
++#ifdef SK_ASF
++ {OID_SKGE_ASF,
++ 0,
++ 0,
++ 0,
++ SK_PNMI_RW, Asf, 0},
++ {OID_SKGE_ASF_STORE_CONFIG,
++ 0,
++ 0,
++ 0,
++ SK_PNMI_RW, Asf, 0},
++ {OID_SKGE_ASF_ENA,
++ 0,
++ 0,
++ 0,
++ SK_PNMI_RW, Asf, 0},
++ {OID_SKGE_ASF_RETRANS,
++ 0,
++ 0,
++ 0,
++ SK_PNMI_RW, Asf, 0},
++ {OID_SKGE_ASF_RETRANS_INT,
++ 0,
++ 0,
++ 0,
++ SK_PNMI_RW, Asf, 0},
++ {OID_SKGE_ASF_HB_ENA,
++ 0,
++ 0,
++ 0,
++ SK_PNMI_RW, Asf, 0},
++ {OID_SKGE_ASF_HB_INT,
++ 0,
++ 0,
++ 0,
++ SK_PNMI_RW, Asf, 0},
++ {OID_SKGE_ASF_WD_ENA,
++ 0,
++ 0,
++ 0,
++ SK_PNMI_RW, Asf, 0},
++ {OID_SKGE_ASF_WD_TIME,
++ 0,
++ 0,
++ 0,
++ SK_PNMI_RW, Asf, 0},
++ {OID_SKGE_ASF_IP_SOURCE,
++ 0,
++ 0,
++ 0,
++ SK_PNMI_RW, Asf, 0},
++ {OID_SKGE_ASF_MAC_SOURCE,
++ 0,
++ 0,
++ 0,
++ SK_PNMI_RW, Asf, 0},
++ {OID_SKGE_ASF_IP_DEST,
++ 0,
++ 0,
++ 0,
++ SK_PNMI_RW, Asf, 0},
++ {OID_SKGE_ASF_MAC_DEST,
++ 0,
++ 0,
++ 0,
++ SK_PNMI_RW, Asf, 0},
++ {OID_SKGE_ASF_COMMUNITY_NAME,
++ 0,
++ 0,
++ 0,
++ SK_PNMI_RW, Asf, 0},
++ {OID_SKGE_ASF_RSP_ENA,
++ 0,
++ 0,
++ 0,
++ SK_PNMI_RW, Asf, 0},
++ {OID_SKGE_ASF_RETRANS_COUNT_MIN,
++ 0,
++ 0,
++ 0,
++ SK_PNMI_RW, Asf, 0},
++ {OID_SKGE_ASF_RETRANS_COUNT_MAX,
++ 0,
++ 0,
++ 0,
++ SK_PNMI_RW, Asf, 0},
++ {OID_SKGE_ASF_RETRANS_INT_MIN,
++ 0,
++ 0,
++ 0,
++ SK_PNMI_RW, Asf, 0},
++ {OID_SKGE_ASF_RETRANS_INT_MAX,
++ 0,
++ 0,
++ 0,
++ SK_PNMI_RW, Asf, 0},
++ {OID_SKGE_ASF_HB_INT_MIN,
++ 0,
++ 0,
++ 0,
++ SK_PNMI_RW, Asf, 0},
++ {OID_SKGE_ASF_HB_INT_MAX,
++ 0,
++ 0,
++ 0,
++ SK_PNMI_RW, Asf, 0},
++ {OID_SKGE_ASF_WD_TIME_MIN,
++ 0,
++ 0,
++ 0,
++ SK_PNMI_RW, Asf, 0},
++ {OID_SKGE_ASF_WD_TIME_MAX,
++ 0,
++ 0,
++ 0,
++ SK_PNMI_RW, Asf, 0},
++ {OID_SKGE_ASF_HB_CAP,
++ 0,
++ 0,
++ 0,
++ SK_PNMI_RW, Asf, 0},
++ {OID_SKGE_ASF_WD_TIMER_RES,
++ 0,
++ 0,
++ 0,
++ SK_PNMI_RW, Asf, 0},
++ {OID_SKGE_ASF_GUID,
++ 0,
++ 0,
++ 0,
++ SK_PNMI_RW, Asf, 0},
++ {OID_SKGE_ASF_KEY_OP,
++ 0,
++ 0,
++ 0,
++ SK_PNMI_RW, Asf, 0},
++ {OID_SKGE_ASF_KEY_ADM,
++ 0,
++ 0,
++ 0,
++ SK_PNMI_RW, Asf, 0},
++ {OID_SKGE_ASF_KEY_GEN,
++ 0,
++ 0,
++ 0,
++ SK_PNMI_RW, Asf, 0},
++ {OID_SKGE_ASF_CAP,
++ 0,
++ 0,
++ 0,
++ SK_PNMI_RW, Asf, 0},
++ {OID_SKGE_ASF_PAR_1,
++ 0,
++ 0,
++ 0,
++ SK_PNMI_RW, Asf, 0},
++ {OID_SKGE_ASF_OVERALL_OID,
++ 0,
++ 0,
++ 0,
++ SK_PNMI_RW, Asf, 0},
++ {OID_SKGE_ASF_FWVER_OID,
++ 0,
++ 0,
++ 0,
++ SK_PNMI_RO, Asf, 0},
++ {OID_SKGE_ASF_ACPI_OID,
++ 0,
++ 0,
++ 0,
++ SK_PNMI_RO, Asf, 0},
++ {OID_SKGE_ASF_SMBUS_OID,
++ 0,
++ 0,
++ 0,
++ SK_PNMI_RO, Asf, 0},
++#endif /* SK_ASF */
+ {OID_SKGE_MDB_VERSION,
+ 1,
+ 0,
+@@ -1073,6 +1250,11 @@
+ 0,
+ 0,
+ SK_PNMI_RO, Vct, 0},
++ {OID_SKGE_VCT_CAPABILITIES,
++ 0,
++ 0,
++ 0,
++ SK_PNMI_RO, Vct, 0},
+ {OID_SKGE_BOARDLEVEL,
+ 0,
+ 0,
+diff -ruN linux/drivers/net/sk98lin/skgepnmi.c linux-new/drivers/net/sk98lin/skgepnmi.c
+--- linux/drivers/net/sk98lin/skgepnmi.c 2005-09-26 13:32:48.000000000 +0400
++++ linux-new/drivers/net/sk98lin/skgepnmi.c 2005-08-09 17:15:51.000000000 +0400
+@@ -1,9 +1,9 @@
+ /*****************************************************************************
+ *
+ * Name: skgepnmi.c
+- * Project: GEnesis, PCI Gigabit Ethernet Adapter
+- * Version: $Revision: 1.111 $
+- * Date: $Date: 2003/09/15 13:35:35 $
++ * Project: Gigabit Ethernet Adapters, PNMI-Module
++ * Version: $Revision: 2.23 $
++ * Date: $Date: 2005/08/09 09:05:12 $
+ * Purpose: Private Network Management Interface
+ *
+ ****************************************************************************/
+@@ -22,11 +22,10 @@
+ *
+ ******************************************************************************/
+
+-
+-#ifndef _lint
++#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
+ static const char SysKonnectFileId[] =
+- "@(#) $Id: skgepnmi.c,v 1.111 2003/09/15 13:35:35 tschilli Exp $ (C) Marvell.";
+-#endif /* !_lint */
++ "@(#) $Id: skgepnmi.c,v 2.23 2005/08/09 09:05:12 tschilli Exp $ (C) Marvell.";
++#endif
+
+ #include "h/skdrv1st.h"
+ #include "h/sktypes.h"
+@@ -38,12 +37,14 @@
+ #include "h/skcsum.h"
+ #include "h/skvpd.h"
+ #include "h/skgehw.h"
++#include "h/sky2le.h"
+ #include "h/skgeinit.h"
+ #include "h/skdrv2nd.h"
+ #include "h/skgepnm2.h"
+ #ifdef SK_POWER_MGMT
+ #include "h/skgepmgt.h"
+-#endif
++#endif /* SK_POWER_MGMT */
++
+ /* defines *******************************************************************/
+
+ #ifndef DEBUG
+@@ -72,7 +73,6 @@
+ int SkPnmiGenIoctl(SK_AC *pAC, SK_IOC IoC, void * pBuf,
+ unsigned int * pLen, SK_U32 NetIndex);
+
+-
+ /*
+ * Private Function prototypes
+ */
+@@ -112,6 +112,12 @@
+ PNMI_STATIC int Vct(SK_AC *pAC, SK_IOC IoC, int Action, SK_U32 Id, char *pBuf,
+ unsigned int *pLen, SK_U32 Instance, unsigned int TableIndex, SK_U32 NetIndex);
+ PNMI_STATIC void CheckVctStatus(SK_AC *, SK_IOC, char *, SK_U32, SK_U32);
++PNMI_STATIC void VctGetResults(SK_AC *, SK_IOC, SK_U32);
++#ifdef SK_ASF
++PNMI_STATIC int Asf(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
++ char *pBuf, unsigned int *pLen, SK_U32 Instance,
++ unsigned int TableIndex, SK_U32 NetIndex);
++#endif /* SK_ASF */
+
+ /*
+ * Table to correlate OID with handler function and index to
+@@ -353,17 +359,13 @@
+ * Always 0
+ */
+ int SkPnmiInit(
+-SK_AC *pAC, /* Pointer to adapter context */
+-SK_IOC IoC, /* IO context handle */
+-int Level) /* Initialization level */
++SK_AC *pAC, /* Pointer to adapter context */
++SK_IOC IoC, /* IO context handle */
++int Level) /* Initialization level */
+ {
+ unsigned int PortMax; /* Number of ports */
+ unsigned int PortIndex; /* Current port index in loop */
+- SK_U16 Val16; /* Multiple purpose 16 bit variable */
+- SK_U8 Val8; /* Mulitple purpose 8 bit variable */
+- SK_EVPARA EventParam; /* Event struct for timer event */
+- SK_PNMI_VCT *pVctBackupData;
+-
++ SK_EVPARA EventParam; /* Event struct for timer event */
+
+ SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+ ("PNMI: SkPnmiInit: Called, level=%d\n", Level));
+@@ -372,13 +374,19 @@
+
+ case SK_INIT_DATA:
+ SK_MEMSET((char *)&pAC->Pnmi, 0, sizeof(pAC->Pnmi));
++
+ pAC->Pnmi.TrapBufFree = SK_PNMI_TRAP_QUEUE_LEN;
+ pAC->Pnmi.StartUpTime = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC));
+ pAC->Pnmi.RlmtChangeThreshold = SK_PNMI_DEF_RLMT_CHG_THRES;
++
+ for (PortIndex = 0; PortIndex < SK_MAX_MACS; PortIndex ++) {
+
+ pAC->Pnmi.Port[PortIndex].ActiveFlag = SK_FALSE;
+ pAC->Pnmi.DualNetActiveFlag = SK_FALSE;
++
++ /* Initialize DSP variables for Vct() to 0xff => Never written! */
++ pAC->GIni.GP[PortIndex].PCableLen = 0xff;
++ pAC->Pnmi.VctBackup[PortIndex].CableLen = 0xff;
+ }
+
+ #ifdef SK_PNMI_CHECK
+@@ -408,51 +416,36 @@
+ break;
+
+ case SK_INIT_IO:
+- /*
+- * Reset MAC counters
+- */
++
++ /* Reset MAC counters. */
+ PortMax = pAC->GIni.GIMacsFound;
+
+ for (PortIndex = 0; PortIndex < PortMax; PortIndex ++) {
+
+ pAC->GIni.GIFunc.pFnMacResetCounter(pAC, IoC, PortIndex);
+ }
+-
+- /* Initialize DSP variables for Vct() to 0xff => Never written! */
+- for (PortIndex = 0; PortIndex < PortMax; PortIndex ++) {
+- pAC->GIni.GP[PortIndex].PCableLen = 0xff;
+- pVctBackupData = &pAC->Pnmi.VctBackup[PortIndex];
+- pVctBackupData->PCableLen = 0xff;
+- }
+-
+- /*
+- * Get pci bus speed
+- */
+- SK_IN16(IoC, B0_CTST, &Val16);
+- if ((Val16 & CS_BUS_CLOCK) == 0) {
+
+- pAC->Pnmi.PciBusSpeed = 33;
++ /* Get PCI bus speed. */
++ if (pAC->GIni.GIPciClock66) {
++
++ pAC->Pnmi.PciBusSpeed = 66;
+ }
+ else {
+- pAC->Pnmi.PciBusSpeed = 66;
++ pAC->Pnmi.PciBusSpeed = 33;
+ }
+
+- /*
+- * Get pci bus width
+- */
+- SK_IN16(IoC, B0_CTST, &Val16);
+- if ((Val16 & CS_BUS_SLOT_SZ) == 0) {
++ /* Get PCI bus width. */
++ if (pAC->GIni.GIPciSlot64) {
+
+- pAC->Pnmi.PciBusWidth = 32;
++ pAC->Pnmi.PciBusWidth = 64;
+ }
+ else {
+- pAC->Pnmi.PciBusWidth = 64;
++ pAC->Pnmi.PciBusWidth = 32;
+ }
+
+- /*
+- * Get chipset
+- */
++ /* Get chipset. */
+ switch (pAC->GIni.GIChipId) {
++
+ case CHIP_ID_GENESIS:
+ pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_XMAC;
+ break;
+@@ -461,57 +454,51 @@
+ pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_YUKON;
+ break;
+
++ case CHIP_ID_YUKON_LITE:
++ pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_YUKON_LITE;
++ break;
++
++ case CHIP_ID_YUKON_LP:
++ pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_YUKON_LP;
++ break;
++
++ case CHIP_ID_YUKON_XL:
++ pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_YUKON_XL;
++ break;
++
++ case CHIP_ID_YUKON_EC:
++ pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_YUKON_EC;
++ break;
++
++ case CHIP_ID_YUKON_FE:
++ pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_YUKON_FE;
++ break;
++
+ default:
+ break;
+ }
+
+- /*
+- * Get PMD and DeviceType
+- */
+- SK_IN8(IoC, B2_PMD_TYP, &Val8);
+- switch (Val8) {
++ /* Get PMD and Device Type. */
++ switch (pAC->GIni.GIPmdTyp) {
++
+ case 'S':
+ pAC->Pnmi.PMD = 3;
+- if (pAC->GIni.GIMacsFound > 1) {
+-
+- pAC->Pnmi.DeviceType = 0x00020002;
+- }
+- else {
+- pAC->Pnmi.DeviceType = 0x00020001;
+- }
++ pAC->Pnmi.DeviceType = 0x00020001;
+ break;
+
+ case 'L':
+ pAC->Pnmi.PMD = 2;
+- if (pAC->GIni.GIMacsFound > 1) {
+-
+- pAC->Pnmi.DeviceType = 0x00020004;
+- }
+- else {
+- pAC->Pnmi.DeviceType = 0x00020003;
+- }
++ pAC->Pnmi.DeviceType = 0x00020003;
+ break;
+
+ case 'C':
+ pAC->Pnmi.PMD = 4;
+- if (pAC->GIni.GIMacsFound > 1) {
+-
+- pAC->Pnmi.DeviceType = 0x00020006;
+- }
+- else {
+- pAC->Pnmi.DeviceType = 0x00020005;
+- }
++ pAC->Pnmi.DeviceType = 0x00020005;
+ break;
+
+ case 'T':
+ pAC->Pnmi.PMD = 5;
+- if (pAC->GIni.GIMacsFound > 1) {
+-
+- pAC->Pnmi.DeviceType = 0x00020008;
+- }
+- else {
+- pAC->Pnmi.DeviceType = 0x00020007;
+- }
++ pAC->Pnmi.DeviceType = 0x00020007;
+ break;
+
+ default :
+@@ -520,11 +507,14 @@
+ break;
+ }
+
+- /*
+- * Get connector
+- */
+- SK_IN8(IoC, B2_CONN_TYP, &Val8);
+- switch (Val8) {
++ if (pAC->GIni.GIMacsFound > 1) {
++
++ pAC->Pnmi.DeviceType++;
++ }
++
++ /* Get connector type. */
++ switch (pAC->GIni.GIConTyp) {
++
+ case 'C':
+ pAC->Pnmi.Connector = 2;
+ break;
+@@ -552,17 +542,17 @@
+ break;
+
+ case SK_INIT_RUN:
+- /*
+- * Start timer for RLMT change counter
+- */
++
++ /* Start timer for RLMT change counter. */
+ SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
++
+ SkTimerStart(pAC, IoC, &pAC->Pnmi.RlmtChangeEstimate.EstTimer,
+- 28125000, SKGE_PNMI, SK_PNMI_EVT_CHG_EST_TIMER,
++ SK_PNMI_EVT_TIMER_CHECK, SKGE_PNMI, SK_PNMI_EVT_CHG_EST_TIMER,
+ EventParam);
+ break;
+
+ default:
+- break; /* Nothing todo */
++ break; /* Nothing to do. */
+ }
+
+ return (0);
+@@ -642,7 +632,6 @@
+ ("PNMI: SkPnmiPreSetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n",
+ Id, *pLen, Instance, NetIndex));
+
+-
+ return (PnmiVar(pAC, IoC, SK_PNMI_PRESET, Id, (char *)pBuf, pLen,
+ Instance, NetIndex));
+ }
+@@ -724,7 +713,6 @@
+ unsigned int TmpLen;
+ char KeyArr[SK_PNMI_VPD_ENTRIES][SK_PNMI_VPD_KEY_SIZE];
+
+-
+ SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+ ("PNMI: SkPnmiGetStruct: Called, BufLen=%d, NetIndex=%d\n",
+ *pLen, NetIndex));
+@@ -733,22 +721,19 @@
+
+ if (*pLen >= SK_PNMI_MIN_STRUCT_SIZE) {
+
+- SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_TOO_SHORT,
+- (SK_U32)(-1));
++ SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_TOO_SHORT, (SK_U32)(-1));
+ }
+
+ *pLen = SK_PNMI_STRUCT_SIZE;
+ return (SK_PNMI_ERR_TOO_SHORT);
+ }
+
+- /*
+- * Check NetIndex
+- */
++ /* Check NetIndex. */
+ if (NetIndex >= pAC->Rlmt.NumNets) {
+ return (SK_PNMI_ERR_UNKNOWN_NET);
+ }
+
+- /* Update statistic */
++ /* Update statistics. */
+ SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On call");
+
+ if ((Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1)) !=
+@@ -773,35 +758,37 @@
+ return (Ret);
+ }
+
+- /*
+- * Increment semaphores to indicate that an update was
+- * already done
+- */
++ /* Increment semaphores to indicate that an update was already done. */
+ pAC->Pnmi.MacUpdatedFlag ++;
+ pAC->Pnmi.RlmtUpdatedFlag ++;
+ pAC->Pnmi.SirqUpdatedFlag ++;
+
+- /* Get vpd keys for instance calculation */
+- Ret = GetVpdKeyArr(pAC, IoC, &KeyArr[0][0], sizeof(KeyArr), &TmpLen);
+- if (Ret != SK_PNMI_ERR_OK) {
++ /*
++ * Get VPD keys for instance calculation.
++ * Please read comment in Vpd().
++ */
++ if (pAC->Pnmi.VpdKeyReadError == SK_FALSE) {
++ Ret = GetVpdKeyArr(pAC, IoC, &KeyArr[0][0], sizeof(KeyArr), &TmpLen);
++ if (Ret != SK_PNMI_ERR_OK) {
+
+- pAC->Pnmi.MacUpdatedFlag --;
+- pAC->Pnmi.RlmtUpdatedFlag --;
+- pAC->Pnmi.SirqUpdatedFlag --;
++ pAC->Pnmi.MacUpdatedFlag --;
++ pAC->Pnmi.RlmtUpdatedFlag --;
++ pAC->Pnmi.SirqUpdatedFlag --;
+
+- SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return");
+- SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
+- *pLen = SK_PNMI_MIN_STRUCT_SIZE;
+- return (SK_PNMI_ERR_GENERAL);
++ SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return");
++ SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
++ *pLen = SK_PNMI_MIN_STRUCT_SIZE;
++ return (SK_PNMI_ERR_GENERAL);
++ }
+ }
+
+- /* Retrieve values */
++ /* Retrieve values. */
+ SK_MEMSET((char *)pBuf, 0, SK_PNMI_STRUCT_SIZE);
++
+ for (TableIndex = 0; TableIndex < ID_TABLE_SIZE; TableIndex ++) {
+
+ InstanceNo = IdTable[TableIndex].InstanceNo;
+- for (InstanceCnt = 1; InstanceCnt <= InstanceNo;
+- InstanceCnt ++) {
++ for (InstanceCnt = 1; InstanceCnt <= InstanceNo; InstanceCnt ++) {
+
+ DstOffset = IdTable[TableIndex].Offset +
+ (InstanceCnt - 1) *
+@@ -998,7 +985,6 @@
+ unsigned int PhysPortIndex;
+ unsigned int MaxNetNumber;
+ int CounterIndex;
+- int Ret;
+ SK_U16 MacStatus;
+ SK_U64 OverflowStatus;
+ SK_U64 Mask;
+@@ -1012,12 +998,7 @@
+ SK_U64 Delta;
+ SK_PNMI_ESTIMATE *pEst;
+ SK_U32 NetIndex;
+- SK_GEPORT *pPrt;
+- SK_PNMI_VCT *pVctBackupData;
+ SK_U32 RetCode;
+- int i;
+- SK_U32 CableLength;
+-
+
+ #ifdef DEBUG
+ if (Event != SK_PNMI_EVT_XMAC_RESET) {
+@@ -1048,9 +1029,7 @@
+ #endif /* DEBUG */
+ OverflowStatus = 0;
+
+- /*
+- * Check which source caused an overflow interrupt.
+- */
++ /* Check which source caused an overflow interrupt. */
+ if ((pAC->GIni.GIFunc.pFnMacOverflow(pAC, IoC, PhysPortIndex,
+ MacStatus, &OverflowStatus) != 0) ||
+ (OverflowStatus == 0)) {
+@@ -1068,7 +1047,6 @@
+
+ Mask = (SK_U64)1 << CounterIndex;
+ if ((OverflowStatus & Mask) == 0) {
+-
+ continue;
+ }
+
+@@ -1100,9 +1078,7 @@
+ case SK_PNMI_HRX_IRLENGTH:
+ case SK_PNMI_HRX_RESERVED:
+
+- /*
+- * the following counters aren't be handled (id > 63)
+- */
++ /* The following counters aren't be handled (id > 63). */
+ case SK_PNMI_HTX_SYNC:
+ case SK_PNMI_HTX_SYNC_OCTET:
+ break;
+@@ -1189,7 +1165,7 @@
+ if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) {
+
+ SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
+- ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_ERR_UPP parameter wrong, SensorIndex=%d\n",
++ ("PNMI: ERR: SK_PNMI_EVT_SEN_ERR_UPP parameter wrong, SensorIndex=%d\n",
+ (unsigned int)Param.Para64));
+ return (0);
+ }
+@@ -1208,16 +1184,14 @@
+ case SK_PNMI_EVT_CHG_EST_TIMER:
+ /*
+ * Calculate port switch average on a per hour basis
+- * Time interval for check : 28125 ms
++ * Time interval for check : 28125 ms (SK_PNMI_EVT_TIMER_CHECK)
+ * Number of values for average : 8
+ *
+ * Be careful in changing these values, on change check
+ * - typedef of SK_PNMI_ESTIMATE (Size of EstValue
+ * array one less than value number)
+ * - Timer initialization SkTimerStart() in SkPnmiInit
+- * - Delta value below must be multiplicated with
+- * power of 2
+- *
++ * - Delta value below must be multiplicated with power of 2
+ */
+ pEst = &pAC->Pnmi.RlmtChangeEstimate;
+ CounterIndex = pEst->EstValueIndex + 1;
+@@ -1240,7 +1214,7 @@
+ Delta = NewestValue - OldestValue;
+ }
+ else {
+- /* Overflow situation */
++ /* Overflow situation. */
+ Delta = (SK_U64)(0 - OldestValue) + NewestValue;
+ }
+
+@@ -1266,8 +1240,9 @@
+ }
+
+ SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
++
+ SkTimerStart(pAC, IoC, &pAC->Pnmi.RlmtChangeEstimate.EstTimer,
+- 28125000, SKGE_PNMI, SK_PNMI_EVT_CHG_EST_TIMER,
++ SK_PNMI_EVT_TIMER_CHECK, SKGE_PNMI, SK_PNMI_EVT_CHG_EST_TIMER,
+ EventParam);
+ break;
+
+@@ -1311,29 +1286,25 @@
+ (unsigned int)Param.Para64));
+ return (0);
+ }
+-#endif
++#endif /* DEBUG */
++
+ PhysPortIndex = (unsigned int)Param.Para64;
+
+- /*
+- * Update XMAC statistic to get fresh values
+- */
+- Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1);
+- if (Ret != SK_PNMI_ERR_OK) {
++ /* Update XMAC statistic to get fresh values. */
++ if (MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1) !=
++ SK_PNMI_ERR_OK) {
+
+ SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
+ return (0);
+ }
+- /*
+- * Increment semaphore to indicate that an update was
+- * already done
+- */
++
++ /* Increment semaphore to indicate that an update was already done. */
+ pAC->Pnmi.MacUpdatedFlag ++;
+
+ for (CounterIndex = 0; CounterIndex < SK_PNMI_MAX_IDX;
+ CounterIndex ++) {
+
+ if (!StatAddr[CounterIndex][MacType].GetOffset) {
+-
+ continue;
+ }
+
+@@ -1366,14 +1337,15 @@
+ QueueRlmtPortTrap(pAC, OID_SKGE_TRAP_RLMT_PORT_UP, PhysPortIndex);
+ (void)SK_DRIVER_SENDEVENT(pAC, IoC);
+
+- /* Bugfix for XMAC errata (#10620)*/
++ /* Bugfix for XMAC errata (#10620). */
+ if (MacType == SK_MAC_XMAC) {
+- /* Add incremental difference to offset (#10620)*/
++ /* Add incremental difference to offset (#10620). */
+ (void)pAC->GIni.GIFunc.pFnMacStatistic(pAC, IoC, PhysPortIndex,
+ XM_RXE_SHT_ERR, &Val32);
+
+ Value = (((SK_U64)pAC->Pnmi.Port[PhysPortIndex].
+ CounterHigh[SK_PNMI_HRX_SHORTS] << 32) | (SK_U64)Val32);
++
+ pAC->Pnmi.Port[PhysPortIndex].CounterOffset[SK_PNMI_HRX_SHORTS] +=
+ Value - pAC->Pnmi.Port[PhysPortIndex].RxShortZeroMark;
+ }
+@@ -1403,7 +1375,7 @@
+ QueueRlmtPortTrap(pAC, OID_SKGE_TRAP_RLMT_PORT_DOWN, PhysPortIndex);
+ (void)SK_DRIVER_SENDEVENT(pAC, IoC);
+
+- /* Bugfix #10620 - get zero level for incremental difference */
++ /* Bugfix #10620 - get zero level for incremental difference. */
+ if (MacType == SK_MAC_XMAC) {
+
+ (void)pAC->GIni.GIFunc.pFnMacStatistic(pAC, IoC, PhysPortIndex,
+@@ -1435,17 +1407,13 @@
+ }
+ #endif /* DEBUG */
+
+- /*
+- * For now, ignore event if NetIndex != 0.
+- */
++ /* For now, ignore event if NetIndex != 0. */
+ if (Param.Para32[1] != 0) {
+
+ return (0);
+ }
+
+- /*
+- * Nothing to do if port is already inactive
+- */
++ /* Nothing to do if port is already inactive. */
+ if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
+
+ return (0);
+@@ -1476,7 +1444,6 @@
+ CounterIndex ++) {
+
+ if (!StatAddr[CounterIndex][MacType].GetOffset) {
+-
+ continue;
+ }
+
+@@ -1485,9 +1452,7 @@
+ pAC->Pnmi.VirtualCounterOffset[CounterIndex] += Value;
+ }
+
+- /*
+- * Set port to inactive
+- */
++ /* Set port to inactive. */
+ pAC->Pnmi.Port[PhysPortIndex].ActiveFlag = SK_FALSE;
+
+ pAC->Pnmi.MacUpdatedFlag --;
+@@ -1513,25 +1478,19 @@
+ }
+ #endif /* DEBUG */
+
+- /*
+- * For now, ignore event if NetIndex != 0.
+- */
++ /* For now, ignore event if NetIndex != 0. */
+ if (Param.Para32[1] != 0) {
+
+ return (0);
+ }
+
+- /*
+- * Nothing to do if port is already active
+- */
++ /* Nothing to do if port is already inactive. */
+ if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
+
+ return (0);
+ }
+
+- /*
+- * Statistic maintenance
+- */
++ /* Statistic maintenance. */
+ pAC->Pnmi.RlmtChangeCts ++;
+ pAC->Pnmi.RlmtChangeTime = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC));
+
+@@ -1565,7 +1524,6 @@
+ CounterIndex ++) {
+
+ if (!StatAddr[CounterIndex][MacType].GetOffset) {
+-
+ continue;
+ }
+
+@@ -1574,16 +1532,14 @@
+ pAC->Pnmi.VirtualCounterOffset[CounterIndex] -= Value;
+ }
+
+- /* Set port to active */
++ /* Set port to active. */
+ pAC->Pnmi.Port[PhysPortIndex].ActiveFlag = SK_TRUE;
+
+ pAC->Pnmi.MacUpdatedFlag --;
+ break;
+
+ case SK_PNMI_EVT_RLMT_SEGMENTATION:
+- /*
+- * Para.Para32[0] contains the NetIndex.
+- */
++ /* Para.Para32[0] contains the NetIndex. */
+
+ /*
+ * Store a trap message in the trap buffer and generate an event for
+@@ -1598,71 +1554,53 @@
+ * Param.Para32[0] contains the number of Nets.
+ * Param.Para32[1] is reserved, contains -1.
+ */
+- /*
+- * Check number of nets
+- */
++ /* Check number of nets. */
+ MaxNetNumber = pAC->GIni.GIMacsFound;
+- if (((unsigned int)Param.Para32[0] < 1)
+- || ((unsigned int)Param.Para32[0] > MaxNetNumber)) {
++
++ if (((unsigned int)Param.Para32[0] < 1) ||
++ ((unsigned int)Param.Para32[0] > MaxNetNumber)) {
++
+ return (SK_PNMI_ERR_UNKNOWN_NET);
+ }
+
+- if ((unsigned int)Param.Para32[0] == 1) { /* single net mode */
++ if ((unsigned int)Param.Para32[0] == 1) { /* SingleNet mode. */
+ pAC->Pnmi.DualNetActiveFlag = SK_FALSE;
+ }
+- else { /* dual net mode */
++ else { /* DualNet mode. */
+ pAC->Pnmi.DualNetActiveFlag = SK_TRUE;
+ }
+ break;
+
+ case SK_PNMI_EVT_VCT_RESET:
+ PhysPortIndex = Param.Para32[0];
+- pPrt = &pAC->GIni.GP[PhysPortIndex];
+- pVctBackupData = &pAC->Pnmi.VctBackup[PhysPortIndex];
+
+ if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING) {
++
+ RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_FALSE);
++
+ if (RetCode == 2) {
+ /*
+ * VCT test is still running.
+ * Start VCT timer counter again.
+ */
+- SK_MEMSET((char *) &Param, 0, sizeof(Param));
++ SK_MEMSET((char *)&Param, 0, sizeof(Param));
++
+ Param.Para32[0] = PhysPortIndex;
+ Param.Para32[1] = -1;
+- SkTimerStart(pAC, IoC,
+- &pAC->Pnmi.VctTimeout[PhysPortIndex].VctTimer,
+- 4000000, SKGE_PNMI, SK_PNMI_EVT_VCT_RESET, Param);
++
++ SkTimerStart(pAC, IoC, &pAC->Pnmi.VctTimeout[PhysPortIndex],
++ SK_PNMI_VCT_TIMER_CHECK, SKGE_PNMI, SK_PNMI_EVT_VCT_RESET, Param);
++
+ break;
+ }
+- pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_PENDING;
+- pAC->Pnmi.VctStatus[PhysPortIndex] |=
+- (SK_PNMI_VCT_NEW_VCT_DATA | SK_PNMI_VCT_TEST_DONE);
+
+- /* Copy results for later use to PNMI struct. */
+- for (i = 0; i < 4; i++) {
+- if (pPrt->PMdiPairSts[i] == SK_PNMI_VCT_NORMAL_CABLE) {
+- if ((pPrt->PMdiPairLen[i] > 35) &&
+- (pPrt->PMdiPairLen[i] < 0xff)) {
+- pPrt->PMdiPairSts[i] = SK_PNMI_VCT_IMPEDANCE_MISMATCH;
+- }
+- }
+- if ((pPrt->PMdiPairLen[i] > 35) &&
+- (pPrt->PMdiPairLen[i] != 0xff)) {
+- CableLength = 1000 *
+- (((175 * pPrt->PMdiPairLen[i]) / 210) - 28);
+- }
+- else {
+- CableLength = 0;
+- }
+- pVctBackupData->PMdiPairLen[i] = CableLength;
+- pVctBackupData->PMdiPairSts[i] = pPrt->PMdiPairSts[i];
+- }
++ VctGetResults(pAC, IoC, PhysPortIndex);
+
+- Param.Para32[0] = PhysPortIndex;
+- Param.Para32[1] = -1;
+- SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Param);
+- SkEventDispatcher(pAC, IoC);
++ EventParam.Para32[0] = PhysPortIndex;
++ EventParam.Para32[1] = -1;
++ SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, EventParam);
++
++ /* SkEventDispatcher(pAC, IoC); */
+ }
+
+ break;
+@@ -1710,14 +1648,13 @@
+ unsigned int TableIndex;
+ int Ret;
+
+-
+ if ((TableIndex = LookupId(Id)) == (unsigned int)(-1)) {
+
+ *pLen = 0;
+ return (SK_PNMI_ERR_UNKNOWN_OID);
+ }
+
+- /* Check NetIndex */
++ /* Check NetIndex. */
+ if (NetIndex >= pAC->Rlmt.NumNets) {
+ return (SK_PNMI_ERR_UNKNOWN_NET);
+ }
+@@ -1767,22 +1704,20 @@
+ SK_U32 Instance;
+ SK_U32 Id;
+
+-
+- /* Check if the passed buffer has the right size */
++ /* Check if the passed buffer has the right size. */
+ if (*pLen < SK_PNMI_STRUCT_SIZE) {
+
+- /* Check if we can return the error within the buffer */
++ /* Check if we can return the error within the buffer. */
+ if (*pLen >= SK_PNMI_MIN_STRUCT_SIZE) {
+
+- SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_TOO_SHORT,
+- (SK_U32)(-1));
++ SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_TOO_SHORT, (SK_U32)(-1));
+ }
+
+ *pLen = SK_PNMI_STRUCT_SIZE;
+ return (SK_PNMI_ERR_TOO_SHORT);
+ }
+
+- /* Check NetIndex */
++ /* Check NetIndex. */
+ if (NetIndex >= pAC->Rlmt.NumNets) {
+ return (SK_PNMI_ERR_UNKNOWN_NET);
+ }
+@@ -1810,12 +1745,11 @@
+ pAC->Pnmi.RlmtUpdatedFlag ++;
+ pAC->Pnmi.SirqUpdatedFlag ++;
+
+- /* Preset/Set values */
++ /* PRESET/SET values. */
+ for (TableIndex = 0; TableIndex < ID_TABLE_SIZE; TableIndex ++) {
+
+ if ((IdTable[TableIndex].Access != SK_PNMI_RW) &&
+ (IdTable[TableIndex].Access != SK_PNMI_WO)) {
+-
+ continue;
+ }
+
+@@ -1826,8 +1760,7 @@
+ InstanceCnt ++) {
+
+ DstOffset = IdTable[TableIndex].Offset +
+- (InstanceCnt - 1) *
+- IdTable[TableIndex].StructSize;
++ (InstanceCnt - 1) * IdTable[TableIndex].StructSize;
+
+ /*
+ * Because VPD multiple instance variables are
+@@ -1837,9 +1770,7 @@
+ */
+ Instance = (SK_U32)InstanceCnt;
+
+- /*
+- * Evaluate needed buffer length
+- */
++ /* Evaluate needed buffer length. */
+ Len = 0;
+ Ret = IdTable[TableIndex].Func(pAC, IoC,
+ SK_PNMI_GET, IdTable[TableIndex].Id,
+@@ -1855,8 +1786,7 @@
+ pAC->Pnmi.SirqUpdatedFlag --;
+
+ SK_PNMI_CHECKFLAGS("PnmiStruct: On return");
+- SK_PNMI_SET_STAT(pBuf,
+- SK_PNMI_ERR_GENERAL, DstOffset);
++ SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_GENERAL, DstOffset);
+ *pLen = SK_PNMI_MIN_STRUCT_SIZE;
+ return (SK_PNMI_ERR_GENERAL);
+ }
+@@ -1878,7 +1808,7 @@
+ }
+ }
+
+- /* Call the OID handler function */
++ /* Call the OID handler function. */
+ Ret = IdTable[TableIndex].Func(pAC, IoC, Action,
+ IdTable[TableIndex].Id, pBuf + DstOffset,
+ &Len, Instance, TableIndex, NetIndex);
+@@ -1889,8 +1819,7 @@
+ pAC->Pnmi.SirqUpdatedFlag --;
+
+ SK_PNMI_CHECKFLAGS("PnmiStruct: On return");
+- SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_BAD_VALUE,
+- DstOffset);
++ SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_BAD_VALUE, DstOffset);
+ *pLen = SK_PNMI_MIN_STRUCT_SIZE;
+ return (SK_PNMI_ERR_BAD_VALUE);
+ }
+@@ -1924,7 +1853,7 @@
+
+ if (IdTable[i].Id == Id) {
+
+- return i;
++ return (i);
+ }
+ }
+
+@@ -1965,16 +1894,13 @@
+ {
+ if (Id != OID_SKGE_ALL_DATA) {
+
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR003,
+- SK_PNMI_ERR003MSG);
++ SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR003, SK_PNMI_ERR003MSG);
+
+ *pLen = 0;
+ return (SK_PNMI_ERR_GENERAL);
+ }
+
+- /*
+- * Check instance. We only handle single instance variables
+- */
++ /* Check instance. We only handle single instance variables. */
+ if (Instance != (SK_U32)(-1) && Instance != 1) {
+
+ *pLen = 0;
+@@ -2033,10 +1959,7 @@
+ int Ret;
+ SK_U32 ActionOp;
+
+-
+- /*
+- * Check instance. We only handle single instance variables
+- */
++ /* Check instance. We only handle single instance variables. */
+ if (Instance != (SK_U32)(-1) && Instance != 1) {
+
+ *pLen = 0;
+@@ -2049,10 +1972,10 @@
+ return (SK_PNMI_ERR_TOO_SHORT);
+ }
+
+- /* Check if a get should be performed */
++ /* Check if a GET should be performed. */
+ if (Action == SK_PNMI_GET) {
+
+- /* A get is easy. We always return the same value */
++ /* A GET is easy. We always return the same value. */
+ ActionOp = (SK_U32)SK_PNMI_ACT_IDLE;
+ SK_PNMI_STORE_U32(pBuf, ActionOp);
+ *pLen = sizeof(SK_U32);
+@@ -2060,13 +1983,13 @@
+ return (SK_PNMI_ERR_OK);
+ }
+
+- /* Continue with PRESET/SET action */
++ /* Continue with PRESET/SET action. */
+ if (*pLen > sizeof(SK_U32)) {
+
+ return (SK_PNMI_ERR_BAD_VALUE);
+ }
+
+- /* Check if the command is a known one */
++ /* Check if the command is a known one. */
+ SK_PNMI_READ_U32(pBuf, ActionOp);
+ if (*pLen > sizeof(SK_U32) ||
+ (ActionOp != SK_PNMI_ACT_IDLE &&
+@@ -2078,7 +2001,7 @@
+ return (SK_PNMI_ERR_BAD_VALUE);
+ }
+
+- /* A preset ends here */
++ /* A PRESET ends here. */
+ if (Action == SK_PNMI_PRESET) {
+
+ return (SK_PNMI_ERR_OK);
+@@ -2087,19 +2010,15 @@
+ switch (ActionOp) {
+
+ case SK_PNMI_ACT_IDLE:
+- /* Nothing to do */
++ /* Nothing to do. */
+ break;
+
+ case SK_PNMI_ACT_RESET:
+- /*
+- * Perform a driver reset or something that comes near
+- * to this.
+- */
++ /* Perform a driver reset or something that comes near to this. */
+ Ret = SK_DRIVER_RESET(pAC, IoC);
+ if (Ret != 0) {
+
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR005,
+- SK_PNMI_ERR005MSG);
++ SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR005, SK_PNMI_ERR005MSG);
+
+ return (SK_PNMI_ERR_GENERAL);
+ }
+@@ -2116,13 +2035,12 @@
+ break;
+
+ case SK_PNMI_ACT_RESETCNT:
+- /* Set all counters and timestamps to zero */
++ /* Set all counters and timestamps to zero. */
+ ResetCounter(pAC, IoC, NetIndex);
+ break;
+
+ default:
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR006,
+- SK_PNMI_ERR006MSG);
++ SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR006, SK_PNMI_ERR006MSG);
+
+ return (SK_PNMI_ERR_GENERAL);
+ }
+@@ -2166,25 +2084,21 @@
+ SK_U32 StatVal32;
+ SK_BOOL Is64BitReq = SK_FALSE;
+
+- /*
+- * Only the active Mac is returned
+- */
++ /* Only the active MAC is returned. */
+ if (Instance != (SK_U32)(-1) && Instance != 1) {
+
+ *pLen = 0;
+ return (SK_PNMI_ERR_UNKNOWN_INST);
+ }
+
+- /*
+- * Check action type
+- */
++ /* Check action type. */
+ if (Action != SK_PNMI_GET) {
+
+ *pLen = 0;
+ return (SK_PNMI_ERR_READ_ONLY);
+ }
+
+- /* Check length */
++ /* Check length. */
+ switch (Id) {
+
+ case OID_802_3_PERMANENT_ADDRESS:
+@@ -2205,12 +2119,12 @@
+
+ #else /* SK_NDIS_64BIT_CTR */
+
+- /* for compatibility, at least 32bit are required for OID */
++ /* For compatibility, at least 32 bits are required for OID. */
+ if (*pLen < sizeof(SK_U32)) {
+ /*
+- * but indicate handling for 64bit values,
+- * if insufficient space is provided
+- */
++ * Indicate handling for 64 bit values,
++ * if insufficient space is provided.
++ */
+ *pLen = sizeof(SK_U64);
+ return (SK_PNMI_ERR_TOO_SHORT);
+ }
+@@ -2226,16 +2140,14 @@
+ * to indicate that an update was already done.
+ */
+ Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1);
+- if ( Ret != SK_PNMI_ERR_OK) {
++ if (Ret != SK_PNMI_ERR_OK) {
+
+ *pLen = 0;
+ return (Ret);
+ }
+ pAC->Pnmi.MacUpdatedFlag ++;
+
+- /*
+- * Get value (MAC Index 0 identifies the virtual MAC)
+- */
++ /* Get value (MAC index 0 identifies the virtual MAC). */
+ switch (Id) {
+
+ case OID_802_3_PERMANENT_ADDRESS:
+@@ -2251,7 +2163,7 @@
+ default:
+ StatVal = GetStatVal(pAC, IoC, 0, IdTable[TableIndex].Param, NetIndex);
+
+- /* by default 32bit values are evaluated */
++ /* By default 32 bit values are evaluated. */
+ if (!Is64BitReq) {
+ StatVal32 = (SK_U32)StatVal;
+ SK_PNMI_STORE_U32(pBuf, StatVal32);
+@@ -2305,21 +2217,19 @@
+ int MacType;
+ int Ret;
+ SK_U64 StatVal;
+-
+-
+
+- /* Calculate instance if wished. MAC index 0 is the virtual MAC */
++ /* Calculate instance if wished. MAC index 0 is the virtual MAC. */
+ PhysPortMax = pAC->GIni.GIMacsFound;
+ LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax);
+
+ MacType = pAC->GIni.GIMacType;
+
+- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */
++ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* DualNet mode. */
+ LogPortMax--;
+ }
+
+- if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried */
+- /* Check instance range */
++ if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried. */
++ /* Check instance range. */
+ if ((Instance < 1) || (Instance > LogPortMax)) {
+
+ *pLen = 0;
+@@ -2329,20 +2239,20 @@
+ Limit = LogPortIndex + 1;
+ }
+
+- else { /* Instance == (SK_U32)(-1), get all Instances of that OID */
++ else { /* Instance == (SK_U32)(-1), get all Instances of that OID. */
+
+ LogPortIndex = 0;
+ Limit = LogPortMax;
+ }
+
+- /* Check action */
++ /* Check action. */
+ if (Action != SK_PNMI_GET) {
+
+ *pLen = 0;
+ return (SK_PNMI_ERR_READ_ONLY);
+ }
+
+- /* Check length */
++ /* Check length. */
+ if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U64)) {
+
+ *pLen = (Limit - LogPortIndex) * sizeof(SK_U64);
+@@ -2361,7 +2271,7 @@
+ }
+ pAC->Pnmi.MacUpdatedFlag ++;
+
+- /* Get value */
++ /* Get value. */
+ Offset = 0;
+ for (; LogPortIndex < Limit; LogPortIndex ++) {
+
+@@ -2467,19 +2377,16 @@
+ unsigned int Limit;
+ unsigned int Offset = 0;
+
+- /*
+- * Calculate instance if wished. MAC index 0 is the virtual
+- * MAC.
+- */
++ /* Calculate instance if wished. MAC index 0 is the virtual MAC. */
+ PhysPortMax = pAC->GIni.GIMacsFound;
+ LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax);
+
+- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */
++ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* DualNet mode. */
+ LogPortMax--;
+ }
+
+- if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried */
+- /* Check instance range */
++ if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried. */
++ /* Check instance range. */
+ if ((Instance < 1) || (Instance > LogPortMax)) {
+
+ *pLen = 0;
+@@ -2488,27 +2395,23 @@
+ LogPortIndex = SK_PNMI_PORT_INST2LOG(Instance);
+ Limit = LogPortIndex + 1;
+ }
+- else { /* Instance == (SK_U32)(-1), get all Instances of that OID */
++ else { /* Instance == (SK_U32)(-1), get all Instances of that OID. */
+
+ LogPortIndex = 0;
+ Limit = LogPortMax;
+ }
+
+- /*
+- * Perform Action
+- */
++ /* Perform action. */
+ if (Action == SK_PNMI_GET) {
+
+- /* Check length */
++ /* Check length. */
+ if (*pLen < (Limit - LogPortIndex) * 6) {
+
+ *pLen = (Limit - LogPortIndex) * 6;
+ return (SK_PNMI_ERR_TOO_SHORT);
+ }
+
+- /*
+- * Get value
+- */
++ /* Get value. */
+ for (; LogPortIndex < Limit; LogPortIndex ++) {
+
+ switch (Id) {
+@@ -2532,8 +2435,7 @@
+ &pAC->Addr.Net[NetIndex].PermanentMacAddress);
+ }
+ else {
+- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+- pAC, LogPortIndex);
++ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex);
+
+ CopyMac(pBuf + Offset,
+ &pAC->Addr.Port[PhysPortIndex].PermanentMacAddress);
+@@ -2542,8 +2444,7 @@
+ break;
+
+ default:
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR008,
+- SK_PNMI_ERR008MSG);
++ SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR008, SK_PNMI_ERR008MSG);
+
+ *pLen = 0;
+ return (SK_PNMI_ERR_GENERAL);
+@@ -2554,8 +2455,8 @@
+ }
+ else {
+ /*
+- * The logical MAC address may not be changed only
+- * the physical ones
++ * The logical MAC address may not be changed,
++ * only the physical ones.
+ */
+ if (Id == OID_SKGE_PHYS_FAC_ADDR) {
+
+@@ -2563,19 +2464,16 @@
+ return (SK_PNMI_ERR_READ_ONLY);
+ }
+
+- /*
+- * Only the current address may be changed
+- */
++ /* Only the current address may be changed. */
+ if (Id != OID_SKGE_PHYS_CUR_ADDR) {
+
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR009,
+- SK_PNMI_ERR009MSG);
++ SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR009, SK_PNMI_ERR009MSG);
+
+ *pLen = 0;
+ return (SK_PNMI_ERR_GENERAL);
+ }
+
+- /* Check length */
++ /* Check length. */
+ if (*pLen < (Limit - LogPortIndex) * 6) {
+
+ *pLen = (Limit - LogPortIndex) * 6;
+@@ -2587,32 +2485,26 @@
+ return (SK_PNMI_ERR_BAD_VALUE);
+ }
+
+- /*
+- * Check Action
+- */
++ /* Check action. */
+ if (Action == SK_PNMI_PRESET) {
+
+ *pLen = 0;
+ return (SK_PNMI_ERR_OK);
+ }
+
+- /*
+- * Set OID_SKGE_MAC_CUR_ADDR
+- */
++ /* Set OID_SKGE_MAC_CUR_ADDR. */
+ for (; LogPortIndex < Limit; LogPortIndex ++, Offset += 6) {
+
+ /*
+ * A set to virtual port and set of broadcast
+- * address will be ignored
++ * address will be ignored.
+ */
+ if (LogPortIndex == 0 || SK_MEMCMP(pBuf + Offset,
+ "\xff\xff\xff\xff\xff\xff", 6) == 0) {
+-
+ continue;
+ }
+
+- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC,
+- LogPortIndex);
++ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex);
+
+ Ret = SkAddrOverride(pAC, IoC, PhysPortIndex,
+ (SK_MAC_ADDR *)(pBuf + Offset),
+@@ -2665,10 +2557,7 @@
+ unsigned int Offset = 0;
+ SK_U64 StatVal;
+
+-
+- /*
+- * Calculate instance if wished
+- */
++ /* Calculate instance if wished. */
+ if (Instance != (SK_U32)(-1)) {
+
+ if ((Instance < 1) || (Instance > SKCS_NUM_PROTOCOLS)) {
+@@ -2684,25 +2573,21 @@
+ Limit = SKCS_NUM_PROTOCOLS;
+ }
+
+- /*
+- * Check action
+- */
++ /* Check action. */
+ if (Action != SK_PNMI_GET) {
+
+ *pLen = 0;
+ return (SK_PNMI_ERR_READ_ONLY);
+ }
+
+- /* Check length */
++ /* Check length. */
+ if (*pLen < (Limit - Index) * sizeof(SK_U64)) {
+
+ *pLen = (Limit - Index) * sizeof(SK_U64);
+ return (SK_PNMI_ERR_TOO_SHORT);
+ }
+
+- /*
+- * Get value
+- */
++ /* Get value. */
+ for (; Index < Limit; Index ++) {
+
+ switch (Id) {
+@@ -2728,8 +2613,7 @@
+ break;
+
+ default:
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR010,
+- SK_PNMI_ERR010MSG);
++ SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR010, SK_PNMI_ERR010MSG);
+
+ *pLen = 0;
+ return (SK_PNMI_ERR_GENERAL);
+@@ -2739,9 +2623,7 @@
+ Offset += sizeof(SK_U64);
+ }
+
+- /*
+- * Store used buffer space
+- */
++ /* Store used buffer space. */
+ *pLen = Offset;
+
+ return (SK_PNMI_ERR_OK);
+@@ -2784,10 +2666,7 @@
+ SK_U32 Val32;
+ SK_U64 Val64;
+
+-
+- /*
+- * Calculate instance if wished
+- */
++ /* Calculate instance if wished. */
+ if ((Instance != (SK_U32)(-1))) {
+
+ if ((Instance < 1) || (Instance > (SK_U32)pAC->I2c.MaxSens)) {
+@@ -2804,16 +2683,14 @@
+ Limit = (unsigned int) pAC->I2c.MaxSens;
+ }
+
+- /*
+- * Check action
+- */
++ /* Check action. */
+ if (Action != SK_PNMI_GET) {
+
+ *pLen = 0;
+ return (SK_PNMI_ERR_READ_ONLY);
+ }
+
+- /* Check length */
++ /* Check length. */
+ switch (Id) {
+
+ case OID_SKGE_SENSOR_VALUE:
+@@ -2872,38 +2749,33 @@
+ break;
+
+ default:
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR012,
+- SK_PNMI_ERR012MSG);
++ SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR012, SK_PNMI_ERR012MSG);
+
+ *pLen = 0;
+ return (SK_PNMI_ERR_GENERAL);
+
+ }
+
+- /*
+- * Get value
+- */
++ /* Get value. */
+ for (Offset = 0; Index < Limit; Index ++) {
+
+ switch (Id) {
+
+ case OID_SKGE_SENSOR_INDEX:
+ *(pBuf + Offset) = (char)Index;
+- Offset += sizeof(char);
++ Offset ++;
+ break;
+
+ case OID_SKGE_SENSOR_DESCR:
+ Len = SK_STRLEN(pAC->I2c.SenTable[Index].SenDesc);
+- SK_MEMCPY(pBuf + Offset + 1,
+- pAC->I2c.SenTable[Index].SenDesc, Len);
++ SK_MEMCPY(pBuf + Offset + 1, pAC->I2c.SenTable[Index].SenDesc, Len);
+ *(pBuf + Offset) = (char)Len;
+ Offset += Len + 1;
+ break;
+
+ case OID_SKGE_SENSOR_TYPE:
+- *(pBuf + Offset) =
+- (char)pAC->I2c.SenTable[Index].SenType;
+- Offset += sizeof(char);
++ *(pBuf + Offset) = (char)pAC->I2c.SenTable[Index].SenType;
++ Offset ++;
+ break;
+
+ case OID_SKGE_SENSOR_VALUE:
+@@ -2940,9 +2812,8 @@
+ break;
+
+ case OID_SKGE_SENSOR_STATUS:
+- *(pBuf + Offset) =
+- (char)pAC->I2c.SenTable[Index].SenErrFlag;
+- Offset += sizeof(char);
++ *(pBuf + Offset) = (char)pAC->I2c.SenTable[Index].SenErrFlag;
++ Offset ++;
+ break;
+
+ case OID_SKGE_SENSOR_WAR_CTS:
+@@ -2979,9 +2850,7 @@
+ }
+ }
+
+- /*
+- * Store used buffer space
+- */
++ /* Store used buffer space. */
+ *pLen = Offset;
+
+ return (SK_PNMI_ERR_OK);
+@@ -3036,8 +2905,29 @@
+ SK_U32 Val32;
+
+ /*
+- * Get array of all currently stored VPD keys
+- */
++ * VpdKeyReadError will be set in GetVpdKeyArr() if an error occurs.
++ * Due to the fact that some drivers use SkPnmiGetStruct() to retrieve
++ * all statistical data, an error in GetVpdKeyArr() will generate a PNMI
++ * error and terminate SkPnmiGetStruct() without filling in statistical
++ * data into the PNMI struct. In this case the driver will get no values
++ * for statistical purposes (netstat, ifconfig etc.). GetVpdKeyArr() is
++ * the first function to be called in SkPnmiGetStruct(), so any error
++ * will terminate SkPnmiGetStruct() immediately. Hence, VpdKeyReadError will
++ * be set during the first call to GetVpdKeyArr() to make successful calls
++ * to SkPnmiGetStruct() possible. But there is another point to consider:
++ * When filling in the statistical data into the PNMI struct, the VPD
++ * handler Vpd() will also be called. If GetVpdKeyArr() in Vpd() would
++ * return with SK_PNMI_ERR_GENERAL, SkPnmiGetStruct() would fail again.
++ * For this reason VpdKeyReadError is checked here and, if set, Vpd()
++ * will return without doing anything and the return value SK_PNMI_ERR_OK.
++ * Therefore SkPnmiGetStruct() is able to continue and fill in all other
++ * statistical data.
++ */
++ if (pAC->Pnmi.VpdKeyReadError == SK_TRUE) {
++ return (SK_PNMI_ERR_OK);
++ }
++
++ /* Get array of all currently stored VPD keys. */
+ Ret = GetVpdKeyArr(pAC, IoC, &KeyArr[0][0], sizeof(KeyArr), &KeyNo);
+ if (Ret != SK_PNMI_ERR_OK) {
+ *pLen = 0;
+@@ -3082,34 +2972,32 @@
+ }
+ }
+
+- /*
+- * Get value, if a query should be performed
+- */
++ /* Get value, if a query should be performed. */
+ if (Action == SK_PNMI_GET) {
+
+ switch (Id) {
+
+ case OID_SKGE_VPD_FREE_BYTES:
+- /* Check length of buffer */
++ /* Check length of buffer. */
+ if (*pLen < sizeof(SK_U32)) {
+
+ *pLen = sizeof(SK_U32);
+ return (SK_PNMI_ERR_TOO_SHORT);
+ }
+- /* Get number of free bytes */
++ /* Get number of free bytes. */
+ pVpdStatus = VpdStat(pAC, IoC);
+ if (pVpdStatus == NULL) {
+
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR017,
+- SK_PNMI_ERR017MSG);
++ SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
++ (SK_PNMI_ERR017MSG));
+
+ *pLen = 0;
+ return (SK_PNMI_ERR_GENERAL);
+ }
+ if ((pVpdStatus->vpd_status & VPD_VALID) == 0) {
+
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR018,
+- SK_PNMI_ERR018MSG);
++ SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
++ (SK_PNMI_ERR018MSG));
+
+ *pLen = 0;
+ return (SK_PNMI_ERR_GENERAL);
+@@ -3121,7 +3009,7 @@
+ break;
+
+ case OID_SKGE_VPD_ENTRIES_LIST:
+- /* Check length */
++ /* Check length. */
+ for (Len = 0, Index = 0; Index < KeyNo; Index ++) {
+
+ Len += SK_STRLEN(KeyArr[Index]) + 1;
+@@ -3132,7 +3020,7 @@
+ return (SK_PNMI_ERR_TOO_SHORT);
+ }
+
+- /* Get value */
++ /* Get value. */
+ *(pBuf) = (char)Len - 1;
+ for (Offset = 1, Index = 0; Index < KeyNo; Index ++) {
+
+@@ -3151,7 +3039,7 @@
+ break;
+
+ case OID_SKGE_VPD_ENTRIES_NUMBER:
+- /* Check length */
++ /* Check length. */
+ if (*pLen < sizeof(SK_U32)) {
+
+ *pLen = sizeof(SK_U32);
+@@ -3164,7 +3052,7 @@
+ break;
+
+ case OID_SKGE_VPD_KEY:
+- /* Check buffer length, if it is large enough */
++ /* Check buffer length, if it is large enough. */
+ for (Len = 0, Index = FirstIndex;
+ Index < LastIndex; Index ++) {
+
+@@ -3180,32 +3068,28 @@
+ * Get the key to an intermediate buffer, because
+ * we have to prepend a length byte.
+ */
+- for (Offset = 0, Index = FirstIndex;
+- Index < LastIndex; Index ++) {
++ for (Offset = 0, Index = FirstIndex; Index < LastIndex; Index ++) {
+
+ Len = SK_STRLEN(KeyArr[Index]);
+
+ *(pBuf + Offset) = (char)Len;
+- SK_MEMCPY(pBuf + Offset + 1, KeyArr[Index],
+- Len);
++ SK_MEMCPY(pBuf + Offset + 1, KeyArr[Index], Len);
+ Offset += Len + 1;
+ }
+ *pLen = Offset;
+ break;
+
+ case OID_SKGE_VPD_VALUE:
+- /* Check the buffer length if it is large enough */
+- for (Offset = 0, Index = FirstIndex;
+- Index < LastIndex; Index ++) {
++ /* Check the buffer length if it is large enough. */
++ for (Offset = 0, Index = FirstIndex; Index < LastIndex; Index ++) {
+
+ BufLen = 256;
+ if (VpdRead(pAC, IoC, KeyArr[Index], Buf,
+ (int *)&BufLen) > 0 ||
+ BufLen >= SK_PNMI_VPD_DATALEN) {
+
+- SK_ERR_LOG(pAC, SK_ERRCL_SW,
+- SK_PNMI_ERR021,
+- SK_PNMI_ERR021MSG);
++ SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
++ (SK_PNMI_ERR021MSG));
+
+ return (SK_PNMI_ERR_GENERAL);
+ }
+@@ -3221,17 +3105,15 @@
+ * Get the value to an intermediate buffer, because
+ * we have to prepend a length byte.
+ */
+- for (Offset = 0, Index = FirstIndex;
+- Index < LastIndex; Index ++) {
++ for (Offset = 0, Index = FirstIndex; Index < LastIndex; Index ++) {
+
+ BufLen = 256;
+ if (VpdRead(pAC, IoC, KeyArr[Index], Buf,
+ (int *)&BufLen) > 0 ||
+ BufLen >= SK_PNMI_VPD_DATALEN) {
+
+- SK_ERR_LOG(pAC, SK_ERRCL_SW,
+- SK_PNMI_ERR022,
+- SK_PNMI_ERR022MSG);
++ SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
++ (SK_PNMI_ERR022MSG));
+
+ *pLen = 0;
+ return (SK_PNMI_ERR_GENERAL);
+@@ -3251,8 +3133,7 @@
+ return (SK_PNMI_ERR_TOO_SHORT);
+ }
+
+- for (Offset = 0, Index = FirstIndex;
+- Index < LastIndex; Index ++) {
++ for (Offset = 0, Index = FirstIndex; Index < LastIndex; Index ++) {
+
+ if (VpdMayWrite(KeyArr[Index])) {
+
+@@ -3278,15 +3159,15 @@
+ break;
+
+ default:
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR023,
+- SK_PNMI_ERR023MSG);
++ SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
++ (SK_PNMI_ERR023MSG));
+
+ *pLen = 0;
+ return (SK_PNMI_ERR_GENERAL);
+ }
+ }
+ else {
+- /* The only OID which can be set is VPD_ACTION */
++ /* The only OID which can be set is VPD_ACTION. */
+ if (Id != OID_SKGE_VPD_ACTION) {
+
+ if (Id == OID_SKGE_VPD_FREE_BYTES ||
+@@ -3300,8 +3181,8 @@
+ return (SK_PNMI_ERR_READ_ONLY);
+ }
+
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR024,
+- SK_PNMI_ERR024MSG);
++ SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
++ (SK_PNMI_ERR024MSG));
+
+ *pLen = 0;
+ return (SK_PNMI_ERR_GENERAL);
+@@ -3317,14 +3198,11 @@
+ return (SK_PNMI_ERR_TOO_SHORT);
+ }
+
+- /*
+- * The first byte contains the VPD action type we should
+- * perform.
+- */
++ /* The first byte contains the VPD action type we should perform. */
+ switch (*pBuf) {
+
+ case SK_PNMI_VPD_IGNORE:
+- /* Nothing to do */
++ /* Nothing to do. */
+ break;
+
+ case SK_PNMI_VPD_CREATE:
+@@ -3356,13 +3234,13 @@
+ SK_MEMCPY(Buf, pBuf + 4, Offset);
+ Buf[Offset] = 0;
+
+- /* A preset ends here */
++ /* A PRESET ends here. */
+ if (Action == SK_PNMI_PRESET) {
+
+ return (SK_PNMI_ERR_OK);
+ }
+
+- /* Write the new entry or modify an existing one */
++ /* Write the new entry or modify an existing one .*/
+ Ret = VpdWrite(pAC, IoC, KeyStr, Buf);
+ if (Ret == SK_PNMI_VPD_NOWRITE ) {
+
+@@ -3371,8 +3249,8 @@
+ }
+ else if (Ret != SK_PNMI_VPD_OK) {
+
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR025,
+- SK_PNMI_ERR025MSG);
++ SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
++ (SK_PNMI_ERR025MSG));
+
+ *pLen = 0;
+ return (SK_PNMI_ERR_GENERAL);
+@@ -3385,8 +3263,8 @@
+ Ret = VpdUpdate(pAC, IoC);
+ if (Ret != SK_PNMI_VPD_OK) {
+
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR026,
+- SK_PNMI_ERR026MSG);
++ SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
++ (SK_PNMI_ERR026MSG));
+
+ *pLen = 0;
+ return (SK_PNMI_ERR_GENERAL);
+@@ -3394,7 +3272,7 @@
+ break;
+
+ case SK_PNMI_VPD_DELETE:
+- /* Check if the buffer size is plausible */
++ /* Check if the buffer size is plausible. */
+ if (*pLen < 3) {
+
+ *pLen = 3;
+@@ -3409,7 +3287,7 @@
+ KeyStr[1] = pBuf[2];
+ KeyStr[2] = 0;
+
+- /* Find the passed key in the array */
++ /* Find the passed key in the array. */
+ for (Index = 0; Index < KeyNo; Index ++) {
+
+ if (SK_STRCMP(KeyStr, KeyArr[Index]) == 0) {
+@@ -3417,6 +3295,7 @@
+ break;
+ }
+ }
++
+ /*
+ * If we cannot find the key it is wrong, so we
+ * return an appropriate error value.
+@@ -3432,12 +3311,12 @@
+ return (SK_PNMI_ERR_OK);
+ }
+
+- /* Ok, you wanted it and you will get it */
++ /* Ok, you wanted it and you will get it. */
+ Ret = VpdDelete(pAC, IoC, KeyStr);
+ if (Ret != SK_PNMI_VPD_OK) {
+
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR027,
+- SK_PNMI_ERR027MSG);
++ SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
++ (SK_PNMI_ERR027MSG));
+
+ *pLen = 0;
+ return (SK_PNMI_ERR_GENERAL);
+@@ -3450,8 +3329,8 @@
+ Ret = VpdUpdate(pAC, IoC);
+ if (Ret != SK_PNMI_VPD_OK) {
+
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR028,
+- SK_PNMI_ERR028MSG);
++ SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
++ (SK_PNMI_ERR028MSG));
+
+ *pLen = 0;
+ return (SK_PNMI_ERR_GENERAL);
+@@ -3505,23 +3384,21 @@
+ SK_U32 Val32;
+ SK_U64 Val64;
+ SK_U64 Val64RxHwErrs = 0;
++ SK_U64 Val64RxRunt = 0;
++ SK_U64 Val64RxFcs = 0;
+ SK_U64 Val64TxHwErrs = 0;
+ SK_BOOL Is64BitReq = SK_FALSE;
+ char Buf[256];
+ int MacType;
+
+- /*
+- * Check instance. We only handle single instance variables.
+- */
++ /* Check instance. We only handle single instance variables. */
+ if (Instance != (SK_U32)(-1) && Instance != 1) {
+
+ *pLen = 0;
+ return (SK_PNMI_ERR_UNKNOWN_INST);
+ }
+
+- /*
+- * Check action. We only allow get requests.
+- */
++ /* Check action. We only allow get requests. */
+ if (Action != SK_PNMI_GET) {
+
+ *pLen = 0;
+@@ -3530,9 +3407,7 @@
+
+ MacType = pAC->GIni.GIMacType;
+
+- /*
+- * Check length for the various supported OIDs
+- */
++ /* Check length for the various supported OIDs. */
+ switch (Id) {
+
+ case OID_GEN_XMIT_ERROR:
+@@ -3546,14 +3421,12 @@
+
+ #else /* SK_NDIS_64BIT_CTR */
+
+- /*
+- * for compatibility, at least 32bit are required for oid
+- */
++ /* For compatibility, at least 32bit are required for OID. */
+ if (*pLen < sizeof(SK_U32)) {
+ /*
+- * but indicate handling for 64bit values,
+- * if insufficient space is provided
+- */
++ * Indicate handling for 64bit values,
++ * if insufficient space is provided.
++ */
+ *pLen = sizeof(SK_U64);
+ return (SK_PNMI_ERR_TOO_SHORT);
+ }
+@@ -3624,11 +3497,11 @@
+ break;
+
+ default:
+- /* Checked later */
++ /* Checked later. */
+ break;
+ }
+
+- /* Update statistic */
++ /* Update statistics. */
+ if (Id == OID_SKGE_RX_HW_ERROR_CTS ||
+ Id == OID_SKGE_TX_HW_ERROR_CTS ||
+ Id == OID_SKGE_IN_ERRORS_CTS ||
+@@ -3636,7 +3509,8 @@
+ Id == OID_GEN_XMIT_ERROR ||
+ Id == OID_GEN_RCV_ERROR) {
+
+- /* Force the XMAC to update its statistic counters and
++ /*
++ * Force the XMAC to update its statistic counters and
+ * Increment semaphore to indicate that an update was
+ * already done.
+ */
+@@ -3667,27 +3541,40 @@
+ GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_IRLENGTH, NetIndex) +
+ GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_SYMBOL, NetIndex) +
+ GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_SHORTS, NetIndex) +
+- GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_RUNT, NetIndex) +
+ GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_TOO_LONG, NetIndex) +
+- GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_FCS, NetIndex) +
+ GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_CEXT, NetIndex);
+- break;
+
+- case OID_SKGE_TX_HW_ERROR_CTS:
+- case OID_SKGE_OUT_ERROR_CTS:
+- case OID_GEN_XMIT_ERROR:
+- Val64TxHwErrs =
+- GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_EXCESS_COL, NetIndex) +
+- GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_LATE_COL, NetIndex) +
+- GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_UNDERRUN, NetIndex) +
+- GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_CARRIER, NetIndex);
++
++ /*
++ * In some cases the runt and fcs counters are incremented when collisions
++ * occur. We have to correct those counters here.
++ */
++ Val64RxRunt = GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_RUNT, NetIndex);
++ Val64RxFcs = GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_FCS, NetIndex);
++
++ if (Val64RxRunt > Val64RxFcs) {
++ Val64RxRunt -= Val64RxFcs;
++ Val64RxHwErrs += Val64RxRunt;
++ }
++ else {
++ Val64RxFcs -= Val64RxRunt;
++ Val64RxHwErrs += Val64RxFcs;
++ }
++ break;
++
++ case OID_SKGE_TX_HW_ERROR_CTS:
++ case OID_SKGE_OUT_ERROR_CTS:
++ case OID_GEN_XMIT_ERROR:
++ Val64TxHwErrs =
++ GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_EXCESS_COL, NetIndex) +
++ GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_LATE_COL, NetIndex) +
++ GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_UNDERRUN, NetIndex) +
++ GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_CARRIER, NetIndex);
+ break;
+ }
+ }
+
+- /*
+- * Retrieve value
+- */
++ /* Retrieve value. */
+ switch (Id) {
+
+ case OID_SKGE_SUPPORTED_LIST:
+@@ -3697,11 +3584,11 @@
+ *pLen = Len;
+ return (SK_PNMI_ERR_TOO_SHORT);
+ }
+- for (Offset = 0, Index = 0; Offset < Len;
+- Offset += sizeof(SK_U32), Index ++) {
++ for (Offset = 0, Index = 0; Offset < Len; Index ++) {
+
+ Val32 = (SK_U32)IdTable[Index].Id;
+ SK_PNMI_STORE_U32(pBuf + Offset, Val32);
++ Offset += sizeof(SK_U32);
+ }
+ *pLen = Len;
+ break;
+@@ -3727,8 +3614,7 @@
+ case OID_SKGE_DRIVER_DESCR:
+ if (pAC->Pnmi.pDriverDescription == NULL) {
+
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR007,
+- SK_PNMI_ERR007MSG);
++ SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR007, SK_PNMI_ERR007MSG);
+
+ *pLen = 0;
+ return (SK_PNMI_ERR_GENERAL);
+@@ -3737,8 +3623,7 @@
+ Len = SK_STRLEN(pAC->Pnmi.pDriverDescription) + 1;
+ if (Len > SK_PNMI_STRINGLEN1) {
+
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR029,
+- SK_PNMI_ERR029MSG);
++ SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR029, SK_PNMI_ERR029MSG);
+
+ *pLen = 0;
+ return (SK_PNMI_ERR_GENERAL);
+@@ -3757,8 +3642,7 @@
+ case OID_SKGE_DRIVER_VERSION:
+ if (pAC->Pnmi.pDriverVersion == NULL) {
+
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR030,
+- SK_PNMI_ERR030MSG);
++ SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR030, SK_PNMI_ERR030MSG);
+
+ *pLen = 0;
+ return (SK_PNMI_ERR_GENERAL);
+@@ -3767,8 +3651,7 @@
+ Len = SK_STRLEN(pAC->Pnmi.pDriverVersion) + 1;
+ if (Len > SK_PNMI_STRINGLEN1) {
+
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR031,
+- SK_PNMI_ERR031MSG);
++ SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR031, SK_PNMI_ERR031MSG);
+
+ *pLen = 0;
+ return (SK_PNMI_ERR_GENERAL);
+@@ -3787,8 +3670,7 @@
+ case OID_SKGE_DRIVER_RELDATE:
+ if (pAC->Pnmi.pDriverReleaseDate == NULL) {
+
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR030,
+- SK_PNMI_ERR053MSG);
++ SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR053, SK_PNMI_ERR053MSG);
+
+ *pLen = 0;
+ return (SK_PNMI_ERR_GENERAL);
+@@ -3797,8 +3679,7 @@
+ Len = SK_STRLEN(pAC->Pnmi.pDriverReleaseDate) + 1;
+ if (Len > SK_PNMI_STRINGLEN1) {
+
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR031,
+- SK_PNMI_ERR054MSG);
++ SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR054, SK_PNMI_ERR054MSG);
+
+ *pLen = 0;
+ return (SK_PNMI_ERR_GENERAL);
+@@ -3817,8 +3698,7 @@
+ case OID_SKGE_DRIVER_FILENAME:
+ if (pAC->Pnmi.pDriverFileName == NULL) {
+
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR030,
+- SK_PNMI_ERR055MSG);
++ SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR055, SK_PNMI_ERR055MSG);
+
+ *pLen = 0;
+ return (SK_PNMI_ERR_GENERAL);
+@@ -3827,8 +3707,7 @@
+ Len = SK_STRLEN(pAC->Pnmi.pDriverFileName) + 1;
+ if (Len > SK_PNMI_STRINGLEN1) {
+
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR031,
+- SK_PNMI_ERR056MSG);
++ SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR056, SK_PNMI_ERR056MSG);
+
+ *pLen = 0;
+ return (SK_PNMI_ERR_GENERAL);
+@@ -3850,12 +3729,16 @@
+ * query may move to the initialisation routine. But
+ * the VPD data is cached and therefore a call here
+ * will not make much difference.
++ * Please read comment in Vpd().
+ */
++ if (pAC->Pnmi.VpdKeyReadError == SK_TRUE) {
++ return (SK_PNMI_ERR_OK);
++ }
++
+ Len = 256;
+ if (VpdRead(pAC, IoC, VPD_NAME, Buf, (int *)&Len) > 0) {
+
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR032,
+- SK_PNMI_ERR032MSG);
++ SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR032, SK_PNMI_ERR032MSG);
+
+ *pLen = 0;
+ return (SK_PNMI_ERR_GENERAL);
+@@ -3863,8 +3746,7 @@
+ Len ++;
+ if (Len > SK_PNMI_STRINGLEN1) {
+
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR033,
+- SK_PNMI_ERR033MSG);
++ SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR033, SK_PNMI_ERR033MSG);
+
+ *pLen = 0;
+ return (SK_PNMI_ERR_GENERAL);
+@@ -3880,7 +3762,6 @@
+ break;
+
+ case OID_SKGE_HW_VERSION:
+- /* Oh, I love to do some string manipulation */
+ if (*pLen < 5) {
+
+ *pLen = 5;
+@@ -3889,9 +3770,9 @@
+ Val8 = (SK_U8)pAC->GIni.GIPciHwRev;
+ pBuf[0] = 4;
+ pBuf[1] = 'v';
+- pBuf[2] = (char)(0x30 | ((Val8 >> 4) & 0x0F));
++ pBuf[2] = (char)('0' | ((Val8 >> 4) & 0x0f));
+ pBuf[3] = '.';
+- pBuf[4] = (char)(0x30 | (Val8 & 0x0F));
++ pBuf[4] = (char)('0' | (Val8 & 0x0f));
+ *pLen = 5;
+ break;
+
+@@ -3914,12 +3795,12 @@
+ break;
+
+ case OID_SKGE_VAUXAVAIL:
+- *pBuf = (char) pAC->GIni.GIVauxAvail;
++ *pBuf = (char)pAC->GIni.GIVauxAvail;
+ *pLen = sizeof(char);
+ break;
+
+ case OID_SKGE_BUS_TYPE:
+- *pBuf = (char) SK_PNMI_BUS_PCI;
++ *pBuf = (char)SK_PNMI_BUS_PCI;
+ *pLen = sizeof(char);
+ break;
+
+@@ -3968,31 +3849,31 @@
+ break;
+
+ case OID_SKGE_RLMT_MONITOR_NUMBER:
+-/* XXX Not yet implemented by RLMT therefore we return zero elements */
++ /* Not yet implemented by RLMT, therefore we return zero elements. */
+ Val32 = 0;
+ SK_PNMI_STORE_U32(pBuf, Val32);
+ *pLen = sizeof(SK_U32);
+ break;
+
+ case OID_SKGE_TX_SW_QUEUE_LEN:
+- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
++ /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */
+ if (MacType == SK_MAC_XMAC) {
+- /* Dual net mode */
++ /* DualNet mode. */
+ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+ Val64 = pAC->Pnmi.BufPort[NetIndex].TxSwQueueLen;
+ }
+- /* Single net mode */
++ /* SingleNet mode. */
+ else {
+ Val64 = pAC->Pnmi.BufPort[0].TxSwQueueLen +
+ pAC->Pnmi.BufPort[1].TxSwQueueLen;
+ }
+ }
+ else {
+- /* Dual net mode */
++ /* DualNet mode. */
+ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+ Val64 = pAC->Pnmi.Port[NetIndex].TxSwQueueLen;
+ }
+- /* Single net mode */
++ /* SingleNet mode. */
+ else {
+ Val64 = pAC->Pnmi.Port[0].TxSwQueueLen +
+ pAC->Pnmi.Port[1].TxSwQueueLen;
+@@ -4004,24 +3885,24 @@
+
+
+ case OID_SKGE_TX_SW_QUEUE_MAX:
+- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
++ /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */
+ if (MacType == SK_MAC_XMAC) {
+- /* Dual net mode */
++ /* DualNet mode. */
+ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+ Val64 = pAC->Pnmi.BufPort[NetIndex].TxSwQueueMax;
+ }
+- /* Single net mode */
++ /* SingleNet mode. */
+ else {
+ Val64 = pAC->Pnmi.BufPort[0].TxSwQueueMax +
+ pAC->Pnmi.BufPort[1].TxSwQueueMax;
+ }
+ }
+ else {
+- /* Dual net mode */
++ /* DualNet mode. */
+ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+ Val64 = pAC->Pnmi.Port[NetIndex].TxSwQueueMax;
+ }
+- /* Single net mode */
++ /* SingleNet mode. */
+ else {
+ Val64 = pAC->Pnmi.Port[0].TxSwQueueMax +
+ pAC->Pnmi.Port[1].TxSwQueueMax;
+@@ -4032,24 +3913,24 @@
+ break;
+
+ case OID_SKGE_TX_RETRY:
+- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
++ /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */
+ if (MacType == SK_MAC_XMAC) {
+- /* Dual net mode */
++ /* DualNet mode. */
+ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+ Val64 = pAC->Pnmi.BufPort[NetIndex].TxRetryCts;
+ }
+- /* Single net mode */
++ /* SingleNet mode. */
+ else {
+ Val64 = pAC->Pnmi.BufPort[0].TxRetryCts +
+ pAC->Pnmi.BufPort[1].TxRetryCts;
+ }
+ }
+ else {
+- /* Dual net mode */
++ /* DualNet mode. */
+ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+ Val64 = pAC->Pnmi.Port[NetIndex].TxRetryCts;
+ }
+- /* Single net mode */
++ /* SingleNet mode. */
+ else {
+ Val64 = pAC->Pnmi.Port[0].TxRetryCts +
+ pAC->Pnmi.Port[1].TxRetryCts;
+@@ -4060,24 +3941,24 @@
+ break;
+
+ case OID_SKGE_RX_INTR_CTS:
+- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
++ /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */
+ if (MacType == SK_MAC_XMAC) {
+- /* Dual net mode */
++ /* DualNet mode. */
+ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+ Val64 = pAC->Pnmi.BufPort[NetIndex].RxIntrCts;
+ }
+- /* Single net mode */
++ /* SingleNet mode. */
+ else {
+ Val64 = pAC->Pnmi.BufPort[0].RxIntrCts +
+ pAC->Pnmi.BufPort[1].RxIntrCts;
+ }
+ }
+ else {
+- /* Dual net mode */
++ /* DualNet mode. */
+ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+ Val64 = pAC->Pnmi.Port[NetIndex].RxIntrCts;
+ }
+- /* Single net mode */
++ /* SingleNet mode. */
+ else {
+ Val64 = pAC->Pnmi.Port[0].RxIntrCts +
+ pAC->Pnmi.Port[1].RxIntrCts;
+@@ -4088,24 +3969,24 @@
+ break;
+
+ case OID_SKGE_TX_INTR_CTS:
+- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
++ /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */
+ if (MacType == SK_MAC_XMAC) {
+- /* Dual net mode */
++ /* DualNet mode. */
+ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+ Val64 = pAC->Pnmi.BufPort[NetIndex].TxIntrCts;
+ }
+- /* Single net mode */
++ /* SingleNet mode. */
+ else {
+ Val64 = pAC->Pnmi.BufPort[0].TxIntrCts +
+ pAC->Pnmi.BufPort[1].TxIntrCts;
+ }
+ }
+ else {
+- /* Dual net mode */
++ /* DualNet mode. */
+ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+ Val64 = pAC->Pnmi.Port[NetIndex].TxIntrCts;
+ }
+- /* Single net mode */
++ /* SingleNet mode. */
+ else {
+ Val64 = pAC->Pnmi.Port[0].TxIntrCts +
+ pAC->Pnmi.Port[1].TxIntrCts;
+@@ -4116,24 +3997,24 @@
+ break;
+
+ case OID_SKGE_RX_NO_BUF_CTS:
+- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
++ /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */
+ if (MacType == SK_MAC_XMAC) {
+- /* Dual net mode */
++ /* DualNet mode. */
+ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+ Val64 = pAC->Pnmi.BufPort[NetIndex].RxNoBufCts;
+ }
+- /* Single net mode */
++ /* SingleNet mode. */
+ else {
+ Val64 = pAC->Pnmi.BufPort[0].RxNoBufCts +
+ pAC->Pnmi.BufPort[1].RxNoBufCts;
+ }
+ }
+ else {
+- /* Dual net mode */
++ /* DualNet mode. */
+ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+ Val64 = pAC->Pnmi.Port[NetIndex].RxNoBufCts;
+ }
+- /* Single net mode */
++ /* SingleNet mode. */
+ else {
+ Val64 = pAC->Pnmi.Port[0].RxNoBufCts +
+ pAC->Pnmi.Port[1].RxNoBufCts;
+@@ -4144,24 +4025,24 @@
+ break;
+
+ case OID_SKGE_TX_NO_BUF_CTS:
+- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
++ /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */
+ if (MacType == SK_MAC_XMAC) {
+- /* Dual net mode */
++ /* DualNet mode. */
+ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+ Val64 = pAC->Pnmi.BufPort[NetIndex].TxNoBufCts;
+ }
+- /* Single net mode */
++ /* SingleNet mode. */
+ else {
+ Val64 = pAC->Pnmi.BufPort[0].TxNoBufCts +
+ pAC->Pnmi.BufPort[1].TxNoBufCts;
+ }
+ }
+ else {
+- /* Dual net mode */
++ /* DualNet mode. */
+ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+ Val64 = pAC->Pnmi.Port[NetIndex].TxNoBufCts;
+ }
+- /* Single net mode */
++ /* SingleNet mode. */
+ else {
+ Val64 = pAC->Pnmi.Port[0].TxNoBufCts +
+ pAC->Pnmi.Port[1].TxNoBufCts;
+@@ -4172,24 +4053,24 @@
+ break;
+
+ case OID_SKGE_TX_USED_DESCR_NO:
+- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
++ /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */
+ if (MacType == SK_MAC_XMAC) {
+- /* Dual net mode */
++ /* DualNet mode. */
+ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+ Val64 = pAC->Pnmi.BufPort[NetIndex].TxUsedDescrNo;
+ }
+- /* Single net mode */
++ /* SingleNet mode. */
+ else {
+ Val64 = pAC->Pnmi.BufPort[0].TxUsedDescrNo +
+ pAC->Pnmi.BufPort[1].TxUsedDescrNo;
+ }
+ }
+ else {
+- /* Dual net mode */
++ /* DualNet mode. */
+ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+ Val64 = pAC->Pnmi.Port[NetIndex].TxUsedDescrNo;
+ }
+- /* Single net mode */
++ /* SingleNet mode. */
+ else {
+ Val64 = pAC->Pnmi.Port[0].TxUsedDescrNo +
+ pAC->Pnmi.Port[1].TxUsedDescrNo;
+@@ -4200,24 +4081,24 @@
+ break;
+
+ case OID_SKGE_RX_DELIVERED_CTS:
+- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
++ /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */
+ if (MacType == SK_MAC_XMAC) {
+- /* Dual net mode */
++ /* DualNet mode. */
+ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+ Val64 = pAC->Pnmi.BufPort[NetIndex].RxDeliveredCts;
+ }
+- /* Single net mode */
++ /* SingleNet mode. */
+ else {
+ Val64 = pAC->Pnmi.BufPort[0].RxDeliveredCts +
+ pAC->Pnmi.BufPort[1].RxDeliveredCts;
+ }
+ }
+ else {
+- /* Dual net mode */
++ /* DualNet mode. */
+ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+ Val64 = pAC->Pnmi.Port[NetIndex].RxDeliveredCts;
+ }
+- /* Single net mode */
++ /* SingleNet mode. */
+ else {
+ Val64 = pAC->Pnmi.Port[0].RxDeliveredCts +
+ pAC->Pnmi.Port[1].RxDeliveredCts;
+@@ -4228,24 +4109,24 @@
+ break;
+
+ case OID_SKGE_RX_OCTETS_DELIV_CTS:
+- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
++ /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */
+ if (MacType == SK_MAC_XMAC) {
+- /* Dual net mode */
++ /* DualNet mode. */
+ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+ Val64 = pAC->Pnmi.BufPort[NetIndex].RxOctetsDeliveredCts;
+ }
+- /* Single net mode */
++ /* SingleNet mode. */
+ else {
+ Val64 = pAC->Pnmi.BufPort[0].RxOctetsDeliveredCts +
+ pAC->Pnmi.BufPort[1].RxOctetsDeliveredCts;
+ }
+ }
+ else {
+- /* Dual net mode */
++ /* DualNet mode. */
+ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+ Val64 = pAC->Pnmi.Port[NetIndex].RxOctetsDeliveredCts;
+ }
+- /* Single net mode */
++ /* SingleNet mode. */
+ else {
+ Val64 = pAC->Pnmi.Port[0].RxOctetsDeliveredCts +
+ pAC->Pnmi.Port[1].RxOctetsDeliveredCts;
+@@ -4266,13 +4147,13 @@
+ break;
+
+ case OID_SKGE_IN_ERRORS_CTS:
+- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
++ /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */
+ if (MacType == SK_MAC_XMAC) {
+- /* Dual net mode */
++ /* DualNet mode. */
+ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+ Val64 = Val64RxHwErrs + pAC->Pnmi.BufPort[NetIndex].RxNoBufCts;
+ }
+- /* Single net mode */
++ /* SingleNet mode. */
+ else {
+ Val64 = Val64RxHwErrs +
+ pAC->Pnmi.BufPort[0].RxNoBufCts +
+@@ -4280,11 +4161,11 @@
+ }
+ }
+ else {
+- /* Dual net mode */
++ /* DualNet mode. */
+ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+ Val64 = Val64RxHwErrs + pAC->Pnmi.Port[NetIndex].RxNoBufCts;
+ }
+- /* Single net mode */
++ /* SingleNet mode. */
+ else {
+ Val64 = Val64RxHwErrs +
+ pAC->Pnmi.Port[0].RxNoBufCts +
+@@ -4296,13 +4177,13 @@
+ break;
+
+ case OID_SKGE_OUT_ERROR_CTS:
+- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
++ /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */
+ if (MacType == SK_MAC_XMAC) {
+- /* Dual net mode */
++ /* DualNet mode. */
+ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+ Val64 = Val64TxHwErrs + pAC->Pnmi.BufPort[NetIndex].TxNoBufCts;
+ }
+- /* Single net mode */
++ /* SingleNet mode. */
+ else {
+ Val64 = Val64TxHwErrs +
+ pAC->Pnmi.BufPort[0].TxNoBufCts +
+@@ -4310,11 +4191,11 @@
+ }
+ }
+ else {
+- /* Dual net mode */
++ /* DualNet mode. */
+ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+ Val64 = Val64TxHwErrs + pAC->Pnmi.Port[NetIndex].TxNoBufCts;
+ }
+- /* Single net mode */
++ /* SingleNet mode. */
+ else {
+ Val64 = Val64TxHwErrs +
+ pAC->Pnmi.Port[0].TxNoBufCts +
+@@ -4326,24 +4207,24 @@
+ break;
+
+ case OID_SKGE_ERR_RECOVERY_CTS:
+- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
++ /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */
+ if (MacType == SK_MAC_XMAC) {
+- /* Dual net mode */
++ /* DualNet mode. */
+ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+ Val64 = pAC->Pnmi.BufPort[NetIndex].ErrRecoveryCts;
+ }
+- /* Single net mode */
++ /* SingleNet mode. */
+ else {
+ Val64 = pAC->Pnmi.BufPort[0].ErrRecoveryCts +
+ pAC->Pnmi.BufPort[1].ErrRecoveryCts;
+ }
+ }
+ else {
+- /* Dual net mode */
++ /* DualNet mode. */
+ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+ Val64 = pAC->Pnmi.Port[NetIndex].ErrRecoveryCts;
+ }
+- /* Single net mode */
++ /* SingleNet mode. */
+ else {
+ Val64 = pAC->Pnmi.Port[0].ErrRecoveryCts +
+ pAC->Pnmi.Port[1].ErrRecoveryCts;
+@@ -4367,7 +4248,7 @@
+ break;
+
+ case OID_GEN_RCV_ERROR:
+- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
++ /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */
+ if (MacType == SK_MAC_XMAC) {
+ Val64 = Val64RxHwErrs + pAC->Pnmi.BufPort[NetIndex].RxNoBufCts;
+ }
+@@ -4376,7 +4257,7 @@
+ }
+
+ /*
+- * by default 32bit values are evaluated
++ * By default 32bit values are evaluated.
+ */
+ if (!Is64BitReq) {
+ Val32 = (SK_U32)Val64;
+@@ -4390,7 +4271,7 @@
+ break;
+
+ case OID_GEN_XMIT_ERROR:
+- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
++ /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */
+ if (MacType == SK_MAC_XMAC) {
+ Val64 = Val64TxHwErrs + pAC->Pnmi.BufPort[NetIndex].TxNoBufCts;
+ }
+@@ -4399,7 +4280,7 @@
+ }
+
+ /*
+- * by default 32bit values are evaluated
++ * By default 32bit values are evaluated.
+ */
+ if (!Is64BitReq) {
+ Val32 = (SK_U32)Val64;
+@@ -4413,16 +4294,19 @@
+ break;
+
+ case OID_GEN_RCV_NO_BUFFER:
+- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
++ /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */
+ if (MacType == SK_MAC_XMAC) {
+- Val64 = pAC->Pnmi.BufPort[NetIndex].RxNoBufCts;
++ Val64 = pAC->Pnmi.BufPort[NetIndex].RxNoBufCts +
++ GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_OVERFLOW, NetIndex);
++
+ }
+ else {
+- Val64 = pAC->Pnmi.Port[NetIndex].RxNoBufCts;
++ Val64 = pAC->Pnmi.Port[NetIndex].RxNoBufCts +
++ GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_OVERFLOW, NetIndex);
+ }
+
+ /*
+- * by default 32bit values are evaluated
++ * By default 32bit values are evaluated.
+ */
+ if (!Is64BitReq) {
+ Val32 = (SK_U32)Val64;
+@@ -4442,8 +4326,7 @@
+ break;
+
+ default:
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR034,
+- SK_PNMI_ERR034MSG);
++ SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR034, SK_PNMI_ERR034MSG);
+
+ *pLen = 0;
+ return (SK_PNMI_ERR_GENERAL);
+@@ -4500,25 +4383,17 @@
+ SK_U32 Val32;
+ SK_U64 Val64;
+
+-
+- /*
+- * Check instance. Only single instance OIDs are allowed here.
+- */
++ /* Check instance. Only single instance OIDs are allowed here. */
+ if (Instance != (SK_U32)(-1) && Instance != 1) {
+
+ *pLen = 0;
+ return (SK_PNMI_ERR_UNKNOWN_INST);
+ }
+
+- /*
+- * Perform the requested action.
+- */
++ /* Perform the requested action. */
+ if (Action == SK_PNMI_GET) {
+
+- /*
+- * Check if the buffer length is large enough.
+- */
+-
++ /* Check if the buffer length is large enough. */
+ switch (Id) {
+
+ case OID_SKGE_RLMT_MODE:
+@@ -4551,8 +4426,7 @@
+ break;
+
+ default:
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR035,
+- SK_PNMI_ERR035MSG);
++ SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR035, SK_PNMI_ERR035MSG);
+
+ *pLen = 0;
+ return (SK_PNMI_ERR_GENERAL);
+@@ -4571,9 +4445,7 @@
+ }
+ pAC->Pnmi.RlmtUpdatedFlag ++;
+
+- /*
+- * Retrieve Value
+- */
++ /* Retrieve value. */
+ switch (Id) {
+
+ case OID_SKGE_RLMT_MODE:
+@@ -4651,17 +4523,17 @@
+ pAC->Pnmi.RlmtUpdatedFlag --;
+ }
+ else {
+- /* Perform a preset or set */
++ /* Perform a PRESET or SET. */
+ switch (Id) {
+
+ case OID_SKGE_RLMT_MODE:
+- /* Check if the buffer length is plausible */
++ /* Check if the buffer length is plausible. */
+ if (*pLen < sizeof(char)) {
+
+ *pLen = sizeof(char);
+ return (SK_PNMI_ERR_TOO_SHORT);
+ }
+- /* Check if the value range is correct */
++ /* Check if the value range is correct. */
+ if (*pLen != sizeof(char) ||
+ (*pBuf & SK_PNMI_RLMT_MODE_CHK_LINK) == 0 ||
+ *(SK_U8 *)pBuf > 15) {
+@@ -4669,21 +4541,21 @@
+ *pLen = 0;
+ return (SK_PNMI_ERR_BAD_VALUE);
+ }
+- /* The preset ends here */
++ /* The PRESET ends here. */
+ if (Action == SK_PNMI_PRESET) {
+
+ *pLen = 0;
+ return (SK_PNMI_ERR_OK);
+ }
+- /* Send an event to RLMT to change the mode */
++ /* Send an event to RLMT to change the mode. */
+ SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
++
+ EventParam.Para32[0] |= (SK_U32)(*pBuf);
+ EventParam.Para32[1] = 0;
+ if (SkRlmtEvent(pAC, IoC, SK_RLMT_MODE_CHANGE,
+ EventParam) > 0) {
+
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR037,
+- SK_PNMI_ERR037MSG);
++ SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR037, SK_PNMI_ERR037MSG);
+
+ *pLen = 0;
+ return (SK_PNMI_ERR_GENERAL);
+@@ -4691,20 +4563,25 @@
+ break;
+
+ case OID_SKGE_RLMT_PORT_PREFERRED:
+- /* Check if the buffer length is plausible */
++ /* PRESET/SET action makes no sense in Dual Net mode. */
++ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
++ break;
++ }
++
++ /* Check if the buffer length is plausible. */
+ if (*pLen < sizeof(char)) {
+
+ *pLen = sizeof(char);
+ return (SK_PNMI_ERR_TOO_SHORT);
+ }
+- /* Check if the value range is correct */
++ /* Check if the value range is correct. */
+ if (*pLen != sizeof(char) || *(SK_U8 *)pBuf >
+ (SK_U8)pAC->GIni.GIMacsFound) {
+
+ *pLen = 0;
+ return (SK_PNMI_ERR_BAD_VALUE);
+ }
+- /* The preset ends here */
++ /* The PRESET ends here. */
+ if (Action == SK_PNMI_PRESET) {
+
+ *pLen = 0;
+@@ -4717,13 +4594,13 @@
+ * make the decision which is the preferred port.
+ */
+ SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
++
+ EventParam.Para32[0] = (SK_U32)(*pBuf) - 1;
+ EventParam.Para32[1] = NetIndex;
+ if (SkRlmtEvent(pAC, IoC, SK_RLMT_PREFPORT_CHANGE,
+ EventParam) > 0) {
+
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR038,
+- SK_PNMI_ERR038MSG);
++ SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR038, SK_PNMI_ERR038MSG);
+
+ *pLen = 0;
+ return (SK_PNMI_ERR_GENERAL);
+@@ -4731,22 +4608,20 @@
+ break;
+
+ case OID_SKGE_RLMT_CHANGE_THRES:
+- /* Check if the buffer length is plausible */
++ /* Check if the buffer length is plausible. */
+ if (*pLen < sizeof(SK_U64)) {
+
+ *pLen = sizeof(SK_U64);
+ return (SK_PNMI_ERR_TOO_SHORT);
+ }
+- /*
+- * There are not many restrictions to the
+- * value range.
+- */
++
++ /* There are not many restrictions to the value range. */
+ if (*pLen != sizeof(SK_U64)) {
+
+ *pLen = 0;
+ return (SK_PNMI_ERR_BAD_VALUE);
+ }
+- /* A preset ends here */
++ /* The PRESET ends here. */
+ if (Action == SK_PNMI_PRESET) {
+
+ *pLen = 0;
+@@ -4761,7 +4636,7 @@
+ break;
+
+ default:
+- /* The other OIDs are not be able for set */
++ /* The other OIDs are not be able for set. */
+ *pLen = 0;
+ return (SK_PNMI_ERR_READ_ONLY);
+ }
+@@ -4806,54 +4681,49 @@
+ SK_U32 Val32;
+ SK_U64 Val64;
+
+- /*
+- * Calculate the port indexes from the instance.
+- */
++
++ /* Calculate the port indexes from the instance. */
+ PhysPortMax = pAC->GIni.GIMacsFound;
+
+ if ((Instance != (SK_U32)(-1))) {
+- /* Check instance range */
++ /* Check instance range. */
+ if ((Instance < 1) || (Instance > PhysPortMax)) {
+
+ *pLen = 0;
+ return (SK_PNMI_ERR_UNKNOWN_INST);
+ }
+
+- /* Single net mode */
++ /* SingleNet mode. */
+ PhysPortIndex = Instance - 1;
+
+- /* Dual net mode */
++ /* DualNet mode. */
+ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+ PhysPortIndex = NetIndex;
+ }
+
+- /* Both net modes */
++ /* Both net modes. */
+ Limit = PhysPortIndex + 1;
+ }
+ else {
+- /* Single net mode */
++ /* SingleNet mode. */
+ PhysPortIndex = 0;
+ Limit = PhysPortMax;
+
+- /* Dual net mode */
++ /* DualNet mode. */
+ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+ PhysPortIndex = NetIndex;
+ Limit = PhysPortIndex + 1;
+ }
+ }
+
+- /*
+- * Currently only get requests are allowed.
+- */
++ /* Currently only GET requests are allowed. */
+ if (Action != SK_PNMI_GET) {
+
+ *pLen = 0;
+ return (SK_PNMI_ERR_READ_ONLY);
+ }
+
+- /*
+- * Check if the buffer length is large enough.
+- */
++ /* Check if the buffer length is large enough. */
+ switch (Id) {
+
+ case OID_SKGE_RLMT_PORT_INDEX:
+@@ -4877,8 +4747,7 @@
+ break;
+
+ default:
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR039,
+- SK_PNMI_ERR039MSG);
++ SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR039, SK_PNMI_ERR039MSG);
+
+ *pLen = 0;
+ return (SK_PNMI_ERR_GENERAL);
+@@ -4896,9 +4765,7 @@
+ }
+ pAC->Pnmi.RlmtUpdatedFlag ++;
+
+- /*
+- * Get value
+- */
++ /* Get value. */
+ Offset = 0;
+ for (; PhysPortIndex < Limit; PhysPortIndex ++) {
+
+@@ -5011,19 +4878,21 @@
+ int Ret;
+ SK_EVPARA EventParam;
+ SK_U32 Val32;
++#ifdef SK_PHY_LP_MODE
++ SK_U8 CurrentPhyPowerState;
++#endif /* SK_PHY_LP_MODE */
+
+- /*
+- * Calculate instance if wished. MAC index 0 is the virtual MAC.
+- */
++
++ /* Calculate instance if wished. MAC index 0 is the virtual MAC. */
+ PhysPortMax = pAC->GIni.GIMacsFound;
+ LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax);
+
+- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */
++ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* DualNet mode. */
+ LogPortMax--;
+ }
+
+- if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried */
+- /* Check instance range */
++ if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried. */
++ /* Check instance range. */
+ if ((Instance < 1) || (Instance > LogPortMax)) {
+
+ *pLen = 0;
+@@ -5033,18 +4902,16 @@
+ Limit = LogPortIndex + 1;
+ }
+
+- else { /* Instance == (SK_U32)(-1), get all Instances of that OID */
++ else { /* Instance == (SK_U32)(-1), get all Instances of that OID. */
+
+ LogPortIndex = 0;
+ Limit = LogPortMax;
+ }
+
+- /*
+- * Perform action
+- */
++ /* Perform action. */
+ if (Action == SK_PNMI_GET) {
+
+- /* Check length */
++ /* Check length. */
+ switch (Id) {
+
+ case OID_SKGE_PMD:
+@@ -5082,8 +4949,7 @@
+ break;
+
+ default:
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR041,
+- SK_PNMI_ERR041MSG);
++ SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR041, SK_PNMI_ERR041MSG);
+ *pLen = 0;
+ return (SK_PNMI_ERR_GENERAL);
+ }
+@@ -5099,9 +4965,7 @@
+ }
+ pAC->Pnmi.SirqUpdatedFlag ++;
+
+- /*
+- * Get value
+- */
++ /* Get value. */
+ Offset = 0;
+ for (; LogPortIndex < Limit; LogPortIndex ++) {
+
+@@ -5111,107 +4975,99 @@
+
+ case OID_SKGE_PMD:
+ *pBufPtr = pAC->Pnmi.PMD;
+- Offset += sizeof(char);
++ Offset ++;
+ break;
+
+ case OID_SKGE_CONNECTOR:
+ *pBufPtr = pAC->Pnmi.Connector;
+- Offset += sizeof(char);
++ Offset ++;
+ break;
+
+ case OID_SKGE_PHY_TYPE:
+- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
++ if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */
+ if (LogPortIndex == 0) {
+ continue;
+ }
+- else {
+- /* Get value for physical ports */
+- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+- pAC, LogPortIndex);
+- Val32 = pAC->GIni.GP[PhysPortIndex].PhyType;
+- SK_PNMI_STORE_U32(pBufPtr, Val32);
+- }
++ /* Get value for physical port. */
++ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex);
++ Val32 = pAC->GIni.GP[PhysPortIndex].PhyType;
+ }
+- else { /* DualNetMode */
++ else { /* DualNet mode. */
+
+ Val32 = pAC->GIni.GP[NetIndex].PhyType;
+- SK_PNMI_STORE_U32(pBufPtr, Val32);
+ }
++ SK_PNMI_STORE_U32(pBufPtr, Val32);
+ Offset += sizeof(SK_U32);
+ break;
+
+ #ifdef SK_PHY_LP_MODE
+ case OID_SKGE_PHY_LP_MODE:
+- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
++ if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */
+ if (LogPortIndex == 0) {
+ continue;
+ }
+- else {
+- /* Get value for physical ports */
+- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex);
+- Val8 = (SK_U8) pAC->GIni.GP[PhysPortIndex].PPhyPowerState;
+- *pBufPtr = Val8;
+- }
++ /* Get value for physical port. */
++ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex);
++ *pBufPtr = (SK_U8)pAC->GIni.GP[PhysPortIndex].PPhyPowerState;
+ }
+- else { /* DualNetMode */
++ else { /* DualNet mode. */
+
+- Val8 = (SK_U8) pAC->GIni.GP[PhysPortIndex].PPhyPowerState;
+- *pBufPtr = Val8;
++ *pBufPtr = (SK_U8)pAC->GIni.GP[NetIndex].PPhyPowerState;
+ }
+ Offset += sizeof(SK_U8);
+ break;
+ #endif
+
+ case OID_SKGE_LINK_CAP:
+- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
++ if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */
+ if (LogPortIndex == 0) {
+- /* Get value for virtual port */
++ /* Get value for virtual port. */
+ VirtualConf(pAC, IoC, Id, pBufPtr);
+ }
+ else {
+- /* Get value for physical ports */
++ /* Get value for physical port. */
+ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+ pAC, LogPortIndex);
+
+ *pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkCap;
+ }
+ }
+- else { /* DualNetMode */
++ else { /* DualNet mode. */
+
+ *pBufPtr = pAC->GIni.GP[NetIndex].PLinkCap;
+ }
+- Offset += sizeof(char);
++ Offset ++;
+ break;
+
+ case OID_SKGE_LINK_MODE:
+- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
++ if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */
+ if (LogPortIndex == 0) {
+- /* Get value for virtual port */
++ /* Get value for virtual port. */
+ VirtualConf(pAC, IoC, Id, pBufPtr);
+ }
+ else {
+- /* Get value for physical ports */
++ /* Get value for physical port. */
+ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+ pAC, LogPortIndex);
+
+ *pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkModeConf;
+ }
+ }
+- else { /* DualNetMode */
++ else { /* DualNet mode. */
+
+ *pBufPtr = pAC->GIni.GP[NetIndex].PLinkModeConf;
+ }
+- Offset += sizeof(char);
++ Offset ++;
+ break;
+
+ case OID_SKGE_LINK_MODE_STATUS:
+- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
++ if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */
+ if (LogPortIndex == 0) {
+- /* Get value for virtual port */
++ /* Get value for virtual port. */
+ VirtualConf(pAC, IoC, Id, pBufPtr);
+ }
+ else {
+- /* Get value for physical port */
++ /* Get value for physical port. */
+ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+ pAC, LogPortIndex);
+
+@@ -5219,147 +5075,147 @@
+ CalculateLinkModeStatus(pAC, IoC, PhysPortIndex);
+ }
+ }
+- else { /* DualNetMode */
++ else { /* DualNet mode. */
+
+ *pBufPtr = CalculateLinkModeStatus(pAC, IoC, NetIndex);
+ }
+- Offset += sizeof(char);
++ Offset ++;
+ break;
+
+ case OID_SKGE_LINK_STATUS:
+- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
++ if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */
+ if (LogPortIndex == 0) {
+- /* Get value for virtual port */
++ /* Get value for virtual port. */
+ VirtualConf(pAC, IoC, Id, pBufPtr);
+ }
+ else {
+- /* Get value for physical ports */
++ /* Get value for physical port. */
+ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+ pAC, LogPortIndex);
+
+ *pBufPtr = CalculateLinkStatus(pAC, IoC, PhysPortIndex);
+ }
+ }
+- else { /* DualNetMode */
++ else { /* DualNet mode. */
+
+ *pBufPtr = CalculateLinkStatus(pAC, IoC, NetIndex);
+ }
+- Offset += sizeof(char);
++ Offset ++;
+ break;
+
+ case OID_SKGE_FLOWCTRL_CAP:
+- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
++ if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */
+ if (LogPortIndex == 0) {
+- /* Get value for virtual port */
++ /* Get value for virtual port. */
+ VirtualConf(pAC, IoC, Id, pBufPtr);
+ }
+ else {
+- /* Get value for physical ports */
++ /* Get value for physical port. */
+ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+ pAC, LogPortIndex);
+
+ *pBufPtr = pAC->GIni.GP[PhysPortIndex].PFlowCtrlCap;
+ }
+ }
+- else { /* DualNetMode */
++ else { /* DualNet mode. */
+
+ *pBufPtr = pAC->GIni.GP[NetIndex].PFlowCtrlCap;
+ }
+- Offset += sizeof(char);
++ Offset ++;
+ break;
+
+ case OID_SKGE_FLOWCTRL_MODE:
+- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
++ if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */
+ if (LogPortIndex == 0) {
+- /* Get value for virtual port */
++ /* Get value for virtual port. */
+ VirtualConf(pAC, IoC, Id, pBufPtr);
+ }
+ else {
+- /* Get value for physical port */
++ /* Get value for physical port. */
+ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+ pAC, LogPortIndex);
+
+ *pBufPtr = pAC->GIni.GP[PhysPortIndex].PFlowCtrlMode;
+ }
+ }
+- else { /* DualNetMode */
++ else { /* DualNet mode. */
+
+ *pBufPtr = pAC->GIni.GP[NetIndex].PFlowCtrlMode;
+ }
+- Offset += sizeof(char);
++ Offset ++;
+ break;
+
+ case OID_SKGE_FLOWCTRL_STATUS:
+- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
++ if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */
+ if (LogPortIndex == 0) {
+- /* Get value for virtual port */
++ /* Get value for virtual port. */
+ VirtualConf(pAC, IoC, Id, pBufPtr);
+ }
+ else {
+- /* Get value for physical port */
++ /* Get value for physical port. */
+ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+ pAC, LogPortIndex);
+
+ *pBufPtr = pAC->GIni.GP[PhysPortIndex].PFlowCtrlStatus;
+ }
+ }
+- else { /* DualNetMode */
++ else { /* DualNet mode. */
+
+ *pBufPtr = pAC->GIni.GP[NetIndex].PFlowCtrlStatus;
+ }
+- Offset += sizeof(char);
++ Offset ++;
+ break;
+
+ case OID_SKGE_PHY_OPERATION_CAP:
+- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
++ if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet Mode. */
+ if (LogPortIndex == 0) {
+- /* Get value for virtual port */
++ /* Get value for virtual port. */
+ VirtualConf(pAC, IoC, Id, pBufPtr);
+ }
+ else {
+- /* Get value for physical ports */
++ /* Get value for physical port. */
+ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+ pAC, LogPortIndex);
+
+ *pBufPtr = pAC->GIni.GP[PhysPortIndex].PMSCap;
+ }
+ }
+- else { /* DualNetMode */
++ else { /* DualNet mode. */
+
+ *pBufPtr = pAC->GIni.GP[NetIndex].PMSCap;
+ }
+- Offset += sizeof(char);
++ Offset ++;
+ break;
+
+ case OID_SKGE_PHY_OPERATION_MODE:
+- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
++ if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */
+ if (LogPortIndex == 0) {
+- /* Get value for virtual port */
++ /* Get value for virtual port. */
+ VirtualConf(pAC, IoC, Id, pBufPtr);
+ }
+ else {
+- /* Get value for physical port */
++ /* Get value for physical port. */
+ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+ pAC, LogPortIndex);
+
+ *pBufPtr = pAC->GIni.GP[PhysPortIndex].PMSMode;
+ }
+ }
+- else { /* DualNetMode */
++ else { /* DualNet mode. */
+
+ *pBufPtr = pAC->GIni.GP[NetIndex].PMSMode;
+ }
+- Offset += sizeof(char);
++ Offset ++;
+ break;
+
+ case OID_SKGE_PHY_OPERATION_STATUS:
+- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
++ if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */
+ if (LogPortIndex == 0) {
+- /* Get value for virtual port */
++ /* Get value for virtual port. */
+ VirtualConf(pAC, IoC, Id, pBufPtr);
+ }
+ else {
+- /* Get value for physical port */
++ /* Get value for physical port. */
+ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+ pAC, LogPortIndex);
+
+@@ -5370,70 +5226,70 @@
+
+ *pBufPtr = pAC->GIni.GP[NetIndex].PMSStatus;
+ }
+- Offset += sizeof(char);
++ Offset ++;
+ break;
+
+ case OID_SKGE_SPEED_CAP:
+- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
++ if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */
+ if (LogPortIndex == 0) {
+- /* Get value for virtual port */
++ /* Get value for virtual port. */
+ VirtualConf(pAC, IoC, Id, pBufPtr);
+ }
+ else {
+- /* Get value for physical ports */
++ /* Get value for physical port. */
+ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+ pAC, LogPortIndex);
+
+ *pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkSpeedCap;
+ }
+ }
+- else { /* DualNetMode */
++ else { /* DualNet mode. */
+
+ *pBufPtr = pAC->GIni.GP[NetIndex].PLinkSpeedCap;
+ }
+- Offset += sizeof(char);
++ Offset ++;
+ break;
+
+ case OID_SKGE_SPEED_MODE:
+- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
++ if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */
+ if (LogPortIndex == 0) {
+- /* Get value for virtual port */
++ /* Get value for virtual port. */
+ VirtualConf(pAC, IoC, Id, pBufPtr);
+ }
+ else {
+- /* Get value for physical port */
++ /* Get value for physical port. */
+ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+ pAC, LogPortIndex);
+
+ *pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkSpeed;
+ }
+ }
+- else { /* DualNetMode */
++ else { /* DualNet mode. */
+
+ *pBufPtr = pAC->GIni.GP[NetIndex].PLinkSpeed;
+ }
+- Offset += sizeof(char);
++ Offset ++;
+ break;
+
+ case OID_SKGE_SPEED_STATUS:
+- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
++ if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */
+ if (LogPortIndex == 0) {
+- /* Get value for virtual port */
++ /* Get value for virtual port. */
+ VirtualConf(pAC, IoC, Id, pBufPtr);
+ }
+ else {
+- /* Get value for physical port */
++ /* Get value for physical port. */
+ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
+ pAC, LogPortIndex);
+
+ *pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkSpeedUsed;
+ }
+ }
+- else { /* DualNetMode */
++ else { /* DualNet mode. */
+
+ *pBufPtr = pAC->GIni.GP[NetIndex].PLinkSpeedUsed;
+ }
+- Offset += sizeof(char);
++ Offset ++;
+ break;
+
+ case OID_SKGE_MTU:
+@@ -5486,40 +5342,33 @@
+ return (SK_PNMI_ERR_TOO_SHORT);
+ }
+ break;
+-#endif
++#endif /* SK_PHY_LP_MODE */
+
+ case OID_SKGE_MTU:
+- if (*pLen < sizeof(SK_U32)) {
++ if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U32)) {
+
+- *pLen = sizeof(SK_U32);
++ *pLen = (Limit - LogPortIndex) * sizeof(SK_U32);
+ return (SK_PNMI_ERR_TOO_SHORT);
+ }
+- if (*pLen != sizeof(SK_U32)) {
+-
+- *pLen = 0;
+- return (SK_PNMI_ERR_BAD_VALUE);
+- }
+ break;
+-
++
+ default:
+ *pLen = 0;
+ return (SK_PNMI_ERR_READ_ONLY);
+ }
+
+- /*
+- * Perform preset or set
+- */
++ /* Perform PRESET or SET. */
+ Offset = 0;
+ for (; LogPortIndex < Limit; LogPortIndex ++) {
+
++ Val8 = *(pBuf + Offset);
++
+ switch (Id) {
+
+ case OID_SKGE_LINK_MODE:
+- /* Check the value range */
+- Val8 = *(pBuf + Offset);
++ /* Check the value range. */
+ if (Val8 == 0) {
+-
+- Offset += sizeof(char);
++ Offset++;
+ break;
+ }
+ if (Val8 < SK_LMODE_HALF ||
+@@ -5530,51 +5379,68 @@
+ return (SK_PNMI_ERR_BAD_VALUE);
+ }
+
+- /* The preset ends here */
++ /* The PRESET ends here. */
+ if (Action == SK_PNMI_PRESET) {
+
+ return (SK_PNMI_ERR_OK);
+ }
+
+- if (LogPortIndex == 0) {
+-
+- /*
+- * The virtual port consists of all currently
+- * active ports. Find them and send an event
+- * with the new link mode to SIRQ.
+- */
+- for (PhysPortIndex = 0;
+- PhysPortIndex < PhysPortMax;
+- PhysPortIndex ++) {
+-
+- if (!pAC->Pnmi.Port[PhysPortIndex].
+- ActiveFlag) {
+-
+- continue;
+- }
++ if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */
++ if (LogPortIndex == 0) {
++ /*
++ * The virtual port consists of all currently
++ * active ports. Find them and send an event
++ * with the new link mode to SIRQ.
++ */
++ for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax;
++ PhysPortIndex ++) {
+
+- EventParam.Para32[0] = PhysPortIndex;
++ if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
++ continue;
++ }
++
++ EventParam.Para32[0] = PhysPortIndex;
++ EventParam.Para32[1] = (SK_U32)Val8;
++ if (SkGeSirqEvent(pAC, IoC,
++ SK_HWEV_SET_LMODE,
++ EventParam) > 0) {
++
++ SK_ERR_LOG(pAC, SK_ERRCL_SW,
++ SK_PNMI_ERR043,
++ SK_PNMI_ERR043MSG);
++
++ *pLen = 0;
++ return (SK_PNMI_ERR_GENERAL);
++ }
++ } /* for */
++ }
++ else {
++ /*
++ * Send an event with the new link mode to
++ * the SIRQ module.
++ */
++ EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS(
++ pAC, LogPortIndex);
+ EventParam.Para32[1] = (SK_U32)Val8;
+- if (SkGeSirqEvent(pAC, IoC,
+- SK_HWEV_SET_LMODE,
++ if (SkGeSirqEvent(pAC, IoC, SK_HWEV_SET_LMODE,
+ EventParam) > 0) {
+-
++
+ SK_ERR_LOG(pAC, SK_ERRCL_SW,
+ SK_PNMI_ERR043,
+ SK_PNMI_ERR043MSG);
+-
++
+ *pLen = 0;
+ return (SK_PNMI_ERR_GENERAL);
+ }
+ }
+ }
+- else {
++ else { /* DualNet mode. */
++
+ /*
+ * Send an event with the new link mode to
+ * the SIRQ module.
+ */
+- EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS(
+- pAC, LogPortIndex);
++ EventParam.Para32[0] = NetIndex;
+ EventParam.Para32[1] = (SK_U32)Val8;
+ if (SkGeSirqEvent(pAC, IoC, SK_HWEV_SET_LMODE,
+ EventParam) > 0) {
+@@ -5587,15 +5453,13 @@
+ return (SK_PNMI_ERR_GENERAL);
+ }
+ }
+- Offset += sizeof(char);
++ Offset++;
+ break;
+
+ case OID_SKGE_FLOWCTRL_MODE:
+- /* Check the value range */
+- Val8 = *(pBuf + Offset);
++ /* Check the value range. */
+ if (Val8 == 0) {
+-
+- Offset += sizeof(char);
++ Offset++;
+ break;
+ }
+ if (Val8 < SK_FLOW_MODE_NONE ||
+@@ -5606,30 +5470,48 @@
+ return (SK_PNMI_ERR_BAD_VALUE);
+ }
+
+- /* The preset ends here */
++ /* The PRESET ends here. */
+ if (Action == SK_PNMI_PRESET) {
+
+ return (SK_PNMI_ERR_OK);
+ }
+
+- if (LogPortIndex == 0) {
++ if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */
++ if (LogPortIndex == 0) {
++ /*
++ * The virtual port consists of all currently
++ * active ports. Find them and send an event
++ * with the new flow control mode to SIRQ.
++ */
++ for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax;
++ PhysPortIndex ++) {
+
+- /*
+- * The virtual port consists of all currently
+- * active ports. Find them and send an event
+- * with the new flow control mode to SIRQ.
+- */
+- for (PhysPortIndex = 0;
+- PhysPortIndex < PhysPortMax;
+- PhysPortIndex ++) {
++ if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
++ continue;
++ }
+
+- if (!pAC->Pnmi.Port[PhysPortIndex].
+- ActiveFlag) {
++ EventParam.Para32[0] = PhysPortIndex;
++ EventParam.Para32[1] = (SK_U32)Val8;
++ if (SkGeSirqEvent(pAC, IoC,
++ SK_HWEV_SET_FLOWMODE,
++ EventParam) > 0) {
++
++ SK_ERR_LOG(pAC, SK_ERRCL_SW,
++ SK_PNMI_ERR044,
++ SK_PNMI_ERR044MSG);
+
+- continue;
++ *pLen = 0;
++ return (SK_PNMI_ERR_GENERAL);
++ }
+ }
+-
+- EventParam.Para32[0] = PhysPortIndex;
++ }
++ else {
++ /*
++ * Send an event with the new flow control
++ * mode to the SIRQ module.
++ */
++ EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS(
++ pAC, LogPortIndex);
+ EventParam.Para32[1] = (SK_U32)Val8;
+ if (SkGeSirqEvent(pAC, IoC,
+ SK_HWEV_SET_FLOWMODE,
+@@ -5644,17 +5526,16 @@
+ }
+ }
+ }
+- else {
++ else { /* DualNet mode. */
++
+ /*
+- * Send an event with the new flow control
+- * mode to the SIRQ module.
++ * Send an event with the new link mode to
++ * the SIRQ module.
+ */
+- EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS(
+- pAC, LogPortIndex);
++ EventParam.Para32[0] = NetIndex;
+ EventParam.Para32[1] = (SK_U32)Val8;
+- if (SkGeSirqEvent(pAC, IoC,
+- SK_HWEV_SET_FLOWMODE, EventParam)
+- > 0) {
++ if (SkGeSirqEvent(pAC, IoC, SK_HWEV_SET_FLOWMODE,
++ EventParam) > 0) {
+
+ SK_ERR_LOG(pAC, SK_ERRCL_SW,
+ SK_PNMI_ERR044,
+@@ -5664,15 +5545,14 @@
+ return (SK_PNMI_ERR_GENERAL);
+ }
+ }
+- Offset += sizeof(char);
++ Offset++;
+ break;
+
+ case OID_SKGE_PHY_OPERATION_MODE :
+- /* Check the value range */
+- Val8 = *(pBuf + Offset);
++ /* Check the value range. */
+ if (Val8 == 0) {
+- /* mode of this port remains unchanged */
+- Offset += sizeof(char);
++ /* Mode of this port remains unchanged. */
++ Offset++;
+ break;
+ }
+ if (Val8 < SK_MS_MODE_AUTO ||
+@@ -5683,34 +5563,51 @@
+ return (SK_PNMI_ERR_BAD_VALUE);
+ }
+
+- /* The preset ends here */
++ /* The PRESET ends here. */
+ if (Action == SK_PNMI_PRESET) {
+
+ return (SK_PNMI_ERR_OK);
+ }
+
+- if (LogPortIndex == 0) {
++ if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */
++ if (LogPortIndex == 0) {
++ /*
++ * The virtual port consists of all currently
++ * active ports. Find them and send an event
++ * with new master/slave (role) mode to SIRQ.
++ */
++ for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax;
++ PhysPortIndex ++) {
+
+- /*
+- * The virtual port consists of all currently
+- * active ports. Find them and send an event
+- * with new master/slave (role) mode to SIRQ.
+- */
+- for (PhysPortIndex = 0;
+- PhysPortIndex < PhysPortMax;
+- PhysPortIndex ++) {
++ if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
++ continue;
++ }
+
+- if (!pAC->Pnmi.Port[PhysPortIndex].
+- ActiveFlag) {
++ EventParam.Para32[0] = PhysPortIndex;
++ EventParam.Para32[1] = (SK_U32)Val8;
++ if (SkGeSirqEvent(pAC, IoC,
++ SK_HWEV_SET_ROLE,
++ EventParam) > 0) {
++
++ SK_ERR_LOG(pAC, SK_ERRCL_SW,
++ SK_PNMI_ERR042,
++ SK_PNMI_ERR042MSG);
+
+- continue;
++ *pLen = 0;
++ return (SK_PNMI_ERR_GENERAL);
++ }
+ }
+-
+- EventParam.Para32[0] = PhysPortIndex;
++ }
++ else {
++ /*
++ * Send an event with the new master/slave
++ * (role) mode to the SIRQ module.
++ */
++ EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS(
++ pAC, LogPortIndex);
+ EventParam.Para32[1] = (SK_U32)Val8;
+ if (SkGeSirqEvent(pAC, IoC,
+- SK_HWEV_SET_ROLE,
+- EventParam) > 0) {
++ SK_HWEV_SET_ROLE, EventParam) > 0) {
+
+ SK_ERR_LOG(pAC, SK_ERRCL_SW,
+ SK_PNMI_ERR042,
+@@ -5721,16 +5618,16 @@
+ }
+ }
+ }
+- else {
++ else { /* DualNet mode. */
++
+ /*
+- * Send an event with the new master/slave
+- * (role) mode to the SIRQ module.
++ * Send an event with the new link mode to
++ * the SIRQ module.
+ */
+- EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS(
+- pAC, LogPortIndex);
++ EventParam.Para32[0] = NetIndex;
+ EventParam.Para32[1] = (SK_U32)Val8;
+- if (SkGeSirqEvent(pAC, IoC,
+- SK_HWEV_SET_ROLE, EventParam) > 0) {
++ if (SkGeSirqEvent(pAC, IoC, SK_HWEV_SET_ROLE,
++ EventParam) > 0) {
+
+ SK_ERR_LOG(pAC, SK_ERRCL_SW,
+ SK_PNMI_ERR042,
+@@ -5740,16 +5637,13 @@
+ return (SK_PNMI_ERR_GENERAL);
+ }
+ }
+-
+- Offset += sizeof(char);
++ Offset++;
+ break;
+
+ case OID_SKGE_SPEED_MODE:
+- /* Check the value range */
+- Val8 = *(pBuf + Offset);
++ /* Check the value range. */
+ if (Val8 == 0) {
+-
+- Offset += sizeof(char);
++ Offset++;
+ break;
+ }
+ if (Val8 < (SK_LSPEED_AUTO) ||
+@@ -5760,29 +5654,49 @@
+ return (SK_PNMI_ERR_BAD_VALUE);
+ }
+
+- /* The preset ends here */
++ /* The PRESET ends here. */
+ if (Action == SK_PNMI_PRESET) {
+
+ return (SK_PNMI_ERR_OK);
+ }
+
+- if (LogPortIndex == 0) {
++ if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */
++ if (LogPortIndex == 0) {
+
+- /*
+- * The virtual port consists of all currently
+- * active ports. Find them and send an event
+- * with the new flow control mode to SIRQ.
+- */
+- for (PhysPortIndex = 0;
+- PhysPortIndex < PhysPortMax;
+- PhysPortIndex ++) {
++ /*
++ * The virtual port consists of all currently
++ * active ports. Find them and send an event
++ * with the new flow control mode to SIRQ.
++ */
++ for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax;
++ PhysPortIndex ++) {
+
+- if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
++ if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
++ continue;
++ }
+
+- continue;
+- }
++ EventParam.Para32[0] = PhysPortIndex;
++ EventParam.Para32[1] = (SK_U32)Val8;
++ if (SkGeSirqEvent(pAC, IoC,
++ SK_HWEV_SET_SPEED,
++ EventParam) > 0) {
++
++ SK_ERR_LOG(pAC, SK_ERRCL_SW,
++ SK_PNMI_ERR045,
++ SK_PNMI_ERR045MSG);
+
+- EventParam.Para32[0] = PhysPortIndex;
++ *pLen = 0;
++ return (SK_PNMI_ERR_GENERAL);
++ }
++ }
++ }
++ else {
++ /*
++ * Send an event with the new flow control
++ * mode to the SIRQ module.
++ */
++ EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS(
++ pAC, LogPortIndex);
+ EventParam.Para32[1] = (SK_U32)Val8;
+ if (SkGeSirqEvent(pAC, IoC,
+ SK_HWEV_SET_SPEED,
+@@ -5797,16 +5711,15 @@
+ }
+ }
+ }
+- else {
++ else { /* DualNet mode. */
++
+ /*
+- * Send an event with the new flow control
+- * mode to the SIRQ module.
++ * Send an event with the new link mode to
++ * the SIRQ module.
+ */
+- EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS(
+- pAC, LogPortIndex);
++ EventParam.Para32[0] = NetIndex;
+ EventParam.Para32[1] = (SK_U32)Val8;
+- if (SkGeSirqEvent(pAC, IoC,
+- SK_HWEV_SET_SPEED,
++ if (SkGeSirqEvent(pAC, IoC, SK_HWEV_SET_SPEED,
+ EventParam) > 0) {
+
+ SK_ERR_LOG(pAC, SK_ERRCL_SW,
+@@ -5817,23 +5730,25 @@
+ return (SK_PNMI_ERR_GENERAL);
+ }
+ }
+- Offset += sizeof(char);
++ Offset++;
+ break;
+
+- case OID_SKGE_MTU :
+- /* Check the value range */
+- Val32 = *(SK_U32*)(pBuf + Offset);
++ case OID_SKGE_MTU:
++ /* Check the value range. */
++ SK_PNMI_READ_U32((pBuf + Offset), Val32);
++
+ if (Val32 == 0) {
+- /* mtu of this port remains unchanged */
++ /* MTU of this port remains unchanged. */
+ Offset += sizeof(SK_U32);
+ break;
+ }
++
+ if (SK_DRIVER_PRESET_MTU(pAC, IoC, NetIndex, Val32) != 0) {
+ *pLen = 0;
+ return (SK_PNMI_ERR_BAD_VALUE);
+ }
+
+- /* The preset ends here */
++ /* The PRESET ends here. */
+ if (Action == SK_PNMI_PRESET) {
+ return (SK_PNMI_ERR_OK);
+ }
+@@ -5844,116 +5759,69 @@
+
+ Offset += sizeof(SK_U32);
+ break;
+-
++
+ #ifdef SK_PHY_LP_MODE
+ case OID_SKGE_PHY_LP_MODE:
+- /* The preset ends here */
++ /* The PRESET ends here. */
+ if (Action == SK_PNMI_PRESET) {
+
+ return (SK_PNMI_ERR_OK);
+ }
+
+- if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
++ if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNet mode. */
+ if (LogPortIndex == 0) {
+ Offset = 0;
+ continue;
+ }
+- else {
+- /* Set value for physical ports */
+- PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex);
+-
+- switch (*(pBuf + Offset)) {
+- case 0:
+- /* If LowPowerMode is active, we can leave it. */
+- if (pAC->GIni.GP[PhysPortIndex].PPhyPowerState) {
+-
+- Val32 = SkGmLeaveLowPowerMode(pAC, IoC, PhysPortIndex);
+-
+- if (pAC->GIni.GP[PhysPortIndex].PPhyPowerState < 3) {
+-
+- SkDrvInitAdapter(pAC);
+- }
+- break;
+- }
+- else {
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
+- }
+- case 1:
+- case 2:
+- case 3:
+- case 4:
+- /* If no LowPowerMode is active, we can enter it. */
+- if (!pAC->GIni.GP[PhysPortIndex].PPhyPowerState) {
+-
+- if ((*(pBuf + Offset)) < 3) {
+-
+- SkDrvDeInitAdapter(pAC);
+- }
+-
+- Val32 = SkGmEnterLowPowerMode(pAC, IoC, PhysPortIndex, *pBuf);
+- break;
+- }
+- else {
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
+- }
+- default:
+- *pLen = 0;
+- return (SK_PNMI_ERR_BAD_VALUE);
+- }
+- }
+ }
+- else { /* DualNetMode */
+-
+- switch (*(pBuf + Offset)) {
+- case 0:
+- /* If we are in a LowPowerMode, we can leave it. */
+- if (pAC->GIni.GP[PhysPortIndex].PPhyPowerState) {
++ /* Set value for physical port. */
++ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex);
++ CurrentPhyPowerState = pAC->GIni.GP[PhysPortIndex].PPhyPowerState;
+
+- Val32 = SkGmLeaveLowPowerMode(pAC, IoC, PhysPortIndex);
+-
+- if (pAC->GIni.GP[PhysPortIndex].PPhyPowerState < 3) {
++ switch (Val8) {
++ case PHY_PM_OPERATIONAL_MODE:
++ /* If LowPowerMode is active, we can leave it. */
++ if (CurrentPhyPowerState) {
+
+- SkDrvInitAdapter(pAC);
+- }
+- break;
+- }
+- else {
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
+- }
+-
+- case 1:
+- case 2:
+- case 3:
+- case 4:
+- /* If we are not already in LowPowerMode, we can enter it. */
+- if (!pAC->GIni.GP[PhysPortIndex].PPhyPowerState) {
+-
+- if ((*(pBuf + Offset)) < 3) {
+-
+- SkDrvDeInitAdapter(pAC);
+- }
+- else {
+-
+- Val32 = SkGmEnterLowPowerMode(pAC, IoC, PhysPortIndex, *pBuf);
+- }
+- break;
+- }
+- else {
+- *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
++ Val32 = SkGmLeaveLowPowerMode(pAC, IoC, PhysPortIndex);
++
++ if ((CurrentPhyPowerState == PHY_PM_DEEP_SLEEP) ||
++ (CurrentPhyPowerState == PHY_PM_IEEE_POWER_DOWN)) {
++
++ SkDrvInitAdapter(pAC);
+ }
+-
+- default:
++ break;
++ }
++ else {
+ *pLen = 0;
+- return (SK_PNMI_ERR_BAD_VALUE);
+- }
++ return (SK_PNMI_ERR_GENERAL);
++ }
++ case PHY_PM_DEEP_SLEEP:
++ case PHY_PM_IEEE_POWER_DOWN:
++ /* If no LowPowerMode is active, we can enter it. */
++ if (!CurrentPhyPowerState) {
++ SkDrvDeInitAdapter(pAC);
++ }
++
++ case PHY_PM_ENERGY_DETECT:
++ case PHY_PM_ENERGY_DETECT_PLUS:
++ /* If no LowPowerMode is active, we can enter it. */
++ if (!CurrentPhyPowerState) {
++
++ Val32 = SkGmEnterLowPowerMode(pAC, IoC, PhysPortIndex, *pBuf);
++ break;
++ }
++ else {
++ *pLen = 0;
++ return (SK_PNMI_ERR_GENERAL);
++ }
++ default:
++ *pLen = 0;
++ return (SK_PNMI_ERR_BAD_VALUE);
+ }
+- Offset += sizeof(SK_U8);
++ Offset++;
+ break;
+-#endif
++#endif /* SK_PHY_LP_MODE */
+
+ default:
+ SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR,
+@@ -6003,14 +5871,11 @@
+ unsigned int Limit;
+ unsigned int Offset;
+ unsigned int Entries;
+-
+
+- /*
+- * Calculate instance if wished.
+- */
+- /* XXX Not yet implemented. Return always an empty table. */
++ /* Not implemented yet. Return always an empty table. */
+ Entries = 0;
+
++ /* Calculate instance if wished. */
+ if ((Instance != (SK_U32)(-1))) {
+
+ if ((Instance < 1) || (Instance > Entries)) {
+@@ -6027,12 +5892,10 @@
+ Limit = Entries;
+ }
+
+- /*
+- * Get/Set value
+- */
++ /* GET/SET value. */
+ if (Action == SK_PNMI_GET) {
+
+- for (Offset=0; Index < Limit; Index ++) {
++ for (Offset = 0; Index < Limit; Index ++) {
+
+ switch (Id) {
+
+@@ -6054,32 +5917,29 @@
+ *pLen = Offset;
+ }
+ else {
+- /* Only MONITOR_ADMIN can be set */
++ /* Only MONITOR_ADMIN can be set. */
+ if (Id != OID_SKGE_RLMT_MONITOR_ADMIN) {
+
+ *pLen = 0;
+ return (SK_PNMI_ERR_READ_ONLY);
+ }
+
+- /* Check if the length is plausible */
++ /* Check if the length is plausible. */
+ if (*pLen < (Limit - Index)) {
+
+ return (SK_PNMI_ERR_TOO_SHORT);
+ }
+- /* Okay, we have a wide value range */
++ /* Okay, we have a wide value range. */
+ if (*pLen != (Limit - Index)) {
+
+ *pLen = 0;
+ return (SK_PNMI_ERR_BAD_VALUE);
+ }
+-/*
+- for (Offset=0; Index < Limit; Index ++) {
+- }
+-*/
+-/*
+- * XXX Not yet implemented. Return always BAD_VALUE, because the table
+- * is empty.
+- */
++
++ /*
++ * Not yet implemented. Return always BAD_VALUE,
++ * because the table is empty.
++ */
+ *pLen = 0;
+ return (SK_PNMI_ERR_BAD_VALUE);
+ }
+@@ -6120,14 +5980,12 @@
+ PortActiveFlag = SK_FALSE;
+ PhysPortMax = pAC->GIni.GIMacsFound;
+
+- for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax;
+- PhysPortIndex ++) {
++ for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax; PhysPortIndex ++) {
+
+ pPrt = &pAC->GIni.GP[PhysPortIndex];
+
+- /* Check if the physical port is active */
++ /* Check if the physical port is active. */
+ if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
+-
+ continue;
+ }
+
+@@ -6136,12 +5994,13 @@
+ switch (Id) {
+
+ case OID_SKGE_PHY_TYPE:
+- /* Check if it is the first active port */
++ /* Check if it is the first active port. */
+ if (*pBuf == 0) {
+ Val32 = pPrt->PhyType;
+ SK_PNMI_STORE_U32(pBuf, Val32);
+ continue;
+ }
++ break;
+
+ case OID_SKGE_LINK_CAP:
+
+@@ -6155,7 +6014,7 @@
+ break;
+
+ case OID_SKGE_LINK_MODE:
+- /* Check if it is the first active port */
++ /* Check if it is the first active port. */
+ if (*pBuf == 0) {
+
+ *pBuf = pPrt->PLinkModeConf;
+@@ -6163,9 +6022,8 @@
+ }
+
+ /*
+- * If we find an active port with a different link
+- * mode than the first one we return a value that
+- * indicates that the link mode is indeterminated.
++ * If we find an active port with a different link mode
++ * than the first one we return indeterminated.
+ */
+ if (*pBuf != pPrt->PLinkModeConf) {
+
+@@ -6174,10 +6032,10 @@
+ break;
+
+ case OID_SKGE_LINK_MODE_STATUS:
+- /* Get the link mode of the physical port */
++ /* Get the link mode of the physical port. */
+ Val8 = CalculateLinkModeStatus(pAC, IoC, PhysPortIndex);
+
+- /* Check if it is the first active port */
++ /* Check if it is the first active port. */
+ if (*pBuf == 0) {
+
+ *pBuf = Val8;
+@@ -6185,10 +6043,8 @@
+ }
+
+ /*
+- * If we find an active port with a different link
+- * mode status than the first one we return a value
+- * that indicates that the link mode status is
+- * indeterminated.
++ * If we find an active port with a different link mode status
++ * than the first one we return indeterminated.
+ */
+ if (*pBuf != Val8) {
+
+@@ -6197,10 +6053,10 @@
+ break;
+
+ case OID_SKGE_LINK_STATUS:
+- /* Get the link status of the physical port */
++ /* Get the link status of the physical port. */
+ Val8 = CalculateLinkStatus(pAC, IoC, PhysPortIndex);
+
+- /* Check if it is the first active port */
++ /* Check if it is the first active port. */
+ if (*pBuf == 0) {
+
+ *pBuf = Val8;
+@@ -6208,10 +6064,8 @@
+ }
+
+ /*
+- * If we find an active port with a different link
+- * status than the first one, we return a value
+- * that indicates that the link status is
+- * indeterminated.
++ * If we find an active port with a different link status
++ * than the first one we return indeterminated.
+ */
+ if (*pBuf != Val8) {
+
+@@ -6220,7 +6074,7 @@
+ break;
+
+ case OID_SKGE_FLOWCTRL_CAP:
+- /* Check if it is the first active port */
++ /* Check if it is the first active port. */
+ if (*pBuf == 0) {
+
+ *pBuf = pPrt->PFlowCtrlCap;
+@@ -6235,7 +6089,7 @@
+ break;
+
+ case OID_SKGE_FLOWCTRL_MODE:
+- /* Check if it is the first active port */
++ /* Check if it is the first active port. */
+ if (*pBuf == 0) {
+
+ *pBuf = pPrt->PFlowCtrlMode;
+@@ -6243,9 +6097,8 @@
+ }
+
+ /*
+- * If we find an active port with a different flow
+- * control mode than the first one, we return a value
+- * that indicates that the mode is indeterminated.
++ * If we find an active port with a different flow-control mode
++ * than the first one we return indeterminated.
+ */
+ if (*pBuf != pPrt->PFlowCtrlMode) {
+
+@@ -6254,7 +6107,7 @@
+ break;
+
+ case OID_SKGE_FLOWCTRL_STATUS:
+- /* Check if it is the first active port */
++ /* Check if it is the first active port. */
+ if (*pBuf == 0) {
+
+ *pBuf = pPrt->PFlowCtrlStatus;
+@@ -6262,10 +6115,8 @@
+ }
+
+ /*
+- * If we find an active port with a different flow
+- * control status than the first one, we return a
+- * value that indicates that the status is
+- * indeterminated.
++ * If we find an active port with a different flow-control status
++ * than the first one we return indeterminated.
+ */
+ if (*pBuf != pPrt->PFlowCtrlStatus) {
+
+@@ -6274,7 +6125,7 @@
+ break;
+
+ case OID_SKGE_PHY_OPERATION_CAP:
+- /* Check if it is the first active port */
++ /* Check if it is the first active port. */
+ if (*pBuf == 0) {
+
+ *pBuf = pPrt->PMSCap;
+@@ -6289,7 +6140,7 @@
+ break;
+
+ case OID_SKGE_PHY_OPERATION_MODE:
+- /* Check if it is the first active port */
++ /* Check if it is the first active port. */
+ if (*pBuf == 0) {
+
+ *pBuf = pPrt->PMSMode;
+@@ -6297,9 +6148,8 @@
+ }
+
+ /*
+- * If we find an active port with a different master/
+- * slave mode than the first one, we return a value
+- * that indicates that the mode is indeterminated.
++ * If we find an active port with a different master/slave mode
++ * than the first one we return indeterminated.
+ */
+ if (*pBuf != pPrt->PMSMode) {
+
+@@ -6308,7 +6158,7 @@
+ break;
+
+ case OID_SKGE_PHY_OPERATION_STATUS:
+- /* Check if it is the first active port */
++ /* Check if it is the first active port. */
+ if (*pBuf == 0) {
+
+ *pBuf = pPrt->PMSStatus;
+@@ -6316,10 +6166,8 @@
+ }
+
+ /*
+- * If we find an active port with a different master/
+- * slave status than the first one, we return a
+- * value that indicates that the status is
+- * indeterminated.
++ * If we find an active port with a different master/slave status
++ * than the first one we return indeterminated.
+ */
+ if (*pBuf != pPrt->PMSStatus) {
+
+@@ -6328,7 +6176,7 @@
+ break;
+
+ case OID_SKGE_SPEED_MODE:
+- /* Check if it is the first active port */
++ /* Check if it is the first active port. */
+ if (*pBuf == 0) {
+
+ *pBuf = pPrt->PLinkSpeed;
+@@ -6336,9 +6184,8 @@
+ }
+
+ /*
+- * If we find an active port with a different flow
+- * control mode than the first one, we return a value
+- * that indicates that the mode is indeterminated.
++ * If we find an active port with a different link speed
++ * than the first one we return indeterminated.
+ */
+ if (*pBuf != pPrt->PLinkSpeed) {
+
+@@ -6347,7 +6194,7 @@
+ break;
+
+ case OID_SKGE_SPEED_STATUS:
+- /* Check if it is the first active port */
++ /* Check if it is the first active port. */
+ if (*pBuf == 0) {
+
+ *pBuf = pPrt->PLinkSpeedUsed;
+@@ -6355,10 +6202,8 @@
+ }
+
+ /*
+- * If we find an active port with a different flow
+- * control status than the first one, we return a
+- * value that indicates that the status is
+- * indeterminated.
++ * If we find an active port with a different link speed used
++ * than the first one we return indeterminated.
+ */
+ if (*pBuf != pPrt->PLinkSpeedUsed) {
+
+@@ -6368,9 +6213,7 @@
+ }
+ }
+
+- /*
+- * If no port is active return an indeterminated answer
+- */
++ /* If no port is active return an indeterminated answer. */
+ if (!PortActiveFlag) {
+
+ switch (Id) {
+@@ -6487,16 +6330,15 @@
+ {
+ SK_U8 Result;
+
+- /* Get the current mode, which can be full or half duplex */
++ /* Get the current mode, which can be full or half duplex. */
+ Result = pAC->GIni.GP[PhysPortIndex].PLinkModeStatus;
+
+- /* Check if no valid mode could be found (link is down) */
++ /* Check if no valid mode could be found (link is down). */
+ if (Result < SK_LMODE_STAT_HALF) {
+
+ Result = SK_LMODE_STAT_UNKNOWN;
+ }
+ else if (pAC->GIni.GP[PhysPortIndex].PLinkMode >= SK_LMODE_AUTOHALF) {
+-
+ /*
+ * Auto-negotiation was used to bring up the link. Change
+ * the already found duplex status that it indicates
+@@ -6541,22 +6383,22 @@
+ int Index;
+ int Ret;
+
+-
+ SK_MEMSET(pKeyArr, 0, KeyArrLen);
+
+- /*
+- * Get VPD key list
+- */
+- Ret = VpdKeys(pAC, IoC, (char *)&BufKeys, (int *)&BufKeysLen,
++ /* Get VPD key list. */
++ Ret = VpdKeys(pAC, IoC, BufKeys, (int *)&BufKeysLen,
+ (int *)pKeyNo);
++
+ if (Ret > 0) {
+
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR014,
+- SK_PNMI_ERR014MSG);
++ SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
++ (SK_PNMI_ERR014MSG));
+
++ /* Please read comment in Vpd(). */
++ pAC->Pnmi.VpdKeyReadError = SK_TRUE;
+ return (SK_PNMI_ERR_GENERAL);
+ }
+- /* If no keys are available return now */
++ /* If no keys are available return now. */
+ if (*pKeyNo == 0 || BufKeysLen == 0) {
+
+ return (SK_PNMI_ERR_OK);
+@@ -6564,12 +6406,12 @@
+ /*
+ * If the key list is too long for us trunc it and give a
+ * errorlog notification. This case should not happen because
+- * the maximum number of keys is limited due to RAM limitations
++ * the maximum number of keys is limited due to RAM limitations.
+ */
+ if (*pKeyNo > SK_PNMI_VPD_ENTRIES) {
+
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR015,
+- SK_PNMI_ERR015MSG);
++ SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
++ (SK_PNMI_ERR015MSG));
+
+ *pKeyNo = SK_PNMI_VPD_ENTRIES;
+ }
+@@ -6582,14 +6424,14 @@
+ Offset ++) {
+
+ if (BufKeys[Offset] != 0) {
+-
+ continue;
+ }
+
+ if (Offset - StartOffset > SK_PNMI_VPD_KEY_SIZE) {
+
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR016,
+- SK_PNMI_ERR016MSG);
++ SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
++ (SK_PNMI_ERR016MSG));
++
+ return (SK_PNMI_ERR_GENERAL);
+ }
+
+@@ -6600,7 +6442,7 @@
+ StartOffset = Offset + 1;
+ }
+
+- /* Last key not zero terminated? Get it anyway */
++ /* Last key not zero terminated? Get it anyway. */
+ if (StartOffset < Offset) {
+
+ SK_STRNCPY(pKeyArr + Index * SK_PNMI_VPD_KEY_SIZE,
+@@ -6629,19 +6471,18 @@
+ {
+ SK_EVPARA EventParam;
+
+-
+ /* Was the module already updated during the current PNMI call? */
+ if (pAC->Pnmi.SirqUpdatedFlag > 0) {
+
+ return (SK_PNMI_ERR_OK);
+ }
+
+- /* Send an synchronuous update event to the module */
++ /* Send an synchronuous update event to the module. */
+ SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
+- if (SkGeSirqEvent(pAC, IoC, SK_HWEV_UPDATE_STAT, EventParam) > 0) {
++
++ if (SkGeSirqEvent(pAC, IoC, SK_HWEV_UPDATE_STAT, EventParam)) {
+
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR047,
+- SK_PNMI_ERR047MSG);
++ SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR047, SK_PNMI_ERR047MSG);
+
+ return (SK_PNMI_ERR_GENERAL);
+ }
+@@ -6669,21 +6510,19 @@
+ {
+ SK_EVPARA EventParam;
+
+-
+ /* Was the module already updated during the current PNMI call? */
+ if (pAC->Pnmi.RlmtUpdatedFlag > 0) {
+
+ return (SK_PNMI_ERR_OK);
+ }
+
+- /* Send an synchronuous update event to the module */
++ /* Send an synchronuous update event to the module. */
+ SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
+ EventParam.Para32[0] = NetIndex;
+ EventParam.Para32[1] = (SK_U32)-1;
+ if (SkRlmtEvent(pAC, IoC, SK_RLMT_STATS_UPDATE, EventParam) > 0) {
+
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR048,
+- SK_PNMI_ERR048MSG);
++ SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR048, SK_PNMI_ERR048MSG);
+
+ return (SK_PNMI_ERR_GENERAL);
+ }
+@@ -6721,20 +6560,20 @@
+ return (SK_PNMI_ERR_OK);
+ }
+
+- /* Send an update command to all MACs specified */
++ /* Send an update command to all MACs specified. */
+ for (MacIndex = FirstMac; MacIndex <= LastMac; MacIndex ++) {
+
+ /*
+ * 2002-09-13 pweber: Freeze the current SW counters.
+ * (That should be done as close as
+ * possible to the update of the
+- * HW counters)
++ * HW counters).
+ */
+ if (pAC->GIni.GIMacType == SK_MAC_XMAC) {
+ pAC->Pnmi.BufPort[MacIndex] = pAC->Pnmi.Port[MacIndex];
+ }
+
+- /* 2002-09-13 pweber: Update the HW counter */
++ /* 2002-09-13 pweber: Update the HW counter. */
+ if (pAC->GIni.GIFunc.pFnMacUpdateStats(pAC, IoC, MacIndex) != 0) {
+
+ return (SK_PNMI_ERR_GENERAL);
+@@ -6772,19 +6611,19 @@
+ SK_U64 Val = 0;
+
+
+- if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */
++ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* DualNet mode. */
+
+ PhysPortIndex = NetIndex;
+
+ Val = GetPhysStatVal(pAC, IoC, PhysPortIndex, StatIndex);
+ }
+- else { /* Single Net mode */
++ else { /* SingleNet mode. */
+
+ if (LogPortIndex == 0) {
+
+ PhysPortMax = pAC->GIni.GIMacsFound;
+
+- /* Add counter of all active ports */
++ /* Add counter of all active ports. */
+ for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax;
+ PhysPortIndex ++) {
+
+@@ -6794,11 +6633,11 @@
+ }
+ }
+
+- /* Correct value because of port switches */
++ /* Correct value because of port switches. */
+ Val += pAC->Pnmi.VirtualCounterOffset[StatIndex];
+ }
+ else {
+- /* Get counter value of physical port */
++ /* Get counter value of physical port. */
+ PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex);
+
+ Val = GetPhysStatVal(pAC, IoC, PhysPortIndex, StatIndex);
+@@ -6844,7 +6683,7 @@
+
+ MacType = pAC->GIni.GIMacType;
+
+- /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
++ /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort). */
+ if (MacType == SK_MAC_XMAC) {
+ pPnmiPrt = &pAC->Pnmi.BufPort[PhysPortIndex];
+ }
+@@ -6912,7 +6751,7 @@
+ case SK_PNMI_HTX_BURST:
+ case SK_PNMI_HTX_EXCESS_DEF:
+ case SK_PNMI_HTX_CARRIER:
+- /* Not supported by GMAC */
++ /* Not supported by GMAC. */
+ if (MacType == SK_MAC_GMAC) {
+ return (Val);
+ }
+@@ -6924,7 +6763,7 @@
+ break;
+
+ case SK_PNMI_HTX_MACC:
+- /* GMAC only supports PAUSE MAC control frames */
++ /* GMAC only supports PAUSE MAC control frames. */
+ if (MacType == SK_MAC_GMAC) {
+ HelpIndex = SK_PNMI_HTX_PMACC;
+ }
+@@ -6941,7 +6780,7 @@
+
+ case SK_PNMI_HTX_COL:
+ case SK_PNMI_HRX_UNDERSIZE:
+- /* Not supported by XMAC */
++ /* Not supported by XMAC. */
+ if (MacType == SK_MAC_XMAC) {
+ return (Val);
+ }
+@@ -6953,7 +6792,7 @@
+ break;
+
+ case SK_PNMI_HTX_DEFFERAL:
+- /* Not supported by GMAC */
++ /* Not supported by GMAC. */
+ if (MacType == SK_MAC_GMAC) {
+ return (Val);
+ }
+@@ -6971,7 +6810,7 @@
+ HighVal = 0;
+ }
+ else {
+- /* Otherwise get contents of hardware register */
++ /* Otherwise get contents of hardware register. */
+ (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+ StatAddr[StatIndex][MacType].Reg,
+ &LowVal);
+@@ -6980,7 +6819,7 @@
+ break;
+
+ case SK_PNMI_HRX_BADOCTET:
+- /* Not supported by XMAC */
++ /* Not supported by XMAC. */
+ if (MacType == SK_MAC_XMAC) {
+ return (Val);
+ }
+@@ -6999,7 +6838,7 @@
+ return (Val);
+
+ case SK_PNMI_HRX_LONGFRAMES:
+- /* For XMAC the SW counter is managed by PNMI */
++ /* For XMAC the SW counter is managed by PNMI. */
+ if (MacType == SK_MAC_XMAC) {
+ return (pPnmiPrt->StatRxLongFrameCts);
+ }
+@@ -7019,7 +6858,7 @@
+ Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal);
+
+ if (MacType == SK_MAC_GMAC) {
+- /* For GMAC the SW counter is additionally managed by PNMI */
++ /* For GMAC the SW counter is additionally managed by PNMI. */
+ Val += pPnmiPrt->StatRxFrameTooLongCts;
+ }
+ else {
+@@ -7037,20 +6876,19 @@
+ break;
+
+ case SK_PNMI_HRX_SHORTS:
+- /* Not supported by GMAC */
++ /* Not supported by GMAC. */
+ if (MacType == SK_MAC_GMAC) {
+ /* GM_RXE_FRAG?? */
+ return (Val);
+ }
+
+ /*
+- * XMAC counts short frame errors even if link down (#10620)
+- *
+- * If link-down the counter remains constant
++ * XMAC counts short frame errors even if link down (#10620).
++ * If the link is down, the counter remains constant.
+ */
+ if (pPrt->PLinkModeStatus != SK_LMODE_STAT_UNKNOWN) {
+
+- /* Otherwise get incremental difference */
++ /* Otherwise get incremental difference. */
+ (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+ StatAddr[StatIndex][MacType].Reg,
+ &LowVal);
+@@ -7073,7 +6911,7 @@
+ case SK_PNMI_HRX_IRLENGTH:
+ case SK_PNMI_HRX_SYMBOL:
+ case SK_PNMI_HRX_CEXT:
+- /* Not supported by GMAC */
++ /* Not supported by GMAC. */
+ if (MacType == SK_MAC_GMAC) {
+ return (Val);
+ }
+@@ -7085,7 +6923,7 @@
+ break;
+
+ case SK_PNMI_HRX_PMACC_ERR:
+- /* For GMAC the SW counter is managed by PNMI */
++ /* For GMAC the SW counter is managed by PNMI. */
+ if (MacType == SK_MAC_GMAC) {
+ return (pPnmiPrt->StatRxPMaccErr);
+ }
+@@ -7096,13 +6934,13 @@
+ HighVal = pPnmiPrt->CounterHigh[StatIndex];
+ break;
+
+- /* SW counter managed by PNMI */
++ /* SW counter managed by PNMI. */
+ case SK_PNMI_HTX_SYNC:
+ LowVal = (SK_U32)pPnmiPrt->StatSyncCts;
+ HighVal = (SK_U32)(pPnmiPrt->StatSyncCts >> 32);
+ break;
+
+- /* SW counter managed by PNMI */
++ /* SW counter managed by PNMI. */
+ case SK_PNMI_HTX_SYNC_OCTET:
+ LowVal = (SK_U32)pPnmiPrt->StatSyncOctetsCts;
+ HighVal = (SK_U32)(pPnmiPrt->StatSyncOctetsCts >> 32);
+@@ -7110,17 +6948,19 @@
+
+ case SK_PNMI_HRX_FCS:
+ /*
+- * Broadcom filters FCS errors and counts it in
+- * Receive Error Counter register
++ * Broadcom filters FCS errors and counts them in
++ * Receive Error Counter register.
+ */
+ if (pPrt->PhyType == SK_PHY_BCOM) {
+- /* do not read while not initialized (PHY_READ hangs!)*/
++#ifdef GENESIS
++ /* Do not read while not initialized (PHY_READ hangs!). */
+ if (pPrt->PState != SK_PRT_RESET) {
+ SkXmPhyRead(pAC, IoC, PhysPortIndex, PHY_BCOM_RE_CTR, &Word);
+
+ LowVal = Word;
+ }
+ HighVal = pPnmiPrt->CounterHigh[StatIndex];
++#endif /* GENESIS */
+ }
+ else {
+ (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
+@@ -7140,7 +6980,7 @@
+
+ Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal);
+
+- /* Correct value because of possible XMAC reset. XMAC Errata #2 */
++ /* Correct value because of possible XMAC reset (XMAC Errata #2). */
+ Val += pPnmiPrt->CounterOffset[StatIndex];
+
+ return (Val);
+@@ -7165,22 +7005,21 @@
+ unsigned int PhysPortIndex;
+ SK_EVPARA EventParam;
+
+-
+ SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
+
+- /* Notify sensor module */
++ /* Notify sensor module. */
+ SkEventQueue(pAC, SKGE_I2C, SK_I2CEV_CLEAR, EventParam);
+
+- /* Notify RLMT module */
++ /* Notify RLMT module. */
+ EventParam.Para32[0] = NetIndex;
+ EventParam.Para32[1] = (SK_U32)-1;
+ SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STATS_CLEAR, EventParam);
+ EventParam.Para32[1] = 0;
+
+- /* Notify SIRQ module */
++ /* Notify SIRQ module. */
+ SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_CLEAR_STAT, EventParam);
+
+- /* Notify CSUM module */
++ /* Notify CSUM module. */
+ #ifdef SK_USE_CSUM
+ EventParam.Para32[0] = NetIndex;
+ EventParam.Para32[1] = (SK_U32)-1;
+@@ -7188,7 +7027,7 @@
+ EventParam);
+ #endif /* SK_USE_CSUM */
+
+- /* Clear XMAC statistic */
++ /* Clear XMAC statistics. */
+ for (PhysPortIndex = 0; PhysPortIndex <
+ (unsigned int)pAC->GIni.GIMacsFound; PhysPortIndex ++) {
+
+@@ -7215,13 +7054,13 @@
+ PhysPortIndex].StatRxPMaccErr));
+ }
+
+- /*
+- * Clear local statistics
+- */
++ /* Clear local statistics. */
+ SK_MEMSET((char *)&pAC->Pnmi.VirtualCounterOffset, 0,
+ sizeof(pAC->Pnmi.VirtualCounterOffset));
++
+ pAC->Pnmi.RlmtChangeCts = 0;
+ pAC->Pnmi.RlmtChangeTime = 0;
++
+ SK_MEMSET((char *)&pAC->Pnmi.RlmtChangeEstimate.EstValue[0], 0,
+ sizeof(pAC->Pnmi.RlmtChangeEstimate.EstValue));
+ pAC->Pnmi.RlmtChangeEstimate.EstValueIndex = 0;
+@@ -7258,23 +7097,21 @@
+ SK_U32 TrapId, /* SNMP ID of the trap */
+ unsigned int Size) /* Space needed for trap entry */
+ {
+- unsigned int BufPad = pAC->Pnmi.TrapBufPad;
+- unsigned int BufFree = pAC->Pnmi.TrapBufFree;
+- unsigned int Beg = pAC->Pnmi.TrapQueueBeg;
+- unsigned int End = pAC->Pnmi.TrapQueueEnd;
++ unsigned int BufPad = pAC->Pnmi.TrapBufPad;
++ unsigned int BufFree = pAC->Pnmi.TrapBufFree;
++ unsigned int Beg = pAC->Pnmi.TrapQueueBeg;
++ unsigned int End = pAC->Pnmi.TrapQueueEnd;
+ char *pBuf = &pAC->Pnmi.TrapBuf[0];
+ int Wrap;
+- unsigned int NeededSpace;
+- unsigned int EntrySize;
++ unsigned int NeededSpace;
++ unsigned int EntrySize;
+ SK_U32 Val32;
+ SK_U64 Val64;
+
+-
+- /* Last byte of entry will get a copy of the entry length */
++ /* Last byte of entry will get a copy of the entry length. */
+ Size ++;
+
+- /*
+- * Calculate needed buffer space */
++ /* Calculate needed buffer space. */
+ if (Beg >= Size) {
+
+ NeededSpace = Size;
+@@ -7289,7 +7126,7 @@
+ * Check if enough buffer space is provided. Otherwise
+ * free some entries. Leave one byte space between begin
+ * and end of buffer to make it possible to detect whether
+- * the buffer is full or empty
++ * the buffer is full or empty.
+ */
+ while (BufFree < NeededSpace + 1) {
+
+@@ -7328,13 +7165,13 @@
+ }
+ BufFree -= NeededSpace;
+
+- /* Save the current offsets */
++ /* Save the current offsets. */
+ pAC->Pnmi.TrapQueueBeg = Beg;
+ pAC->Pnmi.TrapQueueEnd = End;
+ pAC->Pnmi.TrapBufPad = BufPad;
+ pAC->Pnmi.TrapBufFree = BufFree;
+
+- /* Initialize the trap entry */
++ /* Initialize the trap entry. */
+ *(pBuf + Beg + Size - 1) = (char)Size;
+ *(pBuf + Beg) = (char)Size;
+ Val32 = (pAC->Pnmi.TrapUnique) ++;
+@@ -7369,7 +7206,6 @@
+ unsigned int Len;
+ unsigned int DstOff = 0;
+
+-
+ while (Trap != End) {
+
+ Len = (unsigned int)*(pBuf + Trap);
+@@ -7414,7 +7250,6 @@
+ unsigned int Entries = 0;
+ unsigned int TotalLen = 0;
+
+-
+ while (Trap != End) {
+
+ Len = (unsigned int)*(pBuf + Trap);
+@@ -7471,14 +7306,14 @@
+ unsigned int DescrLen;
+ SK_U32 Val32;
+
+-
+- /* Get trap buffer entry */
++ /* Get trap buffer entry. */
+ DescrLen = SK_STRLEN(pAC->I2c.SenTable[SensorIndex].SenDesc);
++
+ pBuf = GetTrapEntry(pAC, TrapId,
+ SK_PNMI_TRAP_SENSOR_LEN_BASE + DescrLen);
+ Offset = SK_PNMI_TRAP_SIMPLE_LEN;
+
+- /* Store additionally sensor trap related data */
++ /* Store additionally sensor trap related data. */
+ Val32 = OID_SKGE_SENSOR_INDEX;
+ SK_PNMI_STORE_U32(pBuf + Offset, Val32);
+ *(pBuf + Offset + 4) = 4;
+@@ -7523,7 +7358,6 @@
+ char *pBuf;
+ SK_U32 Val32;
+
+-
+ pBuf = GetTrapEntry(pAC, OID_SKGE_TRAP_RLMT_CHANGE_PORT,
+ SK_PNMI_TRAP_RLMT_CHANGE_LEN);
+
+@@ -7551,7 +7385,6 @@
+ char *pBuf;
+ SK_U32 Val32;
+
+-
+ pBuf = GetTrapEntry(pAC, TrapId, SK_PNMI_TRAP_RLMT_PORT_LEN);
+
+ Val32 = OID_SKGE_RLMT_PORT_INDEX;
+@@ -7571,12 +7404,11 @@
+ * Nothing
+ */
+ PNMI_STATIC void CopyMac(
+-char *pDst, /* Pointer to destination buffer */
++char *pDst, /* Pointer to destination buffer */
+ SK_MAC_ADDR *pMac) /* Pointer of Source */
+ {
+ int i;
+
+-
+ for (i = 0; i < sizeof(SK_MAC_ADDR); i ++) {
+
+ *(pDst + i) = pMac->a[i];
+@@ -7616,17 +7448,14 @@
+
+ SK_U32 RetCode = SK_PNMI_ERR_GENERAL;
+
+- /*
+- * Check instance. We only handle single instance variables
+- */
++ /* Check instance. We only handle single instance variables. */
+ if (Instance != (SK_U32)(-1) && Instance != 1) {
+
+ *pLen = 0;
+ return (SK_PNMI_ERR_UNKNOWN_INST);
+ }
+
+-
+- /* Check length */
++ /* Check length. */
+ switch (Id) {
+
+ case OID_PNP_CAPABILITIES:
+@@ -7664,14 +7493,10 @@
+ break;
+ }
+
+- /*
+- * Perform action
+- */
++ /* Perform action. */
+ if (Action == SK_PNMI_GET) {
+
+- /*
+- * Get value
+- */
++ /* Get value. */
+ switch (Id) {
+
+ case OID_PNP_CAPABILITIES:
+@@ -7679,18 +7504,21 @@
+ break;
+
+ case OID_PNP_QUERY_POWER:
+- /* The Windows DDK describes: An OID_PNP_QUERY_POWER requests
+- the miniport to indicate whether it can transition its NIC
+- to the low-power state.
+- A miniport driver must always return NDIS_STATUS_SUCCESS
+- to a query of OID_PNP_QUERY_POWER. */
++ /*
++ * The Windows DDK describes: An OID_PNP_QUERY_POWER requests
++ * the miniport to indicate whether it can transition its NIC
++ * to the low-power state.
++ * A miniport driver must always return NDIS_STATUS_SUCCESS
++ * to a query of OID_PNP_QUERY_POWER.
++ */
+ *pLen = sizeof(SK_DEVICE_POWER_STATE);
+ RetCode = SK_PNMI_ERR_OK;
+ break;
+
+- /* NDIS handles these OIDs as write-only.
++ /*
++ * NDIS handles these OIDs as write-only.
+ * So in case of get action the buffer with written length = 0
+- * is returned
++ * is returned.
+ */
+ case OID_PNP_SET_POWER:
+ case OID_PNP_ADD_WAKE_UP_PATTERN:
+@@ -7711,13 +7539,11 @@
+ return (RetCode);
+ }
+
+-
+- /*
+- * Perform preset or set
+- */
++ /* Perform PRESET or SET. */
+
+- /* POWER module does not support PRESET action */
++ /* The POWER module does not support PRESET action. */
+ if (Action == SK_PNMI_PRESET) {
++
+ return (SK_PNMI_ERR_OK);
+ }
+
+@@ -7749,7 +7575,7 @@
+ #ifdef SK_DIAG_SUPPORT
+ /*****************************************************************************
+ *
+- * DiagActions - OID handler function of Diagnostic driver
++ * DiagActions - OID handler function of Diagnostic driver
+ *
+ * Description:
+ * The code is simple. No description necessary.
+@@ -7776,22 +7602,17 @@
+ unsigned int TableIndex, /* Index to the Id table */
+ SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
+ {
+-
+ SK_U32 DiagStatus;
+ SK_U32 RetCode = SK_PNMI_ERR_GENERAL;
+
+- /*
+- * Check instance. We only handle single instance variables.
+- */
++ /* Check instance. We only handle single instance variables. */
+ if (Instance != (SK_U32)(-1) && Instance != 1) {
+
+ *pLen = 0;
+ return (SK_PNMI_ERR_UNKNOWN_INST);
+ }
+
+- /*
+- * Check length.
+- */
++ /* Check length. */
+ switch (Id) {
+
+ case OID_SKGE_DIAG_MODE:
+@@ -7809,10 +7630,9 @@
+ }
+
+ /* Perform action. */
+-
+- /* GET value. */
+ if (Action == SK_PNMI_GET) {
+
++ /* Get value. */
+ switch (Id) {
+
+ case OID_SKGE_DIAG_MODE:
+@@ -7827,14 +7647,15 @@
+ RetCode = SK_PNMI_ERR_GENERAL;
+ break;
+ }
+- return (RetCode);
++ return (RetCode);
+ }
+
+ /* From here SET or PRESET value. */
+
+ /* PRESET value is not supported. */
+ if (Action == SK_PNMI_PRESET) {
+- return (SK_PNMI_ERR_OK);
++
++ return (SK_PNMI_ERR_OK);
+ }
+
+ /* SET value. */
+@@ -7846,7 +7667,7 @@
+
+ /* Attach the DIAG to this adapter. */
+ case SK_DIAG_ATTACHED:
+- /* Check if we come from running */
++ /* Check if we come from running. */
+ if (pAC->Pnmi.DiagAttached == SK_DIAG_RUNNING) {
+
+ RetCode = SkDrvLeaveDiagMode(pAC);
+@@ -7881,7 +7702,7 @@
+ /* If DiagMode is not active, we can enter it. */
+ if (!pAC->DiagModeActive) {
+
+- RetCode = SkDrvEnterDiagMode(pAC);
++ RetCode = SkDrvEnterDiagMode(pAC);
+ }
+ else {
+
+@@ -7900,7 +7721,7 @@
+ break;
+
+ case SK_DIAG_IDLE:
+- /* Check if we come from running */
++ /* Check if we come from running. */
+ if (pAC->Pnmi.DiagAttached == SK_DIAG_RUNNING) {
+
+ RetCode = SkDrvLeaveDiagMode(pAC);
+@@ -7946,7 +7767,7 @@
+
+ /*****************************************************************************
+ *
+- * Vct - OID handler function of OIDs
++ * Vct - OID handler function of OIDs for Virtual Cable Tester (VCT)
+ *
+ * Description:
+ * The code is simple. No description necessary.
+@@ -7982,153 +7803,150 @@
+ SK_U32 PhysPortIndex;
+ SK_U32 Limit;
+ SK_U32 Offset;
+- SK_BOOL Link;
+- SK_U32 RetCode = SK_PNMI_ERR_GENERAL;
+- int i;
++ SK_U32 RetCode;
++ int i;
+ SK_EVPARA Para;
+- SK_U32 CableLength;
+-
+- /*
+- * Calculate the port indexes from the instance.
+- */
++
++ RetCode = SK_PNMI_ERR_GENERAL;
++
++ /* Calculate the port indexes from the instance. */
+ PhysPortMax = pAC->GIni.GIMacsFound;
+ LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax);
+-
++
+ /* Dual net mode? */
+ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+ LogPortMax--;
+ }
+-
++
+ if ((Instance != (SK_U32) (-1))) {
+- /* Check instance range. */
+- if ((Instance < 2) || (Instance > LogPortMax)) {
+- *pLen = 0;
+- return (SK_PNMI_ERR_UNKNOWN_INST);
+- }
+-
++ /*
++ * Get one instance of that OID, so check the instance range:
++ * There is no virtual port with an Instance == 1, so we get
++ * the values from one physical port only.
++ */
+ if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
+ PhysPortIndex = NetIndex;
+ }
+ else {
++ if ((Instance < 2) || (Instance > LogPortMax)) {
++ *pLen = 0;
++ return (SK_PNMI_ERR_UNKNOWN_INST);
++ }
+ PhysPortIndex = Instance - 2;
+ }
+ Limit = PhysPortIndex + 1;
+ }
+ else {
+ /*
+- * Instance == (SK_U32) (-1), get all Instances of that OID.
+- *
+- * Not implemented yet. May be used in future releases.
++ * Instance == (SK_U32) (-1), so get all instances of that OID.
++ * There is no virtual port with an Instance == 1, so we get
++ * the values from all physical ports.
+ */
+ PhysPortIndex = 0;
+ Limit = PhysPortMax;
+ }
+-
+- pPrt = &pAC->GIni.GP[PhysPortIndex];
+- if (pPrt->PHWLinkUp) {
+- Link = SK_TRUE;
+- }
+- else {
+- Link = SK_FALSE;
+- }
+-
+- /* Check MAC type */
+- if (pPrt->PhyType != SK_PHY_MARV_COPPER) {
++
++ /* Check MAC type. */
++ if ((Id != OID_SKGE_VCT_CAPABILITIES) &&
++ (pAC->GIni.GP[PhysPortIndex].PhyType != SK_PHY_MARV_COPPER)) {
+ *pLen = 0;
+- return (SK_PNMI_ERR_GENERAL);
++ return (SK_PNMI_ERR_NOT_SUPPORTED);
+ }
+-
+- /* Initialize backup data pointer. */
+- pVctBackupData = &pAC->Pnmi.VctBackup[PhysPortIndex];
+-
+- /* Check action type */
++
++ /* Check action type. */
+ if (Action == SK_PNMI_GET) {
+- /* Check length */
++ /* Check length. */
+ switch (Id) {
+-
++
+ case OID_SKGE_VCT_GET:
+ if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_PNMI_VCT)) {
+ *pLen = (Limit - PhysPortIndex) * sizeof(SK_PNMI_VCT);
+ return (SK_PNMI_ERR_TOO_SHORT);
+ }
+ break;
+-
++
+ case OID_SKGE_VCT_STATUS:
++ case OID_SKGE_VCT_CAPABILITIES:
+ if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U8)) {
+ *pLen = (Limit - PhysPortIndex) * sizeof(SK_U8);
+ return (SK_PNMI_ERR_TOO_SHORT);
+ }
+ break;
+-
++
+ default:
+ *pLen = 0;
+ return (SK_PNMI_ERR_GENERAL);
+ }
+-
+- /* Get value */
++
++ /* Get value. */
+ Offset = 0;
+ for (; PhysPortIndex < Limit; PhysPortIndex++) {
++
++ pPrt = &pAC->GIni.GP[PhysPortIndex];
++
+ switch (Id) {
+-
++
+ case OID_SKGE_VCT_GET:
+- if ((Link == SK_FALSE) &&
++ if (!pPrt->PHWLinkUp &&
+ (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING)) {
++
+ RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_FALSE);
++
+ if (RetCode == 0) {
+- pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_PENDING;
+- pAC->Pnmi.VctStatus[PhysPortIndex] |=
+- (SK_PNMI_VCT_NEW_VCT_DATA | SK_PNMI_VCT_TEST_DONE);
+-
+- /* Copy results for later use to PNMI struct. */
+- for (i = 0; i < 4; i++) {
+- if (pPrt->PMdiPairSts[i] == SK_PNMI_VCT_NORMAL_CABLE) {
+- if ((pPrt->PMdiPairLen[i] > 35) && (pPrt->PMdiPairLen[i] < 0xff)) {
+- pPrt->PMdiPairSts[i] = SK_PNMI_VCT_IMPEDANCE_MISMATCH;
+- }
+- }
+- if ((pPrt->PMdiPairLen[i] > 35) && (pPrt->PMdiPairLen[i] != 0xff)) {
+- CableLength = 1000 * (((175 * pPrt->PMdiPairLen[i]) / 210) - 28);
+- }
+- else {
+- CableLength = 0;
+- }
+- pVctBackupData->PMdiPairLen[i] = CableLength;
+- pVctBackupData->PMdiPairSts[i] = pPrt->PMdiPairSts[i];
+- }
++
++ /* VCT test is finished, so save the data. */
++ VctGetResults(pAC, IoC, PhysPortIndex);
+
+ Para.Para32[0] = PhysPortIndex;
+ Para.Para32[1] = -1;
+ SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para);
+- SkEventDispatcher(pAC, IoC);
+- }
+- else {
+- ; /* VCT test is running. */
++
++ /* SkEventDispatcher(pAC, IoC); */
+ }
+ }
+-
++
++ /* Initialize backup data pointer. */
++ pVctBackupData = &pAC->Pnmi.VctBackup[PhysPortIndex];
++
+ /* Get all results. */
+ CheckVctStatus(pAC, IoC, pBuf, Offset, PhysPortIndex);
+- Offset += sizeof(SK_U8);
++
++ Offset++;
+ *(pBuf + Offset) = pPrt->PCableLen;
+- Offset += sizeof(SK_U8);
++ Offset++;
+ for (i = 0; i < 4; i++) {
+- SK_PNMI_STORE_U32((pBuf + Offset), pVctBackupData->PMdiPairLen[i]);
++
++ SK_PNMI_STORE_U32((pBuf + Offset), pVctBackupData->MdiPairLen[i]);
+ Offset += sizeof(SK_U32);
+ }
+ for (i = 0; i < 4; i++) {
+- *(pBuf + Offset) = pVctBackupData->PMdiPairSts[i];
+- Offset += sizeof(SK_U8);
++
++ *(pBuf + Offset) = pVctBackupData->MdiPairSts[i];
++ Offset++;
+ }
+-
++
+ RetCode = SK_PNMI_ERR_OK;
+ break;
+-
++
+ case OID_SKGE_VCT_STATUS:
+ CheckVctStatus(pAC, IoC, pBuf, Offset, PhysPortIndex);
+- Offset += sizeof(SK_U8);
++
++ Offset++;
+ RetCode = SK_PNMI_ERR_OK;
+ break;
+-
++
++ case OID_SKGE_VCT_CAPABILITIES:
++ if (pPrt->PhyType != SK_PHY_MARV_COPPER) {
++ *(pBuf + Offset) = SK_PNMI_VCT_NOT_SUPPORTED;
++ }
++ else {
++ *(pBuf + Offset) = SK_PNMI_VCT_SUPPORTED;
++ }
++ Offset++;
++
++ RetCode = SK_PNMI_ERR_OK;
++ break;
++
+ default:
+ *pLen = 0;
+ return (SK_PNMI_ERR_GENERAL);
+@@ -8136,15 +7954,15 @@
+ } /* for */
+ *pLen = Offset;
+ return (RetCode);
+-
++
+ } /* if SK_PNMI_GET */
+-
++
+ /*
+ * From here SET or PRESET action. Check if the passed
+ * buffer length is plausible.
+ */
+-
+- /* Check length */
++
++ /* Check length. */
+ switch (Id) {
+ case OID_SKGE_VCT_SET:
+ if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U32)) {
+@@ -8152,42 +7970,45 @@
+ return (SK_PNMI_ERR_TOO_SHORT);
+ }
+ break;
+-
++
+ default:
+ *pLen = 0;
+ return (SK_PNMI_ERR_GENERAL);
+ }
+-
+- /*
+- * Perform preset or set.
+- */
+-
++
++ /* Perform PRESET or SET. */
++
+ /* VCT does not support PRESET action. */
+ if (Action == SK_PNMI_PRESET) {
++
+ return (SK_PNMI_ERR_OK);
+ }
+-
++
+ Offset = 0;
+ for (; PhysPortIndex < Limit; PhysPortIndex++) {
++
++ pPrt = &pAC->GIni.GP[PhysPortIndex];
++
+ switch (Id) {
+ case OID_SKGE_VCT_SET: /* Start VCT test. */
+- if (Link == SK_FALSE) {
++ if (!pPrt->PHWLinkUp) {
+ SkGeStopPort(pAC, IoC, PhysPortIndex, SK_STOP_ALL, SK_SOFT_RST);
+-
++
+ RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_TRUE);
++
+ if (RetCode == 0) { /* RetCode: 0 => Start! */
+ pAC->Pnmi.VctStatus[PhysPortIndex] |= SK_PNMI_VCT_PENDING;
+- pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_NEW_VCT_DATA;
+- pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_LINK;
+-
+- /*
+- * Start VCT timer counter.
+- */
+- SK_MEMSET((char *) &Para, 0, sizeof(Para));
++ pAC->Pnmi.VctStatus[PhysPortIndex] &=
++ ~(SK_PNMI_VCT_NEW_VCT_DATA | SK_PNMI_VCT_LINK);
++
++ /* Start VCT timer counter. */
++ SK_MEMSET((char *)&Para, 0, sizeof(Para));
+ Para.Para32[0] = PhysPortIndex;
+ Para.Para32[1] = -1;
+- SkTimerStart(pAC, IoC, &pAC->Pnmi.VctTimeout[PhysPortIndex].VctTimer,
+- 4000000, SKGE_PNMI, SK_PNMI_EVT_VCT_RESET, Para);
++
++ SkTimerStart(pAC, IoC, &pAC->Pnmi.VctTimeout[PhysPortIndex],
++ SK_PNMI_VCT_TIMER_CHECK, SKGE_PNMI, SK_PNMI_EVT_VCT_RESET, Para);
++
+ SK_PNMI_STORE_U32((pBuf + Offset), RetCode);
+ RetCode = SK_PNMI_ERR_OK;
+ }
+@@ -8203,7 +8024,7 @@
+ }
+ Offset += sizeof(SK_U32);
+ break;
+-
++
+ default:
+ *pLen = 0;
+ return (SK_PNMI_ERR_GENERAL);
+@@ -8215,6 +8036,65 @@
+ } /* Vct */
+
+
++PNMI_STATIC void VctGetResults(
++SK_AC *pAC,
++SK_IOC IoC,
++SK_U32 Port)
++{
++ SK_GEPORT *pPrt;
++ int i;
++ SK_U8 PairLen;
++ SK_U8 PairSts;
++ SK_U32 MinLength;
++ SK_U32 CableLength;
++
++ pPrt = &pAC->GIni.GP[Port];
++
++ if (pAC->GIni.GIChipId == CHIP_ID_YUKON_FE) {
++ MinLength = 25;
++ }
++ else {
++ MinLength = 35;
++ }
++
++ /* Copy results for later use to PNMI struct. */
++ for (i = 0; i < 4; i++) {
++
++ PairLen = pPrt->PMdiPairLen[i];
++
++ if (((pPrt->PLinkSpeedCap & SK_LSPEED_CAP_1000MBPS) == 0) && (i > 1)) {
++ PairSts = SK_PNMI_VCT_NOT_PRESENT;
++ }
++ else {
++ PairSts = pPrt->PMdiPairSts[i];
++ }
++
++ if ((PairSts == SK_PNMI_VCT_NORMAL_CABLE) &&
++ (PairLen > 28) && (PairLen < 0xff)) {
++
++ PairSts = SK_PNMI_VCT_IMPEDANCE_MISMATCH;
++ }
++
++ /* Ignore values <= MinLength, the linear factor is 4/5. */
++ if ((PairLen > MinLength) && (PairLen < 0xff)) {
++
++ CableLength = 1000UL * (PairLen - MinLength) * 4 / 5;
++ }
++ else {
++ /* No cable or short cable. */
++ CableLength = 0;
++ }
++
++ pAC->Pnmi.VctBackup[Port].MdiPairLen[i] = CableLength;
++ pAC->Pnmi.VctBackup[Port].MdiPairSts[i] = PairSts;
++ }
++
++ pAC->Pnmi.VctStatus[Port] &= ~SK_PNMI_VCT_PENDING;
++ pAC->Pnmi.VctStatus[Port] |= (SK_PNMI_VCT_NEW_VCT_DATA |
++ SK_PNMI_VCT_TEST_DONE);
++
++} /* GetVctResults */
++
+ PNMI_STATIC void CheckVctStatus(
+ SK_AC *pAC,
+ SK_IOC IoC,
+@@ -8224,54 +8104,57 @@
+ {
+ SK_GEPORT *pPrt;
+ SK_PNMI_VCT *pVctData;
++ SK_U8 VctStatus;
+ SK_U32 RetCode;
+-
++
+ pPrt = &pAC->GIni.GP[PhysPortIndex];
+-
++
+ pVctData = (SK_PNMI_VCT *) (pBuf + Offset);
+ pVctData->VctStatus = SK_PNMI_VCT_NONE;
+-
++
++ VctStatus = pAC->Pnmi.VctStatus[PhysPortIndex];
++
+ if (!pPrt->PHWLinkUp) {
+-
++
+ /* Was a VCT test ever made before? */
+- if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_TEST_DONE) {
+- if ((pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_LINK)) {
++ if (VctStatus & SK_PNMI_VCT_TEST_DONE) {
++ if (VctStatus & SK_PNMI_VCT_LINK) {
+ pVctData->VctStatus |= SK_PNMI_VCT_OLD_VCT_DATA;
+ }
+ else {
+ pVctData->VctStatus |= SK_PNMI_VCT_NEW_VCT_DATA;
+ }
+ }
+-
++
+ /* Check VCT test status. */
+ RetCode = SkGmCableDiagStatus(pAC,IoC, PhysPortIndex, SK_FALSE);
++
+ if (RetCode == 2) { /* VCT test is running. */
+ pVctData->VctStatus |= SK_PNMI_VCT_RUNNING;
+ }
+ else { /* VCT data was copied to pAC here. Check PENDING state. */
+- if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING) {
++ if (VctStatus & SK_PNMI_VCT_PENDING) {
+ pVctData->VctStatus |= SK_PNMI_VCT_NEW_VCT_DATA;
+ }
+ }
+-
++
+ if (pPrt->PCableLen != 0xff) { /* Old DSP value. */
+ pVctData->VctStatus |= SK_PNMI_VCT_OLD_DSP_DATA;
+ }
+ }
+ else {
+-
+ /* Was a VCT test ever made before? */
+- if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_TEST_DONE) {
++ if (VctStatus & SK_PNMI_VCT_TEST_DONE) {
+ pVctData->VctStatus &= ~SK_PNMI_VCT_NEW_VCT_DATA;
+ pVctData->VctStatus |= SK_PNMI_VCT_OLD_VCT_DATA;
+ }
+-
++
+ /* DSP only valid in 100/1000 modes. */
+- if (pAC->GIni.GP[PhysPortIndex].PLinkSpeedUsed !=
+- SK_LSPEED_STAT_10MBPS) {
++ if (pPrt->PLinkSpeedUsed != SK_LSPEED_STAT_10MBPS) {
+ pVctData->VctStatus |= SK_PNMI_VCT_NEW_DSP_DATA;
+ }
+ }
++
+ } /* CheckVctStatus */
+
+
+@@ -8314,29 +8197,29 @@
+ ReturnCode = SK_PNMI_ERR_GENERAL;
+
+ SK_MEMCPY(&Mode, pBuf, sizeof(SK_I32));
+- SK_MEMCPY(&Oid, (char *) pBuf + sizeof(SK_I32), sizeof(SK_U32));
++ SK_MEMCPY(&Oid, (char *)pBuf + sizeof(SK_I32), sizeof(SK_U32));
+ HeaderLength = sizeof(SK_I32) + sizeof(SK_U32);
+ *pLen = *pLen - HeaderLength;
+- SK_MEMCPY((char *) pBuf + sizeof(SK_I32), (char *) pBuf + HeaderLength, *pLen);
++ SK_MEMCPY((char *)pBuf + sizeof(SK_I32), (char *)pBuf + HeaderLength, *pLen);
+
+ switch(Mode) {
+ case SK_GET_SINGLE_VAR:
+- ReturnCode = SkPnmiGetVar(pAC, IoC, Oid,
+- (char *) pBuf + sizeof(SK_I32), pLen,
++ ReturnCode = SkPnmiGetVar(pAC, IoC, Oid,
++ (char *)pBuf + sizeof(SK_I32), pLen,
+ ((SK_U32) (-1)), NetIndex);
+ SK_PNMI_STORE_U32(pBuf, ReturnCode);
+ *pLen = *pLen + sizeof(SK_I32);
+ break;
+ case SK_PRESET_SINGLE_VAR:
+- ReturnCode = SkPnmiPreSetVar(pAC, IoC, Oid,
+- (char *) pBuf + sizeof(SK_I32), pLen,
++ ReturnCode = SkPnmiPreSetVar(pAC, IoC, Oid,
++ (char *)pBuf + sizeof(SK_I32), pLen,
+ ((SK_U32) (-1)), NetIndex);
+ SK_PNMI_STORE_U32(pBuf, ReturnCode);
+ *pLen = *pLen + sizeof(SK_I32);
+ break;
+ case SK_SET_SINGLE_VAR:
+- ReturnCode = SkPnmiSetVar(pAC, IoC, Oid,
+- (char *) pBuf + sizeof(SK_I32), pLen,
++ ReturnCode = SkPnmiSetVar(pAC, IoC, Oid,
++ (char *)pBuf + sizeof(SK_I32), pLen,
+ ((SK_U32) (-1)), NetIndex);
+ SK_PNMI_STORE_U32(pBuf, ReturnCode);
+ *pLen = *pLen + sizeof(SK_I32);
+@@ -8357,3 +8240,86 @@
+ return (ReturnCode);
+
+ } /* SkGeIocGen */
++
++#ifdef SK_ASF
++/*****************************************************************************
++ *
++ * Asf
++ *
++ * Description:
++ * The code is simple. No description necessary.
++ *
++ * Returns:
++ * SK_PNMI_ERR_OK The request was successfully performed.
++ * SK_PNMI_ERR_GENERAL A general severe internal error occured.
++ * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
++ * the correct data (e.g. a 32bit value is
++ * needed, but a 16 bit value was passed).
++ * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
++ * exist (e.g. port instance 3 on a two port
++ * adapter.
++ */
++
++PNMI_STATIC int Asf(
++SK_AC *pAC, /* Pointer to adapter context */
++SK_IOC IoC, /* IO context handle */
++int Action, /* GET/PRESET/SET action */
++SK_U32 Id, /* Object ID that is to be processed */
++char *pBuf, /* Buffer used for the management data transfer */
++unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
++SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
++unsigned int TableIndex, /* Index to the Id table */
++SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
++{
++ SK_U32 RetCode = SK_PNMI_ERR_GENERAL;
++
++ /*
++ * Check instance. We only handle single instance variables.
++ */
++ if (Instance != (SK_U32)(-1) && Instance != 1) {
++
++ *pLen = 0;
++ return (SK_PNMI_ERR_UNKNOWN_INST);
++ }
++
++ /* Perform action. */
++ /* GET value. */
++ if (Action == SK_PNMI_GET) {
++ switch (Id) {
++ case OID_SKGE_ASF:
++ RetCode = SkAsfGet(pAC, IoC, (SK_U8 *) pBuf, pLen);
++ break;
++ default:
++ RetCode = SkAsfGetOid( pAC, IoC, Id, Instance, (SK_U8 *) pBuf, pLen );
++ break;
++ }
++
++ return (RetCode);
++ }
++
++ /* PRESET value. */
++ if (Action == SK_PNMI_PRESET) {
++ switch (Id) {
++ case OID_SKGE_ASF:
++ RetCode = SkAsfPreSet(pAC, IoC, (SK_U8 *) pBuf, pLen);
++ break;
++ default:
++ RetCode = SkAsfPreSetOid( pAC, IoC, Id, Instance, (SK_U8 *) pBuf, pLen );
++ break;
++ }
++ }
++
++ /* SET value. */
++ if (Action == SK_PNMI_SET) {
++ switch (Id) {
++ case OID_SKGE_ASF:
++ RetCode = SkAsfSet(pAC, IoC, (SK_U8 *) pBuf, pLen);
++ break;
++ default:
++ RetCode = SkAsfSetOid( pAC, IoC, Id, Instance, (SK_U8 *) pBuf, pLen );
++ break;
++ }
++ }
++ return (RetCode);
++}
++#endif /* SK_ASF */
+diff -ruN linux/drivers/net/sk98lin/skgesirq.c linux-new/drivers/net/sk98lin/skgesirq.c
+--- linux/drivers/net/sk98lin/skgesirq.c 2005-09-26 13:32:47.000000000 +0400
++++ linux-new/drivers/net/sk98lin/skgesirq.c 2005-08-09 17:15:51.000000000 +0400
+@@ -2,8 +2,8 @@
+ *
+ * Name: skgesirq.c
+ * Project: Gigabit Ethernet Adapters, Common Modules
+- * Version: $Revision: 1.92 $
+- * Date: $Date: 2003/09/16 14:37:07 $
++ * Version: $Revision: 2.22 $
++ * Date: $Date: 2005/07/14 10:22:57 $
+ * Purpose: Special IRQ module
+ *
+ ******************************************************************************/
+@@ -11,13 +11,12 @@
+ /******************************************************************************
+ *
+ * (C)Copyright 1998-2002 SysKonnect.
+- * (C)Copyright 2002-2003 Marvell.
++ * (C)Copyright 2002-2005 Marvell.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+- *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+@@ -38,7 +37,7 @@
+ * right after this ISR.
+ *
+ * The Interrupt source register of the adapter is NOT read by this module.
+- * SO if the drivers implementor needs a while loop around the
++ * SO if the drivers implementor needs a while loop around the
+ * slow data paths interrupt bits, he needs to call the SkGeSirqIsr() for
+ * each loop entered.
+ *
+@@ -46,11 +45,6 @@
+ *
+ */
+
+-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
+-static const char SysKonnectFileId[] =
+- "@(#) $Id: skgesirq.c,v 1.92 2003/09/16 14:37:07 rschmidt Exp $ (C) Marvell.";
+-#endif
+-
+ #include "h/skdrv1st.h" /* Driver Specific Definitions */
+ #ifndef SK_SLIM
+ #include "h/skgepnmi.h" /* PNMI Definitions */
+@@ -58,6 +52,13 @@
+ #endif
+ #include "h/skdrv2nd.h" /* Adapter Control and Driver specific Def. */
+
++/* local variables ************************************************************/
++
++#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
++static const char SysKonnectFileId[] =
++ "@(#) $Id: skgesirq.c,v 2.22 2005/07/14 10:22:57 rschmidt Exp $ (C) Marvell.";
++#endif
++
+ /* local function prototypes */
+ #ifdef GENESIS
+ static int SkGePortCheckUpXmac(SK_AC*, SK_IOC, int, SK_BOOL);
+@@ -86,7 +87,7 @@
+ XM_RXF_511B,
+ XM_RXF_1023B,
+ XM_RXF_MAX_SZ
+-} ;
++};
+ #endif /* GENESIS */
+
+ #ifdef __C2MAN__
+@@ -109,8 +110,8 @@
+ * Returns: N/A
+ */
+ static void SkHWInitDefSense(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O context */
+ int Port) /* Port Index (MAC_1 + n) */
+ {
+ SK_GEPORT *pPrt; /* GIni Port struct pointer */
+@@ -119,7 +120,7 @@
+
+ pPrt->PAutoNegTimeOut = 0;
+
+- if (pPrt->PLinkModeConf != SK_LMODE_AUTOSENSE) {
++ if (pPrt->PLinkModeConf != (SK_U8)SK_LMODE_AUTOSENSE) {
+ pPrt->PLinkMode = pPrt->PLinkModeConf;
+ return;
+ }
+@@ -145,8 +146,8 @@
+ *
+ */
+ static SK_U8 SkHWSenseGetNext(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O context */
+ int Port) /* Port Index (MAC_1 + n) */
+ {
+ SK_GEPORT *pPrt; /* GIni Port struct pointer */
+@@ -155,18 +156,18 @@
+
+ pPrt->PAutoNegTimeOut = 0;
+
+- if (pPrt->PLinkModeConf != (SK_U8)SK_LMODE_AUTOSENSE) {
++ if (pPrt->PLinkModeConf != (SK_U8)SK_LMODE_AUTOSENSE) {
+ /* Leave all as configured */
+ return(pPrt->PLinkModeConf);
+ }
+
+- if (pPrt->PLinkMode == (SK_U8)SK_LMODE_AUTOFULL) {
++ if (pPrt->PLinkMode == (SK_U8)SK_LMODE_AUTOFULL) {
+ /* Return next mode AUTOBOTH */
+- return ((SK_U8)SK_LMODE_AUTOBOTH);
++ return((SK_U8)SK_LMODE_AUTOBOTH);
+ }
+
+ /* Return default autofull */
+- return ((SK_U8)SK_LMODE_AUTOFULL);
++ return((SK_U8)SK_LMODE_AUTOFULL);
+ } /* SkHWSenseGetNext */
+
+
+@@ -179,8 +180,8 @@
+ * Returns: N/A
+ */
+ static void SkHWSenseSetNext(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O context */
+ int Port, /* Port Index (MAC_1 + n) */
+ SK_U8 NewMode) /* New Mode to be written in sense mode */
+ {
+@@ -190,7 +191,7 @@
+
+ pPrt->PAutoNegTimeOut = 0;
+
+- if (pPrt->PLinkModeConf != (SK_U8)SK_LMODE_AUTOSENSE) {
++ if (pPrt->PLinkModeConf != (SK_U8)SK_LMODE_AUTOSENSE) {
+ return;
+ }
+
+@@ -214,8 +215,8 @@
+ * Returns: N/A
+ */
+ void SkHWLinkDown(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O context */
+ int Port) /* Port Index (MAC_1 + n) */
+ {
+ SK_GEPORT *pPrt; /* GIni Port struct pointer */
+@@ -227,11 +228,11 @@
+
+ /* Disable Receiver and Transmitter */
+ SkMacRxTxDisable(pAC, IoC, Port);
+-
++
+ /* Init default sense mode */
+ SkHWInitDefSense(pAC, IoC, Port);
+
+- if (pPrt->PHWLinkUp == SK_FALSE) {
++ if (!pPrt->PHWLinkUp) {
+ return;
+ }
+
+@@ -242,8 +243,8 @@
+ pPrt->PHWLinkUp = SK_FALSE;
+
+ /* Reset Port stati */
+- pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN;
+- pPrt->PFlowCtrlStatus = (SK_U8)SK_FLOW_STAT_NONE;
++ pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN;
++ pPrt->PFlowCtrlStatus = (SK_U8)SK_FLOW_STAT_NONE;
+ pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_INDETERMINATED;
+
+ /* Re-init Phy especially when the AutoSense default is set now */
+@@ -266,8 +267,8 @@
+ * Returns: N/A
+ */
+ void SkHWLinkUp(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O context */
+ int Port) /* Port Index (MAC_1 + n) */
+ {
+ SK_GEPORT *pPrt; /* GIni Port struct pointer */
+@@ -281,11 +282,11 @@
+
+ pPrt->PHWLinkUp = SK_TRUE;
+ pPrt->PAutoNegFail = SK_FALSE;
+- pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN;
++ pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN;
+
+- if (pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOHALF &&
+- pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOFULL &&
+- pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOBOTH) {
++ if (pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOHALF &&
++ pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOFULL &&
++ pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOBOTH) {
+ /* Link is up and no Auto-negotiation should be done */
+
+ /* Link speed should be the configured one */
+@@ -304,18 +305,18 @@
+ }
+
+ /* Set Link Mode Status */
+- if (pPrt->PLinkMode == SK_LMODE_FULL) {
++ if (pPrt->PLinkMode == (SK_U8)SK_LMODE_FULL) {
+ pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_FULL;
+ }
+ else {
+- pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_HALF;
++ pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_HALF;
+ }
+
+ /* No flow control without auto-negotiation */
+- pPrt->PFlowCtrlStatus = (SK_U8)SK_FLOW_STAT_NONE;
++ pPrt->PFlowCtrlStatus = (SK_U8)SK_FLOW_STAT_NONE;
+
+ /* enable Rx/Tx */
+- (void)SkMacRxTxEnable(pAC, IoC, Port);
++ (void)SkMacRxTxEnable(pAC, IoC, Port);
+ }
+ } /* SkHWLinkUp */
+
+@@ -329,14 +330,16 @@
+ * Returns: N/A
+ */
+ static void SkMacParity(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
+-int Port) /* Port Index of the port failed */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O context */
++int Port) /* Port Index (MAC_1 + n) */
+ {
+ SK_EVPARA Para;
+ SK_GEPORT *pPrt; /* GIni Port struct pointer */
+ SK_U32 TxMax; /* Tx Max Size Counter */
+
++ TxMax = 0;
++
+ pPrt = &pAC->GIni.GP[Port];
+
+ /* Clear IRQ Tx Parity Error */
+@@ -346,7 +349,7 @@
+ SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_PERR);
+ }
+ #endif /* GENESIS */
+-
++
+ #ifdef YUKON
+ if (pAC->GIni.GIYukon) {
+ /* HW-Bug #8: cleared by GMF_CLI_TX_FC instead of GMF_CLI_TX_PE */
+@@ -355,7 +358,7 @@
+ pAC->GIni.GIChipRev == 0) ? GMF_CLI_TX_FC : GMF_CLI_TX_PE));
+ }
+ #endif /* YUKON */
+-
++
+ if (pPrt->PCheckPar) {
+
+ if (Port == MAC_1) {
+@@ -366,7 +369,7 @@
+ }
+ Para.Para64 = Port;
+ SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
+-
++
+ Para.Para32[0] = Port;
+ SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
+
+@@ -378,18 +381,18 @@
+ if (pAC->GIni.GIGenesis) {
+ /* Snap statistic counters */
+ (void)SkXmUpdateStats(pAC, IoC, Port);
+-
++
+ (void)SkXmMacStatistic(pAC, IoC, Port, XM_TXF_MAX_SZ, &TxMax);
+ }
+ #endif /* GENESIS */
+-
++
+ #ifdef YUKON
+ if (pAC->GIni.GIYukon) {
+
+ (void)SkGmMacStatistic(pAC, IoC, Port, GM_TXF_1518B, &TxMax);
+ }
+ #endif /* YUKON */
+-
++
+ if (TxMax > 0) {
+ /* From now on check the parity */
+ pPrt->PCheckPar = SK_TRUE;
+@@ -399,15 +402,15 @@
+
+ /******************************************************************************
+ *
+- * SkGeHwErr() - Hardware Error service routine
++ * SkGeYuHwErr() - Hardware Error service routine (Genesis and Yukon)
+ *
+ * Description: handles all HW Error interrupts
+ *
+ * Returns: N/A
+ */
+-static void SkGeHwErr(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++static void SkGeYuHwErr(
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O context */
+ SK_U32 HwStatus) /* Interrupt status word */
+ {
+ SK_EVPARA Para;
+@@ -423,10 +426,10 @@
+ }
+
+ /* Reset all bits in the PCI STATUS register */
+- SK_IN16(IoC, PCI_C(PCI_STATUS), &Word);
+-
++ SK_IN16(IoC, PCI_C(pAC, PCI_STATUS), &Word);
++
+ SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON);
+- SK_OUT16(IoC, PCI_C(PCI_STATUS), (SK_U16)(Word | PCI_ERRBITS));
++ SK_OUT16(IoC, PCI_C(pAC, PCI_STATUS), (SK_U16)(Word | PCI_ERRBITS));
+ SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
+
+ Para.Para64 = 0;
+@@ -484,14 +487,18 @@
+ #endif /* YUKON */
+
+ if ((HwStatus & IS_RAM_RD_PAR) != 0) {
++
+ SK_OUT16(IoC, B3_RI_CTRL, RI_CLR_RD_PERR);
++
+ SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E014, SKERR_SIRQ_E014MSG);
+ Para.Para64 = 0;
+ SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);
+ }
+
+ if ((HwStatus & IS_RAM_WR_PAR) != 0) {
++
+ SK_OUT16(IoC, B3_RI_CTRL, RI_CLR_WR_PERR);
++
+ SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E015, SKERR_SIRQ_E015MSG);
+ Para.Para64 = 0;
+ SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);
+@@ -512,7 +519,7 @@
+ SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E018, SKERR_SIRQ_E018MSG);
+ Para.Para64 = MAC_1;
+ SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
+-
++
+ Para.Para32[0] = MAC_1;
+ SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
+ }
+@@ -524,37 +531,288 @@
+ SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E019, SKERR_SIRQ_E019MSG);
+ Para.Para64 = MAC_2;
+ SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
+-
++
+ Para.Para32[0] = MAC_2;
+ SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
+ }
+-} /* SkGeHwErr */
++} /* SkGeYuHwErr */
++
++#ifdef YUK2
++/******************************************************************************
++ *
++ * SkYuk2HwPortErr() - Service HW Errors for specified port (Yukon-2 only)
++ *
++ * Description: handles the HW Error interrupts for a specific port.
++ *
++ * Returns: N/A
++ */
++static void SkYuk2HwPortErr(
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
++SK_U32 HwStatus, /* Interrupt status word */
++int Port) /* Port Index (MAC_1 + n) */
++{
++ SK_EVPARA Para;
++ int Queue;
++
++ if (Port == MAC_2) {
++ HwStatus >>= 8;
++ }
++
++ if ((HwStatus & Y2_HWE_L1_MASK) == 0) {
++ return;
++ }
++
++ if ((HwStatus & Y2_IS_PAR_RD1) != 0) {
++ /* Clear IRQ */
++ SK_OUT16(IoC, SELECT_RAM_BUFFER(Port, B3_RI_CTRL), RI_CLR_RD_PERR);
++
++ if (Port == MAC_1) {
++ SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E028, SKERR_SIRQ_E028MSG);
++ }
++ else {
++ SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E030, SKERR_SIRQ_E030MSG);
++ }
++ }
++
++ if ((HwStatus & Y2_IS_PAR_WR1) != 0) {
++ /* Clear IRQ */
++ SK_OUT16(IoC, SELECT_RAM_BUFFER(Port, B3_RI_CTRL), RI_CLR_WR_PERR);
++
++ if (Port == MAC_1) {
++ SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E029, SKERR_SIRQ_E029MSG);
++ }
++ else {
++ SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E031, SKERR_SIRQ_E031MSG);
++ }
++ }
++
++ if ((HwStatus & Y2_IS_PAR_MAC1) != 0) {
++ /* Clear IRQ */
++ SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), GMF_CLI_TX_PE);
++
++ if (Port == MAC_1) {
++ SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E016, SKERR_SIRQ_E016MSG);
++ }
++ else {
++ SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E017, SKERR_SIRQ_E017MSG);
++ }
++ }
++
++ if ((HwStatus & Y2_IS_PAR_RX1) != 0) {
++ if (Port == MAC_1) {
++ Queue = Q_R1;
++ SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E018, SKERR_SIRQ_E018MSG);
++ }
++ else {
++ Queue = Q_R2;
++ SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E019, SKERR_SIRQ_E019MSG);
++ }
++ /* Clear IRQ */
++ SK_OUT32(IoC, Q_ADDR(Queue, Q_CSR), BMU_CLR_IRQ_PAR);
++ }
++
++ if ((HwStatus & Y2_IS_TCP_TXS1) != 0) {
++ if (Port == MAC_1) {
++ Queue = Q_XS1;
++ SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E033, SKERR_SIRQ_E033MSG);
++ }
++ else {
++ Queue = Q_XS2;
++ SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E035, SKERR_SIRQ_E035MSG);
++ }
++ /* Clear IRQ */
++ SK_OUT32(IoC, Q_ADDR(Queue, Q_CSR), BMU_CLR_IRQ_TCP);
++ }
++
++ if ((HwStatus & Y2_IS_TCP_TXA1) != 0) {
++ if (Port == MAC_1) {
++ Queue = Q_XA1;
++ SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E032, SKERR_SIRQ_E032MSG);
++ }
++ else {
++ Queue = Q_XA2;
++ SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E034, SKERR_SIRQ_E034MSG);
++ }
++ /* Clear IRQ */
++ SK_OUT32(IoC, Q_ADDR(Queue, Q_CSR), BMU_CLR_IRQ_TCP);
++ }
++
++ Para.Para64 = Port;
++ SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
++
++ Para.Para32[0] = Port;
++ SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
+
++} /* SkYuk2HwPortErr */
+
+ /******************************************************************************
+ *
+- * SkGeSirqIsr() - Special Interrupt Service Routine
++ * SkYuk2HwErr() - Hardware Error service routine (Yukon-2 only)
+ *
+- * Description: handles all non data transfer specific interrupts (slow path)
++ * Description: handles all HW Error interrupts
++ *
++ * Returns: N/A
++ */
++static void SkYuk2HwErr(
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
++SK_U32 HwStatus) /* Interrupt status word */
++{
++ SK_EVPARA Para;
++ SK_U16 Word;
++ SK_U32 DWord;
++ SK_U32 TlpHead[4];
++ int i;
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
++ ("HW-Error Status: 0x%08lX\n", HwStatus));
++
++ /* This is necessary only for Rx timing measurements */
++ if ((HwStatus & Y2_IS_TIST_OV) != 0) {
++ /* increment Time Stamp Timer counter (high) */
++ pAC->GIni.GITimeStampCnt++;
++
++ /* Clear Time Stamp Timer IRQ */
++ SK_OUT8(IoC, GMAC_TI_ST_CTRL, (SK_U8)GMT_ST_CLR_IRQ);
++ }
++
++ /* Evaluate Y2_IS_PCI_NEXP before Y2_IS_MST_ERR or Y2_IS_IRQ_STAT */
++ if ((HwStatus & Y2_IS_PCI_NEXP) != 0) {
++ /*
++ * This error is also mapped either to Master Abort (Y2_IS_MST_ERR)
++ * or Target Abort (Y2_IS_IRQ_STAT) bit and can only be cleared there.
++ * Therefore handle this event just by printing an error log entry.
++ */
++ SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E027, SKERR_SIRQ_E027MSG);
++ }
++
++ if ((HwStatus & (Y2_IS_MST_ERR | Y2_IS_IRQ_STAT)) != 0) {
++ /* PCI Errors occured */
++ if ((HwStatus & Y2_IS_IRQ_STAT) != 0) {
++ SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E013, SKERR_SIRQ_E013MSG);
++ }
++ else {
++ SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E012, SKERR_SIRQ_E012MSG);
++ }
++
++ /* Reset all bits in the PCI STATUS register */
++ SK_IN16(IoC, PCI_C(pAC, PCI_STATUS), &Word);
++
++ SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON);
++ SK_OUT16(IoC, PCI_C(pAC, PCI_STATUS), (SK_U16)(Word | PCI_ERRBITS));
++ SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
++
++ Para.Para64 = 0;
++ SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);
++ }
++
++ /* check for PCI-Express Uncorrectable Error */
++ if ((HwStatus & Y2_IS_PCI_EXP) != 0) {
++ /*
++ * On PCI-Express bus bridges are called root complexes (RC).
++ * PCI-Express errors are recognized by the root complex too,
++ * which requests the system to handle the problem. After error
++ * occurence it may be that no access to the adapter may be performed
++ * any longer.
++ */
++
++ /* Get uncorrectable error status */
++ SK_IN32(IoC, PCI_C(pAC, PEX_UNC_ERR_STAT), &DWord);
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
++ ("PEX Uncorr.Error Status: 0x%08lX\n", DWord));
++
++ if (DWord != PEX_UNSUP_REQ) {
++ /* ignore Unsupported Request Errors */
++ SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E026, SKERR_SIRQ_E026MSG);
++ }
++
++ if ((DWord & (PEX_FATAL_ERRORS | PEX_POIS_TLP)) != 0) {
++ /*
++ * Stop only, if the uncorrectable error is fatal or
++ * Poisoned TLP occured
++ */
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, ("Header Log:"));
++
++ for (i = 0; i < 4; i++) {
++ /* get TLP Header from Log Registers */
++ SK_IN32(IoC, PCI_C(pAC, PEX_HEADER_LOG + i*4), TlpHead + i);
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
++ (" 0x%08lX", TlpHead[i]));
++ }
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, ("\n"));
++
++ /* check for vendor defined broadcast message */
++ if (TlpHead[0] == 0x73004001 && (SK_U8)TlpHead[1] == 0x7f) {
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
++ ("Vendor defined broadcast message\n"));
++ }
++ else {
++ Para.Para64 = 0;
++ SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);
++
++ pAC->GIni.GIValHwIrqMask &= ~Y2_IS_PCI_EXP;
++ /* Rewrite HW IRQ mask */
++ SK_OUT32(IoC, B0_HWE_IMSK, pAC->GIni.GIValHwIrqMask);
++ }
++ }
++ /* clear the interrupt */
++ SK_OUT32(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON);
++ SK_OUT32(IoC, PCI_C(pAC, PEX_UNC_ERR_STAT), 0xffffffffUL);
++ SK_OUT32(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
++ }
++
++ for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
++
++ SkYuk2HwPortErr(pAC, IoC, HwStatus, i);
++ }
++
++} /* SkYuk2HwErr */
++#endif /* YUK2 */
++
++/******************************************************************************
++ *
++ * SkGeSirqIsr() - Wrapper for Special Interrupt Service Routine
++ *
++ * Description: calls the preselected special ISR (slow path)
+ *
+ * Returns: N/A
+ */
+ void SkGeSirqIsr(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O context */
++SK_U32 Istatus) /* Interrupt status word */
++{
++ pAC->GIni.GIFunc.pSkGeSirqIsr(pAC, IoC, Istatus);
++}
++
++/******************************************************************************
++ *
++ * SkGeYuSirqIsr() - Special Interrupt Service Routine
++ *
++ * Description: handles all non data transfer specific interrupts (slow path)
++ *
++ * Returns: N/A
++ */
++void SkGeYuSirqIsr(
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ SK_U32 Istatus) /* Interrupt status word */
+ {
+ SK_EVPARA Para;
+ SK_U32 RegVal32; /* Read register value */
+ SK_GEPORT *pPrt; /* GIni Port struct pointer */
+- SK_U16 PhyInt;
++ SK_U16 PhyInt;
+ int i;
+
+ if (((Istatus & IS_HW_ERR) & pAC->GIni.GIValIrqMask) != 0) {
+ /* read the HW Error Interrupt source */
+ SK_IN32(IoC, B0_HWE_ISRC, &RegVal32);
+-
+- SkGeHwErr(pAC, IoC, RegVal32);
++
++ SkGeYuHwErr(pAC, IoC, RegVal32);
+ }
+
+ /*
+@@ -569,7 +827,7 @@
+ }
+
+ if (((Istatus & (IS_PA_TO_RX2 | IS_PA_TO_TX2)) != 0) &&
+- pAC->GIni.GP[MAC_2].PState == SK_PRT_RESET) {
++ pAC->GIni.GP[MAC_2].PState == SK_PRT_RESET) {
+ /* MAC 2 was not initialized but Packet timeout occured */
+ SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E005,
+ SKERR_SIRQ_E005MSG);
+@@ -590,8 +848,8 @@
+ }
+
+ if ((Istatus & IS_PA_TO_TX1) != 0) {
+-
+- pPrt = &pAC->GIni.GP[0];
++
++ pPrt = &pAC->GIni.GP[MAC_1];
+
+ /* May be a normal situation in a server with a slow network */
+ SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_TX1);
+@@ -612,25 +870,18 @@
+ * we ignore those
+ */
+ pPrt->HalfDupTimerActive = SK_TRUE;
+-#ifdef XXX
+- Len = sizeof(SK_U64);
+- SkPnmiGetVar(pAC, IoC, OID_SKGE_STAT_TX_OCTETS, (char *)&Octets,
+- &Len, (SK_U32)SK_PNMI_PORT_PHYS2INST(pAC, 0),
+- pAC->Rlmt.Port[0].Net->NetNumber);
+-
+- pPrt->LastOctets = Octets;
+-#endif /* XXX */
++
+ /* Snap statistic counters */
+ (void)SkXmUpdateStats(pAC, IoC, 0);
+
+ (void)SkXmMacStatistic(pAC, IoC, 0, XM_TXO_OK_HI, &RegVal32);
+
+ pPrt->LastOctets = (SK_U64)RegVal32 << 32;
+-
++
+ (void)SkXmMacStatistic(pAC, IoC, 0, XM_TXO_OK_LO, &RegVal32);
+
+ pPrt->LastOctets += RegVal32;
+-
++
+ Para.Para32[0] = 0;
+ SkTimerStart(pAC, IoC, &pPrt->HalfDupChkTimer, SK_HALFDUP_CHK_TIME,
+ SKGE_HWAC, SK_HWEV_HALFDUP_CHK, Para);
+@@ -640,8 +891,8 @@
+ }
+
+ if ((Istatus & IS_PA_TO_TX2) != 0) {
+-
+- pPrt = &pAC->GIni.GP[1];
++
++ pPrt = &pAC->GIni.GP[MAC_2];
+
+ /* May be a normal situation in a server with a slow network */
+ SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_TX2);
+@@ -653,25 +904,18 @@
+ pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) &&
+ !pPrt->HalfDupTimerActive) {
+ pPrt->HalfDupTimerActive = SK_TRUE;
+-#ifdef XXX
+- Len = sizeof(SK_U64);
+- SkPnmiGetVar(pAC, IoC, OID_SKGE_STAT_TX_OCTETS, (char *)&Octets,
+- &Len, (SK_U32)SK_PNMI_PORT_PHYS2INST(pAC, 1),
+- pAC->Rlmt.Port[1].Net->NetNumber);
+-
+- pPrt->LastOctets = Octets;
+-#endif /* XXX */
++
+ /* Snap statistic counters */
+ (void)SkXmUpdateStats(pAC, IoC, 1);
+
+ (void)SkXmMacStatistic(pAC, IoC, 1, XM_TXO_OK_HI, &RegVal32);
+
+ pPrt->LastOctets = (SK_U64)RegVal32 << 32;
+-
++
+ (void)SkXmMacStatistic(pAC, IoC, 1, XM_TXO_OK_LO, &RegVal32);
+
+ pPrt->LastOctets += RegVal32;
+-
++
+ Para.Para32[0] = 1;
+ SkTimerStart(pAC, IoC, &pPrt->HalfDupChkTimer, SK_HALFDUP_CHK_TIME,
+ SKGE_HWAC, SK_HWEV_HALFDUP_CHK, Para);
+@@ -684,6 +928,7 @@
+ if ((Istatus & IS_R1_C) != 0) {
+ /* Clear IRQ */
+ SK_OUT32(IoC, B0_R1_CSR, CSR_IRQ_CL_C);
++
+ SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E006,
+ SKERR_SIRQ_E006MSG);
+ Para.Para64 = MAC_1;
+@@ -695,6 +940,7 @@
+ if ((Istatus & IS_R2_C) != 0) {
+ /* Clear IRQ */
+ SK_OUT32(IoC, B0_R2_CSR, CSR_IRQ_CL_C);
++
+ SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E007,
+ SKERR_SIRQ_E007MSG);
+ Para.Para64 = MAC_2;
+@@ -706,6 +952,7 @@
+ if ((Istatus & IS_XS1_C) != 0) {
+ /* Clear IRQ */
+ SK_OUT32(IoC, B0_XS1_CSR, CSR_IRQ_CL_C);
++
+ SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E008,
+ SKERR_SIRQ_E008MSG);
+ Para.Para64 = MAC_1;
+@@ -717,6 +964,7 @@
+ if ((Istatus & IS_XA1_C) != 0) {
+ /* Clear IRQ */
+ SK_OUT32(IoC, B0_XA1_CSR, CSR_IRQ_CL_C);
++
+ SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E009,
+ SKERR_SIRQ_E009MSG);
+ Para.Para64 = MAC_1;
+@@ -728,6 +976,7 @@
+ if ((Istatus & IS_XS2_C) != 0) {
+ /* Clear IRQ */
+ SK_OUT32(IoC, B0_XS2_CSR, CSR_IRQ_CL_C);
++
+ SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E010,
+ SKERR_SIRQ_E010MSG);
+ Para.Para64 = MAC_2;
+@@ -739,6 +988,7 @@
+ if ((Istatus & IS_XA2_C) != 0) {
+ /* Clear IRQ */
+ SK_OUT32(IoC, B0_XA2_CSR, CSR_IRQ_CL_C);
++
+ SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E011,
+ SKERR_SIRQ_E011MSG);
+ Para.Para64 = MAC_2;
+@@ -751,39 +1001,37 @@
+ if ((Istatus & IS_EXT_REG) != 0) {
+ /* Test IRQs from PHY */
+ for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
+-
++
+ pPrt = &pAC->GIni.GP[i];
+-
++
+ if (pPrt->PState == SK_PRT_RESET) {
+ continue;
+ }
+-
++
+ #ifdef GENESIS
+ if (pAC->GIni.GIGenesis) {
+-
++
+ switch (pPrt->PhyType) {
+-
++
+ case SK_PHY_XMAC:
+ break;
+-
++
+ case SK_PHY_BCOM:
+ SkXmPhyRead(pAC, IoC, i, PHY_BCOM_INT_STAT, &PhyInt);
+-
++
+ if ((PhyInt & ~PHY_B_DEF_MSK) != 0) {
+ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+- ("Port %d Bcom Int: 0x%04X\n",
+- i, PhyInt));
++ ("Port %d PHY Int: 0x%04X\n", i, PhyInt));
+ SkPhyIsrBcom(pAC, IoC, i, PhyInt);
+ }
+ break;
+ #ifdef OTHER_PHY
+ case SK_PHY_LONE:
+ SkXmPhyRead(pAC, IoC, i, PHY_LONE_INT_STAT, &PhyInt);
+-
++
+ if ((PhyInt & PHY_L_DEF_MSK) != 0) {
+ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+- ("Port %d Lone Int: %x\n",
+- i, PhyInt));
++ ("Port %d PHY Int: 0x%04X\n", i, PhyInt));
+ SkPhyIsrLone(pAC, IoC, i, PhyInt);
+ }
+ break;
+@@ -791,7 +1039,7 @@
+ }
+ }
+ #endif /* GENESIS */
+-
++
+ #ifdef YUKON
+ if (pAC->GIni.GIYukon) {
+ /* Read PHY Interrupt Status */
+@@ -799,8 +1047,7 @@
+
+ if ((PhyInt & PHY_M_DEF_MSK) != 0) {
+ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+- ("Port %d Marv Int: 0x%04X\n",
+- i, PhyInt));
++ ("Port %d PHY Int: 0x%04X\n", i, PhyInt));
+ SkPhyIsrGmac(pAC, IoC, i, PhyInt);
+ }
+ }
+@@ -808,65 +1055,241 @@
+ }
+ }
+
+- /* I2C Ready interrupt */
+- if ((Istatus & IS_I2C_READY) != 0) {
++ /* TWSI Ready interrupt */
++ if ((Istatus & IS_I2C_READY) != 0) {
++#ifdef SK_SLIM
++ SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ);
++#else
++ SkI2cIsr(pAC, IoC);
++#endif
++ }
++
++ /* SW forced interrupt */
++ if ((Istatus & IS_IRQ_SW) != 0) {
++ /* clear the software IRQ */
++ SK_OUT8(IoC, B0_CTST, CS_CL_SW_IRQ);
++ }
++
++ if ((Istatus & IS_LNK_SYNC_M1) != 0) {
++ /*
++ * We do NOT need the Link Sync interrupt, because it shows
++ * us only a link going down.
++ */
++ /* clear interrupt */
++ SK_OUT8(IoC, MR_ADDR(MAC_1, LNK_SYNC_CTRL), LNK_CLR_IRQ);
++ }
++
++ /* Check MAC after link sync counter */
++ if ((Istatus & IS_MAC1) != 0) {
++ /* IRQ from MAC 1 */
++ SkMacIrq(pAC, IoC, MAC_1);
++ }
++
++ if ((Istatus & IS_LNK_SYNC_M2) != 0) {
++ /*
++ * We do NOT need the Link Sync interrupt, because it shows
++ * us only a link going down.
++ */
++ /* clear interrupt */
++ SK_OUT8(IoC, MR_ADDR(MAC_2, LNK_SYNC_CTRL), LNK_CLR_IRQ);
++ }
++
++ /* Check MAC after link sync counter */
++ if ((Istatus & IS_MAC2) != 0) {
++ /* IRQ from MAC 2 */
++ SkMacIrq(pAC, IoC, MAC_2);
++ }
++
++ /* Timer interrupt (served last) */
++ if ((Istatus & IS_TIMINT) != 0) {
++ /* check for HW Errors */
++ if (((Istatus & IS_HW_ERR) & ~pAC->GIni.GIValIrqMask) != 0) {
++ /* read the HW Error Interrupt source */
++ SK_IN32(IoC, B0_HWE_ISRC, &RegVal32);
++
++ SkGeYuHwErr(pAC, IoC, RegVal32);
++ }
++
++ SkHwtIsr(pAC, IoC);
++ }
++
++} /* SkGeYuSirqIsr */
++
++#ifdef YUK2
++/******************************************************************************
++ *
++ * SkYuk2PortSirq() - Service HW Errors for specified port (Yukon-2 only)
++ *
++ * Description: handles the HW Error interrupts for a specific port.
++ *
++ * Returns: N/A
++ */
++static void SkYuk2PortSirq(
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
++SK_U32 IStatus, /* Interrupt status word */
++int Port) /* Port Index (MAC_1 + n) */
++{
++ SK_EVPARA Para;
++ int Queue;
++ SK_U16 PhyInt;
++
++ if (Port == MAC_2) {
++ IStatus >>= 8;
++ }
++
++ /* Interrupt from PHY */
++ if ((IStatus & Y2_IS_IRQ_PHY1) != 0) {
++ /* Read PHY Interrupt Status */
++ SkGmPhyRead(pAC, IoC, Port, PHY_MARV_INT_STAT, &PhyInt);
++
++ if ((PhyInt & PHY_M_DEF_MSK) != 0) {
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
++ ("Port %d PHY Int: 0x%04X\n", Port, PhyInt));
++ SkPhyIsrGmac(pAC, IoC, Port, PhyInt);
++ }
++ }
++
++ /* Interrupt from MAC */
++ if ((IStatus & Y2_IS_IRQ_MAC1) != 0) {
++ SkMacIrq(pAC, IoC, Port);
++ }
++
++ if ((IStatus & (Y2_IS_CHK_RX1 | Y2_IS_CHK_TXS1 | Y2_IS_CHK_TXA1)) != 0) {
++ if ((IStatus & Y2_IS_CHK_RX1) != 0) {
++ if (Port == MAC_1) {
++ Queue = Q_R1;
++ SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E006,
++ SKERR_SIRQ_E006MSG);
++ }
++ else {
++ Queue = Q_R2;
++ SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E007,
++ SKERR_SIRQ_E007MSG);
++ }
++ /* Clear IRQ */
++ SK_OUT32(IoC, Q_ADDR(Queue, Q_CSR), BMU_CLR_IRQ_CHK);
++ }
++
++ if ((IStatus & Y2_IS_CHK_TXS1) != 0) {
++ if (Port == MAC_1) {
++ Queue = Q_XS1;
++ SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E008,
++ SKERR_SIRQ_E008MSG);
++ }
++ else {
++ Queue = Q_XS2;
++ SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E010,
++ SKERR_SIRQ_E010MSG);
++ }
++ /* Clear IRQ */
++ SK_OUT32(IoC, Q_ADDR(Queue, Q_CSR), BMU_CLR_IRQ_CHK);
++ }
++
++ if ((IStatus & Y2_IS_CHK_TXA1) != 0) {
++ if (Port == MAC_1) {
++ Queue = Q_XA1;
++ SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E009,
++ SKERR_SIRQ_E009MSG);
++ }
++ else {
++ Queue = Q_XA2;
++ SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E011,
++ SKERR_SIRQ_E011MSG);
++ }
++ /* Clear IRQ */
++ SK_OUT32(IoC, Q_ADDR(Queue, Q_CSR), BMU_CLR_IRQ_CHK);
++ }
++
++ Para.Para64 = Port;
++ SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
++
++ Para.Para32[0] = Port;
++ SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
++ }
++} /* SkYuk2PortSirq */
++#endif /* YUK2 */
++
++/******************************************************************************
++ *
++ * SkYuk2SirqIsr() - Special Interrupt Service Routine (Yukon-2 only)
++ *
++ * Description: handles all non data transfer specific interrupts (slow path)
++ *
++ * Returns: N/A
++ */
++void SkYuk2SirqIsr(
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
++SK_U32 Istatus) /* Interrupt status word */
++{
++#ifdef YUK2
++ SK_EVPARA Para;
++ SK_U32 RegVal32; /* Read register value */
++ SK_U8 Value;
++
++ /* HW Error indicated ? */
++ if (((Istatus & Y2_IS_HW_ERR) & pAC->GIni.GIValIrqMask) != 0) {
++ /* read the HW Error Interrupt source */
++ SK_IN32(IoC, B0_HWE_ISRC, &RegVal32);
++
++ SkYuk2HwErr(pAC, IoC, RegVal32);
++ }
++
++ /* Interrupt from ASF Subsystem */
++ if ((Istatus & Y2_IS_ASF) != 0) {
++ /* clear IRQ */
++ /* later on clearing should be done in ASF ISR handler */
++ SK_IN8(IoC, B28_Y2_ASF_STAT_CMD, &Value);
++ Value |= Y2_ASF_CLR_HSTI;
++ SK_OUT8(IoC, B28_Y2_ASF_STAT_CMD, Value);
++ /* Call IRQ handler in ASF Module */
++ /* TBD */
++ }
++
++ /* Check IRQ from polling unit */
++ if ((Istatus & Y2_IS_POLL_CHK) != 0) {
++ /* Clear IRQ */
++ SK_OUT32(IoC, POLL_CTRL, PC_CLR_IRQ_CHK);
++
++ SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E036,
++ SKERR_SIRQ_E036MSG);
++ Para.Para64 = 0;
++ SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para);
++ }
++
++ /* TWSI Ready interrupt */
++ if ((Istatus & Y2_IS_TWSI_RDY) != 0) {
+ #ifdef SK_SLIM
+- SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ);
+-#else
++ SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ);
++#else
+ SkI2cIsr(pAC, IoC);
+-#endif
++#endif
+ }
+
+ /* SW forced interrupt */
+- if ((Istatus & IS_IRQ_SW) != 0) {
++ if ((Istatus & Y2_IS_IRQ_SW) != 0) {
+ /* clear the software IRQ */
+ SK_OUT8(IoC, B0_CTST, CS_CL_SW_IRQ);
+ }
+
+- if ((Istatus & IS_LNK_SYNC_M1) != 0) {
+- /*
+- * We do NOT need the Link Sync interrupt, because it shows
+- * us only a link going down.
+- */
+- /* clear interrupt */
+- SK_OUT8(IoC, MR_ADDR(MAC_1, LNK_SYNC_CTRL), LED_CLR_IRQ);
+- }
+-
+- /* Check MAC after link sync counter */
+- if ((Istatus & IS_MAC1) != 0) {
+- /* IRQ from MAC 1 */
+- SkMacIrq(pAC, IoC, MAC_1);
+- }
+-
+- if ((Istatus & IS_LNK_SYNC_M2) != 0) {
+- /*
+- * We do NOT need the Link Sync interrupt, because it shows
+- * us only a link going down.
+- */
+- /* clear interrupt */
+- SK_OUT8(IoC, MR_ADDR(MAC_2, LNK_SYNC_CTRL), LED_CLR_IRQ);
++ if ((Istatus & Y2_IS_L1_MASK) != 0) {
++ SkYuk2PortSirq(pAC, IoC, Istatus, MAC_1);
+ }
+
+- /* Check MAC after link sync counter */
+- if ((Istatus & IS_MAC2) != 0) {
+- /* IRQ from MAC 2 */
+- SkMacIrq(pAC, IoC, MAC_2);
++ if ((Istatus & Y2_IS_L2_MASK) != 0) {
++ SkYuk2PortSirq(pAC, IoC, Istatus, MAC_2);
+ }
+
+ /* Timer interrupt (served last) */
+- if ((Istatus & IS_TIMINT) != 0) {
+- /* check for HW Errors */
+- if (((Istatus & IS_HW_ERR) & ~pAC->GIni.GIValIrqMask) != 0) {
+- /* read the HW Error Interrupt source */
+- SK_IN32(IoC, B0_HWE_ISRC, &RegVal32);
+-
+- SkGeHwErr(pAC, IoC, RegVal32);
+- }
+-
++ if ((Istatus & Y2_IS_TIMINT) != 0) {
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
++ ("Timer Int: 0x%08lX\n", Istatus));
+ SkHwtIsr(pAC, IoC);
+ }
++#endif /* YUK2 */
+
+-} /* SkGeSirqIsr */
++} /* SkYuk2SirqIsr */
+
+
+ #ifdef GENESIS
+@@ -880,8 +1303,8 @@
+ */
+ static int SkGePortCheckShorts(
+ SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* IO Context */
+-int Port) /* Which port should be checked */
++SK_IOC IoC, /* I/O Context */
++int Port) /* Port Index (MAC_1 + n) */
+ {
+ SK_U32 Shorts; /* Short Event Counter */
+ SK_U32 CheckShorts; /* Check value for Short Event Counter */
+@@ -909,9 +1332,9 @@
+ RxCts = 0;
+
+ for (i = 0; i < sizeof(SkGeRxRegs)/sizeof(SkGeRxRegs[0]); i++) {
+-
++
+ (void)SkXmMacStatistic(pAC, IoC, Port, SkGeRxRegs[i], &RxTmp);
+-
++
+ RxCts += (SK_U64)RxTmp;
+ }
+
+@@ -928,11 +1351,11 @@
+ CheckShorts = 2;
+
+ (void)SkXmMacStatistic(pAC, IoC, Port, XM_RXF_FCS_ERR, &FcsErrCts);
+-
+- if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE &&
+- pPrt->PLipaAutoNeg == SK_LIPA_UNKNOWN &&
+- (pPrt->PLinkMode == SK_LMODE_HALF ||
+- pPrt->PLinkMode == SK_LMODE_FULL)) {
++
++ if (pPrt->PLinkModeConf == (SK_U8)SK_LMODE_AUTOSENSE &&
++ pPrt->PLipaAutoNeg == (SK_U8)SK_LIPA_UNKNOWN &&
++ (pPrt->PLinkMode == (SK_U8)SK_LMODE_HALF ||
++ pPrt->PLinkMode == (SK_U8)SK_LMODE_FULL)) {
+ /*
+ * This is autosensing and we are in the fallback
+ * manual full/half duplex mode.
+@@ -941,16 +1364,16 @@
+ /* Nothing received, restart link */
+ pPrt->PPrevFcs = FcsErrCts;
+ pPrt->PPrevShorts = Shorts;
+-
++
+ return(SK_HW_PS_RESTART);
+ }
+ else {
+- pPrt->PLipaAutoNeg = SK_LIPA_MANUAL;
++ pPrt->PLipaAutoNeg = (SK_U8)SK_LIPA_MANUAL;
+ }
+ }
+
+ if (((RxCts - pPrt->PPrevRx) > pPrt->PRxLim) ||
+- (!(FcsErrCts - pPrt->PPrevFcs))) {
++ (!(FcsErrCts - pPrt->PPrevFcs))) {
+ /*
+ * Note: The compare with zero above has to be done the way shown,
+ * otherwise the Linux driver will have a problem.
+@@ -995,29 +1418,25 @@
+ */
+ static int SkGePortCheckUp(
+ SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* IO Context */
+-int Port) /* Which port should be checked */
++SK_IOC IoC, /* I/O Context */
++int Port) /* Port Index (MAC_1 + n) */
+ {
+ SK_GEPORT *pPrt; /* GIni Port struct pointer */
+ SK_BOOL AutoNeg; /* Is Auto-negotiation used ? */
+ int Rtv; /* Return value */
+
+ Rtv = SK_HW_PS_NONE;
+-
++
+ pPrt = &pAC->GIni.GP[Port];
+
+- if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
+- AutoNeg = SK_FALSE;
+- }
+- else {
+- AutoNeg = SK_TRUE;
+- }
++ AutoNeg = pPrt->PLinkMode != SK_LMODE_HALF &&
++ pPrt->PLinkMode != SK_LMODE_FULL;
+
+ #ifdef GENESIS
+ if (pAC->GIni.GIGenesis) {
+
+ switch (pPrt->PhyType) {
+-
++
+ case SK_PHY_XMAC:
+ Rtv = SkGePortCheckUpXmac(pAC, IoC, Port, AutoNeg);
+ break;
+@@ -1038,7 +1457,7 @@
+
+ #ifdef YUKON
+ if (pAC->GIni.GIYukon) {
+-
++
+ Rtv = SkGePortCheckUpGmac(pAC, IoC, Port, AutoNeg);
+ }
+ #endif /* YUKON */
+@@ -1059,8 +1478,8 @@
+ */
+ static int SkGePortCheckUpXmac(
+ SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* IO Context */
+-int Port, /* Which port should be checked */
++SK_IOC IoC, /* I/O Context */
++int Port, /* Port Index (MAC_1 + n) */
+ SK_BOOL AutoNeg) /* Is Auto-negotiation used ? */
+ {
+ SK_U32 Shorts; /* Short Event Counter */
+@@ -1098,7 +1517,7 @@
+ XM_IN16(IoC, Port, XM_ISRC, &Isrc);
+ IsrcSum |= Isrc;
+ SkXmAutoNegLipaXmac(pAC, IoC, Port, IsrcSum);
+-
++
+ if ((Isrc & XM_IS_INP_ASS) == 0) {
+ /* It has been in sync since last time */
+ /* Restart the PORT */
+@@ -1117,14 +1536,14 @@
+ * Link Restart Workaround:
+ * it may be possible that the other Link side
+ * restarts its link as well an we detect
+- * another LinkBroken. To prevent this
++ * another PLinkBroken. To prevent this
+ * happening we check for a maximum number
+ * of consecutive restart. If those happens,
+ * we do NOT restart the active link and
+ * check whether the link is now o.k.
+ */
+ pPrt->PLinkResCt++;
+-
++
+ pPrt->PAutoNegTimeOut = 0;
+
+ if (pPrt->PLinkResCt < SK_MAX_LRESTART) {
+@@ -1132,13 +1551,13 @@
+ }
+
+ pPrt->PLinkResCt = 0;
+-
++
+ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+ ("Do NOT restart on Port %d %x %x\n", Port, Isrc, IsrcSum));
+ }
+ else {
+ pPrt->PIsave = (SK_U16)(IsrcSum & XM_IS_AND);
+-
++
+ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+ ("Save Sync/nosync Port %d %x %x\n", Port, Isrc, IsrcSum));
+
+@@ -1165,7 +1584,7 @@
+ if ((Isrc & XM_IS_INP_ASS) != 0) {
+ pPrt->PLinkBroken = SK_TRUE;
+ /* Re-Init Link partner Autoneg flag */
+- pPrt->PLipaAutoNeg = SK_LIPA_UNKNOWN;
++ pPrt->PLipaAutoNeg = (SK_U8)SK_LIPA_UNKNOWN;
+ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+ ("Link broken Port %d\n", Port));
+
+@@ -1178,7 +1597,7 @@
+ }
+ else {
+ SkXmAutoNegLipaXmac(pAC, IoC, Port, Isrc);
+-
++
+ if (SkGePortCheckShorts(pAC, IoC, Port) == SK_HW_PS_RESTART) {
+ return(SK_HW_PS_RESTART);
+ }
+@@ -1210,17 +1629,21 @@
+ }
+
+ if (AutoNeg) {
++ /* Auto-Negotiation Done ? */
+ if ((IsrcSum & XM_IS_AND) != 0) {
++
+ SkHWLinkUp(pAC, IoC, Port);
++
+ Done = SkMacAutoNegDone(pAC, IoC, Port);
++
+ if (Done != SK_AND_OK) {
+ /* Get PHY parameters, for debugging only */
+ SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_LP, &LpAb);
+ SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_RES_ABI, &ResAb);
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR,
+ ("AutoNeg FAIL Port %d (LpAb %x, ResAb %x)\n",
+- Port, LpAb, ResAb));
+-
++ Port, LpAb, ResAb));
++
+ /* Try next possible mode */
+ NextMode = SkHWSenseGetNext(pAC, IoC, Port);
+ SkHWLinkDown(pAC, IoC, Port);
+@@ -1236,42 +1659,41 @@
+ * (clear Page Received bit if set)
+ */
+ SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_EXP, &ExtStat);
+-
++
+ return(SK_HW_PS_LINK);
+ }
+-
++
+ /* AutoNeg not done, but HW link is up. Check for timeouts */
+- pPrt->PAutoNegTimeOut++;
+- if (pPrt->PAutoNegTimeOut >= SK_AND_MAX_TO) {
++ if (pPrt->PAutoNegTimeOut++ >= SK_AND_MAX_TO) {
+ /* Increase the Timeout counter */
+ pPrt->PAutoNegTOCt++;
+
+ /* Timeout occured */
+ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+ ("AutoNeg timeout Port %d\n", Port));
+- if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE &&
+- pPrt->PLipaAutoNeg != SK_LIPA_AUTO) {
++ if (pPrt->PLinkModeConf == (SK_U8)SK_LMODE_AUTOSENSE &&
++ pPrt->PLipaAutoNeg != (SK_U8)SK_LIPA_AUTO) {
+ /* Set Link manually up */
+ SkHWSenseSetNext(pAC, IoC, Port, SK_LMODE_FULL);
+ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+ ("Set manual full duplex Port %d\n", Port));
+ }
+
+- if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE &&
+- pPrt->PLipaAutoNeg == SK_LIPA_AUTO &&
++ if (pPrt->PLinkModeConf == (SK_U8)SK_LMODE_AUTOSENSE &&
++ pPrt->PLipaAutoNeg == (SK_U8)SK_LIPA_AUTO &&
+ pPrt->PAutoNegTOCt >= SK_MAX_ANEG_TO) {
+ /*
+ * This is rather complicated.
+ * we need to check here whether the LIPA_AUTO
+ * we saw before is false alert. We saw at one
+- * switch ( SR8800) that on boot time it sends
++ * switch (SR8800) that on boot time it sends
+ * just one auto-neg packet and does no further
+ * auto-negotiation.
+ * Solution: we restart the autosensing after
+ * a few timeouts.
+ */
+ pPrt->PAutoNegTOCt = 0;
+- pPrt->PLipaAutoNeg = SK_LIPA_UNKNOWN;
++ pPrt->PLipaAutoNeg = (SK_U8)SK_LIPA_UNKNOWN;
+ SkHWInitDefSense(pAC, IoC, Port);
+ }
+
+@@ -1282,18 +1704,18 @@
+ else {
+ /* Link is up and we don't need more */
+ #ifdef DEBUG
+- if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
++ if (pPrt->PLipaAutoNeg == (SK_U8)SK_LIPA_AUTO) {
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR,
+ ("ERROR: Lipa auto detected on port %d\n", Port));
+ }
+ #endif /* DEBUG */
+ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+ ("Link sync(GP), Port %d\n", Port));
+ SkHWLinkUp(pAC, IoC, Port);
+-
++
+ /*
+- * Link sync (GP) and so assume a good connection. But if not received
+- * a bunch of frames received in a time slot (maybe broken tx cable)
++ * Link sync (GP) and so assume a good connection. But if no
++ * bunch of frames received in a time slot (maybe broken Tx cable)
+ * the port is restart.
+ */
+ return(SK_HW_PS_LINK);
+@@ -1314,8 +1736,8 @@
+ */
+ static int SkGePortCheckUpBcom(
+ SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* IO Context */
+-int Port, /* Which port should be checked */
++SK_IOC IoC, /* I/O Context */
++int Port, /* Port Index (MAC_1 + n) */
+ SK_BOOL AutoNeg) /* Is Auto-negotiation used ? */
+ {
+ SK_GEPORT *pPrt; /* GIni Port struct pointer */
+@@ -1334,74 +1756,6 @@
+ /* Check for No HCD Link events (#10523) */
+ SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &Isrc);
+
+-#ifdef xDEBUG
+- if ((Isrc & ~(PHY_B_IS_HCT | PHY_B_IS_LCT) ==
+- (PHY_B_IS_SCR_S_ER | PHY_B_IS_RRS_CHANGE | PHY_B_IS_LRS_CHANGE)) {
+-
+- SK_U32 Stat1, Stat2, Stat3;
+-
+- Stat1 = 0;
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_MASK, &Stat1);
+- CMSMPrintString(
+- pAC->pConfigTable,
+- MSG_TYPE_RUNTIME_INFO,
+- "CheckUp1 - Stat: %x, Mask: %x",
+- (void *)Isrc,
+- (void *)Stat1);
+-
+- Stat1 = 0;
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Stat1);
+- Stat2 = 0;
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &Stat2);
+- Stat1 = Stat1 << 16 | Stat2;
+- Stat2 = 0;
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, &Stat2);
+- Stat3 = 0;
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &Stat3);
+- Stat2 = Stat2 << 16 | Stat3;
+- CMSMPrintString(
+- pAC->pConfigTable,
+- MSG_TYPE_RUNTIME_INFO,
+- "Ctrl/Stat: %x, AN Adv/LP: %x",
+- (void *)Stat1,
+- (void *)Stat2);
+-
+- Stat1 = 0;
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_EXP, &Stat1);
+- Stat2 = 0;
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_EXT_STAT, &Stat2);
+- Stat1 = Stat1 << 16 | Stat2;
+- Stat2 = 0;
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, &Stat2);
+- Stat3 = 0;
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &Stat3);
+- Stat2 = Stat2 << 16 | Stat3;
+- CMSMPrintString(
+- pAC->pConfigTable,
+- MSG_TYPE_RUNTIME_INFO,
+- "AN Exp/IEEE Ext: %x, 1000T Ctrl/Stat: %x",
+- (void *)Stat1,
+- (void *)Stat2);
+-
+- Stat1 = 0;
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, &Stat1);
+- Stat2 = 0;
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_STAT, &Stat2);
+- Stat1 = Stat1 << 16 | Stat2;
+- Stat2 = 0;
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Stat2);
+- Stat3 = 0;
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &Stat3);
+- Stat2 = Stat2 << 16 | Stat3;
+- CMSMPrintString(
+- pAC->pConfigTable,
+- MSG_TYPE_RUNTIME_INFO,
+- "PHY Ext Ctrl/Stat: %x, Aux Ctrl/Stat: %x",
+- (void *)Stat1,
+- (void *)Stat2);
+- }
+-#endif /* DEBUG */
+-
+ if ((Isrc & (PHY_B_IS_NO_HDCL /* | PHY_B_IS_NO_HDC */)) != 0) {
+ /*
+ * Workaround BCom Errata:
+@@ -1414,14 +1768,6 @@
+ (SK_U16)(Ctrl & ~PHY_CT_LOOP));
+ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+ ("No HCD Link event, Port %d\n", Port));
+-#ifdef xDEBUG
+- CMSMPrintString(
+- pAC->pConfigTable,
+- MSG_TYPE_RUNTIME_INFO,
+- "No HCD link event, port %d.",
+- (void *)Port,
+- (void *)NULL);
+-#endif /* DEBUG */
+ }
+
+ /* Not obsolete: link status bit is latched to 0 and autoclearing! */
+@@ -1431,72 +1777,6 @@
+ return(SK_HW_PS_NONE);
+ }
+
+-#ifdef xDEBUG
+- {
+- SK_U32 Stat1, Stat2, Stat3;
+-
+- Stat1 = 0;
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_MASK, &Stat1);
+- CMSMPrintString(
+- pAC->pConfigTable,
+- MSG_TYPE_RUNTIME_INFO,
+- "CheckUp1a - Stat: %x, Mask: %x",
+- (void *)Isrc,
+- (void *)Stat1);
+-
+- Stat1 = 0;
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Stat1);
+- Stat2 = 0;
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat);
+- Stat1 = Stat1 << 16 | PhyStat;
+- Stat2 = 0;
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, &Stat2);
+- Stat3 = 0;
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &Stat3);
+- Stat2 = Stat2 << 16 | Stat3;
+- CMSMPrintString(
+- pAC->pConfigTable,
+- MSG_TYPE_RUNTIME_INFO,
+- "Ctrl/Stat: %x, AN Adv/LP: %x",
+- (void *)Stat1,
+- (void *)Stat2);
+-
+- Stat1 = 0;
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_EXP, &Stat1);
+- Stat2 = 0;
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_EXT_STAT, &Stat2);
+- Stat1 = Stat1 << 16 | Stat2;
+- Stat2 = 0;
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, &Stat2);
+- Stat3 = 0;
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb);
+- Stat2 = Stat2 << 16 | ResAb;
+- CMSMPrintString(
+- pAC->pConfigTable,
+- MSG_TYPE_RUNTIME_INFO,
+- "AN Exp/IEEE Ext: %x, 1000T Ctrl/Stat: %x",
+- (void *)Stat1,
+- (void *)Stat2);
+-
+- Stat1 = 0;
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, &Stat1);
+- Stat2 = 0;
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_STAT, &Stat2);
+- Stat1 = Stat1 << 16 | Stat2;
+- Stat2 = 0;
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Stat2);
+- Stat3 = 0;
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &Stat3);
+- Stat2 = Stat2 << 16 | Stat3;
+- CMSMPrintString(
+- pAC->pConfigTable,
+- MSG_TYPE_RUNTIME_INFO,
+- "PHY Ext Ctrl/Stat: %x, Aux Ctrl/Stat: %x",
+- (void *)Stat1,
+- (void *)Stat2);
+- }
+-#endif /* DEBUG */
+-
+ /*
+ * Here we usually can check whether the link is in sync and
+ * auto-negotiation is done.
+@@ -1505,7 +1785,7 @@
+ SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat);
+
+ SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat);
+-
++
+ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+ ("CheckUp Port %d, PhyStat: 0x%04X\n", Port, PhyStat));
+
+@@ -1513,88 +1793,62 @@
+
+ if ((ResAb & PHY_B_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_ERR,
++ ("Master/Slave Fault, ResAb: 0x%04X\n", ResAb));
++
+ pPrt->PAutoNegFail = SK_TRUE;
+ pPrt->PMSStatus = SK_MS_STAT_FAULT;
+-
++
+ return(SK_HW_PS_RESTART);
+ }
+
+ if ((PhyStat & PHY_ST_LSYNC) == 0) {
+ return(SK_HW_PS_NONE);
+ }
+-
++
+ pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
+ SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE;
+-
++
+ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+ ("Port %d, ResAb: 0x%04X\n", Port, ResAb));
+
+ if (AutoNeg) {
++ /* Auto-Negotiation Over ? */
+ if ((PhyStat & PHY_ST_AN_OVER) != 0) {
+-
++
+ SkHWLinkUp(pAC, IoC, Port);
+-
++
+ Done = SkMacAutoNegDone(pAC, IoC, Port);
+-
++
+ if (Done != SK_AND_OK) {
+ #ifdef DEBUG
+ /* Get PHY parameters, for debugging only */
+ SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &LpAb);
+ SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ExtStat);
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR,
+ ("AutoNeg FAIL Port %d (LpAb %x, 1000TStat %x)\n",
+ Port, LpAb, ExtStat));
+ #endif /* DEBUG */
+ return(SK_HW_PS_RESTART);
+ }
+ else {
+-#ifdef xDEBUG
+- /* Dummy read ISR to prevent extra link downs/ups */
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &ExtStat);
+-
+- if ((ExtStat & ~(PHY_B_IS_HCT | PHY_B_IS_LCT)) != 0) {
+- CMSMPrintString(
+- pAC->pConfigTable,
+- MSG_TYPE_RUNTIME_INFO,
+- "CheckUp2 - Stat: %x",
+- (void *)ExtStat,
+- (void *)NULL);
+- }
+-#endif /* DEBUG */
+ return(SK_HW_PS_LINK);
+ }
+ }
+ }
+ else { /* !AutoNeg */
+- /* Link is up and we don't need more. */
++ /* Link is up and we don't need more */
+ #ifdef DEBUG
+- if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
++ if (pPrt->PLipaAutoNeg == (SK_U8)SK_LIPA_AUTO) {
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR,
+ ("ERROR: Lipa auto detected on port %d\n", Port));
+ }
+ #endif /* DEBUG */
+
+-#ifdef xDEBUG
+- /* Dummy read ISR to prevent extra link downs/ups */
+- SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &ExtStat);
+-
+- if ((ExtStat & ~(PHY_B_IS_HCT | PHY_B_IS_LCT)) != 0) {
+- CMSMPrintString(
+- pAC->pConfigTable,
+- MSG_TYPE_RUNTIME_INFO,
+- "CheckUp3 - Stat: %x",
+- (void *)ExtStat,
+- (void *)NULL);
+- }
+-#endif /* DEBUG */
+-
+ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+ ("Link sync(GP), Port %d\n", Port));
+ SkHWLinkUp(pAC, IoC, Port);
+-
++
+ return(SK_HW_PS_LINK);
+ }
+
+@@ -1615,14 +1869,13 @@
+ */
+ static int SkGePortCheckUpGmac(
+ SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* IO Context */
+-int Port, /* Which port should be checked */
++SK_IOC IoC, /* I/O Context */
++int Port, /* Port Index (MAC_1 + n) */
+ SK_BOOL AutoNeg) /* Is Auto-negotiation used ? */
+ {
+ SK_GEPORT *pPrt; /* GIni Port struct pointer */
+ int Done;
+- SK_U16 PhyIsrc; /* PHY Interrupt source */
+- SK_U16 PhyStat; /* PPY Status */
++ SK_U16 PhyStat; /* PHY Status */
+ SK_U16 PhySpecStat;/* PHY Specific Status */
+ SK_U16 ResAb; /* Master/Slave resolution */
+ SK_EVPARA Para;
+@@ -1642,94 +1895,121 @@
+ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+ ("CheckUp Port %d, PhyStat: 0x%04X\n", Port, PhyStat));
+
+- /* Read PHY Interrupt Status */
+- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_INT_STAT, &PhyIsrc);
++ SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat);
+
+- if ((PhyIsrc & PHY_M_IS_AN_COMPL) != 0) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("Auto-Negotiation Completed, PhyIsrc: 0x%04X\n", PhyIsrc));
+- }
++ if ((pPrt->PLinkSpeedCap & SK_LSPEED_CAP_1000MBPS) != 0) {
+
+- if ((PhyIsrc & PHY_M_IS_LSP_CHANGE) != 0) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("Link Speed Changed, PhyIsrc: 0x%04X\n", PhyIsrc));
+- }
++ SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_STAT, &ResAb);
+
+- SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat);
+-
+- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_STAT, &ResAb);
++ if ((ResAb & PHY_B_1000S_MSF) != 0) {
++ /* Error */
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR,
++ ("Master/Slave Fault, ResAb: 0x%04X\n", ResAb));
+
+- if ((ResAb & PHY_B_1000S_MSF) != 0) {
+- /* Error */
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("Master/Slave Fault port %d\n", Port));
+-
+- pPrt->PAutoNegFail = SK_TRUE;
+- pPrt->PMSStatus = SK_MS_STAT_FAULT;
+-
+- return(SK_HW_PS_RESTART);
++ pPrt->PAutoNegFail = SK_TRUE;
++ pPrt->PMSStatus = SK_MS_STAT_FAULT;
++
++ return(SK_HW_PS_RESTART);
++ }
+ }
+
+ /* Read PHY Specific Status */
+ SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &PhySpecStat);
+-
++
+ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+ ("Phy1000BT: 0x%04X, PhySpecStat: 0x%04X\n", ResAb, PhySpecStat));
+
+ #ifdef DEBUG
+ SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_EXP, &Word);
+
+- if ((PhyIsrc & PHY_M_IS_AN_PR) != 0 || (Word & PHY_ANE_RX_PG) != 0 ||
++ if ((Word & PHY_ANE_RX_PG) != 0 ||
+ (PhySpecStat & PHY_M_PS_PAGE_REC) != 0) {
+ /* Read PHY Next Page Link Partner */
+ SkGmPhyRead(pAC, IoC, Port, PHY_MARV_NEPG_LP, &Word);
+
+ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("Page Received, NextPage: 0x%04X\n", Word));
++ ("Page received, NextPage: 0x%04X\n", Word));
+ }
+ #endif /* DEBUG */
+
+ if ((PhySpecStat & PHY_M_PS_LINK_UP) == 0) {
++ /* Link down */
+ return(SK_HW_PS_NONE);
+ }
+-
+- if ((PhySpecStat & PHY_M_PS_DOWNS_STAT) != 0 ||
+- (PhyIsrc & PHY_M_IS_DOWNSH_DET) != 0) {
+- /* Downshift detected */
+- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E025, SKERR_SIRQ_E025MSG);
+-
+- Para.Para64 = Port;
+- SkEventQueue(pAC, SKGE_DRV, SK_DRV_DOWNSHIFT_DET, Para);
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("Downshift detected, PhyIsrc: 0x%04X\n", PhyIsrc));
++
++#ifdef XXX
++ SK_U16 PhyInt;
++ /* Read PHY Interrupt Status */
++ SkGmPhyRead(pAC, IoC, Port, PHY_MARV_INT_STAT, &PhyInt);
++
++ /* cross check that the link is really up */
++ if ((PhyInt & PHY_M_IS_LST_CHANGE) == 0) {
++ /* Link Status unchanged */
++ return(SK_HW_PS_NONE);
++ }
++#endif /* XXX */
++
++ if (pAC->GIni.GICopperType) {
++
++ if ((pPrt->PLinkSpeedCap & SK_LSPEED_CAP_1000MBPS) != 0) {
++
++ if ((PhySpecStat & PHY_M_PS_DOWNS_STAT) != 0) {
++ /* Downshift detected */
++ Para.Para64 = Port;
++ SkEventQueue(pAC, SKGE_DRV, SK_DRV_DOWNSHIFT_DET, Para);
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
++ ("Downshift detected, PhySpecStat: 0x%04X\n", PhySpecStat));
++
++ SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E025,
++ SKERR_SIRQ_E025MSG);
++ }
++
++ pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
++ SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE;
++ }
++
++ if ((PhySpecStat & PHY_M_PS_MDI_X_STAT) != 0) {
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
++ ("MDI Xover detected, PhyStat: 0x%04X\n", PhySpecStat));
++ }
++
++ /* on PHY 88E1112 cable length is in Reg. 26, Page 5 */
++ if (pAC->GIni.GIChipId == CHIP_ID_YUKON_XL) {
++ /* select page 5 to access VCT DSP distance register */
++ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 5);
++
++ /* get VCT DSP distance */
++ SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL_2, &PhySpecStat);
++
++ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 0);
++
++ pPrt->PCableLen = (SK_U8)(PhySpecStat & PHY_M_EC2_FO_AM_MSK);
++ }
++ else {
++ pPrt->PCableLen = (SK_U8)((PhySpecStat & PHY_M_PS_CABLE_MSK) >> 7);
++ }
+ }
+
+- pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ?
+- SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE;
+-
+- pPrt->PCableLen = (SK_U8)((PhySpecStat & PHY_M_PS_CABLE_MSK) >> 7);
+-
+ if (AutoNeg) {
+- /* Auto-Negotiation Over ? */
++ /* Auto-Negotiation Complete ? */
+ if ((PhyStat & PHY_ST_AN_OVER) != 0) {
+-
++
+ SkHWLinkUp(pAC, IoC, Port);
+-
++
+ Done = SkMacAutoNegDone(pAC, IoC, Port);
+-
++
+ if (Done != SK_AND_OK) {
+ return(SK_HW_PS_RESTART);
+ }
+-
++
+ return(SK_HW_PS_LINK);
+ }
+ }
+ else { /* !AutoNeg */
+- /* Link is up and we don't need more */
+ #ifdef DEBUG
+- if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
++ if (pPrt->PLipaAutoNeg == (SK_U8)SK_LIPA_AUTO) {
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR,
+ ("ERROR: Lipa auto detected on port %d\n", Port));
+ }
+ #endif /* DEBUG */
+@@ -1737,12 +2017,13 @@
+ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+ ("Link sync, Port %d\n", Port));
+ SkHWLinkUp(pAC, IoC, Port);
+-
++
+ return(SK_HW_PS_LINK);
+ }
+
+ return(SK_HW_PS_NONE);
+ } /* SkGePortCheckUpGmac */
++
+ #endif /* YUKON */
+
+
+@@ -1758,8 +2039,8 @@
+ */
+ static int SkGePortCheckUpLone(
+ SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* IO Context */
+-int Port, /* Which port should be checked */
++SK_IOC IoC, /* I/O Context */
++int Port, /* Port Index (MAC_1 + n) */
+ SK_BOOL AutoNeg) /* Is Auto-negotiation used ? */
+ {
+ SK_GEPORT *pPrt; /* GIni Port struct pointer */
+@@ -1788,7 +2069,7 @@
+ StatSum |= PhyStat;
+
+ SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat);
+-
++
+ if ((PhyStat & PHY_ST_LSYNC) == 0) {
+ /* Save Auto-negotiation Done bit */
+ pPrt->PIsave = (SK_U16)(StatSum & PHY_ST_AN_OVER);
+@@ -1802,17 +2083,21 @@
+ }
+
+ if (AutoNeg) {
++ /* Auto-Negotiation Over ? */
+ if ((StatSum & PHY_ST_AN_OVER) != 0) {
++
+ SkHWLinkUp(pAC, IoC, Port);
++
+ Done = SkMacAutoNegDone(pAC, IoC, Port);
++
+ if (Done != SK_AND_OK) {
+ /* Get PHY parameters, for debugging only */
+ SkXmPhyRead(pAC, IoC, Port, PHY_LONE_AUNE_LP, &LpAb);
+ SkXmPhyRead(pAC, IoC, Port, PHY_LONE_1000T_STAT, &ExtStat);
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR,
+ ("AutoNeg FAIL Port %d (LpAb %x, 1000TStat %x)\n",
+ Port, LpAb, ExtStat));
+-
++
+ /* Try next possible mode */
+ NextMode = SkHWSenseGetNext(pAC, IoC, Port);
+ SkHWLinkDown(pAC, IoC, Port);
+@@ -1833,15 +2118,14 @@
+ return(SK_HW_PS_LINK);
+ }
+ }
+-
++
+ /* AutoNeg not done, but HW link is up. Check for timeouts */
+- pPrt->PAutoNegTimeOut++;
+- if (pPrt->PAutoNegTimeOut >= SK_AND_MAX_TO) {
++ if (pPrt->PAutoNegTimeOut++ >= SK_AND_MAX_TO) {
+ /* Timeout occured */
+ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+ ("AutoNeg timeout Port %d\n", Port));
+- if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE &&
+- pPrt->PLipaAutoNeg != SK_LIPA_AUTO) {
++ if (pPrt->PLinkModeConf == (SK_U8)SK_LMODE_AUTOSENSE &&
++ pPrt->PLipaAutoNeg != (SK_U8)SK_LIPA_AUTO) {
+ /* Set Link manually up */
+ SkHWSenseSetNext(pAC, IoC, Port, SK_LMODE_FULL);
+ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+@@ -1855,8 +2139,8 @@
+ else {
+ /* Link is up and we don't need more */
+ #ifdef DEBUG
+- if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
++ if (pPrt->PLipaAutoNeg == (SK_U8)SK_LIPA_AUTO) {
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR,
+ ("ERROR: Lipa auto detected on port %d\n", Port));
+ }
+ #endif /* DEBUG */
+@@ -1866,11 +2150,12 @@
+ * extra link down/ups
+ */
+ SkXmPhyRead(pAC, IoC, Port, PHY_LONE_INT_STAT, &ExtStat);
+-
++
+ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+ ("Link sync(GP), Port %d\n", Port));
++
+ SkHWLinkUp(pAC, IoC, Port);
+-
++
+ return(SK_HW_PS_LINK);
+ }
+
+@@ -1889,8 +2174,8 @@
+ */
+ static int SkGePortCheckUpNat(
+ SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* IO Context */
+-int Port, /* Which port should be checked */
++SK_IOC IoC, /* I/O Context */
++int Port, /* Port Index (MAC_1 + n) */
+ SK_BOOL AutoNeg) /* Is Auto-negotiation used ? */
+ {
+ /* todo: National */
+@@ -1909,12 +2194,12 @@
+ */
+ int SkGeSirqEvent(
+ SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* Io Context */
++SK_IOC IoC, /* I/O Context */
+ SK_U32 Event, /* Module specific Event */
+ SK_EVPARA Para) /* Event specific Parameter */
+ {
+ SK_GEPORT *pPrt; /* GIni Port struct pointer */
+- SK_U32 Port;
++ int Port;
+ SK_U32 Val32;
+ int PortStat;
+ SK_U8 Val8;
+@@ -1922,25 +2207,25 @@
+ SK_U64 Octets;
+ #endif /* GENESIS */
+
+- Port = Para.Para32[0];
++ Port = (int)Para.Para32[0];
+ pPrt = &pAC->GIni.GP[Port];
+
+ switch (Event) {
+ case SK_HWEV_WATIM:
+ if (pPrt->PState == SK_PRT_RESET) {
+-
++
+ PortStat = SK_HW_PS_NONE;
+ }
+ else {
+ /* Check whether port came up */
+- PortStat = SkGePortCheckUp(pAC, IoC, (int)Port);
++ PortStat = SkGePortCheckUp(pAC, IoC, Port);
+ }
+
+ switch (PortStat) {
+ case SK_HW_PS_RESTART:
+ if (pPrt->PHWLinkUp) {
+ /* Set Link to down */
+- SkHWLinkDown(pAC, IoC, (int)Port);
++ SkHWLinkDown(pAC, IoC, Port);
+
+ /*
+ * Signal directly to RLMT to ensure correct
+@@ -1958,19 +2243,23 @@
+ SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_UP, Para);
+ break;
+ }
+-
++
+ /* Start again the check Timer */
+ if (pPrt->PHWLinkUp) {
++
+ Val32 = SK_WA_ACT_TIME;
+ }
+ else {
+ Val32 = SK_WA_INA_TIME;
+- }
+
+- /* Todo: still needed for non-XMAC PHYs??? */
++ if (pAC->GIni.GIYukon) {
++ Val32 *= 5;
++ }
++ }
+ /* Start workaround Errata #2 timer */
+ SkTimerStart(pAC, IoC, &pPrt->PWaTimer, Val32,
+ SKGE_HWAC, SK_HWEV_WATIM, Para);
++
+ break;
+
+ case SK_HWEV_PORT_START:
+@@ -1982,7 +2271,7 @@
+ SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para);
+ }
+
+- SkHWLinkDown(pAC, IoC, (int)Port);
++ SkHWLinkDown(pAC, IoC, Port);
+
+ /* Schedule Port RESET */
+ SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para);
+@@ -1990,6 +2279,7 @@
+ /* Start workaround Errata #2 timer */
+ SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME,
+ SKGE_HWAC, SK_HWEV_WATIM, Para);
++
+ break;
+
+ case SK_HWEV_PORT_STOP:
+@@ -2004,7 +2294,7 @@
+ /* Stop Workaround Timer */
+ SkTimerStop(pAC, IoC, &pPrt->PWaTimer);
+
+- SkHWLinkDown(pAC, IoC, (int)Port);
++ SkHWLinkDown(pAC, IoC, Port);
+ break;
+
+ case SK_HWEV_UPDATE_STAT:
+@@ -2013,7 +2303,7 @@
+
+ case SK_HWEV_CLEAR_STAT:
+ /* We do NOT need to clear any statistics */
+- for (Port = 0; Port < (SK_U32)pAC->GIni.GIMacsFound; Port++) {
++ for (Port = 0; Port < pAC->GIni.GIMacsFound; Port++) {
+ pPrt->PPrevRx = 0;
+ pPrt->PPrevFcs = 0;
+ pPrt->PPrevShorts = 0;
+@@ -2085,23 +2375,18 @@
+ pPrt->HalfDupTimerActive = SK_FALSE;
+ if (pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF ||
+ pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) {
+-#ifdef XXX
+- Len = sizeof(SK_U64);
+- SkPnmiGetVar(pAC, IoC, OID_SKGE_STAT_TX_OCTETS, (char *)&Octets,
+- &Len, (SK_U32)SK_PNMI_PORT_PHYS2INST(pAC, Port),
+- pAC->Rlmt.Port[Port].Net->NetNumber);
+-#endif /* XXX */
++
+ /* Snap statistic counters */
+ (void)SkXmUpdateStats(pAC, IoC, Port);
+
+ (void)SkXmMacStatistic(pAC, IoC, Port, XM_TXO_OK_HI, &Val32);
+
+ Octets = (SK_U64)Val32 << 32;
+-
++
+ (void)SkXmMacStatistic(pAC, IoC, Port, XM_TXO_OK_LO, &Val32);
+
+ Octets += Val32;
+-
++
+ if (pPrt->LastOctets == Octets) {
+ /* Tx hanging, a FIFO flush restarts it */
+ SkMacFlushTxFifo(pAC, IoC, Port);
+@@ -2110,7 +2395,7 @@
+ }
+ break;
+ #endif /* GENESIS */
+-
++
+ default:
+ SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_SIRQ_E001, SKERR_SIRQ_E001MSG);
+ break;
+@@ -2131,8 +2416,8 @@
+ */
+ static void SkPhyIsrBcom(
+ SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* Io Context */
+-int Port, /* Port Num = PHY Num */
++SK_IOC IoC, /* I/O Context */
++int Port, /* Port Index (MAC_1 + n) */
+ SK_U16 IStatus) /* Interrupt Status */
+ {
+ SK_GEPORT *pPrt; /* GIni Port struct pointer */
+@@ -2145,7 +2430,7 @@
+ SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E022,
+ SKERR_SIRQ_E022MSG);
+ }
+-
++
+ if ((IStatus & (PHY_B_IS_AN_PR | PHY_B_IS_LST_CHANGE)) != 0) {
+
+ SkHWLinkDown(pAC, IoC, Port);
+@@ -2174,8 +2459,8 @@
+ */
+ static void SkPhyIsrGmac(
+ SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* Io Context */
+-int Port, /* Port Num = PHY Num */
++SK_IOC IoC, /* I/O Context */
++int Port, /* Port Index (MAC_1 + n) */
+ SK_U16 IStatus) /* Interrupt Status */
+ {
+ SK_GEPORT *pPrt; /* GIni Port struct pointer */
+@@ -2184,37 +2469,69 @@
+
+ pPrt = &pAC->GIni.GP[Port];
+
+- if ((IStatus & (PHY_M_IS_AN_PR | PHY_M_IS_LST_CHANGE)) != 0) {
+-
+- SkHWLinkDown(pAC, IoC, Port);
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
++ ("Port %d PHY IRQ, PhyIsrc: 0x%04X\n", Port, IStatus));
+
+- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_ADV, &Word);
++ if ((IStatus & PHY_M_IS_LST_CHANGE) != 0) {
+
+ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("AutoNeg.Adv: 0x%04X\n", Word));
+-
+- /* Set Auto-negotiation advertisement */
+- if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM) {
+- /* restore Asymmetric Pause bit */
+- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_AUNE_ADV,
+- (SK_U16)(Word | PHY_M_AN_ASP));
+- }
+-
++ ("Link Status changed\n"));
++
+ Para.Para32[0] = (SK_U32)Port;
+- /* Signal to RLMT */
+- SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
++
++ if (pPrt->PHWLinkUp) {
++
++ SkHWLinkDown(pAC, IoC, Port);
++
++ SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_ADV, &Word);
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
++ ("AutoNeg.Adv: 0x%04X\n", Word));
++
++ /* Set Auto-negotiation advertisement */
++ if (pAC->GIni.GIChipId != CHIP_ID_YUKON_FE &&
++ pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM) {
++ /* restore Asymmetric Pause bit */
++ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_AUNE_ADV,
++ (SK_U16)(Word | PHY_M_AN_ASP));
++ }
++
++ /* Signal to RLMT */
++ SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para);
++ }
++ else {
++ if ((IStatus & PHY_M_IS_AN_COMPL) != 0) {
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
++ ("Auto-Negotiation completed\n"));
++ }
++
++ if ((IStatus & PHY_M_IS_LSP_CHANGE) != 0) {
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
++ ("Link Speed changed\n"));
++ }
++
++ SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_WATIM, Para);
++ }
+ }
+-
++
+ if ((IStatus & PHY_M_IS_AN_ERROR) != 0) {
+- /* Auto-Negotiation Error */
+- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E023, SKERR_SIRQ_E023MSG);
++ /* the copper PHY makes 1 retry */
++ if (pAC->GIni.GICopperType) {
++ /* not logged as error, it might be the first attempt */
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
++ ("Auto-Negotiation Error\n"));
++ }
++ else {
++ /* Auto-Negotiation Error */
++ SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E023, SKERR_SIRQ_E023MSG);
++ }
+ }
+-
++
+ if ((IStatus & PHY_M_IS_FIFO_ERROR) != 0) {
+ /* FIFO Overflow/Underrun Error */
+ SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E024, SKERR_SIRQ_E024MSG);
+ }
+-
++
+ } /* SkPhyIsrGmac */
+ #endif /* YUKON */
+
+@@ -2230,8 +2547,8 @@
+ */
+ static void SkPhyIsrLone(
+ SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* Io Context */
+-int Port, /* Port Num = PHY Num */
++SK_IOC IoC, /* I/O Context */
++int Port, /* Port Index (MAC_1 + n) */
+ SK_U16 IStatus) /* Interrupt Status */
+ {
+ SK_EVPARA Para;
+diff -ruN linux/drivers/net/sk98lin/ski2c.c linux-new/drivers/net/sk98lin/ski2c.c
+--- linux/drivers/net/sk98lin/ski2c.c 2005-09-26 13:32:47.000000000 +0400
++++ linux-new/drivers/net/sk98lin/ski2c.c 1970-01-01 03:00:00.000000000 +0300
+@@ -1,1296 +0,0 @@
+-/******************************************************************************
+- *
+- * Name: ski2c.c
+- * Project: Gigabit Ethernet Adapters, TWSI-Module
+- * Version: $Revision: 1.59 $
+- * Date: $Date: 2003/10/20 09:07:25 $
+- * Purpose: Functions to access Voltage and Temperature Sensor
+- *
+- ******************************************************************************/
+-
+-/******************************************************************************
+- *
+- * (C)Copyright 1998-2002 SysKonnect.
+- * (C)Copyright 2002-2003 Marvell.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * The information in this file is provided "AS IS" without warranty.
+- *
+- ******************************************************************************/
+-
+-/*
+- * I2C Protocol
+- */
+-#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
+-static const char SysKonnectFileId[] =
+- "@(#) $Id: ski2c.c,v 1.59 2003/10/20 09:07:25 rschmidt Exp $ (C) Marvell. ";
+-#endif
+-
+-#include "h/skdrv1st.h" /* Driver Specific Definitions */
+-#include "h/lm80.h"
+-#include "h/skdrv2nd.h" /* Adapter Control- and Driver specific Def. */
+-
+-#ifdef __C2MAN__
+-/*
+- I2C protocol implementation.
+-
+- General Description:
+-
+- The I2C protocol is used for the temperature sensors and for
+- the serial EEPROM which hold the configuration.
+-
+- This file covers functions that allow to read write and do
+- some bulk requests a specified I2C address.
+-
+- The Genesis has 2 I2C buses. One for the EEPROM which holds
+- the VPD Data and one for temperature and voltage sensor.
+- The following picture shows the I2C buses, I2C devices and
+- their control registers.
+-
+- Note: The VPD functions are in skvpd.c
+-.
+-. PCI Config I2C Bus for VPD Data:
+-.
+-. +------------+
+-. | VPD EEPROM |
+-. +------------+
+-. |
+-. | <-- I2C
+-. |
+-. +-----------+-----------+
+-. | |
+-. +-----------------+ +-----------------+
+-. | PCI_VPD_ADR_REG | | PCI_VPD_DAT_REG |
+-. +-----------------+ +-----------------+
+-.
+-.
+-. I2C Bus for LM80 sensor:
+-.
+-. +-----------------+
+-. | Temperature and |
+-. | Voltage Sensor |
+-. | LM80 |
+-. +-----------------+
+-. |
+-. |
+-. I2C --> |
+-. |
+-. +----+
+-. +-------------->| OR |<--+
+-. | +----+ |
+-. +------+------+ |
+-. | | |
+-. +--------+ +--------+ +----------+
+-. | B2_I2C | | B2_I2C | | B2_I2C |
+-. | _CTRL | | _DATA | | _SW |
+-. +--------+ +--------+ +----------+
+-.
+- The I2C bus may be driven by the B2_I2C_SW or by the B2_I2C_CTRL
+- and B2_I2C_DATA registers.
+- For driver software it is recommended to use the I2C control and
+- data register, because I2C bus timing is done by the ASIC and
+- an interrupt may be received when the I2C request is completed.
+-
+- Clock Rate Timing: MIN MAX generated by
+- VPD EEPROM: 50 kHz 100 kHz HW
+- LM80 over I2C Ctrl/Data reg. 50 kHz 100 kHz HW
+- LM80 over B2_I2C_SW register 0 400 kHz SW
+-
+- Note: The clock generated by the hardware is dependend on the
+- PCI clock. If the PCI bus clock is 33 MHz, the I2C/VPD
+- clock is 50 kHz.
+- */
+-intro()
+-{}
+-#endif
+-
+-#ifdef SK_DIAG
+-/*
+- * I2C Fast Mode timing values used by the LM80.
+- * If new devices are added to the I2C bus the timing values have to be checked.
+- */
+-#ifndef I2C_SLOW_TIMING
+-#define T_CLK_LOW 1300L /* clock low time in ns */
+-#define T_CLK_HIGH 600L /* clock high time in ns */
+-#define T_DATA_IN_SETUP 100L /* data in Set-up Time */
+-#define T_START_HOLD 600L /* start condition hold time */
+-#define T_START_SETUP 600L /* start condition Set-up time */
+-#define T_STOP_SETUP 600L /* stop condition Set-up time */
+-#define T_BUS_IDLE 1300L /* time the bus must free after Tx */
+-#define T_CLK_2_DATA_OUT 900L /* max. clock low to data output valid */
+-#else /* I2C_SLOW_TIMING */
+-/* I2C Standard Mode Timing */
+-#define T_CLK_LOW 4700L /* clock low time in ns */
+-#define T_CLK_HIGH 4000L /* clock high time in ns */
+-#define T_DATA_IN_SETUP 250L /* data in Set-up Time */
+-#define T_START_HOLD 4000L /* start condition hold time */
+-#define T_START_SETUP 4700L /* start condition Set-up time */
+-#define T_STOP_SETUP 4000L /* stop condition Set-up time */
+-#define T_BUS_IDLE 4700L /* time the bus must free after Tx */
+-#endif /* !I2C_SLOW_TIMING */
+-
+-#define NS2BCLK(x) (((x)*125)/10000)
+-
+-/*
+- * I2C Wire Operations
+- *
+- * About I2C_CLK_LOW():
+- *
+- * The Data Direction bit (I2C_DATA_DIR) has to be set to input when setting
+- * clock to low, to prevent the ASIC and the I2C data client from driving the
+- * serial data line simultaneously (ASIC: last bit of a byte = '1', I2C client
+- * send an 'ACK'). See also Concentrator Bugreport No. 10192.
+- */
+-#define I2C_DATA_HIGH(IoC) SK_I2C_SET_BIT(IoC, I2C_DATA)
+-#define I2C_DATA_LOW(IoC) SK_I2C_CLR_BIT(IoC, I2C_DATA)
+-#define I2C_DATA_OUT(IoC) SK_I2C_SET_BIT(IoC, I2C_DATA_DIR)
+-#define I2C_DATA_IN(IoC) SK_I2C_CLR_BIT(IoC, I2C_DATA_DIR | I2C_DATA)
+-#define I2C_CLK_HIGH(IoC) SK_I2C_SET_BIT(IoC, I2C_CLK)
+-#define I2C_CLK_LOW(IoC) SK_I2C_CLR_BIT(IoC, I2C_CLK | I2C_DATA_DIR)
+-#define I2C_START_COND(IoC) SK_I2C_CLR_BIT(IoC, I2C_CLK)
+-
+-#define NS2CLKT(x) ((x*125L)/10000)
+-
+-/*--------------- I2C Interface Register Functions --------------- */
+-
+-/*
+- * sending one bit
+- */
+-void SkI2cSndBit(
+-SK_IOC IoC, /* I/O Context */
+-SK_U8 Bit) /* Bit to send */
+-{
+- I2C_DATA_OUT(IoC);
+- if (Bit) {
+- I2C_DATA_HIGH(IoC);
+- }
+- else {
+- I2C_DATA_LOW(IoC);
+- }
+- SkDgWaitTime(IoC, NS2BCLK(T_DATA_IN_SETUP));
+- I2C_CLK_HIGH(IoC);
+- SkDgWaitTime(IoC, NS2BCLK(T_CLK_HIGH));
+- I2C_CLK_LOW(IoC);
+-} /* SkI2cSndBit*/
+-
+-
+-/*
+- * Signal a start to the I2C Bus.
+- *
+- * A start is signaled when data goes to low in a high clock cycle.
+- *
+- * Ends with Clock Low.
+- *
+- * Status: not tested
+- */
+-void SkI2cStart(
+-SK_IOC IoC) /* I/O Context */
+-{
+- /* Init data and Clock to output lines */
+- /* Set Data high */
+- I2C_DATA_OUT(IoC);
+- I2C_DATA_HIGH(IoC);
+- /* Set Clock high */
+- I2C_CLK_HIGH(IoC);
+-
+- SkDgWaitTime(IoC, NS2BCLK(T_START_SETUP));
+-
+- /* Set Data Low */
+- I2C_DATA_LOW(IoC);
+-
+- SkDgWaitTime(IoC, NS2BCLK(T_START_HOLD));
+-
+- /* Clock low without Data to Input */
+- I2C_START_COND(IoC);
+-
+- SkDgWaitTime(IoC, NS2BCLK(T_CLK_LOW));
+-} /* SkI2cStart */
+-
+-
+-void SkI2cStop(
+-SK_IOC IoC) /* I/O Context */
+-{
+- /* Init data and Clock to output lines */
+- /* Set Data low */
+- I2C_DATA_OUT(IoC);
+- I2C_DATA_LOW(IoC);
+-
+- SkDgWaitTime(IoC, NS2BCLK(T_CLK_2_DATA_OUT));
+-
+- /* Set Clock high */
+- I2C_CLK_HIGH(IoC);
+-
+- SkDgWaitTime(IoC, NS2BCLK(T_STOP_SETUP));
+-
+- /*
+- * Set Data High: Do it by setting the Data Line to Input.
+- * Because of a pull up resistor the Data Line
+- * floods to high.
+- */
+- I2C_DATA_IN(IoC);
+-
+- /*
+- * When I2C activity is stopped
+- * o DATA should be set to input and
+- * o CLOCK should be set to high!
+- */
+- SkDgWaitTime(IoC, NS2BCLK(T_BUS_IDLE));
+-} /* SkI2cStop */
+-
+-
+-/*
+- * Receive just one bit via the I2C bus.
+- *
+- * Note: Clock must be set to LOW before calling this function.
+- *
+- * Returns The received bit.
+- */
+-int SkI2cRcvBit(
+-SK_IOC IoC) /* I/O Context */
+-{
+- int Bit;
+- SK_U8 I2cSwCtrl;
+-
+- /* Init data as input line */
+- I2C_DATA_IN(IoC);
+-
+- SkDgWaitTime(IoC, NS2BCLK(T_CLK_2_DATA_OUT));
+-
+- I2C_CLK_HIGH(IoC);
+-
+- SkDgWaitTime(IoC, NS2BCLK(T_CLK_HIGH));
+-
+- SK_I2C_GET_SW(IoC, &I2cSwCtrl);
+-
+- Bit = (I2cSwCtrl & I2C_DATA) ? 1 : 0;
+-
+- I2C_CLK_LOW(IoC);
+- SkDgWaitTime(IoC, NS2BCLK(T_CLK_LOW-T_CLK_2_DATA_OUT));
+-
+- return(Bit);
+-} /* SkI2cRcvBit */
+-
+-
+-/*
+- * Receive an ACK.
+- *
+- * returns 0 If acknowledged
+- * 1 in case of an error
+- */
+-int SkI2cRcvAck(
+-SK_IOC IoC) /* I/O Context */
+-{
+- /*
+- * Received bit must be zero.
+- */
+- return(SkI2cRcvBit(IoC) != 0);
+-} /* SkI2cRcvAck */
+-
+-
+-/*
+- * Send an NACK.
+- */
+-void SkI2cSndNAck(
+-SK_IOC IoC) /* I/O Context */
+-{
+- /*
+- * Received bit must be zero.
+- */
+- SkI2cSndBit(IoC, 1);
+-} /* SkI2cSndNAck */
+-
+-
+-/*
+- * Send an ACK.
+- */
+-void SkI2cSndAck(
+-SK_IOC IoC) /* I/O Context */
+-{
+- /*
+- * Received bit must be zero.
+- */
+- SkI2cSndBit(IoC, 0);
+-} /* SkI2cSndAck */
+-
+-
+-/*
+- * Send one byte to the I2C device and wait for ACK.
+- *
+- * Return acknowleged status.
+- */
+-int SkI2cSndByte(
+-SK_IOC IoC, /* I/O Context */
+-int Byte) /* byte to send */
+-{
+- int i;
+-
+- for (i = 0; i < 8; i++) {
+- if (Byte & (1<<(7-i))) {
+- SkI2cSndBit(IoC, 1);
+- }
+- else {
+- SkI2cSndBit(IoC, 0);
+- }
+- }
+-
+- return(SkI2cRcvAck(IoC));
+-} /* SkI2cSndByte */
+-
+-
+-/*
+- * Receive one byte and ack it.
+- *
+- * Return byte.
+- */
+-int SkI2cRcvByte(
+-SK_IOC IoC, /* I/O Context */
+-int Last) /* Last Byte Flag */
+-{
+- int i;
+- int Byte = 0;
+-
+- for (i = 0; i < 8; i++) {
+- Byte <<= 1;
+- Byte |= SkI2cRcvBit(IoC);
+- }
+-
+- if (Last) {
+- SkI2cSndNAck(IoC);
+- }
+- else {
+- SkI2cSndAck(IoC);
+- }
+-
+- return(Byte);
+-} /* SkI2cRcvByte */
+-
+-
+-/*
+- * Start dialog and send device address
+- *
+- * Return 0 if acknowleged, 1 in case of an error
+- */
+-int SkI2cSndDev(
+-SK_IOC IoC, /* I/O Context */
+-int Addr, /* Device Address */
+-int Rw) /* Read / Write Flag */
+-{
+- SkI2cStart(IoC);
+- Rw = ~Rw;
+- Rw &= I2C_WRITE;
+- return(SkI2cSndByte(IoC, (Addr<<1) | Rw));
+-} /* SkI2cSndDev */
+-
+-#endif /* SK_DIAG */
+-
+-/*----------------- I2C CTRL Register Functions ----------*/
+-
+-/*
+- * waits for a completion of an I2C transfer
+- *
+- * returns 0: success, transfer completes
+- * 1: error, transfer does not complete, I2C transfer
+- * killed, wait loop terminated.
+- */
+-int SkI2cWait(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* I/O Context */
+-int Event) /* complete event to wait for (I2C_READ or I2C_WRITE) */
+-{
+- SK_U64 StartTime;
+- SK_U64 CurrentTime;
+- SK_U32 I2cCtrl;
+-
+- StartTime = SkOsGetTime(pAC);
+-
+- do {
+- CurrentTime = SkOsGetTime(pAC);
+-
+- if (CurrentTime - StartTime > SK_TICKS_PER_SEC / 8) {
+-
+- SK_I2C_STOP(IoC);
+-#ifndef SK_DIAG
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E002, SKERR_I2C_E002MSG);
+-#endif /* !SK_DIAG */
+- return(1);
+- }
+-
+- SK_I2C_GET_CTL(IoC, &I2cCtrl);
+-
+-#ifdef xYUKON_DBG
+- printf("StartTime=%lu, CurrentTime=%lu\n",
+- StartTime, CurrentTime);
+- if (kbhit()) {
+- return(1);
+- }
+-#endif /* YUKON_DBG */
+-
+- } while ((I2cCtrl & I2C_FLAG) == (SK_U32)Event << 31);
+-
+- return(0);
+-} /* SkI2cWait */
+-
+-
+-/*
+- * waits for a completion of an I2C transfer
+- *
+- * Returns
+- * Nothing
+- */
+-void SkI2cWaitIrq(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC) /* I/O Context */
+-{
+- SK_SENSOR *pSen;
+- SK_U64 StartTime;
+- SK_U32 IrqSrc;
+-
+- pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
+-
+- if (pSen->SenState == SK_SEN_IDLE) {
+- return;
+- }
+-
+- StartTime = SkOsGetTime(pAC);
+-
+- do {
+- if (SkOsGetTime(pAC) - StartTime > SK_TICKS_PER_SEC / 8) {
+-
+- SK_I2C_STOP(IoC);
+-#ifndef SK_DIAG
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E016, SKERR_I2C_E016MSG);
+-#endif /* !SK_DIAG */
+- return;
+- }
+-
+- SK_IN32(IoC, B0_ISRC, &IrqSrc);
+-
+- } while ((IrqSrc & IS_I2C_READY) == 0);
+-
+- pSen->SenState = SK_SEN_IDLE;
+- return;
+-} /* SkI2cWaitIrq */
+-
+-/*
+- * writes a single byte or 4 bytes into the I2C device
+- *
+- * returns 0: success
+- * 1: error
+- */
+-int SkI2cWrite(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* I/O Context */
+-SK_U32 I2cData, /* I2C Data to write */
+-int I2cDev, /* I2C Device Address */
+-int I2cDevSize, /* I2C Device Size (e.g. I2C_025K_DEV or I2C_2K_DEV) */
+-int I2cReg, /* I2C Device Register Address */
+-int I2cBurst) /* I2C Burst Flag */
+-{
+- SK_OUT32(IoC, B2_I2C_DATA, I2cData);
+-
+- SK_I2C_CTL(IoC, I2C_WRITE, I2cDev, I2cDevSize, I2cReg, I2cBurst);
+-
+- return(SkI2cWait(pAC, IoC, I2C_WRITE));
+-} /* SkI2cWrite*/
+-
+-
+-#ifdef SK_DIAG
+-/*
+- * reads a single byte or 4 bytes from the I2C device
+- *
+- * returns the word read
+- */
+-SK_U32 SkI2cRead(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* I/O Context */
+-int I2cDev, /* I2C Device Address */
+-int I2cDevSize, /* I2C Device Size (e.g. I2C_025K_DEV or I2C_2K_DEV) */
+-int I2cReg, /* I2C Device Register Address */
+-int I2cBurst) /* I2C Burst Flag */
+-{
+- SK_U32 Data;
+-
+- SK_OUT32(IoC, B2_I2C_DATA, 0);
+- SK_I2C_CTL(IoC, I2C_READ, I2cDev, I2cDevSize, I2cReg, I2cBurst);
+-
+- if (SkI2cWait(pAC, IoC, I2C_READ) != 0) {
+- w_print("%s\n", SKERR_I2C_E002MSG);
+- }
+-
+- SK_IN32(IoC, B2_I2C_DATA, &Data);
+-
+- return(Data);
+-} /* SkI2cRead */
+-#endif /* SK_DIAG */
+-
+-
+-/*
+- * read a sensor's value
+- *
+- * This function reads a sensor's value from the I2C sensor chip. The sensor
+- * is defined by its index into the sensors database in the struct pAC points
+- * to.
+- * Returns
+- * 1 if the read is completed
+- * 0 if the read must be continued (I2C Bus still allocated)
+- */
+-int SkI2cReadSensor(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* I/O Context */
+-SK_SENSOR *pSen) /* Sensor to be read */
+-{
+- if (pSen->SenRead != NULL) {
+- return((*pSen->SenRead)(pAC, IoC, pSen));
+- }
+- else {
+- return(0); /* no success */
+- }
+-} /* SkI2cReadSensor */
+-
+-/*
+- * Do the Init state 0 initialization
+- */
+-static int SkI2cInit0(
+-SK_AC *pAC) /* Adapter Context */
+-{
+- int i;
+-
+- /* Begin with first sensor */
+- pAC->I2c.CurrSens = 0;
+-
+- /* Begin with timeout control for state machine */
+- pAC->I2c.TimerMode = SK_TIMER_WATCH_SM;
+-
+- /* Set sensor number to zero */
+- pAC->I2c.MaxSens = 0;
+-
+-#ifndef SK_DIAG
+- /* Initialize Number of Dummy Reads */
+- pAC->I2c.DummyReads = SK_MAX_SENSORS;
+-#endif
+-
+- for (i = 0; i < SK_MAX_SENSORS; i++) {
+- pAC->I2c.SenTable[i].SenDesc = "unknown";
+- pAC->I2c.SenTable[i].SenType = SK_SEN_UNKNOWN;
+- pAC->I2c.SenTable[i].SenThreErrHigh = 0;
+- pAC->I2c.SenTable[i].SenThreErrLow = 0;
+- pAC->I2c.SenTable[i].SenThreWarnHigh = 0;
+- pAC->I2c.SenTable[i].SenThreWarnLow = 0;
+- pAC->I2c.SenTable[i].SenReg = LM80_FAN2_IN;
+- pAC->I2c.SenTable[i].SenInit = SK_SEN_DYN_INIT_NONE;
+- pAC->I2c.SenTable[i].SenValue = 0;
+- pAC->I2c.SenTable[i].SenErrFlag = SK_SEN_ERR_NOT_PRESENT;
+- pAC->I2c.SenTable[i].SenErrCts = 0;
+- pAC->I2c.SenTable[i].SenBegErrTS = 0;
+- pAC->I2c.SenTable[i].SenState = SK_SEN_IDLE;
+- pAC->I2c.SenTable[i].SenRead = NULL;
+- pAC->I2c.SenTable[i].SenDev = 0;
+- }
+-
+- /* Now we are "INIT data"ed */
+- pAC->I2c.InitLevel = SK_INIT_DATA;
+- return(0);
+-} /* SkI2cInit0*/
+-
+-
+-/*
+- * Do the init state 1 initialization
+- *
+- * initialize the following register of the LM80:
+- * Configuration register:
+- * - START, noINT, activeLOW, noINT#Clear, noRESET, noCI, noGPO#, noINIT
+- *
+- * Interrupt Mask Register 1:
+- * - all interrupts are Disabled (0xff)
+- *
+- * Interrupt Mask Register 2:
+- * - all interrupts are Disabled (0xff) Interrupt modi doesn't matter.
+- *
+- * Fan Divisor/RST_OUT register:
+- * - Divisors set to 1 (bits 00), all others 0s.
+- *
+- * OS# Configuration/Temperature resolution Register:
+- * - all 0s
+- *
+- */
+-static int SkI2cInit1(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC) /* I/O Context */
+-{
+- int i;
+- SK_U8 I2cSwCtrl;
+- SK_GEPORT *pPrt; /* GIni Port struct pointer */
+-
+- if (pAC->I2c.InitLevel != SK_INIT_DATA) {
+- /* ReInit not needed in I2C module */
+- return(0);
+- }
+-
+- /* Set the Direction of I2C-Data Pin to IN */
+- SK_I2C_CLR_BIT(IoC, I2C_DATA_DIR | I2C_DATA);
+- /* Check for 32-Bit Yukon with Low at I2C-Data Pin */
+- SK_I2C_GET_SW(IoC, &I2cSwCtrl);
+-
+- if ((I2cSwCtrl & I2C_DATA) == 0) {
+- /* this is a 32-Bit board */
+- pAC->GIni.GIYukon32Bit = SK_TRUE;
+- return(0);
+- }
+-
+- /* Check for 64 Bit Yukon without sensors */
+- if (SkI2cWrite(pAC, IoC, 0, LM80_ADDR, I2C_025K_DEV, LM80_CFG, 0) != 0) {
+- return(0);
+- }
+-
+- (void)SkI2cWrite(pAC, IoC, 0xffUL, LM80_ADDR, I2C_025K_DEV, LM80_IMSK_1, 0);
+-
+- (void)SkI2cWrite(pAC, IoC, 0xffUL, LM80_ADDR, I2C_025K_DEV, LM80_IMSK_2, 0);
+-
+- (void)SkI2cWrite(pAC, IoC, 0, LM80_ADDR, I2C_025K_DEV, LM80_FAN_CTRL, 0);
+-
+- (void)SkI2cWrite(pAC, IoC, 0, LM80_ADDR, I2C_025K_DEV, LM80_TEMP_CTRL, 0);
+-
+- (void)SkI2cWrite(pAC, IoC, (SK_U32)LM80_CFG_START, LM80_ADDR, I2C_025K_DEV,
+- LM80_CFG, 0);
+-
+- /*
+- * MaxSens has to be updated here, because PhyType is not
+- * set when performing Init Level 0
+- */
+- pAC->I2c.MaxSens = 5;
+-
+- pPrt = &pAC->GIni.GP[0];
+-
+- if (pAC->GIni.GIGenesis) {
+- if (pPrt->PhyType == SK_PHY_BCOM) {
+- if (pAC->GIni.GIMacsFound == 1) {
+- pAC->I2c.MaxSens += 1;
+- }
+- else {
+- pAC->I2c.MaxSens += 3;
+- }
+- }
+- }
+- else {
+- pAC->I2c.MaxSens += 3;
+- }
+-
+- for (i = 0; i < pAC->I2c.MaxSens; i++) {
+- switch (i) {
+- case 0:
+- pAC->I2c.SenTable[i].SenDesc = "Temperature";
+- pAC->I2c.SenTable[i].SenType = SK_SEN_TEMP;
+- pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_TEMP_HIGH_ERR;
+- pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_TEMP_HIGH_WARN;
+- pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_TEMP_LOW_WARN;
+- pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_TEMP_LOW_ERR;
+- pAC->I2c.SenTable[i].SenReg = LM80_TEMP_IN;
+- break;
+- case 1:
+- pAC->I2c.SenTable[i].SenDesc = "Voltage PCI";
+- pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
+- pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PCI_5V_HIGH_ERR;
+- pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PCI_5V_HIGH_WARN;
+- pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PCI_5V_LOW_WARN;
+- pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PCI_5V_LOW_ERR;
+- pAC->I2c.SenTable[i].SenReg = LM80_VT0_IN;
+- break;
+- case 2:
+- pAC->I2c.SenTable[i].SenDesc = "Voltage PCI-IO";
+- pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
+- pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PCI_IO_5V_HIGH_ERR;
+- pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PCI_IO_5V_HIGH_WARN;
+- pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PCI_IO_3V3_LOW_WARN;
+- pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PCI_IO_3V3_LOW_ERR;
+- pAC->I2c.SenTable[i].SenReg = LM80_VT1_IN;
+- pAC->I2c.SenTable[i].SenInit = SK_SEN_DYN_INIT_PCI_IO;
+- break;
+- case 3:
+- pAC->I2c.SenTable[i].SenDesc = "Voltage ASIC";
+- pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
+- pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_VDD_HIGH_ERR;
+- pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_VDD_HIGH_WARN;
+- pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_VDD_LOW_WARN;
+- pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_VDD_LOW_ERR;
+- pAC->I2c.SenTable[i].SenReg = LM80_VT2_IN;
+- break;
+- case 4:
+- if (pAC->GIni.GIGenesis) {
+- if (pPrt->PhyType == SK_PHY_BCOM) {
+- pAC->I2c.SenTable[i].SenDesc = "Voltage PHY A PLL";
+- pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PLL_3V3_HIGH_ERR;
+- pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PLL_3V3_HIGH_WARN;
+- pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PLL_3V3_LOW_WARN;
+- pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PLL_3V3_LOW_ERR;
+- }
+- else {
+- pAC->I2c.SenTable[i].SenDesc = "Voltage PMA";
+- pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PLL_3V3_HIGH_ERR;
+- pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PLL_3V3_HIGH_WARN;
+- pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PLL_3V3_LOW_WARN;
+- pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PLL_3V3_LOW_ERR;
+- }
+- }
+- else {
+- pAC->I2c.SenTable[i].SenDesc = "Voltage VAUX";
+- pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_VAUX_3V3_HIGH_ERR;
+- pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_VAUX_3V3_HIGH_WARN;
+- if (pAC->GIni.GIVauxAvail) {
+- pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_VAUX_3V3_LOW_WARN;
+- pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_VAUX_3V3_LOW_ERR;
+- }
+- else {
+- pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_VAUX_0V_WARN_ERR;
+- pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_VAUX_0V_WARN_ERR;
+- }
+- }
+- pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
+- pAC->I2c.SenTable[i].SenReg = LM80_VT3_IN;
+- break;
+- case 5:
+- if (pAC->GIni.GIGenesis) {
+- pAC->I2c.SenTable[i].SenDesc = "Voltage PHY 2V5";
+- pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PHY_2V5_HIGH_ERR;
+- pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PHY_2V5_HIGH_WARN;
+- pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PHY_2V5_LOW_WARN;
+- pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PHY_2V5_LOW_ERR;
+- }
+- else {
+- pAC->I2c.SenTable[i].SenDesc = "Voltage Core 1V5";
+- pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_CORE_1V5_HIGH_ERR;
+- pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_CORE_1V5_HIGH_WARN;
+- pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_CORE_1V5_LOW_WARN;
+- pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_CORE_1V5_LOW_ERR;
+- }
+- pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
+- pAC->I2c.SenTable[i].SenReg = LM80_VT4_IN;
+- break;
+- case 6:
+- if (pAC->GIni.GIGenesis) {
+- pAC->I2c.SenTable[i].SenDesc = "Voltage PHY B PLL";
+- }
+- else {
+- pAC->I2c.SenTable[i].SenDesc = "Voltage PHY 3V3";
+- }
+- pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
+- pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PLL_3V3_HIGH_ERR;
+- pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PLL_3V3_HIGH_WARN;
+- pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PLL_3V3_LOW_WARN;
+- pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PLL_3V3_LOW_ERR;
+- pAC->I2c.SenTable[i].SenReg = LM80_VT5_IN;
+- break;
+- case 7:
+- if (pAC->GIni.GIGenesis) {
+- pAC->I2c.SenTable[i].SenDesc = "Speed Fan";
+- pAC->I2c.SenTable[i].SenType = SK_SEN_FAN;
+- pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_FAN_HIGH_ERR;
+- pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_FAN_HIGH_WARN;
+- pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_FAN_LOW_WARN;
+- pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_FAN_LOW_ERR;
+- pAC->I2c.SenTable[i].SenReg = LM80_FAN2_IN;
+- }
+- else {
+- pAC->I2c.SenTable[i].SenDesc = "Voltage PHY 2V5";
+- pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT;
+- pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PHY_2V5_HIGH_ERR;
+- pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PHY_2V5_HIGH_WARN;
+- pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PHY_2V5_LOW_WARN;
+- pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PHY_2V5_LOW_ERR;
+- pAC->I2c.SenTable[i].SenReg = LM80_VT6_IN;
+- }
+- break;
+- default:
+- SK_ERR_LOG(pAC, SK_ERRCL_INIT | SK_ERRCL_SW,
+- SKERR_I2C_E001, SKERR_I2C_E001MSG);
+- break;
+- }
+-
+- pAC->I2c.SenTable[i].SenValue = 0;
+- pAC->I2c.SenTable[i].SenErrFlag = SK_SEN_ERR_OK;
+- pAC->I2c.SenTable[i].SenErrCts = 0;
+- pAC->I2c.SenTable[i].SenBegErrTS = 0;
+- pAC->I2c.SenTable[i].SenState = SK_SEN_IDLE;
+- pAC->I2c.SenTable[i].SenRead = SkLm80ReadSensor;
+- pAC->I2c.SenTable[i].SenDev = LM80_ADDR;
+- }
+-
+-#ifndef SK_DIAG
+- pAC->I2c.DummyReads = pAC->I2c.MaxSens;
+-#endif /* !SK_DIAG */
+-
+- /* Clear I2C IRQ */
+- SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ);
+-
+- /* Now we are I/O initialized */
+- pAC->I2c.InitLevel = SK_INIT_IO;
+- return(0);
+-} /* SkI2cInit1 */
+-
+-
+-/*
+- * Init level 2: Start first sensor read.
+- */
+-static int SkI2cInit2(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC) /* I/O Context */
+-{
+- int ReadComplete;
+- SK_SENSOR *pSen;
+-
+- if (pAC->I2c.InitLevel != SK_INIT_IO) {
+- /* ReInit not needed in I2C module */
+- /* Init0 and Init2 not permitted */
+- return(0);
+- }
+-
+- pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
+- ReadComplete = SkI2cReadSensor(pAC, IoC, pSen);
+-
+- if (ReadComplete) {
+- SK_ERR_LOG(pAC, SK_ERRCL_INIT, SKERR_I2C_E008, SKERR_I2C_E008MSG);
+- }
+-
+- /* Now we are correctly initialized */
+- pAC->I2c.InitLevel = SK_INIT_RUN;
+-
+- return(0);
+-} /* SkI2cInit2*/
+-
+-
+-/*
+- * Initialize I2C devices
+- *
+- * Get the first voltage value and discard it.
+- * Go into temperature read mode. A default pointer is not set.
+- *
+- * The things to be done depend on the init level in the parameter list:
+- * Level 0:
+- * Initialize only the data structures. Do NOT access hardware.
+- * Level 1:
+- * Initialize hardware through SK_IN / SK_OUT commands. Do NOT use interrupts.
+- * Level 2:
+- * Everything is possible. Interrupts may be used from now on.
+- *
+- * return:
+- * 0 = success
+- * other = error.
+- */
+-int SkI2cInit(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* I/O Context needed in levels 1 and 2 */
+-int Level) /* Init Level */
+-{
+-
+- switch (Level) {
+- case SK_INIT_DATA:
+- return(SkI2cInit0(pAC));
+- case SK_INIT_IO:
+- return(SkI2cInit1(pAC, IoC));
+- case SK_INIT_RUN:
+- return(SkI2cInit2(pAC, IoC));
+- default:
+- break;
+- }
+-
+- return(0);
+-} /* SkI2cInit */
+-
+-
+-#ifndef SK_DIAG
+-
+-/*
+- * Interrupt service function for the I2C Interface
+- *
+- * Clears the Interrupt source
+- *
+- * Reads the register and check it for sending a trap.
+- *
+- * Starts the timer if necessary.
+- */
+-void SkI2cIsr(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC) /* I/O Context */
+-{
+- SK_EVPARA Para;
+-
+- /* Clear I2C IRQ */
+- SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ);
+-
+- Para.Para64 = 0;
+- SkEventQueue(pAC, SKGE_I2C, SK_I2CEV_IRQ, Para);
+-} /* SkI2cIsr */
+-
+-
+-/*
+- * Check this sensors Value against the threshold and send events.
+- */
+-static void SkI2cCheckSensor(
+-SK_AC *pAC, /* Adapter Context */
+-SK_SENSOR *pSen)
+-{
+- SK_EVPARA ParaLocal;
+- SK_BOOL TooHigh; /* Is sensor too high? */
+- SK_BOOL TooLow; /* Is sensor too low? */
+- SK_U64 CurrTime; /* Current Time */
+- SK_BOOL DoTrapSend; /* We need to send a trap */
+- SK_BOOL DoErrLog; /* We need to log the error */
+- SK_BOOL IsError; /* We need to log the error */
+-
+- /* Check Dummy Reads first */
+- if (pAC->I2c.DummyReads > 0) {
+- pAC->I2c.DummyReads--;
+- return;
+- }
+-
+- /* Get the current time */
+- CurrTime = SkOsGetTime(pAC);
+-
+- /* Set para to the most useful setting: The current sensor. */
+- ParaLocal.Para64 = (SK_U64)pAC->I2c.CurrSens;
+-
+- /* Check the Value against the thresholds. First: Error Thresholds */
+- TooHigh = (pSen->SenValue > pSen->SenThreErrHigh);
+- TooLow = (pSen->SenValue < pSen->SenThreErrLow);
+-
+- IsError = SK_FALSE;
+- if (TooHigh || TooLow) {
+- /* Error condition is satisfied */
+- DoTrapSend = SK_TRUE;
+- DoErrLog = SK_TRUE;
+-
+- /* Now error condition is satisfied */
+- IsError = SK_TRUE;
+-
+- if (pSen->SenErrFlag == SK_SEN_ERR_ERR) {
+- /* This state is the former one */
+-
+- /* So check first whether we have to send a trap */
+- if (pSen->SenLastErrTrapTS + SK_SEN_ERR_TR_HOLD >
+- CurrTime) {
+- /*
+- * Do NOT send the Trap. The hold back time
+- * has to run out first.
+- */
+- DoTrapSend = SK_FALSE;
+- }
+-
+- /* Check now whether we have to log an Error */
+- if (pSen->SenLastErrLogTS + SK_SEN_ERR_LOG_HOLD >
+- CurrTime) {
+- /*
+- * Do NOT log the error. The hold back time
+- * has to run out first.
+- */
+- DoErrLog = SK_FALSE;
+- }
+- }
+- else {
+- /* We came from a different state -> Set Begin Time Stamp */
+- pSen->SenBegErrTS = CurrTime;
+- pSen->SenErrFlag = SK_SEN_ERR_ERR;
+- }
+-
+- if (DoTrapSend) {
+- /* Set current Time */
+- pSen->SenLastErrTrapTS = CurrTime;
+- pSen->SenErrCts++;
+-
+- /* Queue PNMI Event */
+- SkEventQueue(pAC, SKGE_PNMI, (TooHigh ?
+- SK_PNMI_EVT_SEN_ERR_UPP :
+- SK_PNMI_EVT_SEN_ERR_LOW),
+- ParaLocal);
+- }
+-
+- if (DoErrLog) {
+- /* Set current Time */
+- pSen->SenLastErrLogTS = CurrTime;
+-
+- if (pSen->SenType == SK_SEN_TEMP) {
+- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E011, SKERR_I2C_E011MSG);
+- }
+- else if (pSen->SenType == SK_SEN_VOLT) {
+- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E012, SKERR_I2C_E012MSG);
+- }
+- else {
+- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E015, SKERR_I2C_E015MSG);
+- }
+- }
+- }
+-
+- /* Check the Value against the thresholds */
+- /* 2nd: Warning thresholds */
+- TooHigh = (pSen->SenValue > pSen->SenThreWarnHigh);
+- TooLow = (pSen->SenValue < pSen->SenThreWarnLow);
+-
+- if (!IsError && (TooHigh || TooLow)) {
+- /* Error condition is satisfied */
+- DoTrapSend = SK_TRUE;
+- DoErrLog = SK_TRUE;
+-
+- if (pSen->SenErrFlag == SK_SEN_ERR_WARN) {
+- /* This state is the former one */
+-
+- /* So check first whether we have to send a trap */
+- if (pSen->SenLastWarnTrapTS + SK_SEN_WARN_TR_HOLD > CurrTime) {
+- /*
+- * Do NOT send the Trap. The hold back time
+- * has to run out first.
+- */
+- DoTrapSend = SK_FALSE;
+- }
+-
+- /* Check now whether we have to log an Error */
+- if (pSen->SenLastWarnLogTS + SK_SEN_WARN_LOG_HOLD > CurrTime) {
+- /*
+- * Do NOT log the error. The hold back time
+- * has to run out first.
+- */
+- DoErrLog = SK_FALSE;
+- }
+- }
+- else {
+- /* We came from a different state -> Set Begin Time Stamp */
+- pSen->SenBegWarnTS = CurrTime;
+- pSen->SenErrFlag = SK_SEN_ERR_WARN;
+- }
+-
+- if (DoTrapSend) {
+- /* Set current Time */
+- pSen->SenLastWarnTrapTS = CurrTime;
+- pSen->SenWarnCts++;
+-
+- /* Queue PNMI Event */
+- SkEventQueue(pAC, SKGE_PNMI, (TooHigh ?
+- SK_PNMI_EVT_SEN_WAR_UPP :
+- SK_PNMI_EVT_SEN_WAR_LOW),
+- ParaLocal);
+- }
+-
+- if (DoErrLog) {
+- /* Set current Time */
+- pSen->SenLastWarnLogTS = CurrTime;
+-
+- if (pSen->SenType == SK_SEN_TEMP) {
+- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E009, SKERR_I2C_E009MSG);
+- }
+- else if (pSen->SenType == SK_SEN_VOLT) {
+- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E010, SKERR_I2C_E010MSG);
+- }
+- else {
+- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E014, SKERR_I2C_E014MSG);
+- }
+- }
+- }
+-
+- /* Check for NO error at all */
+- if (!IsError && !TooHigh && !TooLow) {
+- /* Set o.k. Status if no error and no warning condition */
+- pSen->SenErrFlag = SK_SEN_ERR_OK;
+- }
+-
+- /* End of check against the thresholds */
+-
+- /* Bug fix AF: 16.Aug.2001: Correct the init base
+- * of LM80 sensor.
+- */
+- if (pSen->SenInit == SK_SEN_DYN_INIT_PCI_IO) {
+-
+- pSen->SenInit = SK_SEN_DYN_INIT_NONE;
+-
+- if (pSen->SenValue > SK_SEN_PCI_IO_RANGE_LIMITER) {
+- /* 5V PCI-IO Voltage */
+- pSen->SenThreWarnLow = SK_SEN_PCI_IO_5V_LOW_WARN;
+- pSen->SenThreErrLow = SK_SEN_PCI_IO_5V_LOW_ERR;
+- }
+- else {
+- /* 3.3V PCI-IO Voltage */
+- pSen->SenThreWarnHigh = SK_SEN_PCI_IO_3V3_HIGH_WARN;
+- pSen->SenThreErrHigh = SK_SEN_PCI_IO_3V3_HIGH_ERR;
+- }
+- }
+-
+-#ifdef TEST_ONLY
+- /* Dynamic thresholds also for VAUX of LM80 sensor */
+- if (pSen->SenInit == SK_SEN_DYN_INIT_VAUX) {
+-
+- pSen->SenInit = SK_SEN_DYN_INIT_NONE;
+-
+- /* 3.3V VAUX Voltage */
+- if (pSen->SenValue > SK_SEN_VAUX_RANGE_LIMITER) {
+- pSen->SenThreWarnLow = SK_SEN_VAUX_3V3_LOW_WARN;
+- pSen->SenThreErrLow = SK_SEN_VAUX_3V3_LOW_ERR;
+- }
+- /* 0V VAUX Voltage */
+- else {
+- pSen->SenThreWarnHigh = SK_SEN_VAUX_0V_WARN_ERR;
+- pSen->SenThreErrHigh = SK_SEN_VAUX_0V_WARN_ERR;
+- }
+- }
+-
+- /*
+- * Check initialization state:
+- * The VIO Thresholds need adaption
+- */
+- if (!pSen->SenInit && pSen->SenReg == LM80_VT1_IN &&
+- pSen->SenValue > SK_SEN_WARNLOW2C &&
+- pSen->SenValue < SK_SEN_WARNHIGH2) {
+- pSen->SenThreErrLow = SK_SEN_ERRLOW2C;
+- pSen->SenThreWarnLow = SK_SEN_WARNLOW2C;
+- pSen->SenInit = SK_TRUE;
+- }
+-
+- if (!pSen->SenInit && pSen->SenReg == LM80_VT1_IN &&
+- pSen->SenValue > SK_SEN_WARNLOW2 &&
+- pSen->SenValue < SK_SEN_WARNHIGH2C) {
+- pSen->SenThreErrHigh = SK_SEN_ERRHIGH2C;
+- pSen->SenThreWarnHigh = SK_SEN_WARNHIGH2C;
+- pSen->SenInit = SK_TRUE;
+- }
+-#endif
+-
+- if (pSen->SenInit != SK_SEN_DYN_INIT_NONE) {
+- SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E013, SKERR_I2C_E013MSG);
+- }
+-} /* SkI2cCheckSensor */
+-
+-
+-/*
+- * The only Event to be served is the timeout event
+- *
+- */
+-int SkI2cEvent(
+-SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* I/O Context */
+-SK_U32 Event, /* Module specific Event */
+-SK_EVPARA Para) /* Event specific Parameter */
+-{
+- int ReadComplete;
+- SK_SENSOR *pSen;
+- SK_U32 Time;
+- SK_EVPARA ParaLocal;
+- int i;
+-
+- /* New case: no sensors */
+- if (pAC->I2c.MaxSens == 0) {
+- return(0);
+- }
+-
+- switch (Event) {
+- case SK_I2CEV_IRQ:
+- pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
+- ReadComplete = SkI2cReadSensor(pAC, IoC, pSen);
+-
+- if (ReadComplete) {
+- /* Check sensor against defined thresholds */
+- SkI2cCheckSensor(pAC, pSen);
+-
+- /* Increment Current sensor and set appropriate Timeout */
+- pAC->I2c.CurrSens++;
+- if (pAC->I2c.CurrSens >= pAC->I2c.MaxSens) {
+- pAC->I2c.CurrSens = 0;
+- Time = SK_I2C_TIM_LONG;
+- }
+- else {
+- Time = SK_I2C_TIM_SHORT;
+- }
+-
+- /* Start Timer */
+- ParaLocal.Para64 = (SK_U64)0;
+-
+- pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING;
+-
+- SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time,
+- SKGE_I2C, SK_I2CEV_TIM, ParaLocal);
+- }
+- else {
+- /* Start Timer */
+- ParaLocal.Para64 = (SK_U64)0;
+-
+- pAC->I2c.TimerMode = SK_TIMER_WATCH_SM;
+-
+- SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, SK_I2C_TIM_WATCH,
+- SKGE_I2C, SK_I2CEV_TIM, ParaLocal);
+- }
+- break;
+- case SK_I2CEV_TIM:
+- if (pAC->I2c.TimerMode == SK_TIMER_NEW_GAUGING) {
+-
+- ParaLocal.Para64 = (SK_U64)0;
+- SkTimerStop(pAC, IoC, &pAC->I2c.SenTimer);
+-
+- pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
+- ReadComplete = SkI2cReadSensor(pAC, IoC, pSen);
+-
+- if (ReadComplete) {
+- /* Check sensor against defined thresholds */
+- SkI2cCheckSensor(pAC, pSen);
+-
+- /* Increment Current sensor and set appropriate Timeout */
+- pAC->I2c.CurrSens++;
+- if (pAC->I2c.CurrSens == pAC->I2c.MaxSens) {
+- pAC->I2c.CurrSens = 0;
+- Time = SK_I2C_TIM_LONG;
+- }
+- else {
+- Time = SK_I2C_TIM_SHORT;
+- }
+-
+- /* Start Timer */
+- ParaLocal.Para64 = (SK_U64)0;
+-
+- pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING;
+-
+- SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time,
+- SKGE_I2C, SK_I2CEV_TIM, ParaLocal);
+- }
+- }
+- else {
+- pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
+- pSen->SenErrFlag = SK_SEN_ERR_FAULTY;
+- SK_I2C_STOP(IoC);
+-
+- /* Increment Current sensor and set appropriate Timeout */
+- pAC->I2c.CurrSens++;
+- if (pAC->I2c.CurrSens == pAC->I2c.MaxSens) {
+- pAC->I2c.CurrSens = 0;
+- Time = SK_I2C_TIM_LONG;
+- }
+- else {
+- Time = SK_I2C_TIM_SHORT;
+- }
+-
+- /* Start Timer */
+- ParaLocal.Para64 = (SK_U64)0;
+-
+- pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING;
+-
+- SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time,
+- SKGE_I2C, SK_I2CEV_TIM, ParaLocal);
+- }
+- break;
+- case SK_I2CEV_CLEAR:
+- for (i = 0; i < SK_MAX_SENSORS; i++) {
+- pAC->I2c.SenTable[i].SenErrFlag = SK_SEN_ERR_OK;
+- pAC->I2c.SenTable[i].SenErrCts = 0;
+- pAC->I2c.SenTable[i].SenWarnCts = 0;
+- pAC->I2c.SenTable[i].SenBegErrTS = 0;
+- pAC->I2c.SenTable[i].SenBegWarnTS = 0;
+- pAC->I2c.SenTable[i].SenLastErrTrapTS = (SK_U64)0;
+- pAC->I2c.SenTable[i].SenLastErrLogTS = (SK_U64)0;
+- pAC->I2c.SenTable[i].SenLastWarnTrapTS = (SK_U64)0;
+- pAC->I2c.SenTable[i].SenLastWarnLogTS = (SK_U64)0;
+- }
+- break;
+- default:
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E006, SKERR_I2C_E006MSG);
+- }
+-
+- return(0);
+-} /* SkI2cEvent*/
+-
+-#endif /* !SK_DIAG */
+diff -ruN linux/drivers/net/sk98lin/sklm80.c linux-new/drivers/net/sk98lin/sklm80.c
+--- linux/drivers/net/sk98lin/sklm80.c 2005-09-26 13:32:48.000000000 +0400
++++ linux-new/drivers/net/sk98lin/sklm80.c 2005-08-09 17:15:51.000000000 +0400
+@@ -2,8 +2,8 @@
+ *
+ * Name: sklm80.c
+ * Project: Gigabit Ethernet Adapters, TWSI-Module
+- * Version: $Revision: 1.22 $
+- * Date: $Date: 2003/10/20 09:08:21 $
++ * Version: $Revision: 1.1 $
++ * Date: $Date: 2003/12/19 14:02:31 $
+ * Purpose: Functions to access Voltage and Temperature Sensor (LM80)
+ *
+ ******************************************************************************/
+@@ -27,7 +27,7 @@
+ */
+ #if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
+ static const char SysKonnectFileId[] =
+- "@(#) $Id: sklm80.c,v 1.22 2003/10/20 09:08:21 rschmidt Exp $ (C) Marvell. ";
++ "@(#) $Id: sklm80.c,v 1.1 2003/12/19 14:02:31 mschmid Exp $ (C) Marvell. ";
+ #endif
+
+ #include "h/skdrv1st.h" /* Driver Specific Definitions */
+@@ -111,12 +111,12 @@
+ /*
+ * read a sensors value (LM80 specific)
+ *
+- * This function reads a sensors value from the I2C sensor chip LM80.
++ * This function reads a sensors value from the TWSI sensor chip LM80.
+ * The sensor is defined by its index into the sensors database in the struct
+ * pAC points to.
+ *
+ * Returns 1 if the read is completed
+- * 0 if the read must be continued (I2C Bus still allocated)
++ * 0 if the read must be continued (TWSI Bus still allocated)
+ */
+ int SkLm80ReadSensor(
+ SK_AC *pAC, /* Adapter Context */
+diff -ruN linux/drivers/net/sk98lin/skproc.c linux-new/drivers/net/sk98lin/skproc.c
+--- linux/drivers/net/sk98lin/skproc.c 2005-09-26 13:32:48.000000000 +0400
++++ linux-new/drivers/net/sk98lin/skproc.c 2005-08-09 17:15:51.000000000 +0400
+@@ -2,28 +2,34 @@
+ *
+ * Name: skproc.c
+ * Project: GEnesis, PCI Gigabit Ethernet Adapter
+- * Version: $Revision: 1.11 $
+- * Date: $Date: 2003/12/11 16:03:57 $
+- * Purpose: Funktions to display statictic data
++ * Version: $Revision: 1.14.2.4 $
++ * Date: $Date: 2005/05/23 13:47:33 $
++ * Purpose: Functions to display statictic data
+ *
+ ******************************************************************************/
+
+ /******************************************************************************
+ *
+ * (C)Copyright 1998-2002 SysKonnect GmbH.
+- * (C)Copyright 2002-2003 Marvell.
++ * (C)Copyright 2002-2005 Marvell.
++ *
++ * Driver for Marvell Yukon/2 chipset and SysKonnect Gigabit Ethernet
++ * Server Adapters.
++ *
++ * Author: Ralph Roesler (rroesler@syskonnect.de)
++ * Mirko Lindner (mlindner@syskonnect.de)
++ *
++ * Address all question to: linux@syskonnect.de
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+- * Created 22-Nov-2000
+- * Author: Mirko Lindner (mlindner@syskonnect.de)
+- *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+- ******************************************************************************/
++ *****************************************************************************/
++
+ #include <linux/proc_fs.h>
+ #include <linux/seq_file.h>
+
+@@ -32,9 +38,16 @@
+ #include "h/skversion.h"
+
+ extern struct SK_NET_DEVICE *SkGeRootDev;
++
++/******************************************************************************
++ *
++ * Local Function Prototypes and Local Variables
++ *
++ *****************************************************************************/
++
+ static int sk_proc_print(void *writePtr, char *format, ...);
+ static void sk_gen_browse(void *buffer);
+-int len;
++static int len;
+
+ static int sk_seq_show(struct seq_file *seq, void *v);
+ static int sk_proc_open(struct inode *inode, struct file *file);
+@@ -52,16 +65,18 @@
+ * sk_gen_browse -generic print "summaries" entry
+ *
+ * Description:
+- * This function fills the proc entry with statistic data about
+- * the ethernet device.
++ * This function fills the proc entry with statistic data about
++ * the ethernet device.
+ *
+- * Returns: -
++ * Returns: N/A
+ *
+ */
+-static void sk_gen_browse(void *buffer)
++static void sk_gen_browse(
++void *buffer) /* buffer where the statistics will be stored in */
+ {
+ struct SK_NET_DEVICE *SkgeProcDev = SkGeRootDev;
+ struct SK_NET_DEVICE *next;
++ SK_BOOL DisableStatistic = 0;
+ SK_PNMI_STRUCT_DATA *pPnmiStruct;
+ SK_PNMI_STAT *pPnmiStat;
+ unsigned long Flags;
+@@ -69,6 +84,7 @@
+ DEV_NET *pNet;
+ SK_AC *pAC;
+ char sens_msg[50];
++ int card_type;
+ int MaxSecurityCount = 0;
+ int t;
+ int i;
+@@ -91,7 +107,7 @@
+
+ spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+ Size = SK_PNMI_STRUCT_SIZE;
+-#ifdef SK_DIAG_SUPPORT
++ DisableStatistic = 0;
+ if (pAC->BoardLevel == SK_INIT_DATA) {
+ SK_MEMCPY(&(pAC->PnmiStruct), &(pAC->PnmiBackup), sizeof(SK_PNMI_STRUCT_DATA));
+ if (pAC->DiagModeActive == DIAG_NOTACTIVE) {
+@@ -100,13 +116,13 @@
+ } else {
+ SkPnmiGetStruct(pAC, pAC->IoBase, pPnmiStruct, &Size, t-1);
+ }
+-#else
+- SkPnmiGetStruct(pAC, pAC->IoBase,
+- pPnmiStruct, &Size, t-1);
+-#endif
+ spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+-
+ if (strcmp(pAC->dev[t-1]->name, currDev->name) == 0) {
++ if (!pAC->GIni.GIYukon32Bit)
++ card_type = 64;
++ else
++ card_type = 32;
++
+ pPnmiStat = &pPnmiStruct->Stat[0];
+ len = sk_proc_print(buffer,
+ "\nDetailed statistic for device %s\n",
+@@ -118,6 +134,17 @@
+ len += sk_proc_print(buffer,
+ "\nBoard statistics\n\n");
+ len += sk_proc_print(buffer,
++ "Card name %s\n",
++ pAC->DeviceStr);
++ len += sk_proc_print(buffer,
++ "Vendor/Device ID %x/%x\n",
++ pAC->PciDev->vendor,
++ pAC->PciDev->device);
++ len += sk_proc_print(buffer,
++ "Card type (Bit) %d\n",
++ card_type);
++
++ len += sk_proc_print(buffer,
+ "Active Port %c\n",
+ 'A' + pAC->Rlmt.Net[t-1].Port[pAC->Rlmt.
+ Net[t-1].PrefPort]->PortNumber);
+@@ -126,177 +153,239 @@
+ 'A' + pAC->Rlmt.Net[t-1].Port[pAC->Rlmt.
+ Net[t-1].PrefPort]->PortNumber);
+
+- len += sk_proc_print(buffer,
+- "Bus speed (MHz) %d\n",
+- pPnmiStruct->BusSpeed);
+-
+- len += sk_proc_print(buffer,
+- "Bus width (Bit) %d\n",
+- pPnmiStruct->BusWidth);
+- len += sk_proc_print(buffer,
+- "Driver version %s\n",
+- VER_STRING);
+- len += sk_proc_print(buffer,
+- "Hardware revision v%d.%d\n",
+- (pAC->GIni.GIPciHwRev >> 4) & 0x0F,
+- pAC->GIni.GIPciHwRev & 0x0F);
+-
+- /* Print sensor informations */
+- for (i=0; i < pAC->I2c.MaxSens; i ++) {
+- /* Check type */
+- switch (pAC->I2c.SenTable[i].SenType) {
+- case 1:
+- strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc);
+- strcat(sens_msg, " (C)");
+- len += sk_proc_print(buffer,
+- "%-25s %d.%02d\n",
+- sens_msg,
+- pAC->I2c.SenTable[i].SenValue / 10,
+- pAC->I2c.SenTable[i].SenValue % 10);
++ if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_STATIC) {
++ len += sk_proc_print(buffer,
++ "Interrupt Moderation static (%d ints/sec)\n",
++ pAC->DynIrqModInfo.MaxModIntsPerSec);
++ } else if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_DYNAMIC) {
++ len += sk_proc_print(buffer,
++ "Interrupt Moderation dynamic (%d ints/sec)\n",
++ pAC->DynIrqModInfo.MaxModIntsPerSec);
++ } else {
++ len += sk_proc_print(buffer,
++ "Interrupt Moderation disabled\n");
++ }
+
+- strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc);
+- strcat(sens_msg, " (F)");
++ if (pAC->GIni.GIPciBus == SK_PEX_BUS) {
++ len += sk_proc_print(buffer,
++ "Bus type PCI-Express\n");
++ len += sk_proc_print(buffer,
++ "Bus width (Lanes) %d\n",
++ pAC->GIni.GIPexWidth);
++ } else {
++ if (pAC->GIni.GIPciBus == SK_PCIX_BUS) {
+ len += sk_proc_print(buffer,
+- "%-25s %d.%02d\n",
+- sens_msg,
+- ((((pAC->I2c.SenTable[i].SenValue)
+- *10)*9)/5 + 3200)/100,
+- ((((pAC->I2c.SenTable[i].SenValue)
+- *10)*9)/5 + 3200) % 10);
+- break;
+- case 2:
+- strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc);
+- strcat(sens_msg, " (V)");
++ "Bus type PCI-X\n");
++ if (pAC->GIni.GIPciMode == PCI_OS_SPD_X133) {
++ len += sk_proc_print(buffer,
++ "Bus speed (MHz) 133\n");
++ } else if (pAC->GIni.GIPciMode == PCI_OS_SPD_X100) {
++ len += sk_proc_print(buffer,
++ "Bus speed (MHz) 100\n");
++ } else if (pAC->GIni.GIPciMode == PCI_OS_SPD_X66) {
++ len += sk_proc_print(buffer,
++ "Bus speed (MHz) 66\n");
++ } else {
++ len += sk_proc_print(buffer,
++ "Bus speed (MHz) 33\n");
++ }
++ } else {
+ len += sk_proc_print(buffer,
+- "%-25s %d.%03d\n",
+- sens_msg,
+- pAC->I2c.SenTable[i].SenValue / 1000,
+- pAC->I2c.SenTable[i].SenValue % 1000);
+- break;
+- case 3:
+- strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc);
+- strcat(sens_msg, " (rpm)");
++ "Bus type PCI\n");
+ len += sk_proc_print(buffer,
+- "%-25s %d\n",
+- sens_msg,
+- pAC->I2c.SenTable[i].SenValue);
+- break;
+- default:
+- break;
++ "Bus speed (MHz) %d\n",
++ pPnmiStruct->BusSpeed);
+ }
++ len += sk_proc_print(buffer,
++ "Bus width (Bit) %d\n",
++ pPnmiStruct->BusWidth);
+ }
+-
+- /*Receive statistics */
+- len += sk_proc_print(buffer,
+- "\nReceive statistics\n\n");
+
+ len += sk_proc_print(buffer,
+- "Received bytes %Lu\n",
+- (unsigned long long) pPnmiStat->StatRxOctetsOkCts);
+- len += sk_proc_print(buffer,
+- "Received packets %Lu\n",
+- (unsigned long long) pPnmiStat->StatRxOkCts);
+-#if 0
+- if (pAC->GIni.GP[0].PhyType == SK_PHY_XMAC &&
+- pAC->HWRevision < 12) {
+- pPnmiStruct->InErrorsCts = pPnmiStruct->InErrorsCts -
+- pPnmiStat->StatRxShortsCts;
+- pPnmiStat->StatRxShortsCts = 0;
+- }
+-#endif
+- if (pNet->Mtu > 1500)
+- pPnmiStruct->InErrorsCts = pPnmiStruct->InErrorsCts -
+- pPnmiStat->StatRxTooLongCts;
+-
+- len += sk_proc_print(buffer,
+- "Receive errors %Lu\n",
+- (unsigned long long) pPnmiStruct->InErrorsCts);
+- len += sk_proc_print(buffer,
+- "Receive dropped %Lu\n",
+- (unsigned long long) pPnmiStruct->RxNoBufCts);
++ "Driver version %s (%s)\n",
++ VER_STRING, PATCHLEVEL);
+ len += sk_proc_print(buffer,
+- "Received multicast %Lu\n",
+- (unsigned long long) pPnmiStat->StatRxMulticastOkCts);
++ "Driver release date %s\n",
++ pAC->Pnmi.pDriverReleaseDate);
+ len += sk_proc_print(buffer,
+- "Receive error types\n");
+- len += sk_proc_print(buffer,
+- " length %Lu\n",
+- (unsigned long long) pPnmiStat->StatRxRuntCts);
+- len += sk_proc_print(buffer,
+- " buffer overflow %Lu\n",
+- (unsigned long long) pPnmiStat->StatRxFifoOverflowCts);
+- len += sk_proc_print(buffer,
+- " bad crc %Lu\n",
+- (unsigned long long) pPnmiStat->StatRxFcsCts);
+- len += sk_proc_print(buffer,
+- " framing %Lu\n",
+- (unsigned long long) pPnmiStat->StatRxFramingCts);
+- len += sk_proc_print(buffer,
+- " missed frames %Lu\n",
+- (unsigned long long) pPnmiStat->StatRxMissedCts);
+-
+- if (pNet->Mtu > 1500)
+- pPnmiStat->StatRxTooLongCts = 0;
++ "Hardware revision v%d.%d\n",
++ (pAC->GIni.GIPciHwRev >> 4) & 0x0F,
++ pAC->GIni.GIPciHwRev & 0x0F);
+
+- len += sk_proc_print(buffer,
+- " too long %Lu\n",
+- (unsigned long long) pPnmiStat->StatRxTooLongCts);
+- len += sk_proc_print(buffer,
+- " carrier extension %Lu\n",
+- (unsigned long long) pPnmiStat->StatRxCextCts);
+- len += sk_proc_print(buffer,
+- " too short %Lu\n",
+- (unsigned long long) pPnmiStat->StatRxShortsCts);
+- len += sk_proc_print(buffer,
+- " symbol %Lu\n",
+- (unsigned long long) pPnmiStat->StatRxSymbolCts);
+- len += sk_proc_print(buffer,
+- " LLC MAC size %Lu\n",
+- (unsigned long long) pPnmiStat->StatRxIRLengthCts);
+- len += sk_proc_print(buffer,
+- " carrier event %Lu\n",
+- (unsigned long long) pPnmiStat->StatRxCarrierCts);
+- len += sk_proc_print(buffer,
+- " jabber %Lu\n",
+- (unsigned long long) pPnmiStat->StatRxJabberCts);
++ if (!netif_running(pAC->dev[t-1])) {
++ len += sk_proc_print(buffer,
++ "\n Device %s is down.\n"
++ " Therefore no statistics are available.\n"
++ " After bringing the device up (ifconfig)"
++ " statistics will\n"
++ " be displayed.\n",
++ pAC->dev[t-1]->name);
++ DisableStatistic = 1;
++ }
+
++ /* Display only if statistic info available */
++ /* Print sensor informations */
++ if (!DisableStatistic) {
++ for (i=0; i < pAC->I2c.MaxSens; i ++) {
++ /* Check type */
++ switch (pAC->I2c.SenTable[i].SenType) {
++ case 1:
++ strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc);
++ strcat(sens_msg, " (C)");
++ len += sk_proc_print(buffer,
++ "%-25s %d.%02d\n",
++ sens_msg,
++ pAC->I2c.SenTable[i].SenValue / 10,
++ pAC->I2c.SenTable[i].SenValue %
++ 10);
++
++ strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc);
++ strcat(sens_msg, " (F)");
++ len += sk_proc_print(buffer,
++ "%-25s %d.%02d\n",
++ sens_msg,
++ ((((pAC->I2c.SenTable[i].SenValue)
++ *10)*9)/5 + 3200)/100,
++ ((((pAC->I2c.SenTable[i].SenValue)
++ *10)*9)/5 + 3200) % 10);
++ break;
++ case 2:
++ strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc);
++ strcat(sens_msg, " (V)");
++ len += sk_proc_print(buffer,
++ "%-25s %d.%03d\n",
++ sens_msg,
++ pAC->I2c.SenTable[i].SenValue / 1000,
++ pAC->I2c.SenTable[i].SenValue % 1000);
++ break;
++ case 3:
++ strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc);
++ strcat(sens_msg, " (rpm)");
++ len += sk_proc_print(buffer,
++ "%-25s %d\n",
++ sens_msg,
++ pAC->I2c.SenTable[i].SenValue);
++ break;
++ default:
++ break;
++ }
++ }
++
++ /*Receive statistics */
++ len += sk_proc_print(buffer,
++ "\nReceive statistics\n\n");
++
++ len += sk_proc_print(buffer,
++ "Received bytes %Lu\n",
++ (unsigned long long) pPnmiStat->StatRxOctetsOkCts);
++ len += sk_proc_print(buffer,
++ "Received packets %Lu\n",
++ (unsigned long long) pPnmiStat->StatRxOkCts);
++#if 0
++ if (pAC->GIni.GP[0].PhyType == SK_PHY_XMAC &&
++ pAC->HWRevision < 12) {
++ pPnmiStruct->InErrorsCts = pPnmiStruct->InErrorsCts -
++ pPnmiStat->StatRxShortsCts;
++ pPnmiStat->StatRxShortsCts = 0;
++ }
++#endif
++ if (pAC->dev[t-1]->mtu > 1500)
++ pPnmiStruct->InErrorsCts = pPnmiStruct->InErrorsCts -
++ pPnmiStat->StatRxTooLongCts;
++
++ len += sk_proc_print(buffer,
++ "Receive errors %Lu\n",
++ (unsigned long long) pPnmiStruct->InErrorsCts);
++ len += sk_proc_print(buffer,
++ "Receive dropped %Lu\n",
++ (unsigned long long) pPnmiStruct->RxNoBufCts);
++ len += sk_proc_print(buffer,
++ "Received multicast %Lu\n",
++ (unsigned long long) pPnmiStat->StatRxMulticastOkCts);
++#ifdef ADVANCED_STATISTIC_OUTPUT
++ len += sk_proc_print(buffer,
++ "Receive error types\n");
++ len += sk_proc_print(buffer,
++ " length %Lu\n",
++ (unsigned long long) pPnmiStat->StatRxRuntCts);
++ len += sk_proc_print(buffer,
++ " buffer overflow %Lu\n",
++ (unsigned long long) pPnmiStat->StatRxFifoOverflowCts);
++ len += sk_proc_print(buffer,
++ " bad crc %Lu\n",
++ (unsigned long long) pPnmiStat->StatRxFcsCts);
++ len += sk_proc_print(buffer,
++ " framing %Lu\n",
++ (unsigned long long) pPnmiStat->StatRxFramingCts);
++ len += sk_proc_print(buffer,
++ " missed frames %Lu\n",
++ (unsigned long long) pPnmiStat->StatRxMissedCts);
++
++ if (pAC->dev[t-1]->mtu > 1500)
++ pPnmiStat->StatRxTooLongCts = 0;
++
++ len += sk_proc_print(buffer,
++ " too long %Lu\n",
++ (unsigned long long) pPnmiStat->StatRxTooLongCts);
++ len += sk_proc_print(buffer,
++ " carrier extension %Lu\n",
++ (unsigned long long) pPnmiStat->StatRxCextCts);
++ len += sk_proc_print(buffer,
++ " too short %Lu\n",
++ (unsigned long long) pPnmiStat->StatRxShortsCts);
++ len += sk_proc_print(buffer,
++ " symbol %Lu\n",
++ (unsigned long long) pPnmiStat->StatRxSymbolCts);
++ len += sk_proc_print(buffer,
++ " LLC MAC size %Lu\n",
++ (unsigned long long) pPnmiStat->StatRxIRLengthCts);
++ len += sk_proc_print(buffer,
++ " carrier event %Lu\n",
++ (unsigned long long) pPnmiStat->StatRxCarrierCts);
++ len += sk_proc_print(buffer,
++ " jabber %Lu\n",
++ (unsigned long long) pPnmiStat->StatRxJabberCts);
++#endif
+
+- /*Transmit statistics */
+- len += sk_proc_print(buffer,
+- "\nTransmit statistics\n\n");
++ /*Transmit statistics */
++ len += sk_proc_print(buffer,
++ "\nTransmit statistics\n\n");
+
+- len += sk_proc_print(buffer,
+- "Transmited bytes %Lu\n",
+- (unsigned long long) pPnmiStat->StatTxOctetsOkCts);
+- len += sk_proc_print(buffer,
+- "Transmited packets %Lu\n",
+- (unsigned long long) pPnmiStat->StatTxOkCts);
+- len += sk_proc_print(buffer,
+- "Transmit errors %Lu\n",
+- (unsigned long long) pPnmiStat->StatTxSingleCollisionCts);
+- len += sk_proc_print(buffer,
+- "Transmit dropped %Lu\n",
+- (unsigned long long) pPnmiStruct->TxNoBufCts);
+- len += sk_proc_print(buffer,
+- "Transmit collisions %Lu\n",
+- (unsigned long long) pPnmiStat->StatTxSingleCollisionCts);
+- len += sk_proc_print(buffer,
+- "Transmit error types\n");
+- len += sk_proc_print(buffer,
+- " excessive collision %ld\n",
+- pAC->stats.tx_aborted_errors);
+- len += sk_proc_print(buffer,
+- " carrier %Lu\n",
+- (unsigned long long) pPnmiStat->StatTxCarrierCts);
+- len += sk_proc_print(buffer,
+- " fifo underrun %Lu\n",
+- (unsigned long long) pPnmiStat->StatTxFifoUnderrunCts);
+- len += sk_proc_print(buffer,
+- " heartbeat %Lu\n",
+- (unsigned long long) pPnmiStat->StatTxCarrierCts);
+- len += sk_proc_print(buffer,
+- " window %ld\n",
+- pAC->stats.tx_window_errors);
++ len += sk_proc_print(buffer,
++ "Transmitted bytes %Lu\n",
++ (unsigned long long) pPnmiStat->StatTxOctetsOkCts);
++ len += sk_proc_print(buffer,
++ "Transmitted packets %Lu\n",
++ (unsigned long long) pPnmiStat->StatTxOkCts);
++ len += sk_proc_print(buffer,
++ "Transmit errors %Lu\n",
++ (unsigned long long) pPnmiStat->StatTxSingleCollisionCts);
++ len += sk_proc_print(buffer,
++ "Transmit dropped %Lu\n",
++ (unsigned long long) pPnmiStruct->TxNoBufCts);
++ len += sk_proc_print(buffer,
++ "Transmit collisions %Lu\n",
++ (unsigned long long) pPnmiStat->StatTxSingleCollisionCts);
++#ifdef ADVANCED_STATISTIC_OUTPUT
++ len += sk_proc_print(buffer,
++ "Transmit error types\n");
++ len += sk_proc_print(buffer,
++ " excessive collision %ld\n",
++ pAC->stats.tx_aborted_errors);
++ len += sk_proc_print(buffer,
++ " carrier %Lu\n",
++ (unsigned long long) pPnmiStat->StatTxCarrierCts);
++ len += sk_proc_print(buffer,
++ " fifo underrun %Lu\n",
++ (unsigned long long) pPnmiStat->StatTxFifoUnderrunCts);
++ len += sk_proc_print(buffer,
++ " heartbeat %Lu\n",
++ (unsigned long long) pPnmiStat->StatTxCarrierCts);
++ len += sk_proc_print(buffer,
++ " window %ld\n",
++ pAC->stats.tx_window_errors);
++#endif
++ } /* if (!DisableStatistic) */
+
+ } /* if (strcmp(pACname, currDeviceName) == 0) */
+ }
+@@ -306,16 +395,20 @@
+
+ /*****************************************************************************
+ *
+- * sk_proc_print -generic line print
++ * sk_proc_print - generic line print
+ *
+ * Description:
+- * This function fills the proc entry with statistic data about
+- * the ethernet device.
++ * This function fills the proc entry with statistic data about the
++ * ethernet device.
+ *
+- * Returns: number of bytes written
++ * Returns:
++ * the number of bytes written
+ *
+ */
+-static int sk_proc_print(void *writePtr, char *format, ...)
++static int sk_proc_print(
++void *writePtr, /* the buffer pointer */
++char *format, /* the format of the string */
++...) /* variable list of arguments */
+ {
+ #define MAX_LEN_SINGLE_LINE 256
+ char str[MAX_LEN_SINGLE_LINE];
+@@ -341,19 +434,22 @@
+ * sk_seq_show - show proc information of a particular adapter
+ *
+ * Description:
+- * This function fills the proc entry with statistic data about
+- * the ethernet device. It invokes the generic sk_gen_browse() to
+- * print out all items one per one.
++ * This function fills the proc entry with statistic data about the
++ * ethernet device. It invokes the generic sk_gen_browse() to print
++ * out all items one per one.
+ *
+- * Returns: number of bytes written
++ * Returns:
++ * the number of bytes written
+ *
+ */
+-static int sk_seq_show(struct seq_file *seq, void *v)
++static int sk_seq_show(
++struct seq_file *seq, /* the sequence pointer */
++void *v) /* additional pointer */
+ {
+- void *castedBuffer = (void *) seq;
+- currDev = seq->private;
+- sk_gen_browse(castedBuffer);
+- return 0;
++ void *castedBuffer = (void *) seq;
++ currDev = seq->private;
++ sk_gen_browse(castedBuffer);
++ return 0;
+ }
+
+ /*****************************************************************************
+@@ -361,14 +457,17 @@
+ * sk_proc_open - register the show function when proc is open'ed
+ *
+ * Description:
+- * This function is called whenever a sk98lin proc file is queried.
++ * This function is called whenever a sk98lin proc file is queried.
+ *
+- * Returns: the return value of single_open()
++ * Returns:
++ * the return value of single_open()
+ *
+ */
+-static int sk_proc_open(struct inode *inode, struct file *file)
++static int sk_proc_open(
++struct inode *inode, /* the inode of the file */
++struct file *file) /* the file pointer itself */
+ {
+- return single_open(file, sk_seq_show, PDE(inode)->data);
++ return single_open(file, sk_seq_show, PDE(inode)->data);
+ }
+
+ /*******************************************************************************
+diff -ruN linux/drivers/net/sk98lin/skqueue.c linux-new/drivers/net/sk98lin/skqueue.c
+--- linux/drivers/net/sk98lin/skqueue.c 2005-09-26 13:32:48.000000000 +0400
++++ linux-new/drivers/net/sk98lin/skqueue.c 2005-08-09 17:15:51.000000000 +0400
+@@ -2,8 +2,8 @@
+ *
+ * Name: skqueue.c
+ * Project: Gigabit Ethernet Adapters, Event Scheduler Module
+- * Version: $Revision: 1.20 $
+- * Date: $Date: 2003/09/16 13:44:00 $
++ * Version: $Revision: 2.3 $
++ * Date: $Date: 2004/05/14 13:28:18 $
+ * Purpose: Management of an event queue.
+ *
+ ******************************************************************************/
+@@ -28,7 +28,7 @@
+ */
+ #if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
+ static const char SysKonnectFileId[] =
+- "@(#) $Id: skqueue.c,v 1.20 2003/09/16 13:44:00 rschmidt Exp $ (C) Marvell.";
++ "@(#) $Id: skqueue.c,v 2.3 2004/05/14 13:28:18 malthoff Exp $ (C) Marvell.";
+ #endif
+
+ #include "h/skdrv1st.h" /* Driver Specific Definitions */
+@@ -48,10 +48,16 @@
+
+ #define PRINTF(a,b,c)
+
+-/*
+- * init event queue management
++/******************************************************************************
++ *
++ * SkEventInit() - init event queue management
+ *
+- * Must be called during init level 0.
++ * Description:
++ * This function initializes event queue management.
++ * It must be called during init level 0.
++ *
++ * Returns:
++ * nothing
+ */
+ void SkEventInit(
+ SK_AC *pAC, /* Adapter context */
+@@ -67,8 +73,17 @@
+ }
+ }
+
+-/*
+- * add event to queue
++/******************************************************************************
++ *
++ * SkEventQueue() - add event to queue
++ *
++ * Description:
++ * This function adds an event to the event queue.
++ * At least Init Level 1 is required to queue events,
++ * but will be scheduled add Init Level 2.
++ *
++ * returns:
++ * nothing
+ */
+ void SkEventQueue(
+ SK_AC *pAC, /* Adapters context */
+@@ -76,26 +91,45 @@
+ SK_U32 Event, /* Event to be queued */
+ SK_EVPARA Para) /* Event parameter */
+ {
+- pAC->Event.EvPut->Class = Class;
+- pAC->Event.EvPut->Event = Event;
+- pAC->Event.EvPut->Para = Para;
++
++ if (pAC->GIni.GILevel == SK_INIT_DATA) {
++ SK_ERR_LOG(pAC, SK_ERRCL_NORES, SKERR_Q_E003, SKERR_Q_E003MSG);
++ }
++ else {
++ pAC->Event.EvPut->Class = Class;
++ pAC->Event.EvPut->Event = Event;
++ pAC->Event.EvPut->Para = Para;
+
+- if (++pAC->Event.EvPut == &pAC->Event.EvQueue[SK_MAX_EVENT])
+- pAC->Event.EvPut = pAC->Event.EvQueue;
++ if (++pAC->Event.EvPut == &pAC->Event.EvQueue[SK_MAX_EVENT])
++ pAC->Event.EvPut = pAC->Event.EvQueue;
+
+- if (pAC->Event.EvPut == pAC->Event.EvGet) {
+- SK_ERR_LOG(pAC, SK_ERRCL_NORES, SKERR_Q_E001, SKERR_Q_E001MSG);
++ if (pAC->Event.EvPut == pAC->Event.EvGet) {
++ SK_ERR_LOG(pAC, SK_ERRCL_NORES, SKERR_Q_E001, SKERR_Q_E001MSG);
++ }
+ }
+ }
+
+-/*
+- * event dispatcher
+- * while event queue is not empty
+- * get event from queue
+- * send command to state machine
+- * end
+- * return error reported by individual Event function
+- * 0 if no error occured.
++/******************************************************************************
++ *
++ * SkEventDispatcher() - Event Dispatcher
++ *
++ * Description:
++ * The event dispatcher performs the following operations:
++ * o while event queue is not empty
++ * - get event from queue
++ * - send event to state machine
++ * end
++ *
++ * CAUTION:
++ * The event functions MUST report an error if performing a reinitialization
++ * of the event queue, e.g. performing level Init 0..2 while in dispatcher
++ * call!
++ * ANY OTHER return value delays scheduling the other events in the
++ * queue. In this case the event blocks the queue until
++ * the error condition is cleared!
++ *
++ * Returns:
++ * The return value error reported by individual event function
+ */
+ int SkEventDispatcher(
+ SK_AC *pAC, /* Adapters Context */
+@@ -105,6 +139,10 @@
+ SK_U32 Class;
+ int Rtv;
+
++ if (pAC->GIni.GILevel != SK_INIT_RUN) {
++ SK_ERR_LOG(pAC, SK_ERRCL_NORES, SKERR_Q_E005, SKERR_Q_E005MSG);
++ }
++
+ pEv = pAC->Event.EvGet;
+
+ PRINTF("dispatch get %x put %x\n", pEv, pAC->Event.ev_put);
+@@ -152,6 +190,11 @@
+ Rtv = SkFdEvent(pAC, Ioc, pEv->Event, pEv->Para);
+ break;
+ #endif /* SK_USE_LAC_EV */
++#ifdef SK_ASF
++ case SKGE_ASF :
++ Rtv = SkAsfEvent(pAC,Ioc,pEv->Event,pEv->Para);
++ break ;
++#endif
+ #ifdef SK_USE_CSUM
+ case SKGE_CSUM :
+ Rtv = SkCsEvent(pAC, Ioc, pEv->Event, pEv->Para);
+@@ -163,6 +206,20 @@
+ }
+
+ if (Rtv != 0) {
++ /*
++ * Special Case: See CAUTION statement above.
++ * We assume the event queue is reset.
++ */
++ if (pAC->Event.EvGet != pAC->Event.EvQueue &&
++ pAC->Event.EvGet != pEv) {
++ /*
++ * Create an error log entry if the
++ * event queue isn't reset.
++ * In this case it may be blocked.
++ */
++ SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_Q_E004, SKERR_Q_E004MSG);
++ }
++
+ return(Rtv);
+ }
+
+diff -ruN linux/drivers/net/sk98lin/skrlmt.c linux-new/drivers/net/sk98lin/skrlmt.c
+--- linux/drivers/net/sk98lin/skrlmt.c 2005-09-26 13:32:48.000000000 +0400
++++ linux-new/drivers/net/sk98lin/skrlmt.c 2005-08-09 17:15:51.000000000 +0400
+@@ -2,8 +2,8 @@
+ *
+ * Name: skrlmt.c
+ * Project: GEnesis, PCI Gigabit Ethernet Adapter
+- * Version: $Revision: 1.69 $
+- * Date: $Date: 2003/04/15 09:39:22 $
++ * Version: $Revision: 2.3 $
++ * Date: $Date: 2005/05/04 09:47:53 $
+ * Purpose: Manage links on SK-NET Adapters, esp. redundant ones.
+ *
+ ******************************************************************************/
+@@ -39,7 +39,7 @@
+
+ #ifndef lint
+ static const char SysKonnectFileId[] =
+- "@(#) $Id: skrlmt.c,v 1.69 2003/04/15 09:39:22 tschilli Exp $ (C) Marvell.";
++ "@(#) $Id: skrlmt.c,v 2.3 2005/05/04 09:47:53 tschilli Exp $ (C) Marvell.";
+ #endif /* !defined(lint) */
+
+ #define __SKRLMT_C
+@@ -350,7 +350,7 @@
+ SK_BOOL PhysicalAMacAddressSet;
+
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_INIT,
+- ("RLMT Init level %d.\n", Level))
++ ("RLMT Init level %d.\n", Level));
+
+ switch (Level) {
+ case SK_INIT_DATA: /* Initialize data structures. */
+@@ -390,7 +390,7 @@
+
+ case SK_INIT_IO: /* GIMacsFound first available here. */
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_INIT,
+- ("RLMT: %d MACs were detected.\n", pAC->GIni.GIMacsFound))
++ ("RLMT: %d MACs were detected.\n", pAC->GIni.GIMacsFound));
+
+ pAC->Rlmt.Net[0].NumPorts = pAC->GIni.GIMacsFound;
+
+@@ -512,7 +512,7 @@
+ }
+
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SkRlmtBuildCheckChain.\n"))
++ ("SkRlmtBuildCheckChain.\n"));
+
+ NumMacsUp = 0;
+
+@@ -558,7 +558,7 @@
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+ ("Port %d checks %d other ports: %2X.\n", i,
+ pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked,
+- pAC->Rlmt.Net[NetIdx].Port[i]->PortCheck[0].CheckAddr.a[5]))
++ pAC->Rlmt.Net[NetIdx].Port[i]->PortCheck[0].CheckAddr.a[5]));
+ }
+ #endif /* DEBUG */
+
+@@ -604,7 +604,7 @@
+ if ((CheckSrc == 0) || (CheckDest == 0)) {
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_ERR,
+ ("SkRlmtBuildPacket: Invalid %s%saddr.\n",
+- (CheckSrc == 0 ? "Src" : ""), (CheckDest == 0 ? "Dest" : "")))
++ (CheckSrc == 0 ? "Src" : ""), (CheckDest == 0 ? "Dest" : "")));
+ }
+ #endif
+
+@@ -796,7 +796,7 @@
+
+ SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_TX,
+- ("SkRlmtSend: BPDU Packet on Port %u.\n", PortNumber))
++ ("SkRlmtSend: BPDU Packet on Port %u.\n", PortNumber));
+ }
+ }
+ return;
+@@ -835,7 +835,7 @@
+ * Bring it up.
+ */
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+- ("SkRlmtPacketReceive: Received on PortDown.\n"))
++ ("SkRlmtPacketReceive: Received on PortDown.\n"));
+
+ pRPort->PortState = SK_RLMT_PS_GOING_UP;
+ pRPort->GuTimeStamp = SkOsGetTime(pAC);
+@@ -849,7 +849,7 @@
+ } /* PortDown && !SuspectTx */
+ else if (pRPort->CheckingState & SK_RLMT_PCS_RX) {
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+- ("SkRlmtPacketReceive: Stop bringing port down.\n"))
++ ("SkRlmtPacketReceive: Stop bringing port down.\n"));
+ SkTimerStop(pAC, IoC, &pRPort->DownRxTimer);
+ pRPort->CheckingState &= ~SK_RLMT_PCS_RX;
+ /* pAC->Rlmt.CheckSwitch = SK_TRUE; */
+@@ -896,7 +896,7 @@
+ pRPort = &pAC->Rlmt.Port[PortNumber];
+
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+- ("SkRlmtPacketReceive: PortNumber == %d.\n", PortNumber))
++ ("SkRlmtPacketReceive: PortNumber == %d.\n", PortNumber));
+
+ pRPacket = (SK_RLMT_PACKET*)pMb->pData;
+ pSPacket = (SK_SPTREE_PACKET*)pRPacket;
+@@ -917,7 +917,7 @@
+
+ /* Not sent to current MAC or registered MC address => Trash it. */
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+- ("SkRlmtPacketReceive: Not for me.\n"))
++ ("SkRlmtPacketReceive: Not for me.\n"));
+
+ SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
+ return;
+@@ -955,7 +955,7 @@
+ pRPacket->Indicator[5] == SK_RLMT_INDICATOR5 &&
+ pRPacket->Indicator[6] == SK_RLMT_INDICATOR6) {
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+- ("SkRlmtPacketReceive: Duplicate MAC Address.\n"))
++ ("SkRlmtPacketReceive: Duplicate MAC Address.\n"));
+
+ /* Error Log entry. */
+ SK_ERR_LOG(pAC, SK_ERRCL_COMM, SKERR_RLMT_E006, SKERR_RLMT_E006_MSG);
+@@ -963,7 +963,7 @@
+ else {
+ /* Simply trash it. */
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+- ("SkRlmtPacketReceive: Sent by me.\n"))
++ ("SkRlmtPacketReceive: Sent by me.\n"));
+ }
+
+ SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
+@@ -1007,7 +1007,7 @@
+ #endif /* 0 */
+
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+- ("SkRlmtPacketReceive: Announce.\n"))
++ ("SkRlmtPacketReceive: Announce.\n"));
+
+ SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
+ break;
+@@ -1015,7 +1015,7 @@
+ case SK_PACKET_ALIVE:
+ if (pRPacket->SSap & LLC_COMMAND_RESPONSE_BIT) {
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+- ("SkRlmtPacketReceive: Alive Reply.\n"))
++ ("SkRlmtPacketReceive: Alive Reply.\n"));
+
+ if (!(pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_LLC) ||
+ SK_ADDR_EQUAL(
+@@ -1046,7 +1046,7 @@
+ }
+ else { /* Alive Request Packet. */
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+- ("SkRlmtPacketReceive: Alive Request.\n"))
++ ("SkRlmtPacketReceive: Alive Request.\n"));
+
+ pRPort->RxHelloCts++;
+
+@@ -1065,7 +1065,7 @@
+
+ case SK_PACKET_CHECK_TX:
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+- ("SkRlmtPacketReceive: Check your tx line.\n"))
++ ("SkRlmtPacketReceive: Check your tx line.\n"));
+
+ /* A port checking us requests us to check our tx line. */
+ pRPort->CheckingState |= SK_RLMT_PCS_TX;
+@@ -1088,7 +1088,7 @@
+
+ case SK_PACKET_ADDR_CHANGED:
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+- ("SkRlmtPacketReceive: Address Change.\n"))
++ ("SkRlmtPacketReceive: Address Change.\n"));
+
+ /* Build the check chain. */
+ SkRlmtBuildCheckChain(pAC, pRPort->Net->NetNumber);
+@@ -1097,7 +1097,7 @@
+
+ default:
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+- ("SkRlmtPacketReceive: Unknown RLMT packet.\n"))
++ ("SkRlmtPacketReceive: Unknown RLMT packet.\n"));
+
+ /* RA;:;: ??? */
+ SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
+@@ -1107,7 +1107,7 @@
+ pSPacket->Ctrl == SK_RLMT_SPT_CTRL &&
+ (pSPacket->SSap & ~LLC_COMMAND_RESPONSE_BIT) == SK_RLMT_SPT_SSAP) {
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+- ("SkRlmtPacketReceive: BPDU Packet.\n"))
++ ("SkRlmtPacketReceive: BPDU Packet.\n"));
+
+ /* Spanning Tree packet. */
+ pRPort->RxSpHelloCts++;
+@@ -1139,7 +1139,7 @@
+ pRPort->Root.Id[0], pRPort->Root.Id[1],
+ pRPort->Root.Id[2], pRPort->Root.Id[3],
+ pRPort->Root.Id[4], pRPort->Root.Id[5],
+- pRPort->Root.Id[6], pRPort->Root.Id[7]))
++ pRPort->Root.Id[6], pRPort->Root.Id[7]));
+ }
+
+ SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
+@@ -1150,7 +1150,7 @@
+ }
+ else {
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX,
+- ("SkRlmtPacketReceive: Unknown Packet Type.\n"))
++ ("SkRlmtPacketReceive: Unknown Packet Type.\n"));
+
+ /* Unknown packet. */
+ SkDrvFreeRlmtMbuf(pAC, IoC, pMb);
+@@ -1232,7 +1232,7 @@
+ if ((pRPort->PacketsPerTimeSlot - pRPort->BpduPacketsPerTimeSlot) == 0) {
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+ ("SkRlmtCheckPort %d: No (%d) receives in last time slot.\n",
+- PortNumber, pRPort->PacketsPerTimeSlot))
++ PortNumber, pRPort->PacketsPerTimeSlot));
+
+ /*
+ * Check segmentation if there was no receive at least twice
+@@ -1249,7 +1249,7 @@
+
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+ ("SkRlmtCheckPort: PortsSuspect %d, PcsRx %d.\n",
+- pRPort->PortsSuspect, pRPort->CheckingState & SK_RLMT_PCS_RX))
++ pRPort->PortsSuspect, pRPort->CheckingState & SK_RLMT_PCS_RX));
+
+ if (pRPort->PortState != SK_RLMT_PS_DOWN) {
+ NewTimeout = TO_SHORTEN(pAC->Rlmt.Port[PortNumber].Net->TimeoutValue);
+@@ -1295,7 +1295,7 @@
+ ("SkRlmtCheckPort %d: %d (%d) receives in last time slot.\n",
+ PortNumber,
+ pRPort->PacketsPerTimeSlot - pRPort->BpduPacketsPerTimeSlot,
+- pRPort->PacketsPerTimeSlot))
++ pRPort->PacketsPerTimeSlot));
+
+ SkRlmtPortReceives(pAC, IoC, PortNumber);
+ if (pAC->Rlmt.CheckSwitch) {
+@@ -1345,7 +1345,7 @@
+ i,
+ pAC->Rlmt.Port[i].PortDown, pAC->Rlmt.Port[i].PortNoRx,
+ *((SK_U32*)(&pAC->Rlmt.Port[i].BcTimeStamp) + OFFS_HI32),
+- *((SK_U32*)(&pAC->Rlmt.Port[i].BcTimeStamp) + OFFS_LO32)))
++ *((SK_U32*)(&pAC->Rlmt.Port[i].BcTimeStamp) + OFFS_LO32)));
+
+ if (!pAC->Rlmt.Port[i].PortDown && !pAC->Rlmt.Port[i].PortNoRx) {
+ if (!PortFound || pAC->Rlmt.Port[i].BcTimeStamp > BcTimeStamp) {
+@@ -1358,7 +1358,7 @@
+
+ if (PortFound) {
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("Port %d received the last broadcast.\n", *pSelect))
++ ("Port %d received the last broadcast.\n", *pSelect));
+
+ /* Look if another port's time stamp is similar. */
+ for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) {
+@@ -1373,7 +1373,7 @@
+ PortFound = SK_FALSE;
+
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("Port %d received a broadcast at a similar time.\n", i))
++ ("Port %d received a broadcast at a similar time.\n", i));
+ break;
+ }
+ }
+@@ -1385,7 +1385,7 @@
+ ("SK_RLMT_SELECT_BCRX found Port %d receiving the substantially "
+ "latest broadcast (%u).\n",
+ *pSelect,
+- BcTimeStamp - pAC->Rlmt.Port[1 - *pSelect].BcTimeStamp))
++ BcTimeStamp - pAC->Rlmt.Port[1 - *pSelect].BcTimeStamp));
+ }
+ #endif /* DEBUG */
+
+@@ -1434,7 +1434,7 @@
+ PortFound = SK_TRUE;
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+ ("SK_RLMT_SELECT_NOTSUSPECT found Port %d up and not check RX.\n",
+- *pSelect))
++ *pSelect));
+ break;
+ }
+ }
+@@ -1483,7 +1483,7 @@
+ }
+ PortFound = SK_TRUE;
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_SELECT_UP found Port %d up.\n", *pSelect))
++ ("SK_RLMT_SELECT_UP found Port %d up.\n", *pSelect));
+ break;
+ }
+ }
+@@ -1544,7 +1544,7 @@
+ }
+
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_SELECT_GOINGUP found Port %d going up.\n", *pSelect))
++ ("SK_RLMT_SELECT_GOINGUP found Port %d going up.\n", *pSelect));
+ return (SK_TRUE);
+ } /* SkRlmtSelectGoingUp */
+
+@@ -1590,7 +1590,7 @@
+ }
+ PortFound = SK_TRUE;
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_SELECT_DOWN found Port %d down.\n", *pSelect))
++ ("SK_RLMT_SELECT_DOWN found Port %d down.\n", *pSelect));
+ break;
+ }
+ }
+@@ -1680,16 +1680,19 @@
+ Para.Para32[1] = NetIdx;
+ SkEventQueue(pAC, SKGE_DRV, SK_DRV_NET_UP, Para);
+
+- if ((pAC->Rlmt.Net[NetIdx].RlmtMode & SK_RLMT_TRANSPARENT) == 0 &&
+- (Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC,
+- pAC->Rlmt.Net[NetIdx].Port[i]->PortNumber,
+- SK_PACKET_ANNOUNCE, &pAC->Addr.Net[NetIdx].
+- CurrentMacAddress, &SkRlmtMcAddr)) != NULL) {
+- /*
+- * Send announce packet to RLMT multicast address to force
+- * switches to learn the new location of the logical MAC address.
+- */
+- SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
++ if (pAC->Rlmt.NumNets == 1) {
++ if ((pAC->Rlmt.Net[NetIdx].RlmtMode & SK_RLMT_TRANSPARENT) == 0 &&
++ (Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC,
++ pAC->Rlmt.Net[NetIdx].Port[i]->PortNumber,
++ SK_PACKET_ANNOUNCE, &pAC->Addr.Net[NetIdx].
++ CurrentMacAddress, &SkRlmtMcAddr)) != NULL) {
++
++ /*
++ * Send announce packet to RLMT multicast address to force
++ * switches to learn the new location of the logical MAC address.
++ */
++ SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para);
++ }
+ }
+ }
+ else {
+@@ -1788,7 +1791,7 @@
+
+ if (Para.Para32[1] != Active) {
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("Active: %d, Para1: %d.\n", Active, Para.Para32[1]))
++ ("Active: %d, Para1: %d.\n", Active, Para.Para32[1]));
+ pAC->Rlmt.Net[NetIdx].ActivePort = Para.Para32[1];
+ Para.Para32[0] = pAC->Rlmt.Net[NetIdx].
+ Port[Para.Para32[0]]->PortNumber;
+@@ -1868,7 +1871,7 @@
+ pNet->Port[i]->Root.Id[0], pNet->Port[i]->Root.Id[1],
+ pNet->Port[i]->Root.Id[2], pNet->Port[i]->Root.Id[3],
+ pNet->Port[i]->Root.Id[4], pNet->Port[i]->Root.Id[5],
+- pNet->Port[i]->Root.Id[6], pNet->Port[i]->Root.Id[7]))
++ pNet->Port[i]->Root.Id[6], pNet->Port[i]->Root.Id[7]));
+
+ if (!pNet->RootIdSet) {
+ pNet->Root = pNet->Port[i]->Root;
+@@ -1963,13 +1966,13 @@
+ SK_U32 i;
+
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_PORTSTART_TIMEOUT Port %d Event BEGIN.\n", Para.Para32[0]))
++ ("SK_RLMT_PORTSTART_TIMEOUT Port %d Event BEGIN.\n", Para.Para32[0]));
+
+ if (Para.Para32[1] != (SK_U32)-1) {
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("Bad Parameter.\n"))
++ ("Bad Parameter.\n"));
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_PORTSTART_TIMEOUT Event EMPTY.\n"))
++ ("SK_RLMT_PORTSTART_TIMEOUT Event EMPTY.\n"));
+ return;
+ }
+
+@@ -1990,7 +1993,7 @@
+ }
+
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_PORTSTART_TIMEOUT Event END.\n"))
++ ("SK_RLMT_PORTSTART_TIMEOUT Event END.\n"));
+ } /* SkRlmtEvtPortStartTim */
+
+
+@@ -2018,21 +2021,21 @@
+ SK_EVPARA Para2;
+
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_LINK_UP Port %d Event BEGIN.\n", Para.Para32[0]))
++ ("SK_RLMT_LINK_UP Port %d Event BEGIN.\n", Para.Para32[0]));
+
+ pRPort = &pAC->Rlmt.Port[Para.Para32[0]];
+ if (!pRPort->PortStarted) {
+ SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E008, SKERR_RLMT_E008_MSG);
+
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_LINK_UP Event EMPTY.\n"))
++ ("SK_RLMT_LINK_UP Event EMPTY.\n"));
+ return;
+ }
+
+ if (!pRPort->LinkDown) {
+ /* RA;:;: Any better solution? */
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_LINK_UP Event EMPTY.\n"))
++ ("SK_RLMT_LINK_UP Event EMPTY.\n"));
+ return;
+ }
+
+@@ -2082,16 +2085,19 @@
+ Para2.Para32[1] = (SK_U32)-1;
+ SkTimerStart(pAC, IoC, &pRPort->UpTimer, SK_RLMT_PORTUP_TIM_VAL,
+ SKGE_RLMT, SK_RLMT_PORTUP_TIM, Para2);
+-
++
+ /* Later: if (pAC->Rlmt.RlmtMode & SK_RLMT_CHECK_LOC_LINK) && */
+- if ((pRPort->Net->RlmtMode & SK_RLMT_TRANSPARENT) == 0 &&
+- (pRPort->Net->RlmtMode & SK_RLMT_CHECK_LINK) != 0 &&
+- (Para2.pParaPtr =
+- SkRlmtBuildPacket(pAC, IoC, Para.Para32[0], SK_PACKET_ANNOUNCE,
+- &pAC->Addr.Port[Para.Para32[0]].CurrentMacAddress, &SkRlmtMcAddr)
+- ) != NULL) {
+- /* Send "new" packet to RLMT multicast address. */
+- SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para2);
++ if (pAC->Rlmt.NumNets == 1) {
++ if ((pRPort->Net->RlmtMode & SK_RLMT_TRANSPARENT) == 0 &&
++ (pRPort->Net->RlmtMode & SK_RLMT_CHECK_LINK) != 0 &&
++ (Para2.pParaPtr =
++ SkRlmtBuildPacket(pAC, IoC, Para.Para32[0], SK_PACKET_ANNOUNCE,
++ &pAC->Addr.Port[Para.Para32[0]].CurrentMacAddress, &SkRlmtMcAddr)
++ ) != NULL) {
++
++ /* Send "new" packet to RLMT multicast address. */
++ SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para2);
++ }
+ }
+
+ if (pRPort->Net->RlmtMode & SK_RLMT_CHECK_SEG) {
+@@ -2110,7 +2116,7 @@
+ }
+
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_LINK_UP Event END.\n"))
++ ("SK_RLMT_LINK_UP Event END.\n"));
+ } /* SkRlmtEvtLinkUp */
+
+
+@@ -2136,20 +2142,20 @@
+ SK_RLMT_PORT *pRPort;
+
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_PORTUP_TIM Port %d Event BEGIN.\n", Para.Para32[0]))
++ ("SK_RLMT_PORTUP_TIM Port %d Event BEGIN.\n", Para.Para32[0]));
+
+ if (Para.Para32[1] != (SK_U32)-1) {
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("Bad Parameter.\n"))
++ ("Bad Parameter.\n"));
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_PORTUP_TIM Event EMPTY.\n"))
++ ("SK_RLMT_PORTUP_TIM Event EMPTY.\n"));
+ return;
+ }
+
+ pRPort = &pAC->Rlmt.Port[Para.Para32[0]];
+ if (pRPort->LinkDown || (pRPort->PortState == SK_RLMT_PS_UP)) {
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_PORTUP_TIM Port %d Event EMPTY.\n", Para.Para32[0]))
++ ("SK_RLMT_PORTUP_TIM Port %d Event EMPTY.\n", Para.Para32[0]));
+ return;
+ }
+
+@@ -2164,7 +2170,7 @@
+ }
+
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_PORTUP_TIM Event END.\n"))
++ ("SK_RLMT_PORTUP_TIM Event END.\n"));
+ } /* SkRlmtEvtPortUpTim */
+
+
+@@ -2192,13 +2198,13 @@
+
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+ ("SK_RLMT_PORTDOWN* Port %d Event (%d) BEGIN.\n",
+- Para.Para32[0], Event))
++ Para.Para32[0], Event));
+
+ if (Para.Para32[1] != (SK_U32)-1) {
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("Bad Parameter.\n"))
++ ("Bad Parameter.\n"));
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_PORTDOWN* Event EMPTY.\n"))
++ ("SK_RLMT_PORTDOWN* Event EMPTY.\n"));
+ return;
+ }
+
+@@ -2206,7 +2212,7 @@
+ if (!pRPort->PortStarted || (Event == SK_RLMT_PORTDOWN_TX_TIM &&
+ !(pRPort->CheckingState & SK_RLMT_PCS_TX))) {
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_PORTDOWN* Event (%d) EMPTY.\n", Event))
++ ("SK_RLMT_PORTDOWN* Event (%d) EMPTY.\n", Event));
+ return;
+ }
+
+@@ -2243,7 +2249,7 @@
+ }
+
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_PORTDOWN* Event (%d) END.\n", Event))
++ ("SK_RLMT_PORTDOWN* Event (%d) END.\n", Event));
+ } /* SkRlmtEvtPortDownX */
+
+
+@@ -2270,7 +2276,7 @@
+
+ pRPort = &pAC->Rlmt.Port[Para.Para32[0]];
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_LINK_DOWN Port %d Event BEGIN.\n", Para.Para32[0]))
++ ("SK_RLMT_LINK_DOWN Port %d Event BEGIN.\n", Para.Para32[0]));
+
+ if (!pAC->Rlmt.Port[Para.Para32[0]].LinkDown) {
+ pRPort->Net->LinksUp--;
+@@ -2289,7 +2295,7 @@
+ }
+
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_LINK_DOWN Event END.\n"))
++ ("SK_RLMT_LINK_DOWN Event END.\n"));
+ } /* SkRlmtEvtLinkDown */
+
+
+@@ -2318,13 +2324,13 @@
+ SK_MAC_ADDR *pNewMacAddr;
+
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_PORT_ADDR Port %d Event BEGIN.\n", Para.Para32[0]))
++ ("SK_RLMT_PORT_ADDR Port %d Event BEGIN.\n", Para.Para32[0]));
+
+ if (Para.Para32[1] != (SK_U32)-1) {
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("Bad Parameter.\n"))
++ ("Bad Parameter.\n"));
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_PORT_ADDR Event EMPTY.\n"))
++ ("SK_RLMT_PORT_ADDR Event EMPTY.\n"));
+ return;
+ }
+
+@@ -2348,7 +2354,7 @@
+ }
+
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_PORT_ADDR Event END.\n"))
++ ("SK_RLMT_PORT_ADDR Event END.\n"));
+ } /* SkRlmtEvtPortAddr */
+
+
+@@ -2376,35 +2382,35 @@
+ SK_U32 PortNumber;
+
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_START Net %d Event BEGIN.\n", Para.Para32[0]))
++ ("SK_RLMT_START Net %d Event BEGIN.\n", Para.Para32[0]));
+
+ if (Para.Para32[1] != (SK_U32)-1) {
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("Bad Parameter.\n"))
++ ("Bad Parameter.\n"));
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_START Event EMPTY.\n"))
++ ("SK_RLMT_START Event EMPTY.\n"));
+ return;
+ }
+
+ if (Para.Para32[0] >= pAC->Rlmt.NumNets) {
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("Bad NetNumber %d.\n", Para.Para32[0]))
++ ("Bad NetNumber %d.\n", Para.Para32[0]));
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_START Event EMPTY.\n"))
++ ("SK_RLMT_START Event EMPTY.\n"));
+ return;
+ }
+
+ if (pAC->Rlmt.Net[Para.Para32[0]].RlmtState != SK_RLMT_RS_INIT) {
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_START Event EMPTY.\n"))
++ ("SK_RLMT_START Event EMPTY.\n"));
+ return;
+ }
+
+ if (pAC->Rlmt.NetsStarted >= pAC->Rlmt.NumNets) {
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("All nets should have been started.\n"))
++ ("All nets should have been started.\n"));
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_START Event EMPTY.\n"))
++ ("SK_RLMT_START Event EMPTY.\n"));
+ return;
+ }
+
+@@ -2438,7 +2444,7 @@
+ pAC->Rlmt.NetsStarted++;
+
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_START Event END.\n"))
++ ("SK_RLMT_START Event END.\n"));
+ } /* SkRlmtEvtStart */
+
+
+@@ -2466,35 +2472,35 @@
+ SK_U32 i;
+
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_STOP Net %d Event BEGIN.\n", Para.Para32[0]))
++ ("SK_RLMT_STOP Net %d Event BEGIN.\n", Para.Para32[0]));
+
+ if (Para.Para32[1] != (SK_U32)-1) {
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("Bad Parameter.\n"))
++ ("Bad Parameter.\n"));
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_STOP Event EMPTY.\n"))
++ ("SK_RLMT_STOP Event EMPTY.\n"));
+ return;
+ }
+
+ if (Para.Para32[0] >= pAC->Rlmt.NumNets) {
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("Bad NetNumber %d.\n", Para.Para32[0]))
++ ("Bad NetNumber %d.\n", Para.Para32[0]));
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_STOP Event EMPTY.\n"))
++ ("SK_RLMT_STOP Event EMPTY.\n"));
+ return;
+ }
+
+ if (pAC->Rlmt.Net[Para.Para32[0]].RlmtState == SK_RLMT_RS_INIT) {
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_STOP Event EMPTY.\n"))
++ ("SK_RLMT_STOP Event EMPTY.\n"));
+ return;
+ }
+
+ if (pAC->Rlmt.NetsStarted == 0) {
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("All nets are stopped.\n"))
++ ("All nets are stopped.\n"));
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_STOP Event EMPTY.\n"))
++ ("SK_RLMT_STOP Event EMPTY.\n"));
+ return;
+ }
+
+@@ -2529,7 +2535,7 @@
+ pAC->Rlmt.NetsStarted--;
+
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_STOP Event END.\n"))
++ ("SK_RLMT_STOP Event END.\n"));
+ } /* SkRlmtEvtStop */
+
+
+@@ -2559,13 +2565,13 @@
+ SK_U32 i;
+
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_TIM Event BEGIN.\n"))
++ ("SK_RLMT_TIM Event BEGIN.\n"));
+
+ if (Para.Para32[1] != (SK_U32)-1) {
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("Bad Parameter.\n"))
++ ("Bad Parameter.\n"));
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_TIM Event EMPTY.\n"))
++ ("SK_RLMT_TIM Event EMPTY.\n"));
+ return;
+ }
+
+@@ -2637,7 +2643,7 @@
+ }
+
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_TIM Event END.\n"))
++ ("SK_RLMT_TIM Event END.\n"));
+ } /* SkRlmtEvtTim */
+
+
+@@ -2665,13 +2671,13 @@
+ #endif /* DEBUG */
+
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_SEG_TIM Event BEGIN.\n"))
++ ("SK_RLMT_SEG_TIM Event BEGIN.\n"));
+
+ if (Para.Para32[1] != (SK_U32)-1) {
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("Bad Parameter.\n"))
++ ("Bad Parameter.\n"));
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_SEG_TIM Event EMPTY.\n"))
++ ("SK_RLMT_SEG_TIM Event EMPTY.\n"));
+ return;
+ }
+
+@@ -2695,7 +2701,7 @@
+ InAddr8[3], InAddr8[4], InAddr8[5],
+ pAPort->Exact[k].a[0], pAPort->Exact[k].a[1],
+ pAPort->Exact[k].a[2], pAPort->Exact[k].a[3],
+- pAPort->Exact[k].a[4], pAPort->Exact[k].a[5]))
++ pAPort->Exact[k].a[4], pAPort->Exact[k].a[5]));
+ }
+ }
+ #endif /* xDEBUG */
+@@ -2703,7 +2709,7 @@
+ SkRlmtCheckSeg(pAC, IoC, Para.Para32[0]);
+
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_SEG_TIM Event END.\n"))
++ ("SK_RLMT_SEG_TIM Event END.\n"));
+ } /* SkRlmtEvtSegTim */
+
+
+@@ -2732,18 +2738,18 @@
+
+
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_PACKET_RECEIVED Event BEGIN.\n"))
++ ("SK_RLMT_PACKET_RECEIVED Event BEGIN.\n"));
+
+ /* Should we ignore frames during port switching? */
+
+ #ifdef DEBUG
+ pMb = Para.pParaPtr;
+ if (pMb == NULL) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, ("No mbuf.\n"))
++ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, ("No mbuf.\n"));
+ }
+ else if (pMb->pNext != NULL) {
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("More than one mbuf or pMb->pNext not set.\n"))
++ ("More than one mbuf or pMb->pNext not set.\n"));
+ }
+ #endif /* DEBUG */
+
+@@ -2761,7 +2767,7 @@
+ }
+
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_PACKET_RECEIVED Event END.\n"))
++ ("SK_RLMT_PACKET_RECEIVED Event END.\n"));
+ } /* SkRlmtEvtPacketRx */
+
+
+@@ -2788,21 +2794,21 @@
+ SK_RLMT_PORT *pRPort;
+
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_STATS_CLEAR Event BEGIN.\n"))
++ ("SK_RLMT_STATS_CLEAR Event BEGIN.\n"));
+
+ if (Para.Para32[1] != (SK_U32)-1) {
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("Bad Parameter.\n"))
++ ("Bad Parameter.\n"));
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_STATS_CLEAR Event EMPTY.\n"))
++ ("SK_RLMT_STATS_CLEAR Event EMPTY.\n"));
+ return;
+ }
+
+ if (Para.Para32[0] >= pAC->Rlmt.NumNets) {
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("Bad NetNumber %d.\n", Para.Para32[0]))
++ ("Bad NetNumber %d.\n", Para.Para32[0]));
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_STATS_CLEAR Event EMPTY.\n"))
++ ("SK_RLMT_STATS_CLEAR Event EMPTY.\n"));
+ return;
+ }
+
+@@ -2817,7 +2823,7 @@
+ }
+
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_STATS_CLEAR Event END.\n"))
++ ("SK_RLMT_STATS_CLEAR Event END.\n"));
+ } /* SkRlmtEvtStatsClear */
+
+
+@@ -2841,28 +2847,28 @@
+ SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */
+ {
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_STATS_UPDATE Event BEGIN.\n"))
++ ("SK_RLMT_STATS_UPDATE Event BEGIN.\n"));
+
+ if (Para.Para32[1] != (SK_U32)-1) {
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("Bad Parameter.\n"))
++ ("Bad Parameter.\n"));
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_STATS_UPDATE Event EMPTY.\n"))
++ ("SK_RLMT_STATS_UPDATE Event EMPTY.\n"));
+ return;
+ }
+
+ if (Para.Para32[0] >= pAC->Rlmt.NumNets) {
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("Bad NetNumber %d.\n", Para.Para32[0]))
++ ("Bad NetNumber %d.\n", Para.Para32[0]));
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_STATS_UPDATE Event EMPTY.\n"))
++ ("SK_RLMT_STATS_UPDATE Event EMPTY.\n"));
+ return;
+ }
+
+ /* Update statistics - currently always up-to-date. */
+
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_STATS_UPDATE Event END.\n"))
++ ("SK_RLMT_STATS_UPDATE Event END.\n"));
+ } /* SkRlmtEvtStatsUpdate */
+
+
+@@ -2886,13 +2892,13 @@
+ SK_EVPARA Para) /* SK_U32 PortIndex; SK_U32 NetNumber */
+ {
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_PREFPORT_CHANGE to Port %d Event BEGIN.\n", Para.Para32[0]))
++ ("SK_RLMT_PREFPORT_CHANGE to Port %d Event BEGIN.\n", Para.Para32[0]));
+
+ if (Para.Para32[1] >= pAC->Rlmt.NumNets) {
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("Bad NetNumber %d.\n", Para.Para32[1]))
++ ("Bad NetNumber %d.\n", Para.Para32[1]));
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_PREFPORT_CHANGE Event EMPTY.\n"))
++ ("SK_RLMT_PREFPORT_CHANGE Event EMPTY.\n"));
+ return;
+ }
+
+@@ -2905,7 +2911,7 @@
+ SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E010, SKERR_RLMT_E010_MSG);
+
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_PREFPORT_CHANGE Event EMPTY.\n"))
++ ("SK_RLMT_PREFPORT_CHANGE Event EMPTY.\n"));
+ return;
+ }
+
+@@ -2919,7 +2925,7 @@
+ }
+
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_PREFPORT_CHANGE Event END.\n"))
++ ("SK_RLMT_PREFPORT_CHANGE Event END.\n"));
+ } /* SkRlmtEvtPrefportChange */
+
+
+@@ -2945,37 +2951,37 @@
+ int i;
+
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_SET_NETS Event BEGIN.\n"))
++ ("SK_RLMT_SET_NETS Event BEGIN.\n"));
+
+ if (Para.Para32[1] != (SK_U32)-1) {
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("Bad Parameter.\n"))
++ ("Bad Parameter.\n"));
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_SET_NETS Event EMPTY.\n"))
++ ("SK_RLMT_SET_NETS Event EMPTY.\n"));
+ return;
+ }
+
+ if (Para.Para32[0] == 0 || Para.Para32[0] > SK_MAX_NETS ||
+ Para.Para32[0] > (SK_U32)pAC->GIni.GIMacsFound) {
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("Bad number of nets: %d.\n", Para.Para32[0]))
++ ("Bad number of nets: %d.\n", Para.Para32[0]));
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_SET_NETS Event EMPTY.\n"))
++ ("SK_RLMT_SET_NETS Event EMPTY.\n"));
+ return;
+ }
+
+ if (Para.Para32[0] == pAC->Rlmt.NumNets) { /* No change. */
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_SET_NETS Event EMPTY.\n"))
++ ("SK_RLMT_SET_NETS Event EMPTY.\n"));
+ return;
+ }
+
+ /* Entering and leaving dual mode only allowed while nets are stopped. */
+ if (pAC->Rlmt.NetsStarted > 0) {
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("Changing dual mode only allowed while all nets are stopped.\n"))
++ ("Changing dual mode only allowed while all nets are stopped.\n"));
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_SET_NETS Event EMPTY.\n"))
++ ("SK_RLMT_SET_NETS Event EMPTY.\n"));
+ return;
+ }
+
+@@ -3006,9 +3012,10 @@
+ SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_SET_NETS, Para);
+
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("RLMT: Changed to one net with two ports.\n"))
++ ("RLMT: Changed to one net with two ports.\n"));
+ }
+ else if (Para.Para32[0] == 2) {
++ pAC->Rlmt.RlmtOff = SK_TRUE;
+ pAC->Rlmt.Port[1].Net= &pAC->Rlmt.Net[1];
+ pAC->Rlmt.Net[1].NumPorts = pAC->GIni.GIMacsFound - 1;
+ pAC->Rlmt.Net[0].NumPorts =
+@@ -3035,19 +3042,19 @@
+ SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_SET_NETS, Para);
+
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("RLMT: Changed to two nets with one port each.\n"))
++ ("RLMT: Changed to two nets with one port each.\n"));
+ }
+ else {
+ /* Not implemented for more than two nets. */
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SetNets not implemented for more than two nets.\n"))
++ ("SetNets not implemented for more than two nets.\n"));
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_SET_NETS Event EMPTY.\n"))
++ ("SK_RLMT_SET_NETS Event EMPTY.\n"));
+ return;
+ }
+
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_SET_NETS Event END.\n"))
++ ("SK_RLMT_SET_NETS Event END.\n"));
+ } /* SkRlmtSetNets */
+
+
+@@ -3075,13 +3082,13 @@
+ SK_U32 PrevRlmtMode;
+
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_MODE_CHANGE Event BEGIN.\n"))
++ ("SK_RLMT_MODE_CHANGE Event BEGIN.\n"));
+
+ if (Para.Para32[1] >= pAC->Rlmt.NumNets) {
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("Bad NetNumber %d.\n", Para.Para32[1]))
++ ("Bad NetNumber %d.\n", Para.Para32[1]));
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_MODE_CHANGE Event EMPTY.\n"))
++ ("SK_RLMT_MODE_CHANGE Event EMPTY.\n"));
+ return;
+ }
+
+@@ -3091,9 +3098,9 @@
+ Para.Para32[0] != SK_RLMT_MODE_CLS) {
+ pAC->Rlmt.Net[Para.Para32[1]].RlmtMode = SK_RLMT_MODE_CLS;
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("Forced RLMT mode to CLS on single port net.\n"))
++ ("Forced RLMT mode to CLS on single port net.\n"));
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_MODE_CHANGE Event EMPTY.\n"))
++ ("SK_RLMT_MODE_CHANGE Event EMPTY.\n"));
+ return;
+ }
+
+@@ -3159,7 +3166,7 @@
+ } /* SK_RLMT_CHECK_SEG bit changed. */
+
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("SK_RLMT_MODE_CHANGE Event END.\n"))
++ ("SK_RLMT_MODE_CHANGE Event END.\n"));
+ } /* SkRlmtEvtModeChange */
+
+
+@@ -3245,7 +3252,7 @@
+
+ default: /* Create error log entry. */
+ SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL,
+- ("Unknown RLMT Event %d.\n", Event))
++ ("Unknown RLMT Event %d.\n", Event));
+ SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E003, SKERR_RLMT_E003_MSG);
+ break;
+ } /* switch() */
+diff -ruN linux/drivers/net/sk98lin/sktimer.c linux-new/drivers/net/sk98lin/sktimer.c
+--- linux/drivers/net/sk98lin/sktimer.c 2005-09-26 13:32:48.000000000 +0400
++++ linux-new/drivers/net/sk98lin/sktimer.c 2005-08-09 17:15:51.000000000 +0400
+@@ -2,8 +2,8 @@
+ *
+ * Name: sktimer.c
+ * Project: Gigabit Ethernet Adapters, Event Scheduler Module
+- * Version: $Revision: 1.14 $
+- * Date: $Date: 2003/09/16 13:46:51 $
++ * Version: $Revision: 2.2 $
++ * Date: $Date: 2004/05/28 13:44:39 $
+ * Purpose: High level timer functions.
+ *
+ ******************************************************************************/
+@@ -11,7 +11,7 @@
+ /******************************************************************************
+ *
+ * (C)Copyright 1998-2002 SysKonnect GmbH.
+- * (C)Copyright 2002-2003 Marvell.
++ * (C)Copyright 2002-2004 Marvell.
+ *
+ * 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
+@@ -22,13 +22,12 @@
+ *
+ ******************************************************************************/
+
+-
+ /*
+ * Event queue and dispatcher
+ */
+ #if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
+ static const char SysKonnectFileId[] =
+- "@(#) $Id: sktimer.c,v 1.14 2003/09/16 13:46:51 rschmidt Exp $ (C) Marvell.";
++ "@(#) $Id: sktimer.c,v 2.2 2004/05/28 13:44:39 rschmidt Exp $ (C) Marvell.";
+ #endif
+
+ #include "h/skdrv1st.h" /* Driver Specific Definitions */
+@@ -62,7 +61,7 @@
+ {
+ switch (Level) {
+ case SK_INIT_DATA:
+- pAC->Tim.StQueue = NULL;
++ pAC->Tim.StQueue = 0;
+ break;
+ case SK_INIT_IO:
+ SkHwtInit(pAC, Ioc);
+@@ -85,22 +84,20 @@
+ SK_TIMER **ppTimPrev;
+ SK_TIMER *pTm;
+
+- /*
+- * remove timer from queue
+- */
++ /* remove timer from queue */
+ pTimer->TmActive = SK_FALSE;
+-
++
+ if (pAC->Tim.StQueue == pTimer && !pTimer->TmNext) {
+ SkHwtStop(pAC, Ioc);
+ }
+-
++
+ for (ppTimPrev = &pAC->Tim.StQueue; (pTm = *ppTimPrev);
+ ppTimPrev = &pTm->TmNext ) {
+-
++
+ if (pTm == pTimer) {
+ /*
+ * Timer found in queue
+- * - dequeue it and
++ * - dequeue it
+ * - correct delta of the next timer
+ */
+ *ppTimPrev = pTm->TmNext;
+@@ -121,7 +118,7 @@
+ SK_AC *pAC, /* Adapters context */
+ SK_IOC Ioc, /* IoContext */
+ SK_TIMER *pTimer, /* Timer Pointer to be started */
+-SK_U32 Time, /* Time value */
++SK_U32 Time, /* Time Value (in microsec.) */
+ SK_U32 Class, /* Event Class for this timer */
+ SK_U32 Event, /* Event Value for this timer */
+ SK_EVPARA Para) /* Event Parameter for this timer */
+@@ -130,11 +127,6 @@
+ SK_TIMER *pTm;
+ SK_U32 Delta;
+
+- Time /= 16; /* input is uS, clock ticks are 16uS */
+-
+- if (!Time)
+- Time = 1;
+-
+ SkTimerStop(pAC, Ioc, pTimer);
+
+ pTimer->TmClass = Class;
+@@ -143,31 +135,26 @@
+ pTimer->TmActive = SK_TRUE;
+
+ if (!pAC->Tim.StQueue) {
+- /* First Timer to be started */
++ /* first Timer to be started */
+ pAC->Tim.StQueue = pTimer;
+- pTimer->TmNext = NULL;
++ pTimer->TmNext = 0;
+ pTimer->TmDelta = Time;
+-
++
+ SkHwtStart(pAC, Ioc, Time);
+-
++
+ return;
+ }
+
+- /*
+- * timer correction
+- */
++ /* timer correction */
+ timer_done(pAC, Ioc, 0);
+
+- /*
+- * find position in queue
+- */
++ /* find position in queue */
+ Delta = 0;
+ for (ppTimPrev = &pAC->Tim.StQueue; (pTm = *ppTimPrev);
+ ppTimPrev = &pTm->TmNext ) {
+-
++
+ if (Delta + pTm->TmDelta > Time) {
+- /* Position found */
+- /* Here the timer needs to be inserted. */
++ /* the timer needs to be inserted here */
+ break;
+ }
+ Delta += pTm->TmDelta;
+@@ -179,9 +166,7 @@
+ pTimer->TmDelta = Time - Delta;
+
+ if (pTm) {
+- /* There is a next timer
+- * -> correct its Delta value.
+- */
++ /* there is a next timer: correct its Delta value */
+ pTm->TmDelta -= pTimer->TmDelta;
+ }
+
+@@ -210,7 +195,7 @@
+ int Done = 0;
+
+ Delta = SkHwtRead(pAC, Ioc);
+-
++
+ ppLast = &pAC->Tim.StQueue;
+ pTm = pAC->Tim.StQueue;
+ while (pTm && !Done) {
+@@ -228,13 +213,13 @@
+ Done = 1;
+ }
+ }
+- *ppLast = NULL;
++ *ppLast = 0;
+ /*
+ * pTm points to the first Timer that did not run out.
+ * StQueue points to the first Timer that run out.
+ */
+
+- for ( pTComp = pAC->Tim.StQueue; pTComp; pTComp = pTComp->TmNext) {
++ for (pTComp = pAC->Tim.StQueue; pTComp; pTComp = pTComp->TmNext) {
+ SkEventQueue(pAC,pTComp->TmClass, pTComp->TmEvent, pTComp->TmPara);
+ }
+
+diff -ruN linux/drivers/net/sk98lin/sktwsi.c linux-new/drivers/net/sk98lin/sktwsi.c
+--- linux/drivers/net/sk98lin/sktwsi.c 1970-01-01 03:00:00.000000000 +0300
++++ linux-new/drivers/net/sk98lin/sktwsi.c 2005-08-09 17:15:51.000000000 +0400
+@@ -0,0 +1,1355 @@
++/******************************************************************************
++ *
++ * Name: sktwsi.c
++ * Project: Gigabit Ethernet Adapters, TWSI-Module
++ * Version: $Revision: 1.9 $
++ * Date: $Date: 2004/12/20 15:10:30 $
++ * Purpose: Functions to access Voltage and Temperature Sensor
++ *
++ ******************************************************************************/
++
++/******************************************************************************
++ *
++ * (C)Copyright 1998-2002 SysKonnect.
++ * (C)Copyright 2002-2004 Marvell.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ * The information in this file is provided "AS IS" without warranty.
++ *
++ ******************************************************************************/
++
++/*
++ * TWSI Protocol
++ */
++#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
++static const char SysKonnectFileId[] =
++ "@(#) $Id: sktwsi.c,v 1.9 2004/12/20 15:10:30 rschmidt Exp $ (C) Marvell.";
++#endif
++
++#include "h/skdrv1st.h" /* Driver Specific Definitions */
++#include "h/lm80.h"
++#include "h/skdrv2nd.h" /* Adapter Control- and Driver specific Def. */
++
++#ifdef __C2MAN__
++/*
++ TWSI protocol implementation.
++
++ General Description:
++
++ The TWSI protocol is used for the temperature sensors and for
++ the serial EEPROM which hold the configuration.
++
++ This file covers functions that allow to read write and do
++ some bulk requests a specified TWSI address.
++
++ The Genesis has 2 TWSI buses. One for the EEPROM which holds
++ the VPD Data and one for temperature and voltage sensor.
++ The following picture shows the TWSI buses, TWSI devices and
++ their control registers.
++
++ Note: The VPD functions are in skvpd.c
++.
++. PCI Config TWSI Bus for VPD Data:
++.
++. +------------+
++. | VPD EEPROM |
++. +------------+
++. |
++. | <-- TWSI
++. |
++. +-----------+-----------+
++. | |
++. +-----------------+ +-----------------+
++. | PCI_VPD_ADR_REG | | PCI_VPD_DAT_REG |
++. +-----------------+ +-----------------+
++.
++.
++. TWSI Bus for LM80 sensor:
++.
++. +-----------------+
++. | Temperature and |
++. | Voltage Sensor |
++. | LM80 |
++. +-----------------+
++. |
++. |
++. TWSI --> |
++. |
++. +----+
++. +-------------->| OR |<--+
++. | +----+ |
++. +------+------+ |
++. | | |
++. +--------+ +--------+ +----------+
++. | B2_I2C | | B2_I2C | | B2_I2C |
++. | _CTRL | | _DATA | | _SW |
++. +--------+ +--------+ +----------+
++.
++ The TWSI bus may be driven by the B2_I2C_SW or by the B2_I2C_CTRL
++ and B2_I2C_DATA registers.
++ For driver software it is recommended to use the TWSI control and
++ data register, because TWSI bus timing is done by the ASIC and
++ an interrupt may be received when the TWSI request is completed.
++
++ Clock Rate Timing: MIN MAX generated by
++ VPD EEPROM: 50 kHz 100 kHz HW
++ LM80 over TWSI Ctrl/Data reg. 50 kHz 100 kHz HW
++ LM80 over B2_I2C_SW register 0 400 kHz SW
++
++ Note: The clock generated by the hardware is dependend on the
++ PCI clock. If the PCI bus clock is 33 MHz, the I2C/VPD
++ clock is 50 kHz.
++ */
++intro()
++{}
++#endif
++
++#ifdef SK_DIAG
++/*
++ * TWSI Fast Mode timing values used by the LM80.
++ * If new devices are added to the TWSI bus the timing values have to be checked.
++ */
++#ifndef I2C_SLOW_TIMING
++#define T_CLK_LOW 1300L /* clock low time in ns */
++#define T_CLK_HIGH 600L /* clock high time in ns */
++#define T_DATA_IN_SETUP 100L /* data in Set-up Time */
++#define T_START_HOLD 600L /* start condition hold time */
++#define T_START_SETUP 600L /* start condition Set-up time */
++#define T_STOP_SETUP 600L /* stop condition Set-up time */
++#define T_BUS_IDLE 1300L /* time the bus must free after Tx */
++#define T_CLK_2_DATA_OUT 900L /* max. clock low to data output valid */
++#else /* I2C_SLOW_TIMING */
++/* TWSI Standard Mode Timing */
++#define T_CLK_LOW 4700L /* clock low time in ns */
++#define T_CLK_HIGH 4000L /* clock high time in ns */
++#define T_DATA_IN_SETUP 250L /* data in Set-up Time */
++#define T_START_HOLD 4000L /* start condition hold time */
++#define T_START_SETUP 4700L /* start condition Set-up time */
++#define T_STOP_SETUP 4000L /* stop condition Set-up time */
++#define T_BUS_IDLE 4700L /* time the bus must free after Tx */
++#endif /* !I2C_SLOW_TIMING */
++
++#define NS2BCLK(x) (((x)*125)/10000)
++
++/*
++ * TWSI Wire Operations
++ *
++ * About I2C_CLK_LOW():
++ *
++ * The Data Direction bit (I2C_DATA_DIR) has to be set to input when setting
++ * clock to low, to prevent the ASIC and the TWSI data client from driving the
++ * serial data line simultaneously (ASIC: last bit of a byte = '1', TWSI client
++ * send an 'ACK'). See also Concentrator Bugreport No. 10192.
++ */
++#define I2C_DATA_HIGH(IoC) SK_I2C_SET_BIT(IoC, I2C_DATA)
++#define I2C_DATA_LOW(IoC) SK_I2C_CLR_BIT(IoC, I2C_DATA)
++#define I2C_DATA_OUT(IoC) SK_I2C_SET_BIT(IoC, I2C_DATA_DIR)
++#define I2C_DATA_IN(IoC) SK_I2C_CLR_BIT(IoC, I2C_DATA_DIR | I2C_DATA)
++#define I2C_CLK_HIGH(IoC) SK_I2C_SET_BIT(IoC, I2C_CLK)
++#define I2C_CLK_LOW(IoC) SK_I2C_CLR_BIT(IoC, I2C_CLK | I2C_DATA_DIR)
++#define I2C_START_COND(IoC) SK_I2C_CLR_BIT(IoC, I2C_CLK)
++
++#define NS2CLKT(x) ((x*125L)/10000)
++
++/*--------------- TWSI Interface Register Functions --------------- */
++
++/*
++ * sending one bit
++ */
++void SkI2cSndBit(
++SK_IOC IoC, /* I/O Context */
++SK_U8 Bit) /* Bit to send */
++{
++ I2C_DATA_OUT(IoC);
++ if (Bit) {
++ I2C_DATA_HIGH(IoC);
++ }
++ else {
++ I2C_DATA_LOW(IoC);
++ }
++ SkDgWaitTime(IoC, NS2BCLK(T_DATA_IN_SETUP));
++ I2C_CLK_HIGH(IoC);
++ SkDgWaitTime(IoC, NS2BCLK(T_CLK_HIGH));
++ I2C_CLK_LOW(IoC);
++} /* SkI2cSndBit*/
++
++
++/*
++ * Signal a start to the TWSI Bus.
++ *
++ * A start is signaled when data goes to low in a high clock cycle.
++ *
++ * Ends with Clock Low.
++ *
++ * Status: not tested
++ */
++void SkI2cStart(
++SK_IOC IoC) /* I/O Context */
++{
++ /* Init data and Clock to output lines */
++ /* Set Data high */
++ I2C_DATA_OUT(IoC);
++ I2C_DATA_HIGH(IoC);
++ /* Set Clock high */
++ I2C_CLK_HIGH(IoC);
++
++ SkDgWaitTime(IoC, NS2BCLK(T_START_SETUP));
++
++ /* Set Data Low */
++ I2C_DATA_LOW(IoC);
++
++ SkDgWaitTime(IoC, NS2BCLK(T_START_HOLD));
++
++ /* Clock low without Data to Input */
++ I2C_START_COND(IoC);
++
++ SkDgWaitTime(IoC, NS2BCLK(T_CLK_LOW));
++} /* SkI2cStart */
++
++
++void SkI2cStop(
++SK_IOC IoC) /* I/O Context */
++{
++ /* Init data and Clock to output lines */
++ /* Set Data low */
++ I2C_DATA_OUT(IoC);
++ I2C_DATA_LOW(IoC);
++
++ SkDgWaitTime(IoC, NS2BCLK(T_CLK_2_DATA_OUT));
++
++ /* Set Clock high */
++ I2C_CLK_HIGH(IoC);
++
++ SkDgWaitTime(IoC, NS2BCLK(T_STOP_SETUP));
++
++ /*
++ * Set Data High: Do it by setting the Data Line to Input.
++ * Because of a pull up resistor the Data Line
++ * floods to high.
++ */
++ I2C_DATA_IN(IoC);
++
++ /*
++ * When TWSI activity is stopped
++ * o DATA should be set to input and
++ * o CLOCK should be set to high!
++ */
++ SkDgWaitTime(IoC, NS2BCLK(T_BUS_IDLE));
++} /* SkI2cStop */
++
++
++/*
++ * Receive just one bit via the TWSI bus.
++ *
++ * Note: Clock must be set to LOW before calling this function.
++ *
++ * Returns The received bit.
++ */
++int SkI2cRcvBit(
++SK_IOC IoC) /* I/O Context */
++{
++ int Bit;
++ SK_U8 I2cSwCtrl;
++
++ /* Init data as input line */
++ I2C_DATA_IN(IoC);
++
++ SkDgWaitTime(IoC, NS2BCLK(T_CLK_2_DATA_OUT));
++
++ I2C_CLK_HIGH(IoC);
++
++ SkDgWaitTime(IoC, NS2BCLK(T_CLK_HIGH));
++
++ SK_I2C_GET_SW(IoC, &I2cSwCtrl);
++
++ Bit = (I2cSwCtrl & I2C_DATA) ? 1 : 0;
++
++ I2C_CLK_LOW(IoC);
++ SkDgWaitTime(IoC, NS2BCLK(T_CLK_LOW-T_CLK_2_DATA_OUT));
++
++ return(Bit);
++} /* SkI2cRcvBit */
++
++
++/*
++ * Receive an ACK.
++ *
++ * returns 0 If acknowledged
++ * 1 in case of an error
++ */
++int SkI2cRcvAck(
++SK_IOC IoC) /* I/O Context */
++{
++ /*
++ * Received bit must be zero.
++ */
++ return(SkI2cRcvBit(IoC) != 0);
++} /* SkI2cRcvAck */
++
++
++/*
++ * Send an NACK.
++ */
++void SkI2cSndNAck(
++SK_IOC IoC) /* I/O Context */
++{
++ /*
++ * Received bit must be zero.
++ */
++ SkI2cSndBit(IoC, 1);
++} /* SkI2cSndNAck */
++
++
++/*
++ * Send an ACK.
++ */
++void SkI2cSndAck(
++SK_IOC IoC) /* I/O Context */
++{
++ /*
++ * Received bit must be zero.
++ */
++ SkI2cSndBit(IoC, 0);
++} /* SkI2cSndAck */
++
++
++/*
++ * Send one byte to the TWSI device and wait for ACK.
++ *
++ * Return acknowleged status.
++ */
++int SkI2cSndByte(
++SK_IOC IoC, /* I/O Context */
++int Byte) /* byte to send */
++{
++ int i;
++
++ for (i = 0; i < 8; i++) {
++ if (Byte & (1<<(7-i))) {
++ SkI2cSndBit(IoC, 1);
++ }
++ else {
++ SkI2cSndBit(IoC, 0);
++ }
++ }
++
++ return(SkI2cRcvAck(IoC));
++} /* SkI2cSndByte */
++
++
++/*
++ * Receive one byte and ack it.
++ *
++ * Return byte.
++ */
++int SkI2cRcvByte(
++SK_IOC IoC, /* I/O Context */
++int Last) /* Last Byte Flag */
++{
++ int i;
++ int Byte = 0;
++
++ for (i = 0; i < 8; i++) {
++ Byte <<= 1;
++ Byte |= SkI2cRcvBit(IoC);
++ }
++
++ if (Last) {
++ SkI2cSndNAck(IoC);
++ }
++ else {
++ SkI2cSndAck(IoC);
++ }
++
++ return(Byte);
++} /* SkI2cRcvByte */
++
++
++/*
++ * Start dialog and send device address
++ *
++ * Return 0 if acknowleged, 1 in case of an error
++ */
++int SkI2cSndDev(
++SK_IOC IoC, /* I/O Context */
++int Addr, /* Device Address */
++int Rw) /* Read / Write Flag */
++{
++ SkI2cStart(IoC);
++ Rw = ~Rw;
++ Rw &= I2C_WRITE;
++ return(SkI2cSndByte(IoC, (Addr << 1) | Rw));
++} /* SkI2cSndDev */
++
++#endif /* SK_DIAG */
++
++/*----------------- TWSI CTRL Register Functions ----------*/
++
++/*
++ * waits for a completion of an TWSI transfer
++ *
++ * returns 0: success, transfer completes
++ * 1: error, transfer does not complete, TWSI transfer
++ * killed, wait loop terminated.
++ */
++int SkI2cWait(
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
++int Event) /* complete event to wait for (I2C_READ or I2C_WRITE) */
++{
++ SK_U64 StartTime;
++ SK_U64 CurrentTime;
++ SK_U32 I2cCtrl;
++
++ StartTime = SkOsGetTime(pAC);
++
++ do {
++ CurrentTime = SkOsGetTime(pAC);
++
++ if (CurrentTime - StartTime > SK_TICKS_PER_SEC / 8) {
++
++ SK_I2C_STOP(IoC);
++#ifndef SK_DIAG
++ SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E002, SKERR_I2C_E002MSG);
++#endif /* !SK_DIAG */
++ return(1);
++ }
++
++ SK_I2C_GET_CTL(IoC, &I2cCtrl);
++
++#ifdef xYUKON_DBG
++ printf("StartTime=%lu, CurrentTime=%lu\n",
++ StartTime, CurrentTime);
++ if (kbhit()) {
++ return(1);
++ }
++#endif /* YUKON_DBG */
++
++ } while ((I2cCtrl & I2C_FLAG) == (SK_U32)Event << 31);
++
++ return(0);
++} /* SkI2cWait */
++
++
++/*
++ * waits for a completion of an TWSI transfer
++ *
++ * Returns
++ * Nothing
++ */
++void SkI2cWaitIrq(
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC) /* I/O Context */
++{
++ SK_SENSOR *pSen;
++ SK_U64 StartTime;
++ SK_U32 IrqSrc;
++ SK_U32 IsTwsiReadyBit;
++
++ IsTwsiReadyBit = CHIP_ID_YUKON_2(pAC) ? Y2_IS_TWSI_RDY : IS_I2C_READY;
++
++ pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
++
++ if (pSen->SenState == SK_SEN_IDLE) {
++ return;
++ }
++
++ StartTime = SkOsGetTime(pAC);
++
++ do {
++ if (SkOsGetTime(pAC) - StartTime > SK_TICKS_PER_SEC / 8) {
++
++ SK_I2C_STOP(IoC);
++#ifndef SK_DIAG
++ SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E016, SKERR_I2C_E016MSG);
++#endif /* !SK_DIAG */
++ return;
++ }
++
++ SK_IN32(IoC, B0_ISRC, &IrqSrc);
++
++ } while ((IrqSrc & IsTwsiReadyBit) == 0);
++
++ pSen->SenState = SK_SEN_IDLE;
++ return;
++} /* SkI2cWaitIrq */
++
++/*
++ * writes a single byte or 4 bytes into the TWSI device
++ *
++ * returns 0: success
++ * 1: error
++ */
++int SkI2cWrite(
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
++SK_U32 I2cData, /* TWSI Data to write */
++int I2cDev, /* TWSI Device Address */
++int I2cDevSize, /* TWSI Device Size (e.g. I2C_025K_DEV or I2C_2K_DEV) */
++int I2cReg, /* TWSI Device Register Address */
++int I2cBurst) /* TWSI Burst Flag */
++{
++ SK_OUT32(IoC, B2_I2C_DATA, I2cData);
++
++ SK_I2C_CTL(IoC, I2C_WRITE, I2cDev, I2cDevSize, I2cReg, I2cBurst);
++
++ return(SkI2cWait(pAC, IoC, I2C_WRITE));
++} /* SkI2cWrite*/
++
++
++#ifdef SK_DIAG
++/*
++ * reads a single byte or 4 bytes from the TWSI device
++ *
++ * returns the word read
++ */
++SK_U32 SkI2cRead(
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
++int I2cDev, /* TWSI Device Address */
++int I2cDevSize, /* TWSI Device Size (e.g. I2C_025K_DEV or I2C_2K_DEV) */
++int I2cReg, /* TWSI Device Register Address */
++int I2cBurst) /* TWSI Burst Flag */
++{
++ SK_U32 Data;
++
++ SK_OUT32(IoC, B2_I2C_DATA, 0);
++ SK_I2C_CTL(IoC, I2C_READ, I2cDev, I2cDevSize, I2cReg, I2cBurst);
++
++ if (SkI2cWait(pAC, IoC, I2C_READ) != 0) {
++ w_print("%s\n", SKERR_I2C_E002MSG);
++ }
++
++ SK_IN32(IoC, B2_I2C_DATA, &Data);
++
++ return(Data);
++} /* SkI2cRead */
++#endif /* SK_DIAG */
++
++
++/*
++ * read a sensor's value
++ *
++ * This function reads a sensor's value from the TWSI sensor chip. The sensor
++ * is defined by its index into the sensors database in the struct pAC points
++ * to.
++ * Returns
++ * 1 if the read is completed
++ * 0 if the read must be continued (TWSI Bus still allocated)
++ */
++int SkI2cReadSensor(
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
++SK_SENSOR *pSen) /* Sensor to be read */
++{
++ if (pSen->SenRead != NULL) {
++ return((*pSen->SenRead)(pAC, IoC, pSen));
++ }
++
++ return(0); /* no success */
++} /* SkI2cReadSensor */
++
++/*
++ * Do the Init state 0 initialization
++ */
++static int SkI2cInit0(
++SK_AC *pAC) /* Adapter Context */
++{
++ int i;
++ SK_SENSOR *pSen;
++
++ /* Begin with first sensor */
++ pAC->I2c.CurrSens = 0;
++
++ /* Begin with timeout control for state machine */
++ pAC->I2c.TimerMode = SK_TIMER_WATCH_SM;
++
++ /* Set sensor number to zero */
++ pAC->I2c.MaxSens = 0;
++
++#ifndef SK_DIAG
++ /* Initialize Number of Dummy Reads */
++ pAC->I2c.DummyReads = SK_MAX_SENSORS;
++#endif /* !SK_DIAG */
++
++ for (i = 0; i < SK_MAX_SENSORS; i++) {
++ pSen = &pAC->I2c.SenTable[i];
++
++ pSen->SenDesc = "unknown";
++ pSen->SenType = SK_SEN_UNKNOWN;
++ pSen->SenThreErrHigh = 0;
++ pSen->SenThreErrLow = 0;
++ pSen->SenThreWarnHigh = 0;
++ pSen->SenThreWarnLow = 0;
++ pSen->SenReg = LM80_FAN2_IN;
++ pSen->SenInit = SK_SEN_DYN_INIT_NONE;
++ pSen->SenValue = 0;
++ pSen->SenErrFlag = SK_SEN_ERR_NOT_PRESENT;
++ pSen->SenErrCts = 0;
++ pSen->SenBegErrTS = 0;
++ pSen->SenState = SK_SEN_IDLE;
++ pSen->SenRead = NULL;
++ pSen->SenDev = 0;
++ }
++
++ /* Now we are "INIT data"ed */
++ pAC->I2c.InitLevel = SK_INIT_DATA;
++ return(0);
++} /* SkI2cInit0*/
++
++
++/*
++ * Do the init state 1 initialization
++ *
++ * initialize the following register of the LM80:
++ * Configuration register:
++ * - START, noINT, activeLOW, noINT#Clear, noRESET, noCI, noGPO#, noINIT
++ *
++ * Interrupt Mask Register 1:
++ * - all interrupts are Disabled (0xff)
++ *
++ * Interrupt Mask Register 2:
++ * - all interrupts are Disabled (0xff) Interrupt modi doesn't matter.
++ *
++ * Fan Divisor/RST_OUT register:
++ * - Divisors set to 1 (bits 00), all others 0s.
++ *
++ * OS# Configuration/Temperature resolution Register:
++ * - all 0s
++ *
++ */
++static int SkI2cInit1(
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC) /* I/O Context */
++{
++ int i;
++ SK_U8 I2cSwCtrl;
++ SK_GEPORT *pPrt; /* GIni Port struct pointer */
++ SK_SENSOR *pSen;
++
++ if (pAC->I2c.InitLevel != SK_INIT_DATA) {
++ /* Re-init not needed in TWSI module */
++ return(0);
++ }
++
++ if (pAC->GIni.GIChipId == CHIP_ID_YUKON_EC ||
++ pAC->GIni.GIChipId == CHIP_ID_YUKON_FE) {
++ /* No sensors on Yukon-EC and Yukon-FE */
++ return(0);
++ }
++
++ /* Set the Direction of TWSI-Data Pin to IN */
++ SK_I2C_CLR_BIT(IoC, I2C_DATA_DIR | I2C_DATA);
++ /* Check for 32-Bit Yukon with Low at TWSI-Data Pin */
++ SK_I2C_GET_SW(IoC, &I2cSwCtrl);
++
++ if ((I2cSwCtrl & I2C_DATA) == 0) {
++ /* this is a 32-Bit board */
++ pAC->GIni.GIYukon32Bit = SK_TRUE;
++ return(0);
++ }
++
++ /* Check for 64 Bit Yukon without sensors */
++ if (SkI2cWrite(pAC, IoC, 0, LM80_ADDR, I2C_025K_DEV, LM80_CFG, 0) != 0) {
++ return(0);
++ }
++
++ (void)SkI2cWrite(pAC, IoC, 0xffUL, LM80_ADDR, I2C_025K_DEV, LM80_IMSK_1, 0);
++
++ (void)SkI2cWrite(pAC, IoC, 0xffUL, LM80_ADDR, I2C_025K_DEV, LM80_IMSK_2, 0);
++
++ (void)SkI2cWrite(pAC, IoC, 0, LM80_ADDR, I2C_025K_DEV, LM80_FAN_CTRL, 0);
++
++ (void)SkI2cWrite(pAC, IoC, 0, LM80_ADDR, I2C_025K_DEV, LM80_TEMP_CTRL, 0);
++
++ (void)SkI2cWrite(pAC, IoC, (SK_U32)LM80_CFG_START, LM80_ADDR, I2C_025K_DEV,
++ LM80_CFG, 0);
++
++ /*
++ * MaxSens has to be updated here, because PhyType is not
++ * set when performing Init Level 0
++ */
++ pAC->I2c.MaxSens = 5;
++
++ pPrt = &pAC->GIni.GP[0];
++
++ if (pAC->GIni.GIGenesis) {
++ if (pPrt->PhyType == SK_PHY_BCOM) {
++ if (pAC->GIni.GIMacsFound == 1) {
++ pAC->I2c.MaxSens += 1;
++ }
++ else {
++ pAC->I2c.MaxSens += 3;
++ }
++ }
++ }
++ else {
++ pAC->I2c.MaxSens += 3;
++ }
++
++ for (i = 0; i < pAC->I2c.MaxSens; i++) {
++ pSen = &pAC->I2c.SenTable[i];
++ switch (i) {
++ case 0:
++ pSen->SenDesc = "Temperature";
++ pSen->SenType = SK_SEN_TEMP;
++ pSen->SenThreErrHigh = SK_SEN_TEMP_HIGH_ERR;
++ pSen->SenThreWarnHigh = SK_SEN_TEMP_HIGH_WARN;
++ pSen->SenThreWarnLow = SK_SEN_TEMP_LOW_WARN;
++ pSen->SenThreErrLow = SK_SEN_TEMP_LOW_ERR;
++ pSen->SenReg = LM80_TEMP_IN;
++ break;
++ case 1:
++ pSen->SenDesc = "Voltage PCI";
++ pSen->SenType = SK_SEN_VOLT;
++ pSen->SenThreErrHigh = SK_SEN_PCI_5V_HIGH_ERR;
++ pSen->SenThreWarnHigh = SK_SEN_PCI_5V_HIGH_WARN;
++ if (pAC->GIni.GIPciBus != SK_PEX_BUS) {
++ pSen->SenThreWarnLow = SK_SEN_PCI_5V_LOW_WARN;
++ pSen->SenThreErrLow = SK_SEN_PCI_5V_LOW_ERR;
++ }
++ else {
++ pSen->SenThreWarnLow = 0;
++ pSen->SenThreErrLow = 0;
++ }
++ pSen->SenReg = LM80_VT0_IN;
++ break;
++ case 2:
++ pSen->SenDesc = "Voltage PCI-IO";
++ pSen->SenType = SK_SEN_VOLT;
++ pSen->SenThreErrHigh = SK_SEN_PCI_IO_5V_HIGH_ERR;
++ pSen->SenThreWarnHigh = SK_SEN_PCI_IO_5V_HIGH_WARN;
++ if (pAC->GIni.GIPciBus != SK_PEX_BUS) {
++ pSen->SenThreWarnLow = SK_SEN_PCI_IO_3V3_LOW_WARN;
++ pSen->SenThreErrLow = SK_SEN_PCI_IO_3V3_LOW_ERR;
++ }
++ else {
++ pSen->SenThreWarnLow = 0;
++ pSen->SenThreErrLow = 0;
++ }
++ pSen->SenReg = LM80_VT1_IN;
++ pSen->SenInit = SK_SEN_DYN_INIT_PCI_IO;
++ break;
++ case 3:
++ if (pAC->GIni.GIGenesis) {
++ pSen->SenDesc = "Voltage ASIC";
++ }
++ else {
++ pSen->SenDesc = "Voltage VMAIN";
++ }
++ pSen->SenType = SK_SEN_VOLT;
++ pSen->SenThreErrHigh = SK_SEN_VDD_HIGH_ERR;
++ pSen->SenThreWarnHigh = SK_SEN_VDD_HIGH_WARN;
++ pSen->SenThreWarnLow = SK_SEN_VDD_LOW_WARN;
++ pSen->SenThreErrLow = SK_SEN_VDD_LOW_ERR;
++ pSen->SenReg = LM80_VT2_IN;
++ break;
++ case 4:
++ if (pAC->GIni.GIGenesis) {
++ if (pPrt->PhyType == SK_PHY_BCOM) {
++ pSen->SenDesc = "Voltage PHY A PLL";
++ pSen->SenThreErrHigh = SK_SEN_PLL_3V3_HIGH_ERR;
++ pSen->SenThreWarnHigh = SK_SEN_PLL_3V3_HIGH_WARN;
++ pSen->SenThreWarnLow = SK_SEN_PLL_3V3_LOW_WARN;
++ pSen->SenThreErrLow = SK_SEN_PLL_3V3_LOW_ERR;
++ }
++ else {
++ pSen->SenDesc = "Voltage PMA";
++ pSen->SenThreErrHigh = SK_SEN_PLL_3V3_HIGH_ERR;
++ pSen->SenThreWarnHigh = SK_SEN_PLL_3V3_HIGH_WARN;
++ pSen->SenThreWarnLow = SK_SEN_PLL_3V3_LOW_WARN;
++ pSen->SenThreErrLow = SK_SEN_PLL_3V3_LOW_ERR;
++ }
++ }
++ else {
++ pSen->SenDesc = "Voltage VAUX";
++ pSen->SenThreErrHigh = SK_SEN_VAUX_3V3_HIGH_ERR;
++ pSen->SenThreWarnHigh = SK_SEN_VAUX_3V3_HIGH_WARN;
++ if (pAC->GIni.GIVauxAvail) {
++ pSen->SenThreWarnLow = SK_SEN_VAUX_3V3_LOW_WARN;
++ pSen->SenThreErrLow = SK_SEN_VAUX_3V3_LOW_ERR;
++ }
++ else {
++ pSen->SenThreErrLow = 0;
++ pSen->SenThreWarnLow = 0;
++ }
++ }
++ pSen->SenType = SK_SEN_VOLT;
++ pSen->SenReg = LM80_VT3_IN;
++ break;
++ case 5:
++ if (CHIP_ID_YUKON_2(pAC)) {
++ if (pAC->GIni.GIChipRev == 0) {
++ pSen->SenDesc = "Voltage Core 1V3";
++ pSen->SenThreErrHigh = SK_SEN_CORE_1V3_HIGH_ERR;
++ pSen->SenThreWarnHigh = SK_SEN_CORE_1V3_HIGH_WARN;
++ pSen->SenThreWarnLow = SK_SEN_CORE_1V3_LOW_WARN;
++ pSen->SenThreErrLow = SK_SEN_CORE_1V3_LOW_ERR;
++ }
++ else {
++ pSen->SenDesc = "Voltage Core 1V2";
++ pSen->SenThreErrHigh = SK_SEN_CORE_1V2_HIGH_ERR;
++ pSen->SenThreWarnHigh = SK_SEN_CORE_1V2_HIGH_WARN;
++ pSen->SenThreWarnLow = SK_SEN_CORE_1V2_LOW_WARN;
++ pSen->SenThreErrLow = SK_SEN_CORE_1V2_LOW_ERR;
++ }
++ }
++ else {
++ if (pAC->GIni.GIGenesis) {
++ pSen->SenDesc = "Voltage PHY 2V5";
++ pSen->SenThreErrHigh = SK_SEN_PHY_2V5_HIGH_ERR;
++ pSen->SenThreWarnHigh = SK_SEN_PHY_2V5_HIGH_WARN;
++ pSen->SenThreWarnLow = SK_SEN_PHY_2V5_LOW_WARN;
++ pSen->SenThreErrLow = SK_SEN_PHY_2V5_LOW_ERR;
++ }
++ else {
++ pSen->SenDesc = "Voltage Core 1V5";
++ pSen->SenThreErrHigh = SK_SEN_CORE_1V5_HIGH_ERR;
++ pSen->SenThreWarnHigh = SK_SEN_CORE_1V5_HIGH_WARN;
++ pSen->SenThreWarnLow = SK_SEN_CORE_1V5_LOW_WARN;
++ pSen->SenThreErrLow = SK_SEN_CORE_1V5_LOW_ERR;
++ }
++ }
++ pSen->SenType = SK_SEN_VOLT;
++ pSen->SenReg = LM80_VT4_IN;
++ break;
++ case 6:
++ if (CHIP_ID_YUKON_2(pAC)) {
++ pSen->SenDesc = "Voltage PHY 1V5";
++ pSen->SenThreErrHigh = SK_SEN_CORE_1V5_HIGH_ERR;
++ pSen->SenThreWarnHigh = SK_SEN_CORE_1V5_HIGH_WARN;
++ if (pAC->GIni.GIPciBus == SK_PEX_BUS) {
++ pSen->SenThreWarnLow = SK_SEN_CORE_1V5_LOW_WARN;
++ pSen->SenThreErrLow = SK_SEN_CORE_1V5_LOW_ERR;
++ }
++ else {
++ pSen->SenThreWarnLow = 0;
++ pSen->SenThreErrLow = 0;
++ }
++ }
++ else {
++ if (pAC->GIni.GIGenesis) {
++ pSen->SenDesc = "Voltage PHY B PLL";
++ }
++ else {
++ pSen->SenDesc = "Voltage PHY 3V3";
++ }
++ pSen->SenThreErrHigh = SK_SEN_PLL_3V3_HIGH_ERR;
++ pSen->SenThreWarnHigh = SK_SEN_PLL_3V3_HIGH_WARN;
++ pSen->SenThreWarnLow = SK_SEN_PLL_3V3_LOW_WARN;
++ pSen->SenThreErrLow = SK_SEN_PLL_3V3_LOW_ERR;
++ }
++ pSen->SenType = SK_SEN_VOLT;
++ pSen->SenReg = LM80_VT5_IN;
++ break;
++ case 7:
++ if (pAC->GIni.GIGenesis) {
++ pSen->SenDesc = "Speed Fan";
++ pSen->SenType = SK_SEN_FAN;
++ pSen->SenThreErrHigh = SK_SEN_FAN_HIGH_ERR;
++ pSen->SenThreWarnHigh = SK_SEN_FAN_HIGH_WARN;
++ pSen->SenThreWarnLow = SK_SEN_FAN_LOW_WARN;
++ pSen->SenThreErrLow = SK_SEN_FAN_LOW_ERR;
++ pSen->SenReg = LM80_FAN2_IN;
++ }
++ else {
++ pSen->SenDesc = "Voltage PHY 2V5";
++ pSen->SenType = SK_SEN_VOLT;
++ pSen->SenThreErrHigh = SK_SEN_PHY_2V5_HIGH_ERR;
++ pSen->SenThreWarnHigh = SK_SEN_PHY_2V5_HIGH_WARN;
++ pSen->SenThreWarnLow = SK_SEN_PHY_2V5_LOW_WARN;
++ pSen->SenThreErrLow = SK_SEN_PHY_2V5_LOW_ERR;
++ pSen->SenReg = LM80_VT6_IN;
++ }
++ break;
++ default:
++ SK_ERR_LOG(pAC, SK_ERRCL_INIT | SK_ERRCL_SW,
++ SKERR_I2C_E001, SKERR_I2C_E001MSG);
++ break;
++ }
++
++ pSen->SenValue = 0;
++ pSen->SenErrFlag = SK_SEN_ERR_OK;
++ pSen->SenErrCts = 0;
++ pSen->SenBegErrTS = 0;
++ pSen->SenState = SK_SEN_IDLE;
++ if (pSen->SenThreWarnLow != 0) {
++ pSen->SenRead = SkLm80ReadSensor;
++ }
++ pSen->SenDev = LM80_ADDR;
++ }
++
++#ifndef SK_DIAG
++ pAC->I2c.DummyReads = pAC->I2c.MaxSens;
++#endif /* !SK_DIAG */
++
++ /* Clear TWSI IRQ */
++ SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ);
++
++ /* Now we are I/O initialized */
++ pAC->I2c.InitLevel = SK_INIT_IO;
++ return(0);
++} /* SkI2cInit1 */
++
++
++/*
++ * Init level 2: Start first sensor read.
++ */
++static int SkI2cInit2(
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC) /* I/O Context */
++{
++ int ReadComplete;
++ SK_SENSOR *pSen;
++
++ if (pAC->I2c.InitLevel != SK_INIT_IO) {
++ /* ReInit not needed in TWSI module */
++ /* Init0 and Init2 not permitted */
++ return(0);
++ }
++
++ pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
++
++ ReadComplete = SkI2cReadSensor(pAC, IoC, pSen);
++
++ if (ReadComplete) {
++ SK_ERR_LOG(pAC, SK_ERRCL_INIT, SKERR_I2C_E008, SKERR_I2C_E008MSG);
++ }
++
++ /* Now we are correctly initialized */
++ pAC->I2c.InitLevel = SK_INIT_RUN;
++
++ return(0);
++} /* SkI2cInit2*/
++
++
++/*
++ * Initialize TWSI devices
++ *
++ * Get the first voltage value and discard it.
++ * Go into temperature read mode. A default pointer is not set.
++ *
++ * The things to be done depend on the init level in the parameter list:
++ * Level 0:
++ * Initialize only the data structures. Do NOT access hardware.
++ * Level 1:
++ * Initialize hardware through SK_IN / SK_OUT commands. Do NOT use interrupts.
++ * Level 2:
++ * Everything is possible. Interrupts may be used from now on.
++ *
++ * return:
++ * 0 = success
++ * other = error.
++ */
++int SkI2cInit(
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context needed in levels 1 and 2 */
++int Level) /* Init Level */
++{
++
++ switch (Level) {
++ case SK_INIT_DATA:
++ return(SkI2cInit0(pAC));
++ case SK_INIT_IO:
++ return(SkI2cInit1(pAC, IoC));
++ case SK_INIT_RUN:
++ return(SkI2cInit2(pAC, IoC));
++ default:
++ break;
++ }
++
++ return(0);
++} /* SkI2cInit */
++
++
++#ifndef SK_DIAG
++/*
++ * Interrupt service function for the TWSI Interface
++ *
++ * Clears the Interrupt source
++ *
++ * Reads the register and check it for sending a trap.
++ *
++ * Starts the timer if necessary.
++ */
++void SkI2cIsr(
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC) /* I/O Context */
++{
++ SK_EVPARA Para;
++
++ /* Clear TWSI IRQ */
++ SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ);
++
++ Para.Para64 = 0;
++ SkEventQueue(pAC, SKGE_I2C, SK_I2CEV_IRQ, Para);
++} /* SkI2cIsr */
++
++
++/*
++ * Check this sensors Value against the threshold and send events.
++ */
++static void SkI2cCheckSensor(
++SK_AC *pAC, /* Adapter Context */
++SK_SENSOR *pSen)
++{
++ SK_EVPARA ParaLocal;
++ SK_BOOL TooHigh; /* Is sensor too high? */
++ SK_BOOL TooLow; /* Is sensor too low? */
++ SK_U64 CurrTime; /* Current Time */
++ SK_BOOL DoTrapSend; /* We need to send a trap */
++ SK_BOOL DoErrLog; /* We need to log the error */
++ SK_BOOL IsError; /* Error occured */
++
++ /* Check Dummy Reads first */
++ if (pAC->I2c.DummyReads > 0) {
++ pAC->I2c.DummyReads--;
++ return;
++ }
++
++ /* Get the current time */
++ CurrTime = SkOsGetTime(pAC);
++
++ /* Set para to the most useful setting: The current sensor. */
++ ParaLocal.Para64 = (SK_U64)pAC->I2c.CurrSens;
++
++ /* Check the Value against the thresholds. First: Error Thresholds */
++ TooHigh = pSen->SenValue > pSen->SenThreErrHigh;
++ TooLow = pSen->SenValue < pSen->SenThreErrLow;
++
++ IsError = SK_FALSE;
++
++ if (TooHigh || TooLow) {
++ /* Error condition is satisfied */
++ DoTrapSend = SK_TRUE;
++ DoErrLog = SK_TRUE;
++
++ /* Now error condition is satisfied */
++ IsError = SK_TRUE;
++
++ if (pSen->SenErrFlag == SK_SEN_ERR_ERR) {
++ /* This state is the former one */
++
++ /* So check first whether we have to send a trap */
++ if (pSen->SenLastErrTrapTS + SK_SEN_ERR_TR_HOLD > CurrTime) {
++ /*
++ * Do NOT send the Trap. The hold back time
++ * has to run out first.
++ */
++ DoTrapSend = SK_FALSE;
++ }
++
++ /* Check now whether we have to log an Error */
++ if (pSen->SenLastErrLogTS + SK_SEN_ERR_LOG_HOLD > CurrTime) {
++ /*
++ * Do NOT log the error. The hold back time
++ * has to run out first.
++ */
++ DoErrLog = SK_FALSE;
++ }
++ }
++ else {
++ /* We came from a different state -> Set Begin Time Stamp */
++ pSen->SenBegErrTS = CurrTime;
++ pSen->SenErrFlag = SK_SEN_ERR_ERR;
++ }
++
++ if (DoTrapSend) {
++ /* Set current Time */
++ pSen->SenLastErrTrapTS = CurrTime;
++ pSen->SenErrCts++;
++
++ /* Queue PNMI Event */
++ SkEventQueue(pAC, SKGE_PNMI, TooHigh ?
++ SK_PNMI_EVT_SEN_ERR_UPP : SK_PNMI_EVT_SEN_ERR_LOW,
++ ParaLocal);
++ }
++
++ if (DoErrLog) {
++ /* Set current Time */
++ pSen->SenLastErrLogTS = CurrTime;
++
++ if (pSen->SenType == SK_SEN_TEMP) {
++ SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E011, SKERR_I2C_E011MSG);
++ }
++ else if (pSen->SenType == SK_SEN_VOLT) {
++ SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E012, SKERR_I2C_E012MSG);
++ }
++ else {
++ SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E015, SKERR_I2C_E015MSG);
++ }
++ }
++ }
++
++ /* Check the Value against the thresholds */
++ /* 2nd: Warning thresholds */
++ TooHigh = pSen->SenValue > pSen->SenThreWarnHigh;
++ TooLow = pSen->SenValue < pSen->SenThreWarnLow;
++
++ if (!IsError && (TooHigh || TooLow)) {
++ /* Error condition is satisfied */
++ DoTrapSend = SK_TRUE;
++ DoErrLog = SK_TRUE;
++
++ if (pSen->SenErrFlag == SK_SEN_ERR_WARN) {
++ /* This state is the former one */
++
++ /* So check first whether we have to send a trap */
++ if (pSen->SenLastWarnTrapTS + SK_SEN_WARN_TR_HOLD > CurrTime) {
++ /*
++ * Do NOT send the Trap. The hold back time
++ * has to run out first.
++ */
++ DoTrapSend = SK_FALSE;
++ }
++
++ /* Check now whether we have to log an Error */
++ if (pSen->SenLastWarnLogTS + SK_SEN_WARN_LOG_HOLD > CurrTime) {
++ /*
++ * Do NOT log the error. The hold back time
++ * has to run out first.
++ */
++ DoErrLog = SK_FALSE;
++ }
++ }
++ else {
++ /* We came from a different state -> Set Begin Time Stamp */
++ pSen->SenBegWarnTS = CurrTime;
++ pSen->SenErrFlag = SK_SEN_ERR_WARN;
++ }
++
++ if (DoTrapSend) {
++ /* Set current Time */
++ pSen->SenLastWarnTrapTS = CurrTime;
++ pSen->SenWarnCts++;
++
++ /* Queue PNMI Event */
++ SkEventQueue(pAC, SKGE_PNMI, TooHigh ?
++ SK_PNMI_EVT_SEN_WAR_UPP : SK_PNMI_EVT_SEN_WAR_LOW, ParaLocal);
++ }
++
++ if (DoErrLog) {
++ /* Set current Time */
++ pSen->SenLastWarnLogTS = CurrTime;
++
++ if (pSen->SenType == SK_SEN_TEMP) {
++ SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E009, SKERR_I2C_E009MSG);
++ }
++ else if (pSen->SenType == SK_SEN_VOLT) {
++ SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E010, SKERR_I2C_E010MSG);
++ }
++ else {
++ SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E014, SKERR_I2C_E014MSG);
++ }
++ }
++ }
++
++ /* Check for NO error at all */
++ if (!IsError && !TooHigh && !TooLow) {
++ /* Set o.k. Status if no error and no warning condition */
++ pSen->SenErrFlag = SK_SEN_ERR_OK;
++ }
++
++ /* End of check against the thresholds */
++
++ if (pSen->SenInit == SK_SEN_DYN_INIT_PCI_IO) {
++ /* Bug fix AF: 16.Aug.2001: Correct the init base of LM80 sensor */
++ pSen->SenInit = SK_SEN_DYN_INIT_NONE;
++
++ if (pSen->SenValue > SK_SEN_PCI_IO_RANGE_LIMITER) {
++ /* 5V PCI-IO Voltage */
++ pSen->SenThreWarnLow = SK_SEN_PCI_IO_5V_LOW_WARN;
++ pSen->SenThreErrLow = SK_SEN_PCI_IO_5V_LOW_ERR;
++ }
++ else {
++ /* 3.3V PCI-IO Voltage */
++ pSen->SenThreWarnHigh = SK_SEN_PCI_IO_3V3_HIGH_WARN;
++ pSen->SenThreErrHigh = SK_SEN_PCI_IO_3V3_HIGH_ERR;
++ }
++ }
++
++#ifdef TEST_ONLY
++ /* Dynamic thresholds also for VAUX of LM80 sensor */
++ if (pSen->SenInit == SK_SEN_DYN_INIT_VAUX) {
++
++ pSen->SenInit = SK_SEN_DYN_INIT_NONE;
++
++ /* 3.3V VAUX Voltage */
++ if (pSen->SenValue > SK_SEN_VAUX_RANGE_LIMITER) {
++ pSen->SenThreWarnLow = SK_SEN_VAUX_3V3_LOW_WARN;
++ pSen->SenThreErrLow = SK_SEN_VAUX_3V3_LOW_ERR;
++ }
++ /* 0V VAUX Voltage */
++ else {
++ pSen->SenThreWarnHigh = SK_SEN_VAUX_0V_WARN_ERR;
++ pSen->SenThreErrHigh = SK_SEN_VAUX_0V_WARN_ERR;
++ }
++ }
++
++ /* Check initialization state: the VIO Thresholds need adaption */
++ if (!pSen->SenInit && pSen->SenReg == LM80_VT1_IN &&
++ pSen->SenValue > SK_SEN_WARNLOW2C &&
++ pSen->SenValue < SK_SEN_WARNHIGH2) {
++
++ pSen->SenThreErrLow = SK_SEN_ERRLOW2C;
++ pSen->SenThreWarnLow = SK_SEN_WARNLOW2C;
++ pSen->SenInit = SK_TRUE;
++ }
++
++ if (!pSen->SenInit && pSen->SenReg == LM80_VT1_IN &&
++ pSen->SenValue > SK_SEN_WARNLOW2 &&
++ pSen->SenValue < SK_SEN_WARNHIGH2C) {
++
++ pSen->SenThreErrHigh = SK_SEN_ERRHIGH2C;
++ pSen->SenThreWarnHigh = SK_SEN_WARNHIGH2C;
++ pSen->SenInit = SK_TRUE;
++ }
++#endif
++
++ if (pSen->SenInit != SK_SEN_DYN_INIT_NONE) {
++ SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E013, SKERR_I2C_E013MSG);
++ }
++} /* SkI2cCheckSensor */
++
++
++/*
++ * The only Event to be served is the timeout event
++ *
++ */
++int SkI2cEvent(
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
++SK_U32 Event, /* Module specific Event */
++SK_EVPARA Para) /* Event specific Parameter */
++{
++ int ReadComplete;
++ SK_SENSOR *pSen;
++ SK_U32 Time;
++ SK_EVPARA ParaLocal;
++ int i;
++
++ /* New case: no sensors */
++ if (pAC->I2c.MaxSens == 0) {
++ return(0);
++ }
++
++ switch (Event) {
++ case SK_I2CEV_IRQ:
++ pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
++ ReadComplete = SkI2cReadSensor(pAC, IoC, pSen);
++
++ if (ReadComplete) {
++ /* Check sensor against defined thresholds */
++ SkI2cCheckSensor(pAC, pSen);
++
++ /* Increment Current sensor and set appropriate Timeout */
++ pAC->I2c.CurrSens++;
++ if (pAC->I2c.CurrSens >= pAC->I2c.MaxSens) {
++ pAC->I2c.CurrSens = 0;
++ Time = SK_I2C_TIM_LONG;
++ }
++ else {
++ Time = SK_I2C_TIM_SHORT;
++ }
++
++ /* Start Timer */
++ ParaLocal.Para64 = (SK_U64)0;
++
++ pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING;
++
++ SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time,
++ SKGE_I2C, SK_I2CEV_TIM, ParaLocal);
++ }
++ else {
++ /* Start Timer */
++ ParaLocal.Para64 = (SK_U64)0;
++
++ pAC->I2c.TimerMode = SK_TIMER_WATCH_SM;
++
++ SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, SK_I2C_TIM_WATCH,
++ SKGE_I2C, SK_I2CEV_TIM, ParaLocal);
++ }
++ break;
++ case SK_I2CEV_TIM:
++ if (pAC->I2c.TimerMode == SK_TIMER_NEW_GAUGING) {
++
++ ParaLocal.Para64 = (SK_U64)0;
++ SkTimerStop(pAC, IoC, &pAC->I2c.SenTimer);
++
++ pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
++ ReadComplete = SkI2cReadSensor(pAC, IoC, pSen);
++
++ if (ReadComplete) {
++ /* Check sensor against defined thresholds */
++ SkI2cCheckSensor(pAC, pSen);
++
++ /* Increment Current sensor and set appropriate Timeout */
++ pAC->I2c.CurrSens++;
++ if (pAC->I2c.CurrSens == pAC->I2c.MaxSens) {
++ pAC->I2c.CurrSens = 0;
++ Time = SK_I2C_TIM_LONG;
++ }
++ else {
++ Time = SK_I2C_TIM_SHORT;
++ }
++
++ /* Start Timer */
++ ParaLocal.Para64 = (SK_U64)0;
++
++ pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING;
++
++ SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time,
++ SKGE_I2C, SK_I2CEV_TIM, ParaLocal);
++ }
++ }
++ else {
++ pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens];
++ pSen->SenErrFlag = SK_SEN_ERR_FAULTY;
++ SK_I2C_STOP(IoC);
++
++ /* Increment Current sensor and set appropriate Timeout */
++ pAC->I2c.CurrSens++;
++ if (pAC->I2c.CurrSens == pAC->I2c.MaxSens) {
++ pAC->I2c.CurrSens = 0;
++ Time = SK_I2C_TIM_LONG;
++ }
++ else {
++ Time = SK_I2C_TIM_SHORT;
++ }
++
++ /* Start Timer */
++ ParaLocal.Para64 = (SK_U64)0;
++
++ pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING;
++
++ SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time,
++ SKGE_I2C, SK_I2CEV_TIM, ParaLocal);
++ }
++ break;
++ case SK_I2CEV_CLEAR:
++ for (i = 0; i < SK_MAX_SENSORS; i++) {
++ pSen = &pAC->I2c.SenTable[i];
++
++ pSen->SenErrFlag = SK_SEN_ERR_OK;
++ pSen->SenErrCts = 0;
++ pSen->SenWarnCts = 0;
++ pSen->SenBegErrTS = 0;
++ pSen->SenBegWarnTS = 0;
++ pSen->SenLastErrTrapTS = (SK_U64)0;
++ pSen->SenLastErrLogTS = (SK_U64)0;
++ pSen->SenLastWarnTrapTS = (SK_U64)0;
++ pSen->SenLastWarnLogTS = (SK_U64)0;
++ }
++ break;
++ default:
++ SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E006, SKERR_I2C_E006MSG);
++ }
++
++ return(0);
++} /* SkI2cEvent*/
++
++#endif /* !SK_DIAG */
++
+diff -ruN linux/drivers/net/sk98lin/skvpd.c linux-new/drivers/net/sk98lin/skvpd.c
+--- linux/drivers/net/sk98lin/skvpd.c 2005-09-26 13:32:48.000000000 +0400
++++ linux-new/drivers/net/sk98lin/skvpd.c 2005-08-09 17:15:51.000000000 +0400
+@@ -1,22 +1,22 @@
+ /******************************************************************************
+ *
+ * Name: skvpd.c
+- * Project: GEnesis, PCI Gigabit Ethernet Adapter
+- * Version: $Revision: 1.37 $
+- * Date: $Date: 2003/01/13 10:42:45 $
+- * Purpose: Shared software to read and write VPD data
++ * Project: Gigabit Ethernet Adapters, VPD-Module
++ * Version: $Revision: 2.6 $
++ * Date: $Date: 2004/11/02 10:47:39 $
++ * Purpose: Shared software to read and write VPD
+ *
+ ******************************************************************************/
+
+ /******************************************************************************
+ *
+- * (C)Copyright 1998-2003 SysKonnect GmbH.
++ * (C)Copyright 1998-2002 SysKonnect.
++ * (C)Copyright 2002-2004 Marvell.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+- *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+@@ -25,7 +25,7 @@
+ Please refer skvpd.txt for infomation how to include this module
+ */
+ static const char SysKonnectFileId[] =
+- "@(#)$Id: skvpd.c,v 1.37 2003/01/13 10:42:45 rschmidt Exp $ (C) SK";
++ "@(#) $Id: skvpd.c,v 2.6 2004/11/02 10:47:39 rschmidt Exp $ (C) Marvell.";
+
+ #include "h/skdrv1st.h"
+ #include "h/sktypes.h"
+@@ -59,9 +59,10 @@
+ SK_U64 start_time;
+ SK_U16 state;
+
+- SK_DBG_MSG(pAC,SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
++ SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
+ ("VPD wait for %s\n", event?"Write":"Read"));
+ start_time = SkOsGetTime(pAC);
++
+ do {
+ if (SkOsGetTime(pAC) - start_time > SK_TICKS_PER_SEC) {
+
+@@ -81,17 +82,18 @@
+ ("ERROR:VPD wait timeout\n"));
+ return(1);
+ }
+-
++
+ VPD_IN16(pAC, IoC, PCI_VPD_ADR_REG, &state);
+-
++
+ SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
+ ("state = %x, event %x\n",state,event));
+- } while((int)(state & PCI_VPD_FLAG) == event);
++ } while ((int)(state & PCI_VPD_FLAG) == event);
+
+ return(0);
+ }
+
+-#ifdef SKDIAG
++
++#ifdef SK_DIAG
+
+ /*
+ * Read the dword at address 'addr' from the VPD EEPROM.
+@@ -124,16 +126,15 @@
+ Rtv = 0;
+
+ VPD_IN32(pAC, IoC, PCI_VPD_DAT_REG, &Rtv);
+-
++
+ SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
+ ("VPD read dword data = 0x%x\n",Rtv));
+ return(Rtv);
+ }
++#endif /* SK_DIAG */
+
+-#endif /* SKDIAG */
+-
+-#if 0
+
++#ifdef XXX
+ /*
+ Write the dword 'data' at address 'addr' into the VPD EEPROM, and
+ verify that the data is written.
+@@ -151,7 +152,6 @@
+ . over all 3.8 ms 13.2 ms
+ .
+
+-
+ Returns 0: success
+ 1: error, I2C transfer does not terminate
+ 2: error, data verify error
+@@ -189,7 +189,8 @@
+ return(0);
+ } /* VpdWriteDWord */
+
+-#endif /* 0 */
++#endif /* XXX */
++
+
+ /*
+ * Read one Stream of 'len' bytes of VPD data, starting at 'addr' from
+@@ -215,7 +216,7 @@
+ pComp = (SK_U8 *) buf;
+
+ for (i = 0; i < Len; i++, buf++) {
+- if ((i%sizeof(SK_U32)) == 0) {
++ if ((i % SZ_LONG) == 0) {
+ /*
+ * At the begin of each cycle read the Data Reg
+ * So it is initialized even if only a few bytes
+@@ -233,14 +234,13 @@
+ }
+ }
+
+- /* Write current Byte */
+- VPD_OUT8(pAC, IoC, PCI_VPD_DAT_REG + (i%sizeof(SK_U32)),
+- *(SK_U8*)buf);
++ /* Write current byte */
++ VPD_OUT8(pAC, IoC, PCI_VPD_DAT_REG + (i % SZ_LONG), *(SK_U8*)buf);
+
+- if (((i%sizeof(SK_U32)) == 3) || (i == (Len - 1))) {
++ if (((i % SZ_LONG) == 3) || (i == (Len - 1))) {
+ /* New Address needs to be written to VPD_ADDR reg */
+ AdrReg = (SK_U16) Addr;
+- Addr += sizeof(SK_U32);
++ Addr += SZ_LONG;
+ AdrReg |= VPD_WRITE; /* WRITE operation */
+
+ VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg);
+@@ -250,7 +250,7 @@
+ if (Rtv != 0) {
+ SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+ ("Write Timed Out\n"));
+- return(i - (i%sizeof(SK_U32)));
++ return(i - (i % SZ_LONG));
+ }
+
+ /*
+@@ -265,18 +265,18 @@
+ if (Rtv != 0) {
+ SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+ ("Verify Timed Out\n"));
+- return(i - (i%sizeof(SK_U32)));
++ return(i - (i % SZ_LONG));
+ }
+
+- for (j = 0; j <= (int)(i%sizeof(SK_U32)); j++, pComp++) {
+-
++ for (j = 0; j <= (int)(i % SZ_LONG); j++, pComp++) {
++
+ VPD_IN8(pAC, IoC, PCI_VPD_DAT_REG + j, &Data);
+-
++
+ if (Data != *pComp) {
+ /* Verify Error */
+ SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+ ("WriteStream Verify Error\n"));
+- return(i - (i%sizeof(SK_U32)) + j);
++ return(i - (i % SZ_LONG) + j);
+ }
+ }
+ }
+@@ -284,7 +284,7 @@
+
+ return(Len);
+ }
+-
++
+
+ /*
+ * Read one Stream of 'len' bytes of VPD data, starting at 'addr' from
+@@ -304,10 +304,10 @@
+ int Rtv;
+
+ for (i = 0; i < Len; i++, buf++) {
+- if ((i%sizeof(SK_U32)) == 0) {
++ if ((i % SZ_LONG) == 0) {
+ /* New Address needs to be written to VPD_ADDR reg */
+ AdrReg = (SK_U16) Addr;
+- Addr += sizeof(SK_U32);
++ Addr += SZ_LONG;
+ AdrReg &= ~VPD_WRITE; /* READ operation */
+
+ VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg);
+@@ -318,13 +318,13 @@
+ return(i);
+ }
+ }
+- VPD_IN8(pAC, IoC, PCI_VPD_DAT_REG + (i%sizeof(SK_U32)),
+- (SK_U8 *)buf);
++ VPD_IN8(pAC, IoC, PCI_VPD_DAT_REG + (i % SZ_LONG), (SK_U8 *)buf);
+ }
+
+ return(Len);
+ }
+
++
+ /*
+ * Read ore writes 'len' bytes of VPD data, starting at 'addr' from
+ * or to the I2C EEPROM.
+@@ -350,14 +350,14 @@
+ return(0);
+
+ vpd_rom_size = pAC->vpd.rom_size;
+-
++
+ if (addr > vpd_rom_size - 4) {
+ SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
+ ("Address error: 0x%x, exp. < 0x%x\n",
+ addr, vpd_rom_size - 4));
+ return(0);
+ }
+-
++
+ if (addr + len > vpd_rom_size) {
+ len = vpd_rom_size - addr;
+ SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+@@ -374,8 +374,8 @@
+ return(Rtv);
+ }
+
+-#ifdef SKDIAG
+
++#if defined (SK_DIAG) || defined (SK_ASF)
+ /*
+ * Read 'len' bytes of VPD data, starting at 'addr'.
+ *
+@@ -391,6 +391,7 @@
+ return(VpdTransferBlock(pAC, IoC, buf, addr, len, VPD_READ));
+ }
+
++
+ /*
+ * Write 'len' bytes of *but to the VPD EEPROM, starting at 'addr'.
+ *
+@@ -405,18 +406,27 @@
+ {
+ return(VpdTransferBlock(pAC, IoC, buf, addr, len, VPD_WRITE));
+ }
+-#endif /* SKDIAG */
++#endif /* SK_DIAG */
+
+-/*
+- * (re)initialize the VPD buffer
++
++/******************************************************************************
+ *
+- * Reads the VPD data from the EEPROM into the VPD buffer.
+- * Get the remaining read only and read / write space.
++ * VpdInit() - (re)initialize the VPD buffer
+ *
+- * return 0: success
+- * 1: fatal VPD error
++ * Description:
++ * Reads the VPD data from the EEPROM into the VPD buffer.
++ * Get the remaining read only and read / write space.
++ *
++ * Note:
++ * This is a local function and should be used locally only.
++ * However, the ASF module needs to use this function also.
++ * Therfore it has been published.
++ *
++ * Returns:
++ * 0: success
++ * 1: fatal VPD error
+ */
+-static int VpdInit(
++int VpdInit(
+ SK_AC *pAC, /* Adapters context */
+ SK_IOC IoC) /* IO Context */
+ {
+@@ -427,14 +437,14 @@
+ SK_U16 dev_id;
+ SK_U32 our_reg2;
+
+- SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_INIT, ("VpdInit .. "));
+-
++ SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_INIT, ("VpdInit ... "));
++
+ VPD_IN16(pAC, IoC, PCI_DEVICE_ID, &dev_id);
+-
++
+ VPD_IN32(pAC, IoC, PCI_OUR_REG_2, &our_reg2);
+-
++
+ pAC->vpd.rom_size = 256 << ((our_reg2 & PCI_VPD_ROM_SZ) >> 14);
+-
++
+ /*
+ * this function might get used before the hardware is initialized
+ * therefore we cannot always trust in GIChipId
+@@ -465,19 +475,15 @@
+ ("Block Read Error\n"));
+ return(1);
+ }
+-
++
+ pAC->vpd.vpd_size = vpd_size;
+
+ /* Asus K8V Se Deluxe bugfix. Correct VPD content */
+- /* MBo April 2004 */
+- if (((unsigned char)pAC->vpd.vpd_buf[0x3f] == 0x38) &&
+- ((unsigned char)pAC->vpd.vpd_buf[0x40] == 0x3c) &&
+- ((unsigned char)pAC->vpd.vpd_buf[0x41] == 0x45)) {
+- printk("sk98lin: Asus mainboard with buggy VPD? "
+- "Correcting data.\n");
+- pAC->vpd.vpd_buf[0x40] = 0x38;
+- }
++ i = 62;
++ if (!SK_STRNCMP(pAC->vpd.vpd_buf + i, " 8<E", 4)) {
+
++ pAC->vpd.vpd_buf[i + 2] = '8';
++ }
+
+ /* find the end tag of the RO area */
+ if (!(r = vpd_find_para(pAC, VPD_RV, &rp))) {
+@@ -485,9 +491,9 @@
+ ("Encoding Error: RV Tag not found\n"));
+ return(1);
+ }
+-
++
+ if (r->p_val + r->p_len > pAC->vpd.vpd_buf + vpd_size/2) {
+- SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
++ SK_DBG_MSG(pAC, SK_DBGMOD_VPD,SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
+ ("Encoding Error: Invalid VPD struct size\n"));
+ return(1);
+ }
+@@ -497,7 +503,7 @@
+ for (i = 0, x = 0; (unsigned)i <= (unsigned)vpd_size/2 - r->p_len; i++) {
+ x += pAC->vpd.vpd_buf[i];
+ }
+-
++
+ if (x != 0) {
+ /* checksum error */
+ SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
+@@ -511,7 +517,7 @@
+ ("Encoding Error: RV Tag not found\n"));
+ return(1);
+ }
+-
++
+ if (r->p_val < pAC->vpd.vpd_buf + vpd_size/2) {
+ SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
+ ("Encoding Error: Invalid VPD struct size\n"));
+@@ -531,6 +537,7 @@
+ return(0);
+ }
+
++
+ /*
+ * find the Keyword 'key' in the VPD buffer and fills the
+ * parameter struct 'p' with it's values
+@@ -541,7 +548,7 @@
+ static SK_VPD_PARA *vpd_find_para(
+ SK_AC *pAC, /* common data base */
+ const char *key, /* keyword to find (e.g. "MN") */
+-SK_VPD_PARA *p) /* parameter description struct */
++SK_VPD_PARA *p) /* parameter description struct */
+ {
+ char *v ; /* points to VPD buffer */
+ int max; /* Maximum Number of Iterations */
+@@ -556,10 +563,10 @@
+ if (*v != (char)RES_ID) {
+ SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
+ ("Error: 0x%x missing\n", RES_ID));
+- return NULL;
++ return(0);
+ }
+
+- if (strcmp(key, VPD_NAME) == 0) {
++ if (SK_STRCMP(key, VPD_NAME) == 0) {
+ p->p_len = VPD_GET_RES_LEN(v);
+ p->p_val = VPD_GET_VAL(v);
+ SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
+@@ -569,7 +576,7 @@
+
+ v += 3 + VPD_GET_RES_LEN(v) + 3;
+ for (;; ) {
+- if (SK_MEMCMP(key,v,2) == 0) {
++ if (SK_MEMCMP(key, v, 2) == 0) {
+ p->p_len = VPD_GET_VPD_LEN(v);
+ p->p_val = VPD_GET_VAL(v);
+ SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
+@@ -579,11 +586,11 @@
+
+ /* exit when reaching the "RW" Tag or the maximum of itera. */
+ max--;
+- if (SK_MEMCMP(VPD_RW,v,2) == 0 || max == 0) {
++ if (SK_MEMCMP(VPD_RW, v, 2) == 0 || max == 0) {
+ break;
+ }
+
+- if (SK_MEMCMP(VPD_RV,v,2) == 0) {
++ if (SK_MEMCMP(VPD_RV, v, 2) == 0) {
+ v += 3 + VPD_GET_VPD_LEN(v) + 3; /* skip VPD-W */
+ }
+ else {
+@@ -600,9 +607,10 @@
+ ("Key/Len Encoding error\n"));
+ }
+ #endif /* DEBUG */
+- return NULL;
++ return(0);
+ }
+
++
+ /*
+ * Move 'n' bytes. Begin with the last byte if 'n' is > 0,
+ * Start with the last byte if n is < 0.
+@@ -637,6 +645,7 @@
+ }
+ }
+
++
+ /*
+ * setup the VPD keyword 'key' at 'ip'.
+ *
+@@ -653,10 +662,11 @@
+ p = (SK_VPD_KEY *) ip;
+ p->p_key[0] = key[0];
+ p->p_key[1] = key[1];
+- p->p_len = (unsigned char) len;
+- SK_MEMCPY(&p->p_val,buf,len);
++ p->p_len = (unsigned char)len;
++ SK_MEMCPY(&p->p_val, buf, len);
+ }
+
++
+ /*
+ * Setup the VPD end tag "RV" / "RW".
+ * Also correct the remaining space variables vpd_free_ro / vpd_free_rw.
+@@ -682,7 +692,7 @@
+
+ if (p->p_key[0] != 'R' || (p->p_key[1] != 'V' && p->p_key[1] != 'W')) {
+ /* something wrong here, encoding error */
+- SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
++ SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL,
+ ("Encoding Error: invalid end tag\n"));
+ return(1);
+ }
+@@ -714,6 +724,7 @@
+ return(0);
+ }
+
++
+ /*
+ * Insert a VPD keyword into the VPD buffer.
+ *
+@@ -747,11 +758,11 @@
+
+ SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL,
+ ("VPD setup para key = %s, val = %s\n",key,buf));
+-
++
+ vpd_size = pAC->vpd.vpd_size;
+
+ rtv = 0;
+- ip = NULL;
++ ip = 0;
+ if (type == VPD_RW_KEY) {
+ /* end tag is "RW" */
+ free = pAC->vpd.v.vpd_free_rw;
+@@ -875,18 +886,18 @@
+ }
+ }
+
+- if ((signed)strlen(VPD_NAME) + 1 <= *len) {
++ if ((signed)SK_STRLEN(VPD_NAME) + 1 <= *len) {
+ v = pAC->vpd.vpd_buf;
+- strcpy(buf,VPD_NAME);
+- n = strlen(VPD_NAME) + 1;
++ SK_STRCPY(buf, VPD_NAME);
++ n = SK_STRLEN(VPD_NAME) + 1;
+ buf += n;
+ *elements = 1;
+ SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX,
+- ("'%c%c' ",v[0],v[1]));
++ ("'%c%c' ", v[0], v[1]));
+ }
+ else {
+ *len = 0;
+- SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR,
++ SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+ ("buffer overflow\n"));
+ return(2);
+ }
+@@ -894,17 +905,17 @@
+ v += 3 + VPD_GET_RES_LEN(v) + 3;
+ for (;; ) {
+ /* exit when reaching the "RW" Tag */
+- if (SK_MEMCMP(VPD_RW,v,2) == 0) {
++ if (SK_MEMCMP(VPD_RW, v, 2) == 0) {
+ break;
+ }
+
+- if (SK_MEMCMP(VPD_RV,v,2) == 0) {
++ if (SK_MEMCMP(VPD_RV, v, 2) == 0) {
+ v += 3 + VPD_GET_VPD_LEN(v) + 3; /* skip VPD-W */
+ continue;
+ }
+
+ if (n+3 <= *len) {
+- SK_MEMCPY(buf,v,2);
++ SK_MEMCPY(buf, v, 2);
+ buf += 2;
+ *buf++ = '\0';
+ n += 3;
+@@ -991,13 +1002,14 @@
+ {
+ if ((*key != 'Y' && *key != 'V') ||
+ key[1] < '0' || key[1] > 'Z' ||
+- (key[1] > '9' && key[1] < 'A') || strlen(key) != 2) {
++ (key[1] > '9' && key[1] < 'A') || SK_STRLEN(key) != 2) {
+
+ return(SK_FALSE);
+ }
+ return(SK_TRUE);
+ }
+
++
+ /*
+ * Read the contents of the VPD EEPROM and copy it to the VPD
+ * buffer if not already done. Insert/overwrite the keyword 'key'
+@@ -1026,7 +1038,7 @@
+
+ if ((*key != 'Y' && *key != 'V') ||
+ key[1] < '0' || key[1] > 'Z' ||
+- (key[1] > '9' && key[1] < 'A') || strlen(key) != 2) {
++ (key[1] > '9' && key[1] < 'A') || SK_STRLEN(key) != 2) {
+
+ SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+ ("illegal key tag, keyword not written\n"));
+@@ -1042,13 +1054,13 @@
+ }
+
+ rtv = 0;
+- len = strlen(buf);
++ len = SK_STRLEN(buf);
+ if (len > VPD_MAX_LEN) {
+ /* cut it */
+ len = VPD_MAX_LEN;
+ rtv = 2;
+ SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+- ("keyword too long, cut after %d bytes\n",VPD_MAX_LEN));
++ ("keyword too long, cut after %d bytes\n", VPD_MAX_LEN));
+ }
+ if ((rtv2 = VpdSetupPara(pAC, key, buf, len, VPD_RW_KEY, OWR_KEY)) != 0) {
+ SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+@@ -1059,6 +1071,7 @@
+ return(rtv);
+ }
+
++
+ /*
+ * Read the contents of the VPD EEPROM and copy it to the
+ * VPD buffer if not already done. Remove the VPD keyword
+@@ -1082,7 +1095,7 @@
+
+ vpd_size = pAC->vpd.vpd_size;
+
+- SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_TX,("VPD delete key %s\n",key));
++ SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX, ("VPD delete key %s\n", key));
+ if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) {
+ if (VpdInit(pAC, IoC) != 0) {
+ SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR,
+@@ -1119,6 +1132,7 @@
+ return(0);
+ }
+
++
+ /*
+ * If the VPD buffer contains valid data write the VPD
+ * read/write area back to the VPD EEPROM.
+@@ -1149,7 +1163,6 @@
+ }
+
+
+-
+ /*
+ * Read the contents of the VPD EEPROM and copy it to the VPD buffer
+ * if not already done. If the keyword "VF" is not present it will be
+@@ -1178,7 +1191,7 @@
+ }
+ }
+
+- len = strlen(msg);
++ len = SK_STRLEN(msg);
+ if (len > VPD_MAX_LEN) {
+ /* cut it */
+ len = VPD_MAX_LEN;
+diff -ruN linux/drivers/net/sk98lin/skxmac2.c linux-new/drivers/net/sk98lin/skxmac2.c
+--- linux/drivers/net/sk98lin/skxmac2.c 2005-09-26 13:32:48.000000000 +0400
++++ linux-new/drivers/net/sk98lin/skxmac2.c 2005-08-09 17:15:51.000000000 +0400
+@@ -2,8 +2,8 @@
+ *
+ * Name: skxmac2.c
+ * Project: Gigabit Ethernet Adapters, Common Modules
+- * Version: $Revision: 1.102 $
+- * Date: $Date: 2003/10/02 16:53:58 $
++ * Version: $Revision: 2.39 $
++ * Date: $Date: 2005/07/19 15:48:44 $
+ * Purpose: Contains functions to initialize the MACs and PHYs
+ *
+ ******************************************************************************/
+@@ -11,13 +11,12 @@
+ /******************************************************************************
+ *
+ * (C)Copyright 1998-2002 SysKonnect.
+- * (C)Copyright 2002-2003 Marvell.
++ * (C)Copyright 2002-2005 Marvell.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+- *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+@@ -37,7 +36,7 @@
+
+ #if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
+ static const char SysKonnectFileId[] =
+- "@(#) $Id: skxmac2.c,v 1.102 2003/10/02 16:53:58 rschmidt Exp $ (C) Marvell.";
++ "@(#) $Id: skxmac2.c,v 2.39 2005/07/19 15:48:44 rschmidt Exp $ (C) Marvell.";
+ #endif
+
+ #ifdef GENESIS
+@@ -83,7 +82,7 @@
+ * Returns:
+ * nothing
+ */
+-void SkXmPhyRead(
++int SkXmPhyRead(
+ SK_AC *pAC, /* Adapter Context */
+ SK_IOC IoC, /* I/O Context */
+ int Port, /* Port Index (MAC_1 + n) */
+@@ -94,13 +93,13 @@
+ SK_GEPORT *pPrt;
+
+ pPrt = &pAC->GIni.GP[Port];
+-
++
+ /* 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);
+@@ -110,6 +109,8 @@
+ /* get the PHY register's value */
+ XM_IN16(IoC, Port, XM_PHY_DATA, pVal);
+ }
++
++ return(0);
+ } /* SkXmPhyRead */
+
+
+@@ -122,7 +123,7 @@
+ * Returns:
+ * nothing
+ */
+-void SkXmPhyWrite(
++int SkXmPhyWrite(
+ SK_AC *pAC, /* Adapter Context */
+ SK_IOC IoC, /* I/O Context */
+ int Port, /* Port Index (MAC_1 + n) */
+@@ -133,26 +134,28 @@
+ SK_GEPORT *pPrt;
+
+ 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 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);
+ }
++
++ return(0);
+ } /* SkXmPhyWrite */
+ #endif /* GENESIS */
+
+@@ -165,63 +168,97 @@
+ * Description: reads a 16-bit word from GPHY through MDIO
+ *
+ * Returns:
+- * nothing
++ * 0 o.k.
++ * 1 error during MDIO read
++ * 2 timeout
+ */
+-void SkGmPhyRead(
++int 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 SK_FAR *pVal) /* Pointer to Value */
+ {
++ SK_U16 Word;
+ 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 */
+-
++ SK_U32 StartTime;
++ SK_U32 CurrTime;
++ SK_U32 Delta;
++ SK_U32 TimeOut;
++ int Rtv;
++
++ Rtv = 0;
++
++ *pVal = 0xffff;
++
+ pPrt = &pAC->GIni.GP[Port];
+-
++
+ /* set PHY-Register offset and 'Read' OpCode (= 1) */
+- *pVal = (SK_U16)(GM_SMI_CT_PHY_AD(pPrt->PhyAddr) |
++ Word = (SK_U16)(GM_SMI_CT_PHY_AD(pPrt->PhyAddr) |
+ GM_SMI_CT_REG_AD(PhyReg) | GM_SMI_CT_OP_RD);
+
+- GM_OUT16(IoC, Port, GM_SMI_CTRL, *pVal);
++ GM_OUT16(IoC, Port, GM_SMI_CTRL, Word);
+
+- GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
+-
+ /* additional check for MDC/MDIO activity */
+- if ((Ctrl & GM_SMI_CT_BUSY) == 0) {
+- *pVal = 0;
+- return;
++ GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
++
++ if (Ctrl == 0xffff || (Ctrl & GM_SMI_CT_OP_RD) == 0) {
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR,
++ ("PHY read impossible on Port %d (Ctrl=0x%04x)\n", Port, Ctrl));
++
++ return(1);
+ }
+
+- *pVal |= GM_SMI_CT_BUSY;
+-
+- do {
++ Word |= GM_SMI_CT_BUSY;
++
++ SK_IN32(IoC, GMAC_TI_ST_VAL, &StartTime);
++
++ /* set timeout to 10 ms */
++ TimeOut = HW_MS_TO_TICKS(pAC, 10);
++
++ do { /* wait until 'Busy' is cleared and 'ReadValid' is set */
+ #ifdef VCPU
+ VCPUwaitTime(1000);
+ #endif /* VCPU */
+
++ SK_IN32(IoC, GMAC_TI_ST_VAL, &CurrTime);
++
++ if (CurrTime >= StartTime) {
++ Delta = CurrTime - StartTime;
++ }
++ else {
++ Delta = CurrTime + ~StartTime + 1;
++ }
++
++ if (Delta > TimeOut) {
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR,
++ ("PHY read timeout on Port %d (Ctrl=0x%04x)\n", Port, Ctrl));
++ Rtv = 2;
++ break;
++ }
++
+ GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl);
+
+- /* wait until 'ReadValid' is set */
+- } while (Ctrl == *pVal);
+-
+- /* get the PHY register's value */
++ /* Error on reading SMI Control Register */
++ if (Ctrl == 0xffff) {
++ return(1);
++ }
++
++ } while ((Ctrl ^ Word) != (GM_SMI_CT_RD_VAL | GM_SMI_CT_BUSY));
++
+ 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 */
++ /* dummy read after GM_IN16() */
++ SK_IN32(IoC, GMAC_TI_ST_VAL, &CurrTime);
+
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
++ ("SkGmPhyRead Port:%d, Reg=%d, Val=0x%04X\n",
++ Port, PhyReg, *pVal));
++
++ return(Rtv);
+ } /* SkGmPhyRead */
+
+
+@@ -232,9 +269,11 @@
+ * Description: writes a 16-bit word to GPHY through MDIO
+ *
+ * Returns:
+- * nothing
++ * 0 o.k.
++ * 1 error during MDIO read
++ * 2 timeout
+ */
+-void SkGmPhyWrite(
++int SkGmPhyWrite(
+ SK_AC *pAC, /* Adapter Context */
+ SK_IOC IoC, /* I/O Context */
+ int Port, /* Port Index (MAC_1 + n) */
+@@ -243,54 +282,78 @@
+ {
+ 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 */
+-
++ SK_U32 StartTime;
++ SK_U32 CurrTime;
++ SK_U32 Delta;
++ SK_U32 TimeOut;
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
++ ("SkGmPhyWrite Port:%d, Reg=%d, Val=0x%04X\n",
++ Port, PhyReg, Val));
++
+ 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);
+-
++#ifdef DEBUG
+ /* additional check for MDC/MDIO activity */
+- if ((Ctrl & GM_SMI_CT_BUSY) == 0) {
+- return;
++ GM_IN16(IoC, Port, GM_SMI_DATA, &Ctrl);
++
++ if (Ctrl != Val) {
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR,
++ ("PHY write impossible on Port %d (Val=0x%04x)\n", Port, Ctrl));
++
++ return(1);
+ }
+-
+- Val |= GM_SMI_CT_BUSY;
++#endif /* DEBUG */
+
+- do {
+-#ifdef VCPU
+- /* read Timer value */
+- SK_IN32(IoC, B2_TI_VAL, &DWord);
++ /* set PHY-Register offset and 'Write' OpCode (= 0) */
++ Ctrl = (SK_U16)(GM_SMI_CT_PHY_AD(pPrt->PhyAddr) |
++ GM_SMI_CT_REG_AD(PhyReg));
+
++ GM_OUT16(IoC, Port, GM_SMI_CTRL, Ctrl);
++
++ SK_IN32(IoC, GMAC_TI_ST_VAL, &StartTime);
++
++ /* set timeout to 10 ms */
++ TimeOut = HW_MS_TO_TICKS(pAC, 10);
++
++ do { /* wait until 'Busy' is cleared */
++#ifdef VCPU
+ VCPUwaitTime(1000);
+ #endif /* VCPU */
+
++ SK_IN32(IoC, GMAC_TI_ST_VAL, &CurrTime);
++
++ if (CurrTime >= StartTime) {
++ Delta = CurrTime - StartTime;
++ }
++ else {
++ Delta = CurrTime + ~StartTime + 1;
++ }
++
++ if (Delta > TimeOut) {
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR,
++ ("PHY write timeout on Port %d (Ctrl=0x%04x)\n", Port, Ctrl));
++ return(2);
++ }
++
+ 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 */
++ /* Error on reading SMI Control Register */
++ if (Ctrl == 0xffff) {
++ return(1);
++ }
+
++ } while ((Ctrl & GM_SMI_CT_BUSY) != 0);
++
++ /* dummy read after GM_IN16() */
++ SK_IN32(IoC, GMAC_TI_ST_VAL, &CurrTime);
++
++ return(0);
+ } /* SkGmPhyWrite */
+ #endif /* YUKON */
+
+@@ -312,16 +375,8 @@
+ int PhyReg, /* Register Address (Offset) */
+ SK_U16 *pVal) /* Pointer to Value */
+ {
+- void (*r_func)(SK_AC *pAC, SK_IOC IoC, int Port, int Reg, SK_U16 *pVal);
+
+- if (pAC->GIni.GIGenesis) {
+- r_func = SkXmPhyRead;
+- }
+- else {
+- r_func = SkGmPhyRead;
+- }
+-
+- r_func(pAC, IoC, Port, PhyReg, pVal);
++ pAC->GIni.GIFunc.pFnMacPhyRead(pAC, IoC, Port, PhyReg, pVal);
+ } /* SkGePhyRead */
+
+
+@@ -341,16 +396,8 @@
+ int PhyReg, /* Register Address (Offset) */
+ SK_U16 Val) /* Value */
+ {
+- void (*w_func)(SK_AC *pAC, SK_IOC IoC, int Port, int Reg, SK_U16 Val);
+
+- if (pAC->GIni.GIGenesis) {
+- w_func = SkXmPhyWrite;
+- }
+- else {
+- w_func = SkGmPhyWrite;
+- }
+-
+- w_func(pAC, IoC, Port, PhyReg, Val);
++ pAC->GIni.GIFunc.pFnMacPhyWrite(pAC, IoC, Port, PhyReg, Val);
+ } /* SkGePhyWrite */
+ #endif /* SK_DIAG */
+
+@@ -360,15 +407,15 @@
+ * SkMacPromiscMode() - Enable / Disable Promiscuous Mode
+ *
+ * Description:
+- * enables / disables promiscuous mode by setting Mode Register (XMAC) or
+- * Receive Control Register (GMAC) dep. on board type
++ * enables / disables promiscuous mode by setting Mode Register (XMAC) or
++ * Receive Control Register (GMAC) dep. on board type
+ *
+ * Returns:
+ * nothing
+ */
+ void SkMacPromiscMode(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ int Port, /* Port Index (MAC_1 + n) */
+ SK_BOOL Enable) /* Enable / Disable */
+ {
+@@ -377,11 +424,11 @@
+ #endif
+ #ifdef GENESIS
+ SK_U32 MdReg;
+-#endif
++#endif
+
+ #ifdef GENESIS
+ if (pAC->GIni.GIGenesis) {
+-
++
+ XM_IN32(IoC, Port, XM_MODE, &MdReg);
+ /* enable or disable promiscuous mode */
+ if (Enable) {
+@@ -394,12 +441,12 @@
+ XM_OUT32(IoC, Port, XM_MODE, MdReg);
+ }
+ #endif /* GENESIS */
+-
++
+ #ifdef YUKON
+ if (pAC->GIni.GIYukon) {
+-
++
+ 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);
+@@ -420,28 +467,28 @@
+ * SkMacHashing() - Enable / Disable Hashing
+ *
+ * Description:
+- * enables / disables hashing by setting Mode Register (XMAC) or
+- * Receive Control Register (GMAC) dep. on board type
++ * enables / disables hashing by setting Mode Register (XMAC) or
++ * Receive Control Register (GMAC) dep. on board type
+ *
+ * Returns:
+ * nothing
+ */
+ void SkMacHashing(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ int Port, /* Port Index (MAC_1 + n) */
+ SK_BOOL Enable) /* Enable / Disable */
+ {
+ #ifdef YUKON
+ SK_U16 RcReg;
+-#endif
++#endif
+ #ifdef GENESIS
+ SK_U32 MdReg;
+ #endif
+
+ #ifdef GENESIS
+ if (pAC->GIni.GIGenesis) {
+-
++
+ XM_IN32(IoC, Port, XM_MODE, &MdReg);
+ /* enable or disable hashing */
+ if (Enable) {
+@@ -454,12 +501,12 @@
+ XM_OUT32(IoC, Port, XM_MODE, MdReg);
+ }
+ #endif /* GENESIS */
+-
++
+ #ifdef YUKON
+ if (pAC->GIni.GIYukon) {
+-
++
+ GM_IN16(IoC, Port, GM_RX_CTRL, &RcReg);
+-
++
+ /* enable or disable multicast filtering */
+ if (Enable) {
+ RcReg |= GM_RXCR_MCF_ENA;
+@@ -487,8 +534,8 @@
+ * - 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
++ * 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.
+@@ -499,11 +546,11 @@
+ * nothing
+ */
+ static void SkXmSetRxCmd(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O 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_LENERR_OK_ON/OFF, or SK_BIG_PK_OK_ON/OFF */
+ {
+ SK_U16 OldRxCmd;
+ SK_U16 RxCmd;
+@@ -511,7 +558,7 @@
+ XM_IN16(IoC, Port, XM_RX_CMD, &OldRxCmd);
+
+ RxCmd = OldRxCmd;
+-
++
+ switch (Mode & (SK_STRIP_FCS_ON | SK_STRIP_FCS_OFF)) {
+ case SK_STRIP_FCS_ON:
+ RxCmd |= XM_RX_STRIP_FCS;
+@@ -572,8 +619,8 @@
+ * The features
+ * - FCS (CRC) stripping, SK_STRIP_FCS_ON/OFF
+ * - don't set GMR_FS_LONG_ERR SK_BIG_PK_OK_ON/OFF
+- * for frames > 1514 bytes
+- * - enable Rx of own packets SK_SELF_RX_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.
+@@ -584,20 +631,17 @@
+ * nothing
+ */
+ static void SkGmSetRxCmd(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O 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_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;
++ GM_IN16(IoC, Port, GM_RX_CTRL, &RxCmd);
+
+ if ((Mode & SK_STRIP_FCS_ON) != 0) {
+ RxCmd |= GM_RXCR_CRC_DIS;
+@@ -605,17 +649,13 @@
+ 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);
+- }
++ /* Write the new mode to the Rx Control register */
++ 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;
++ GM_IN16(IoC, Port, GM_SERIAL_MODE, &RxCmd);
+
+ if ((Mode & SK_BIG_PK_OK_ON) != 0) {
+ RxCmd |= GM_SMOD_JUMBO_ENA;
+@@ -623,10 +663,8 @@
+ 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);
+- }
++ /* Write the new mode to the Serial Mode register */
++ GM_OUT16(IoC, Port, GM_SERIAL_MODE, RxCmd);
+ }
+ } /* SkGmSetRxCmd */
+
+@@ -641,17 +679,17 @@
+ * nothing
+ */
+ void SkMacSetRxCmd(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O 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);
+ }
+
+@@ -668,15 +706,15 @@
+ * nothing
+ */
+ void SkMacCrcGener(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O 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) {
+@@ -689,9 +727,9 @@
+ XM_OUT16(IoC, Port, XM_TX_CMD, Word);
+ }
+ else {
+-
++
+ GM_IN16(IoC, Port, GM_TX_CTRL, &Word);
+-
++
+ if (Enable) {
+ Word &= ~GM_TXCR_CRC_DIS;
+ }
+@@ -721,14 +759,14 @@
+ * nothing
+ */
+ void SkXmClrExactAddr(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O 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};
++ SK_U16 ZeroAddr[3] = {0, 0, 0};
+
+ if ((unsigned)StartNum > 15 || (unsigned)StopNum > 15 ||
+ StartNum > StopNum) {
+@@ -738,7 +776,7 @@
+ }
+
+ for (i = StartNum; i <= StopNum; i++) {
+- XM_OUTADDR(IoC, Port, XM_EXM(i), &ZeroAddr[0]);
++ XM_OUTADDR(IoC, Port, XM_EXM(i), ZeroAddr);
+ }
+ } /* SkXmClrExactAddr */
+ #endif /* GENESIS */
+@@ -755,21 +793,21 @@
+ * nothing
+ */
+ void SkMacFlushTxFifo(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ int Port) /* Port Index (MAC_1 + n) */
+ {
+ #ifdef GENESIS
+ SK_U32 MdReg;
+
+ if (pAC->GIni.GIGenesis) {
+-
++
+ XM_IN32(IoC, Port, XM_MODE, &MdReg);
+
+ XM_OUT32(IoC, Port, XM_MODE, MdReg | XM_MD_FTF);
+ }
+ #endif /* GENESIS */
+-
++
+ #ifdef YUKON
+ if (pAC->GIni.GIYukon) {
+ /* no way to flush the FIFO we have to issue a reset */
+@@ -791,8 +829,8 @@
+ * nothing
+ */
+ void SkMacFlushRxFifo(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ int Port) /* Port Index (MAC_1 + n) */
+ {
+ #ifdef GENESIS
+@@ -805,7 +843,7 @@
+ XM_OUT32(IoC, Port, XM_MODE, MdReg | XM_MD_FRF);
+ }
+ #endif /* GENESIS */
+-
++
+ #ifdef YUKON
+ if (pAC->GIni.GIYukon) {
+ /* no way to flush the FIFO we have to issue a reset */
+@@ -853,23 +891,23 @@
+ * nothing
+ */
+ static void SkXmSoftRst(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ int Port) /* Port Index (MAC_1 + n) */
+ {
+- SK_U16 ZeroAddr[4] = {0x0000, 0x0000, 0x0000, 0x0000};
+-
++ SK_U16 ZeroAddr[4] = {0, 0, 0, 0};
++
+ /* 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:
+@@ -887,13 +925,13 @@
+ }
+
+ /* clear the Hash Register */
+- XM_OUTHASH(IoC, Port, XM_HSM, &ZeroAddr);
++ XM_OUTHASH(IoC, Port, XM_HSM, ZeroAddr);
+
+ /* clear the Exact Match Address registers */
+ SkXmClrExactAddr(pAC, IoC, Port, 0, 15);
+-
++
+ /* clear the Source Check Address registers */
+- XM_OUTHASH(IoC, Port, XM_SRC_CHK, &ZeroAddr);
++ XM_OUTHASH(IoC, Port, XM_SRC_CHK, ZeroAddr);
+
+ } /* SkXmSoftRst */
+
+@@ -916,8 +954,8 @@
+ * nothing
+ */
+ static void SkXmHardRst(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ int Port) /* Port Index (MAC_1 + n) */
+ {
+ SK_U32 Reg;
+@@ -940,19 +978,19 @@
+ }
+
+ 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);
+ }
+
+ /* For external PHYs there must be special handling */
+ if (pAC->GIni.GP[Port].PhyType != SK_PHY_XMAC) {
+-
++
+ SK_IN32(IoC, B2_GP_IO, &Reg);
+-
++
+ if (Port == 0) {
+- Reg |= GP_DIR_0; /* set to output */
++ Reg |= GP_DIR_0; /* set to output */
+ Reg &= ~GP_IO_0; /* set PHY reset (active low) */
+ }
+ else {
+@@ -978,12 +1016,12 @@
+ * nothing
+ */
+ static void SkXmClearRst(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ int Port) /* Port Index (MAC_1 + n) */
+ {
+ SK_U32 DWord;
+-
++
+ /* clear HW reset */
+ SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_MAC_RST);
+
+@@ -1000,7 +1038,7 @@
+ /* Clear PHY reset */
+ SK_OUT32(IoC, B2_GP_IO, DWord);
+
+- /* Enable GMII interface */
++ /* enable GMII interface */
+ XM_OUT16(IoC, Port, XM_HW_CFG, XM_HW_GMII_MD);
+ }
+ } /* SkXmClearRst */
+@@ -1020,8 +1058,8 @@
+ * nothing
+ */
+ static void SkGmSoftRst(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ int Port) /* Port Index (MAC_1 + n) */
+ {
+ SK_U16 EmptyHash[4] = {0x0000, 0x0000, 0x0000, 0x0000};
+@@ -1030,19 +1068,18 @@
+ /* reset the statistics module */
+
+ /* disable all GMAC IRQs */
+- SK_OUT8(IoC, GMAC_IRQ_MSK, 0);
+-
++ SK_OUT8(IoC, MR_ADDR(Port, 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 */
++ /* enable Unicast and Multicast filtering */
+ GM_IN16(IoC, Port, GM_RX_CTRL, &RxCtrl);
+-
+- GM_OUT16(IoC, Port, GM_RX_CTRL,
+- (SK_U16)(RxCtrl | GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA));
++
++ GM_OUT16(IoC, Port, GM_RX_CTRL, RxCtrl | GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
+
+ } /* SkGmSoftRst */
+
+@@ -1057,16 +1094,16 @@
+ * nothing
+ */
+ static void SkGmHardRst(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ int Port) /* Port Index (MAC_1 + n) */
+ {
+ SK_U32 DWord;
+-
++
+ /* WA code for COMA mode */
+ if (pAC->GIni.GIYukonLite &&
+- pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) {
+-
++ pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) {
++
+ SK_IN32(IoC, B2_GP_IO, &DWord);
+
+ DWord |= (GP_DIR_9 | GP_IO_9);
+@@ -1076,10 +1113,10 @@
+ }
+
+ /* set GPHY Control reset */
+- SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), GPC_RST_SET);
++ SK_OUT8(IoC, MR_ADDR(Port, GPHY_CTRL), (SK_U8)GPC_RST_SET);
+
+ /* set GMAC Control reset */
+- SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET);
++ SK_OUT8(IoC, MR_ADDR(Port, GMAC_CTRL), (SK_U8)GMC_RST_SET);
+
+ } /* SkGmHardRst */
+
+@@ -1094,24 +1131,27 @@
+ * nothing
+ */
+ static void SkGmClearRst(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ int Port) /* Port Index (MAC_1 + n) */
+ {
+ SK_U32 DWord;
+-
++ SK_U16 PhyId0;
++ SK_U16 PhyId1;
++ SK_U16 Word;
++
+ #ifdef XXX
+- /* clear GMAC Control reset */
+- SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_CLR);
++ /* clear GMAC Control reset */
++ SK_OUT8(IoC, MR_ADDR(Port, GMAC_CTRL), (SK_U8)GMC_RST_CLR);
+
+- /* set GMAC Control reset */
+- SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET);
++ /* set GMAC Control reset */
++ SK_OUT8(IoC, MR_ADDR(Port, GMAC_CTRL), (SK_U8)GMC_RST_SET);
+ #endif /* XXX */
+
+ /* WA code for COMA mode */
+ if (pAC->GIni.GIYukonLite &&
+- pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) {
+-
++ pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) {
++
+ SK_IN32(IoC, B2_GP_IO, &DWord);
+
+ DWord |= GP_DIR_9; /* set to output */
+@@ -1121,30 +1161,85 @@
+ SK_OUT32(IoC, B2_GP_IO, DWord);
+ }
+
+- /* 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);
++#ifdef VCPU
++ /* set MAC Reset before PHY reset is set */
++ SK_OUT8(IoC, MR_ADDR(Port, GMAC_CTRL), (SK_U8)GMC_RST_SET);
++#endif /* VCPU */
+
+- /* set GPHY Control reset */
+- SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_SET);
++ if (CHIP_ID_YUKON_2(pAC)) {
++ /* set GPHY Control reset */
++ SK_OUT8(IoC, MR_ADDR(Port, GPHY_CTRL), (SK_U8)GPC_RST_SET);
++
++ /* release GPHY Control reset */
++ SK_OUT8(IoC, MR_ADDR(Port, GPHY_CTRL), (SK_U8)GPC_RST_CLR);
++
++#ifdef DEBUG
++ /* additional check for PEX */
++ SK_IN16(IoC, GPHY_CTRL, &Word);
++
++ if (pAC->GIni.GIPciBus == SK_PEX_BUS && Word != GPC_RST_CLR) {
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR,
++ ("Error on PEX-bus after GPHY reset\n"));
++ }
++#endif /* DEBUG */
++ }
++ else {
++ /* set HWCFG_MODE */
++ DWord = GPC_INT_POL | 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);
++ /* release GPHY Control reset */
++ SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_CLR);
++ }
+
+ #ifdef VCPU
++ /* wait for internal initialization of GPHY */
++ VCPUprintf(0, "Waiting until PHY %d is ready to initialize\n", Port);
++ VCpuWait(10000);
++
++ /* release GMAC reset */
++ SK_OUT8(IoC, MR_ADDR(Port, GMAC_CTRL), (SK_U8)GMC_RST_CLR);
++
++ /* wait for stable GMAC clock */
+ VCpuWait(9000);
+ #endif /* VCPU */
+
+ /* clear GMAC Control reset */
+- SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_PAUSE_ON | GMC_RST_CLR);
++ SK_OUT8(IoC, MR_ADDR(Port, GMAC_CTRL), (SK_U8)GMC_RST_CLR);
++
++ if (HW_FEATURE(pAC, HWF_WA_DEV_472) && Port == MAC_2) {
++
++ /* clear GMAC 1 Control reset */
++ SK_OUT8(IoC, MR_ADDR(MAC_1, GMAC_CTRL), (SK_U8)GMC_RST_CLR);
++
++ do {
++ /* set GMAC 2 Control reset */
++ SK_OUT8(IoC, MR_ADDR(MAC_2, GMAC_CTRL), (SK_U8)GMC_RST_SET);
++
++ /* clear GMAC 2 Control reset */
++ SK_OUT8(IoC, MR_ADDR(MAC_2, GMAC_CTRL), (SK_U8)GMC_RST_CLR);
++
++ SkGmPhyRead(pAC, IoC, MAC_2, PHY_MARV_ID0, &PhyId0);
++
++ SkGmPhyRead(pAC, IoC, MAC_2, PHY_MARV_ID1, &PhyId1);
++
++ SkGmPhyRead(pAC, IoC, MAC_2, PHY_MARV_INT_MASK, &Word);
++
++ } while (Word != 0 || PhyId0 != PHY_MARV_ID0_VAL ||
++ PhyId1 != PHY_MARV_ID1_Y2);
++ }
+
+ #ifdef VCPU
+ VCpuWait(2000);
+-
++
+ SK_IN32(IoC, MR_ADDR(Port, GPHY_CTRL), &DWord);
+-
++
+ SK_IN32(IoC, B0_ISRC, &DWord);
+ #endif /* VCPU */
+
+@@ -1162,37 +1257,33 @@
+ * nothing
+ */
+ void SkMacSoftRst(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ int Port) /* Port Index (MAC_1 + n) */
+ {
+- SK_GEPORT *pPrt;
+-
+- pPrt = &pAC->GIni.GP[Port];
+-
+ /* disable receiver and transmitter */
+ SkMacRxTxDisable(pAC, IoC, Port);
+
+ #ifdef GENESIS
+ if (pAC->GIni.GIGenesis) {
+-
++
+ SkXmSoftRst(pAC, IoC, Port);
+ }
+ #endif /* GENESIS */
+-
++
+ #ifdef YUKON
+ if (pAC->GIni.GIYukon) {
+-
++
+ SkGmSoftRst(pAC, IoC, Port);
+ }
+ #endif /* YUKON */
+
+ /* flush the MAC's Rx and Tx FIFOs */
+ SkMacFlushTxFifo(pAC, IoC, Port);
+-
++
+ SkMacFlushRxFifo(pAC, IoC, Port);
+
+- pPrt->PState = SK_PRT_STOP;
++ pAC->GIni.GP[Port].PState = SK_PRT_STOP;
+
+ } /* SkMacSoftRst */
+
+@@ -1207,25 +1298,27 @@
+ * nothing
+ */
+ void SkMacHardRst(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ int Port) /* Port Index (MAC_1 + n) */
+ {
+-
++
+ #ifdef GENESIS
+ if (pAC->GIni.GIGenesis) {
+-
++
+ SkXmHardRst(pAC, IoC, Port);
+ }
+ #endif /* GENESIS */
+-
++
+ #ifdef YUKON
+ if (pAC->GIni.GIYukon) {
+-
++
+ SkGmHardRst(pAC, IoC, Port);
+ }
+ #endif /* YUKON */
+
++ pAC->GIni.GP[Port].PHWLinkUp = SK_FALSE;
++
+ pAC->GIni.GP[Port].PState = SK_PRT_RESET;
+
+ } /* SkMacHardRst */
+@@ -1241,21 +1334,21 @@
+ * nothing
+ */
+ void SkMacClearRst(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ int Port) /* Port Index (MAC_1 + n) */
+ {
+-
++
+ #ifdef GENESIS
+ if (pAC->GIni.GIGenesis) {
+-
++
+ SkXmClearRst(pAC, IoC, Port);
+ }
+ #endif /* GENESIS */
+-
++
+ #ifdef YUKON
+ if (pAC->GIni.GIYukon) {
+-
++
+ SkGmClearRst(pAC, IoC, Port);
+ }
+ #endif /* YUKON */
+@@ -1279,8 +1372,8 @@
+ * nothing
+ */
+ void SkXmInitMac(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ int Port) /* Port Index (MAC_1 + n) */
+ {
+ SK_GEPORT *pPrt;
+@@ -1290,13 +1383,13 @@
+ pPrt = &pAC->GIni.GP[Port];
+
+ if (pPrt->PState == SK_PRT_STOP) {
+- /* Port State: SK_PRT_STOP */
+ /* Verify that the reset bit is cleared */
+ SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &SWord);
+
+ if ((SWord & MFF_SET_MAC_RST) != 0) {
+ /* PState does not match HW state */
+- SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E006, SKERR_HWI_E006MSG);
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
++ ("SkXmInitMac: PState does not match HW state"));
+ /* Correct it */
+ pPrt->PState = SK_PRT_RESET;
+ }
+@@ -1315,7 +1408,7 @@
+ * 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 (pPrt->PhyId1 == PHY_BCOM_ID1_C0) {
+@@ -1348,7 +1441,7 @@
+ * 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));
+
+@@ -1357,7 +1450,7 @@
+
+ /* Dummy read the Interrupt source register */
+ XM_IN16(IoC, Port, XM_ISRC, &SWord);
+-
++
+ /*
+ * The auto-negotiation process starts immediately after
+ * clearing the reset. The auto-negotiation process should be
+@@ -1383,7 +1476,7 @@
+ * 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);
+ }
+
+@@ -1401,7 +1494,7 @@
+ SWord = SK_XM_THR_SL; /* for single port */
+
+ if (pAC->GIni.GIMacsFound > 1) {
+- switch (pAC->GIni.GIPortUsage) {
++ switch (pPrt->PPortUsage) {
+ case SK_RED_LINK:
+ SWord = SK_XM_THR_REDL; /* redundant link */
+ break;
+@@ -1424,7 +1517,7 @@
+ /* setup register defaults for the Rx Command Register */
+ SWord = XM_RX_STRIP_FCS | XM_RX_LENERR_OK;
+
+- if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
++ if (pPrt->PPortUsage == SK_JUMBO_LINK) {
+ SWord |= XM_RX_BIG_PK_OK;
+ }
+
+@@ -1436,7 +1529,7 @@
+ */
+ SWord |= XM_RX_DIS_CEXT;
+ }
+-
++
+ XM_OUT16(IoC, Port, XM_RX_CMD, SWord);
+
+ /*
+@@ -1493,8 +1586,8 @@
+ * nothing
+ */
+ void SkGmInitMac(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ int Port) /* Port Index (MAC_1 + n) */
+ {
+ SK_GEPORT *pPrt;
+@@ -1505,24 +1598,29 @@
+ 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);
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
++ ("SkGmInitMac: PState does not match HW state"));
+ /* Correct it */
+ pPrt->PState = SK_PRT_RESET;
+ }
++ else {
++ /* enable all PHY interrupts */
++ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK,
++ (SK_U16)PHY_M_DEF_MSK);
++ }
+ }
+
+ if (pPrt->PState == SK_PRT_RESET) {
+-
++
+ SkGmHardRst(pAC, IoC, Port);
+
+ SkGmClearRst(pAC, IoC, Port);
+-
++
+ /* Auto-negotiation ? */
+ if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
+ /* Auto-negotiation disabled */
+@@ -1532,10 +1630,10 @@
+
+ /* disable auto-update for speed, duplex and flow-control */
+ SWord |= GM_GPCR_AU_ALL_DIS;
+-
++
+ /* setup General Purpose Control Register */
+ GM_OUT16(IoC, Port, GM_GP_CTRL, SWord);
+-
++
+ SWord = GM_GPCR_AU_ALL_DIS;
+ }
+ else {
+@@ -1546,7 +1644,10 @@
+ switch (pPrt->PLinkSpeed) {
+ case SK_LSPEED_AUTO:
+ case SK_LSPEED_1000MBPS:
+- SWord |= GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100;
++ if ((pPrt->PLinkSpeedCap & SK_LSPEED_CAP_1000MBPS) != 0) {
++
++ SWord |= GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100;
++ }
+ break;
+ case SK_LSPEED_100MBPS:
+ SWord |= GM_GPCR_SPEED_100;
+@@ -1564,8 +1665,6 @@
+ /* flow-control settings */
+ switch (pPrt->PFlowCtrlMode) {
+ case SK_FLOW_MODE_NONE:
+- /* set Pause Off */
+- SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_PAUSE_OFF);
+ /* disable Tx & Rx flow-control */
+ SWord |= GM_GPCR_FC_TX_DIS | GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS;
+ break;
+@@ -1583,24 +1682,22 @@
+ GM_OUT16(IoC, Port, GM_GP_CTRL, SWord);
+
+ /* dummy read the Interrupt Source Register */
+- SK_IN16(IoC, GMAC_IRQ_SRC, &SWord);
+-
++ SK_IN16(IoC, MR_ADDR(Port, 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 */
++#endif /* !VCPU */
+ }
+
+ (void)SkGmResetCounter(pAC, IoC, Port);
+
+ /* setup Transmit Control Register */
+- GM_OUT16(IoC, Port, GM_TX_CTRL, TX_COL_THR(pPrt->PMacColThres));
++ GM_OUT16(IoC, Port, GM_TX_CTRL, (SK_U16)TX_COL_THR(pPrt->PMacColThres));
+
+ /* setup Receive Control Register */
+- GM_OUT16(IoC, Port, GM_RX_CTRL, GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA |
+- GM_RXCR_CRC_DIS);
++ SWord = GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA | GM_RXCR_CRC_DIS;
++
++ GM_OUT16(IoC, Port, GM_RX_CTRL, SWord);
+
+ /* setup Transmit Flow Control Register */
+ GM_OUT16(IoC, Port, GM_TX_FLOW_CTRL, 0xffff);
+@@ -1610,31 +1707,29 @@
+ GM_IN16(IoC, Port, GM_TX_PARAM, &SWord);
+ #endif /* VCPU */
+
+- SWord = TX_JAM_LEN_VAL(pPrt->PMacJamLen) |
+- TX_JAM_IPG_VAL(pPrt->PMacJamIpgVal) |
+- TX_IPG_JAM_DATA(pPrt->PMacJamIpgData);
+-
++ SWord = (SK_U16)(TX_JAM_LEN_VAL(pPrt->PMacJamLen) |
++ TX_JAM_IPG_VAL(pPrt->PMacJamIpgVal) |
++ TX_IPG_JAM_DATA(pPrt->PMacJamIpgData) |
++ TX_BACK_OFF_LIM(pPrt->PMacBackOffLim));
++
+ 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_DATA_VAL(pPrt->PMacIpgData);
++ SWord = (SK_U16)(DATA_BLIND_VAL(pPrt->PMacDataBlind) |
++ GM_SMOD_VLAN_ENA | IPG_DATA_VAL(pPrt->PMacIpgData));
+
+ if (pPrt->PMacLimit4) {
+ /* reset of collision counter after 4 consecutive collisions */
+ SWord |= GM_SMOD_LIMIT_4;
+ }
+
+- if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
++ if (pPrt->PPortUsage == 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:
+@@ -1663,17 +1758,17 @@
+ else {
+ GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + i * 4), SWord);
+ }
+-#else
++#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 Multicast filtering Hash registers 1-3 */
+- GM_OUT16(IoC, Port, GM_MC_ADDR_H1 + 4*i, 0);
++ GM_OUT16(IoC, Port, GM_MC_ADDR_H1 + i * 4, 0);
+ }
+
+ /* reset Multicast filtering Hash register 4 */
+@@ -1684,18 +1779,6 @@
+ GM_OUT16(IoC, Port, GM_RX_IRQ_MSK, 0);
+ GM_OUT16(IoC, Port, GM_TR_IRQ_MSK, 0);
+
+-#if defined(SK_DIAG) || defined(DEBUG)
+- /* read General Purpose Status */
+- GM_IN16(IoC, Port, GM_GP_STAT, &SWord);
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("MAC Stat Reg.=0x%04X\n", SWord));
+-#endif /* SK_DIAG || DEBUG */
+-
+-#ifdef SK_DIAG
+- c_print("MAC Stat Reg=0x%04X\n", SWord);
+-#endif /* SK_DIAG */
+-
+ } /* SkGmInitMac */
+ #endif /* YUKON */
+
+@@ -1714,8 +1797,8 @@
+ * nothing
+ */
+ void SkXmInitDupMd(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ int Port) /* Port Index (MAC_1 + n) */
+ {
+ switch (pAC->GIni.GP[Port].PLinkModeStatus) {
+@@ -1762,8 +1845,8 @@
+ * nothing
+ */
+ void SkXmInitPauseMd(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ int Port) /* Port Index (MAC_1 + n) */
+ {
+ SK_GEPORT *pPrt;
+@@ -1773,11 +1856,11 @@
+ 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 */
++ /* disable Pause Frame Reception */
+ Word |= XM_MMU_IGN_PF;
+ }
+ else {
+@@ -1785,10 +1868,10 @@
+ * enabling pause frame reception is required for 1000BT
+ * because the XMAC is not reset if the link is going down
+ */
+- /* Enable Pause Frame Reception */
++ /* enable Pause Frame Reception */
+ Word &= ~XM_MMU_IGN_PF;
+- }
+-
++ }
++
+ XM_OUT16(IoC, Port, XM_MMU_CMD, Word);
+
+ XM_IN32(IoC, Port, XM_MODE, &DWord);
+@@ -1811,10 +1894,10 @@
+ /* remember this value is defined in big endian (!) */
+ XM_OUT16(IoC, Port, XM_MAC_PTIME, 0xffff);
+
+- /* Set Pause Mode in Mode Register */
++ /* set Pause Mode in Mode Register */
+ DWord |= XM_PAUSE_MODE;
+
+- /* Set Pause Mode in MAC Rx FIFO */
++ /* set Pause Mode in MAC Rx FIFO */
+ SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_ENA_PAUSE);
+ }
+ else {
+@@ -1822,13 +1905,13 @@
+ * 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 */
++ /* disable Pause Mode in Mode Register */
+ DWord &= ~XM_PAUSE_MODE;
+
+- /* Disable Pause Mode in MAC Rx FIFO */
++ /* disable Pause Mode in MAC Rx FIFO */
+ SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_DIS_PAUSE);
+ }
+-
++
+ XM_OUT32(IoC, Port, XM_MODE, DWord);
+ } /* SkXmInitPauseMd*/
+
+@@ -1845,8 +1928,8 @@
+ * nothing
+ */
+ static void SkXmInitPhyXmac(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ int Port, /* Port Index (MAC_1 + n) */
+ SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
+ {
+@@ -1855,12 +1938,12 @@
+
+ pPrt = &pAC->GIni.GP[Port];
+ 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 */
++ /* set DuplexMode in Config register */
+ if (pPrt->PLinkMode == SK_LMODE_FULL) {
+ Ctrl |= PHY_CT_DUP_MD;
+ }
+@@ -1873,9 +1956,9 @@
+ else {
+ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+ ("InitPhyXmac: with auto-negotiation Port %d\n", Port));
+- /* Set Auto-negotiation advertisement */
++ /* set Auto-negotiation advertisement */
+
+- /* Set Full/half duplex capabilities */
++ /* set Full/half duplex capabilities */
+ switch (pPrt->PLinkMode) {
+ case SK_LMODE_AUTOHALF:
+ Ctrl |= PHY_X_AN_HD;
+@@ -1891,7 +1974,7 @@
+ SKERR_HWI_E015MSG);
+ }
+
+- /* Set Flow-control capabilities */
++ /* set Flow-control capabilities */
+ switch (pPrt->PFlowCtrlMode) {
+ case SK_FLOW_MODE_NONE:
+ Ctrl |= PHY_X_P_NO_PAUSE;
+@@ -1918,7 +2001,7 @@
+ }
+
+ if (DoLoop) {
+- /* Set the Phy Loopback bit, too */
++ /* set the Phy Loopback bit, too */
+ Ctrl |= PHY_CT_LOOP;
+ }
+
+@@ -1939,8 +2022,8 @@
+ * nothing
+ */
+ static void SkXmInitPhyBcom(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ int Port, /* Port Index (MAC_1 + n) */
+ SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
+ {
+@@ -1962,7 +2045,7 @@
+ /* manually Master/Slave ? */
+ if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
+ Ctrl2 |= PHY_B_1000C_MSE;
+-
++
+ if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
+ Ctrl2 |= PHY_B_1000C_MSC;
+ }
+@@ -1971,7 +2054,7 @@
+ 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 */
++ /* set DuplexMode in Config register */
+ if (pPrt->PLinkMode == SK_LMODE_FULL) {
+ Ctrl1 |= PHY_CT_DUP_MD;
+ }
+@@ -1989,7 +2072,7 @@
+ else {
+ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+ ("InitPhyBcom: with auto-negotiation Port %d\n", Port));
+- /* Set Auto-negotiation advertisement */
++ /* set Auto-negotiation advertisement */
+
+ /*
+ * Workaround BCOM Errata #1 for the C5 type.
+@@ -1997,8 +2080,8 @@
+ * Set Repeater/DTE bit 10 of the 1000Base-T Control Register
+ */
+ Ctrl2 |= PHY_B_1000C_RD;
+-
+- /* Set Full/half duplex capabilities */
++
++ /* set Full/half duplex capabilities */
+ switch (pPrt->PLinkMode) {
+ case SK_LMODE_AUTOHALF:
+ Ctrl2 |= PHY_B_1000C_AHD;
+@@ -2014,7 +2097,7 @@
+ SKERR_HWI_E015MSG);
+ }
+
+- /* Set Flow-control capabilities */
++ /* set Flow-control capabilities */
+ switch (pPrt->PFlowCtrlMode) {
+ case SK_FLOW_MODE_NONE:
+ Ctrl3 |= PHY_B_P_NO_PAUSE;
+@@ -2036,27 +2119,27 @@
+ /* 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) */
+-
++ 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,
+ ("Set 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,
+ ("Set Auto-Neg.Adv.Reg=0x%04X\n", Ctrl3));
+-
++
+ if (DoLoop) {
+- /* Set the Phy Loopback bit, too */
++ /* set the Phy Loopback bit, too */
+ Ctrl1 |= PHY_CT_LOOP;
+ }
+
+- if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) {
++ if (pPrt->PPortUsage == SK_JUMBO_LINK) {
+ /* configure FIFO to high latency for transmission of ext. packets */
+ Ctrl4 |= PHY_B_PEC_HIGH_LA;
+
+@@ -2068,7 +2151,7 @@
+
+ /* 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,
+@@ -2078,17 +2161,17 @@
+
+
+ #ifdef YUKON
+-#ifndef SK_SLIM
++#ifdef SK_PHY_LP_MODE
+ /******************************************************************************
+ *
+ * SkGmEnterLowPowerMode()
+ *
+- * Description:
++ * Description:
+ * This function sets the Marvell Alaska PHY to the low power mode
+ * given by parameter mode.
+ * The following low power modes are available:
+- *
+- * - Coma Mode (Deep Sleep):
++ *
++ * - COMA Mode (Deep Sleep):
+ * Power consumption: ~15 - 30 mW
+ * The PHY cannot wake up on its own.
+ *
+@@ -2115,113 +2198,207 @@
+ * 1: error
+ */
+ int SkGmEnterLowPowerMode(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ int Port, /* Port Index (e.g. MAC_1) */
+ SK_U8 Mode) /* low power mode */
+ {
++ SK_U8 LastMode;
++ SK_U8 Byte;
+ SK_U16 Word;
++ SK_U16 ClkDiv;
+ SK_U32 DWord;
+- SK_U8 LastMode;
++ SK_U32 PowerDownBit;
+ int Ret = 0;
+
+- if (pAC->GIni.GIYukonLite &&
+- pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) {
++ if (!(CHIP_ID_YUKON_2(pAC) || (pAC->GIni.GIYukonLite &&
++ pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3))) {
+
+- /* save current power mode */
+- LastMode = pAC->GIni.GP[Port].PPhyPowerState;
+- pAC->GIni.GP[Port].PPhyPowerState = Mode;
+-
+- switch (Mode) {
+- /* coma mode (deep sleep) */
+- case PHY_PM_DEEP_SLEEP:
+- /* setup General Purpose Control Register */
+- GM_OUT16(IoC, 0, GM_GP_CTRL, GM_GPCR_FL_PASS |
+- GM_GPCR_SPEED_100 | GM_GPCR_AU_ALL_DIS);
+-
+- /* apply COMA mode workaround */
+- SkGmPhyWrite(pAC, IoC, Port, 29, 0x001f);
+- SkGmPhyWrite(pAC, IoC, Port, 30, 0xfff3);
+-
+- SK_IN32(IoC, PCI_C(PCI_OUR_REG_1), &DWord);
+-
+- SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON);
+-
+- /* Set PHY to Coma Mode */
+- SK_OUT32(IoC, PCI_C(PCI_OUR_REG_1), DWord | PCI_PHY_COMA);
+-
+- SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
+-
+- break;
+-
+- /* IEEE 22.2.4.1.5 compatible power down mode */
+- case PHY_PM_IEEE_POWER_DOWN:
+- /*
+- * - disable MAC 125 MHz clock
+- * - allow MAC power down
+- */
+- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word);
+- Word |= PHY_M_PC_DIS_125CLK;
+- Word &= ~PHY_M_PC_MAC_POW_UP;
+- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word);
++ return(1);
++ }
+
+- /*
+- * register changes must be followed by a software
+- * reset to take effect
+- */
+- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &Word);
+- Word |= PHY_CT_RESET;
+- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, Word);
+-
+- /* switch IEEE compatible power down mode on */
+- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &Word);
+- Word |= PHY_CT_PDOWN;
+- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, Word);
+- break;
++ /* save current power mode */
++ LastMode = pAC->GIni.GP[Port].PPhyPowerState;
++ pAC->GIni.GP[Port].PPhyPowerState = Mode;
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_POWM, SK_DBGCAT_CTRL,
++ ("SkGmEnterLowPowerMode: %u\n", Mode));
++
++ switch (Mode) {
++ /* COMA mode (deep sleep) */
++ case PHY_PM_DEEP_SLEEP:
++ /* clear PHY & MAC reset first */
++ SkGmClearRst(pAC, IoC, Port);
+
+- /* energy detect and energy detect plus mode */
+- case PHY_PM_ENERGY_DETECT:
+- case PHY_PM_ENERGY_DETECT_PLUS:
+- /*
+- * - disable MAC 125 MHz clock
+- */
+- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word);
+- Word |= PHY_M_PC_DIS_125CLK;
+- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word);
+-
+- /* activate energy detect mode 1 */
+- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word);
+-
+- /* energy detect mode */
+- if (Mode == PHY_PM_ENERGY_DETECT) {
+- Word |= PHY_M_PC_EN_DET;
++ /* setup General Purpose Control Register */
++ GM_OUT16(IoC, Port, GM_GP_CTRL, GM_GPCR_FL_PASS |
++ GM_GPCR_SPEED_100 | GM_GPCR_AU_ALL_DIS);
++
++ SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON);
++
++ if (CHIP_ID_YUKON_2(pAC)) {
++ /* set power down bit */
++ PowerDownBit = (Port == MAC_1) ? PCI_Y2_PHY1_POWD :
++ PCI_Y2_PHY2_POWD;
++
++ /* no COMA mode on Yukon-FE and Yukon-2 PHY */
++ if (pAC->GIni.GIChipId == CHIP_ID_YUKON_FE ||
++ pAC->GIni.GIChipId == CHIP_ID_YUKON_XL) {
++
++ /* set IEEE compatible Power Down Mode */
++ Ret = SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PHY_CT_PDOWN);
++
++ ClkDiv = 0; /* divide clock by 2 */
++ }
++ else {
++ ClkDiv = 1; /* divide clock by 4 */
++ }
++ }
++ else {
++ /* apply COMA mode workaround */
++ (void)SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PAGE_ADDR, 0x001f);
++
++ Ret = SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PAGE_DATA, 0xfff3);
++
++ PowerDownBit = PCI_PHY_COMA;
++ }
++
++ SK_IN32(IoC, PCI_C(pAC, PCI_OUR_REG_1), &DWord);
++
++ /* set PHY to PowerDown/COMA Mode */
++ SK_OUT32(IoC, PCI_C(pAC, PCI_OUR_REG_1), DWord | PowerDownBit);
++
++ /* check if this routine was called from a for() loop */
++ if (pAC->GIni.GIMacsFound == 1 || Port == MAC_2) {
++
++ /* ASF system clock stopped */
++ SK_OUT8(IoC, B28_Y2_ASF_STAT_CMD, Y2_ASF_CLK_HALT);
++
++ if (HW_FEATURE(pAC, HWF_RED_CORE_CLK_SUP)) {
++ /* on Yukon-2 clock select value is 31 */
++ DWord = (pAC->GIni.GIChipId == CHIP_ID_YUKON_XL) ?
++ (Y2_CLK_DIV_VAL_2(0) | Y2_CLK_SEL_VAL_2(31)) :
++ Y2_CLK_DIV_VAL(ClkDiv);
++
++ /* check for Yukon-2 dual port PCI-Express adapter */
++ if (!(pAC->GIni.GIMacsFound == 2 &&
++ pAC->GIni.GIPciBus == SK_PEX_BUS)) {
++ /* enable Core Clock Division */
++ DWord |= Y2_CLK_DIV_ENA;
++ }
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
++ ("Set Core Clock: 0x%08X\n", DWord));
++
++ /* reduce Core Clock Frequency */
++ SK_OUT32(IoC, B2_Y2_CLK_CTRL, DWord);
++ }
++
++ if (HW_FEATURE(pAC, HWF_CLK_GATING_ENABLE)) {
++ /* check for Yukon-2 Rev. A2 */
++ if (pAC->GIni.GIChipId == CHIP_ID_YUKON_XL &&
++ pAC->GIni.GIChipRev > 1) {
++ /* enable bits are inverted */
++ Byte = 0;
+ }
+- /* energy detect plus mode */
+ else {
+- Word |= PHY_M_PC_EN_DET_PLUS;
++ Byte = (SK_U8)(Y2_PCI_CLK_LNK1_DIS | Y2_COR_CLK_LNK1_DIS |
++ Y2_CLK_GAT_LNK1_DIS | Y2_PCI_CLK_LNK2_DIS |
++ Y2_COR_CLK_LNK2_DIS | Y2_CLK_GAT_LNK2_DIS);
+ }
+
+- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word);
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
++ ("Set Clock Gating: 0x%02X\n", Byte));
+
+- /*
+- * reinitialize the PHY to force a software reset
+- * which is necessary after the register settings
+- * for the energy detect modes.
+- * Furthermore reinitialisation prevents that the
+- * PHY is running out of a stable state.
+- */
+- SkGmInitPhyMarv(pAC, IoC, Port, SK_FALSE);
+- break;
++ /* disable MAC/PHY, PCI and Core Clock for both Links */
++ SK_OUT8(IoC, B2_Y2_CLK_GATE, Byte);
++ }
+
+- /* don't change current power mode */
+- default:
+- pAC->GIni.GP[Port].PPhyPowerState = LastMode;
+- Ret = 1;
+- break;
++ if (pAC->GIni.GIVauxAvail) {
++ /* switch power to VAUX */
++ SK_OUT8(IoC, B0_POWER_CTRL, (SK_U8)(PC_VAUX_ENA | PC_VCC_ENA |
++ PC_VAUX_ON | PC_VCC_OFF));
++ }
++#ifdef DEBUG
++ SK_IN32(IoC, B0_CTST, &DWord);
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
++ ("Ctrl/Stat & Switch: 0x%08x\n", DWord));
++#endif /* DEBUG */
++
++ if (pAC->GIni.GIMacsFound == 1 &&
++ pAC->GIni.GIPciBus == SK_PEX_BUS) {
++
++ /* switch to D1 state */
++ SK_OUT8(IoC, PCI_C(pAC, PCI_PM_CTL_STS), PCI_PM_STATE_D1);
++ }
+ }
+- }
+- /* low power modes are not supported by this chip */
+- else {
++
++ break;
++
++ /* IEEE 22.2.4.1.5 compatible power down mode */
++ case PHY_PM_IEEE_POWER_DOWN:
++
++ Ret = SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word);
++
++ Word |= PHY_M_PC_POL_R_DIS;
++
++ if (!CHIP_ID_YUKON_2(pAC)) {
++ /* disable MAC 125 MHz clock */
++ Word |= PHY_M_PC_DIS_125CLK;
++ Word &= ~PHY_M_PC_MAC_POW_UP;
++ }
++ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word);
++
++ /* these register changes must be followed by a software reset */
++ SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &Word);
++ Word |= PHY_CT_RESET;
++ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, Word);
++
++ /* switch IEEE compatible power down mode on */
++ SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &Word);
++ Word |= PHY_CT_PDOWN;
++ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, Word);
++
++ break;
++
++ /* energy detect and energy detect plus mode */
++ case PHY_PM_ENERGY_DETECT:
++ case PHY_PM_ENERGY_DETECT_PLUS:
++
++ Ret = SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word);
++
++ Word |= PHY_M_PC_POL_R_DIS;
++
++ if (!CHIP_ID_YUKON_2(pAC)) {
++ /* disable MAC 125 MHz clock */
++ Word |= PHY_M_PC_DIS_125CLK;
++ }
++
++ if (pAC->GIni.GIChipId == CHIP_ID_YUKON_FE) {
++ /* enable Energy Detect (sense & pulse) */
++ Word |= PHY_M_PC_ENA_ENE_DT;
++ }
++ else {
++ /* clear energy detect mode bits */
++ Word &= ~PHY_M_PC_EN_DET_MSK;
++
++ Word |= (Mode == PHY_PM_ENERGY_DETECT) ? PHY_M_PC_EN_DET :
++ PHY_M_PC_EN_DET_PLUS;
++ }
++
++ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word);
++
++ /* these register changes must be followed by a software reset */
++ SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &Word);
++ Word |= PHY_CT_RESET;
++ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, Word);
++
++ break;
++
++ /* don't change current power mode */
++ default:
++ pAC->GIni.GP[Port].PPhyPowerState = LastMode;
+ Ret = 1;
+ }
+
+@@ -2233,7 +2410,7 @@
+ *
+ * SkGmLeaveLowPowerMode()
+ *
+- * Description:
++ * Description:
+ * Leave the current low power mode and switch to normal mode
+ *
+ * Note:
+@@ -2243,115 +2420,145 @@
+ * 1: error
+ */
+ int SkGmLeaveLowPowerMode(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ int Port) /* Port Index (e.g. MAC_1) */
+ {
+ SK_U32 DWord;
++ SK_U32 PowerDownBit;
+ SK_U16 Word;
+ SK_U8 LastMode;
+ int Ret = 0;
+
+- if (pAC->GIni.GIYukonLite &&
+- pAC->GIni.GIChipRev == CHIP_REV_YU_LITE_A3) {
++ if (!(CHIP_ID_YUKON_2(pAC) || (pAC->GIni.GIYukonLite &&
++ pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3))) {
+
+- /* save current power mode */
+- LastMode = pAC->GIni.GP[Port].PPhyPowerState;
+- pAC->GIni.GP[Port].PPhyPowerState = PHY_PM_OPERATIONAL_MODE;
+-
+- switch (LastMode) {
+- /* coma mode (deep sleep) */
+- case PHY_PM_DEEP_SLEEP:
+- SK_IN32(IoC, PCI_C(PCI_OUR_REG_1), &DWord);
+-
+- SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON);
+-
+- /* Release PHY from Coma Mode */
+- SK_OUT32(IoC, PCI_C(PCI_OUR_REG_1), DWord & ~PCI_PHY_COMA);
+-
+- SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
+-
+- SK_IN32(IoC, B2_GP_IO, &DWord);
+-
+- /* set to output */
+- DWord |= (GP_DIR_9 | GP_IO_9);
+-
+- /* set PHY reset */
+- SK_OUT32(IoC, B2_GP_IO, DWord);
+-
+- DWord &= ~GP_IO_9; /* clear PHY reset (active high) */
+-
+- /* clear PHY reset */
+- SK_OUT32(IoC, B2_GP_IO, DWord);
+- break;
+-
+- /* IEEE 22.2.4.1.5 compatible power down mode */
+- case PHY_PM_IEEE_POWER_DOWN:
+- /*
+- * - enable MAC 125 MHz clock
+- * - set MAC power up
+- */
+- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word);
+- Word &= ~PHY_M_PC_DIS_125CLK;
+- Word |= PHY_M_PC_MAC_POW_UP;
+- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word);
++ return(1);
++ }
+
+- /*
+- * register changes must be followed by a software
+- * reset to take effect
+- */
+- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &Word);
+- Word |= PHY_CT_RESET;
+- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, Word);
+-
+- /* switch IEEE compatible power down mode off */
+- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &Word);
+- Word &= ~PHY_CT_PDOWN;
+- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, Word);
+- break;
++ /* save current power mode */
++ LastMode = pAC->GIni.GP[Port].PPhyPowerState;
++ pAC->GIni.GP[Port].PPhyPowerState = PHY_PM_OPERATIONAL_MODE;
+
+- /* energy detect and energy detect plus mode */
+- case PHY_PM_ENERGY_DETECT:
+- case PHY_PM_ENERGY_DETECT_PLUS:
+- /*
+- * - enable MAC 125 MHz clock
+- */
+- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word);
+- Word &= ~PHY_M_PC_DIS_125CLK;
+- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word);
+-
+- /* disable energy detect mode */
+- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word);
+- Word &= ~PHY_M_PC_EN_DET_MSK;
+- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word);
++ SK_DBG_MSG(pAC, SK_DBGMOD_POWM, SK_DBGCAT_CTRL,
++ ("SkGmLeaveLowPowerMode: %u\n", LastMode));
+
+- /*
+- * reinitialize the PHY to force a software reset
+- * which is necessary after the register settings
+- * for the energy detect modes.
+- * Furthermore reinitialisation prevents that the
+- * PHY is running out of a stable state.
+- */
+- SkGmInitPhyMarv(pAC, IoC, Port, SK_FALSE);
+- break;
++ switch (LastMode) {
++ /* COMA mode (deep sleep) */
++ case PHY_PM_DEEP_SLEEP:
+
+- /* don't change current power mode */
+- default:
+- pAC->GIni.GP[Port].PPhyPowerState = LastMode;
+- Ret = 1;
+- break;
++ SkPciReadCfgWord(pAC, PCI_PM_CTL_STS, &Word);
++
++ /* reset all DState bits */
++ Word &= ~(PCI_PM_STATE_MSK);
++
++ /* switch to D0 state */
++ SkPciWriteCfgWord(pAC, PCI_PM_CTL_STS, Word);
++
++ SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON);
++
++ if (CHIP_ID_YUKON_2(pAC)) {
++ /* disable Core Clock Division */
++ SK_OUT32(IoC, B2_Y2_CLK_CTRL, Y2_CLK_DIV_DIS);
++
++ /* set power down bit */
++ PowerDownBit = (Port == MAC_1) ? PCI_Y2_PHY1_POWD :
++ PCI_Y2_PHY2_POWD;
+ }
+- }
+- /* low power modes are not supported by this chip */
+- else {
++ else {
++ PowerDownBit = PCI_PHY_COMA;
++ }
++
++ SK_IN32(IoC, PCI_C(pAC, PCI_OUR_REG_1), &DWord);
++
++ /* Release PHY from PowerDown/COMA Mode */
++ SK_OUT32(IoC, PCI_C(pAC, PCI_OUR_REG_1), DWord & ~PowerDownBit);
++
++ SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF);
++
++ if (CHIP_ID_YUKON_2(pAC)) {
++ /* no COMA mode on Yukon-FE */
++ if (pAC->GIni.GIChipId == CHIP_ID_YUKON_FE) {
++ /* release IEEE compatible Power Down Mode */
++ Ret = SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PHY_CT_ANE);
++ }
++ }
++ else {
++ SK_IN32(IoC, B2_GP_IO, &DWord);
++
++ /* set to output */
++ DWord |= (GP_DIR_9 | GP_IO_9);
++
++ /* set PHY reset */
++ SK_OUT32(IoC, B2_GP_IO, DWord);
++
++ DWord &= ~GP_IO_9; /* clear PHY reset (active high) */
++
++ /* clear PHY reset */
++ SK_OUT32(IoC, B2_GP_IO, DWord);
++ }
++
++ break;
++
++ /* IEEE 22.2.4.1.5 compatible power down mode */
++ case PHY_PM_IEEE_POWER_DOWN:
++
++ if (pAC->GIni.GIChipId != CHIP_ID_YUKON_XL) {
++
++ Ret = SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word);
++ Word &= ~PHY_M_PC_DIS_125CLK; /* enable MAC 125 MHz clock */
++ Word |= PHY_M_PC_MAC_POW_UP; /* set MAC power up */
++ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word);
++
++ /* these register changes must be followed by a software reset */
++ SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &Word);
++ Word |= PHY_CT_RESET;
++ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, Word);
++ }
++
++ /* switch IEEE compatible power down mode off */
++ SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &Word);
++ Word &= ~PHY_CT_PDOWN;
++ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, Word);
++
++ break;
++
++ /* energy detect and energy detect plus mode */
++ case PHY_PM_ENERGY_DETECT:
++ case PHY_PM_ENERGY_DETECT_PLUS:
++
++ if (pAC->GIni.GIChipId != CHIP_ID_YUKON_XL) {
++
++ Ret = SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Word);
++
++ if (pAC->GIni.GIChipId == CHIP_ID_YUKON_FE) {
++ /* disable Energy Detect */
++ Word &= ~PHY_M_PC_ENA_ENE_DT;
++ }
++ else {
++ /* disable energy detect mode & enable MAC 125 MHz clock */
++ Word &= ~(PHY_M_PC_EN_DET_MSK | PHY_M_PC_DIS_125CLK);
++ }
++
++ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Word);
++
++ /* these register changes must be followed by a software reset */
++ SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &Word);
++ Word |= PHY_CT_RESET;
++ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, Word);
++ }
++ break;
++
++ /* don't change current power mode */
++ default:
++ pAC->GIni.GP[Port].PPhyPowerState = LastMode;
+ Ret = 1;
+ }
+
+ return(Ret);
+
+ } /* SkGmLeaveLowPowerMode */
+-#endif /* !SK_SLIM */
+-
++#endif /* SK_PHY_LP_MODE */
+
+ /******************************************************************************
+ *
+@@ -2365,74 +2572,182 @@
+ * nothing
+ */
+ static void SkGmInitPhyMarv(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ int Port, /* Port Index (MAC_1 + n) */
+ SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
+ {
+ SK_GEPORT *pPrt;
++ SK_BOOL AutoNeg;
+ SK_U16 PhyCtrl;
+ SK_U16 C1000BaseT;
+ SK_U16 AutoNegAdv;
++ SK_U8 PauseMode;
++#ifndef VCPU
++ SK_U16 SWord;
++ SK_U16 PageReg;
++ SK_U16 LoopSpeed;
+ SK_U16 ExtPhyCtrl;
+ SK_U16 LedCtrl;
+- SK_BOOL AutoNeg;
++ SK_U16 LedOver;
++#ifndef SK_DIAG
++ SK_EVPARA Para;
++#endif /* !SK_DIAG */
+ #if defined(SK_DIAG) || defined(DEBUG)
+ SK_U16 PhyStat;
+ SK_U16 PhyStat1;
+ SK_U16 PhySpecStat;
+ #endif /* SK_DIAG || DEBUG */
++#endif /* !VCPU */
++
++ /* set Pause On */
++ PauseMode = (SK_U8)GMC_PAUSE_ON;
+
+ pPrt = &pAC->GIni.GP[Port];
+
+ /* Auto-negotiation ? */
+- if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) {
+- AutoNeg = SK_FALSE;
++ AutoNeg = pPrt->PLinkMode != SK_LMODE_HALF &&
++ pPrt->PLinkMode != SK_LMODE_FULL;
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
++ ("InitPhyMarv: Port %d, Auto-neg. %s, LMode %d, LSpeed %d, FlowC %d\n",
++ Port, AutoNeg ? "ON" : "OFF",
++ pPrt->PLinkMode, pPrt->PLinkSpeed, pPrt->PFlowCtrlMode));
++
++#ifndef VCPU
++ /* read Id from PHY */
++ if (SkGmPhyRead(pAC, IoC, Port, PHY_MARV_ID1, &pPrt->PhyId1) != 0) {
++
++#ifndef SK_DIAG
++ Para.Para64 = Port;
++ SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para);
++#endif /* !SK_DIAG */
++
++ return;
+ }
+- else {
+- AutoNeg = SK_TRUE;
++
++ if ((pPrt->PLinkSpeedCap & SK_LSPEED_CAP_1000MBPS) != 0) {
++
++ if (DoLoop) {
++ /* special setup for PHY 88E1112 */
++ if (pAC->GIni.GIChipId == CHIP_ID_YUKON_XL) {
++
++ LoopSpeed = pPrt->PLinkSpeed;
++
++ if (LoopSpeed == SK_LSPEED_AUTO) {
++ /* force 1000 Mbps */
++ LoopSpeed = SK_LSPEED_1000MBPS;
++ }
++ LoopSpeed += 2;
++
++ /* save page register */
++ SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_ADR, &PageReg);
++
++ /* select page 2 to access MAC control register */
++ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 2);
++
++ /* set MAC interface speed */
++ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, LoopSpeed << 4);
++
++ /* restore page register */
++ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, PageReg);
++
++ /* disable link pulses */
++ SWord = PHY_M_PC_DIS_LINK_P;
++ }
++ else {
++ /* set 'MAC Power up'-bit, set Manual MDI configuration */
++ SWord = PHY_M_PC_MAC_POW_UP;
++ }
++
++ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, SWord);
++ }
++ else if (AutoNeg && pPrt->PLinkSpeed == SK_LSPEED_AUTO &&
++ pAC->GIni.GIChipId != CHIP_ID_YUKON_XL) {
++ /* 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_MAC_S(MAC_TX_CLK_25_MHZ);
++
++ if (pAC->GIni.GIChipId == CHIP_ID_YUKON_EC) {
++ /* on PHY 88E1111 there is a change for downshift control */
++ ExtPhyCtrl |= PHY_M_EC_DSC_2(2) | PHY_M_EC_DOWN_S_ENA;
++ }
++ else {
++ ExtPhyCtrl |= PHY_M_EC_M_DSC(2) | PHY_M_EC_S_DSC(3);
++ }
++
++ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_CTRL, ExtPhyCtrl);
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
++ ("Set Ext. PHY Ctrl=0x%04X\n", ExtPhyCtrl));
++ }
+ }
+-
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("InitPhyMarv: Port %d, auto-negotiation %s\n",
+- Port, AutoNeg ? "ON" : "OFF"));
+
+-#ifdef VCPU
+- VCPUprintf(0, "SkGmInitPhyMarv(), Port=%u, DoLoop=%u\n",
+- Port, DoLoop);
+-#else /* VCPU */
+- if (DoLoop) {
+- /* Set 'MAC Power up'-bit, set Manual MDI configuration */
+- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL,
+- PHY_M_PC_MAC_POW_UP);
++ if (CHIP_ID_YUKON_2(pAC)) {
++ /* Read PHY Specific Control */
++ SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &PhyCtrl);
++
++ if (!DoLoop && pAC->GIni.GICopperType) {
++
++ if (pAC->GIni.GIChipId == CHIP_ID_YUKON_FE) {
++ /* enable Automatic Crossover (!!! Bits 5..4) */
++ PhyCtrl |= (SK_U16)(PHY_M_PC_MDI_XMODE(PHY_M_PC_ENA_AUTO) >> 1);
++ }
++ else {
++ /* disable Energy Detect Mode */
++ PhyCtrl &= ~PHY_M_PC_EN_DET_MSK;
++
++ /* enable Automatic Crossover */
++ PhyCtrl |= (SK_U16)PHY_M_PC_MDI_XMODE(PHY_M_PC_ENA_AUTO);
++
++ if (AutoNeg && pPrt->PLinkSpeed == SK_LSPEED_AUTO &&
++ pAC->GIni.GIChipId == CHIP_ID_YUKON_XL) {
++ /* on PHY 88E1112 there is a change for downshift control */
++ PhyCtrl &= ~PHY_M_PC_DSC_MSK;
++ PhyCtrl |= PHY_M_PC_DSC(2) | PHY_M_PC_DOWN_S_ENA;
++ }
++ }
++ }
++ /* workaround for deviation #4.88 (CRC errors) */
++ else {
++ /* disable Automatic Crossover */
++ PhyCtrl &= ~PHY_M_PC_MDIX_MSK;
++ }
++
++ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, PhyCtrl);
+ }
+- else if (AutoNeg && pPrt->PLinkSpeed == SK_LSPEED_AUTO) {
+- /* 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_MAC_S(MAC_TX_CLK_25_MHZ) |
+- PHY_M_EC_M_DSC(0) | PHY_M_EC_S_DSC(1);
+-
+- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_CTRL, ExtPhyCtrl);
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("Set Ext. PHY Ctrl=0x%04X\n", ExtPhyCtrl));
++
++ /* special setup for PHY 88E1112 Fiber */
++ if (pAC->GIni.GIChipId == CHIP_ID_YUKON_XL && !pAC->GIni.GICopperType) {
++ /* Fiber: select 1000BASE-X only mode MAC Specific Ctrl Reg. */
++ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 2);
++
++ SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &SWord);
++
++ SWord &= ~PHY_M_MAC_MD_MSK;
++ SWord |= PHY_M_MAC_MODE_SEL(PHY_M_MAC_MD_1000BX);
++
++ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, SWord);
++
++ /* select page 1 to access Fiber registers */
++ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 1);
+ }
+
+ /* Read PHY Control */
+ SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &PhyCtrl);
+
+ if (!AutoNeg) {
+- /* Disable Auto-negotiation */
++ /* disable Auto-negotiation */
+ PhyCtrl &= ~PHY_CT_ANE;
+ }
+
+ PhyCtrl |= PHY_CT_RESET;
+- /* Assert software reset */
++ /* assert software reset */
+ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PhyCtrl);
+-#endif /* VCPU */
++#endif /* !VCPU */
+
+ PhyCtrl = 0 /* PHY_CT_COL_TST */;
+ C1000BaseT = 0;
+@@ -2442,30 +2757,31 @@
+ if (pPrt->PMSMode != SK_MS_MODE_AUTO) {
+ /* enable Manual Master/Slave */
+ C1000BaseT |= PHY_M_1000C_MSE;
+-
++
+ if (pPrt->PMSMode == SK_MS_MODE_MASTER) {
+ C1000BaseT |= PHY_M_1000C_MSC; /* set it to Master */
+ }
+ }
+-
++
+ /* Auto-negotiation ? */
+ if (!AutoNeg) {
+-
++
+ if (pPrt->PLinkMode == SK_LMODE_FULL) {
+- /* Set Full Duplex Mode */
++ /* set Full Duplex Mode */
+ PhyCtrl |= PHY_CT_DUP_MD;
+ }
+
+- /* Set Master/Slave manually if not already done */
++ /* set Master/Slave manually if not already done */
+ if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
+ C1000BaseT |= PHY_M_1000C_MSE; /* set it to Slave */
+ }
+
+- /* Set Speed */
++ /* set Speed */
+ switch (pPrt->PLinkSpeed) {
+ case SK_LSPEED_AUTO:
+ case SK_LSPEED_1000MBPS:
+- PhyCtrl |= PHY_CT_SP1000;
++ PhyCtrl |= (((pPrt->PLinkSpeedCap & SK_LSPEED_CAP_1000MBPS) != 0) ?
++ PHY_CT_SP1000 : PHY_CT_SP100);
+ break;
+ case SK_LSPEED_100MBPS:
+ PhyCtrl |= PHY_CT_SP100;
+@@ -2477,38 +2793,65 @@
+ SKERR_HWI_E019MSG);
+ }
+
++ if ((pPrt->PFlowCtrlMode == SK_FLOW_STAT_NONE) ||
++ /* disable Pause also for 10/100 Mbps in half duplex mode */
++ ((pPrt->PLinkMode == SK_LMODE_HALF) &&
++ ((pPrt->PLinkSpeed == SK_LSPEED_STAT_100MBPS) ||
++ (pPrt->PLinkSpeed == SK_LSPEED_STAT_10MBPS)))) {
++
++ /* set Pause Off */
++ PauseMode = (SK_U8)GMC_PAUSE_OFF;
++ }
++
++ SK_OUT8(IoC, MR_ADDR(Port, GMAC_CTRL), PauseMode);
++
+ if (!DoLoop) {
++ /* assert software reset */
+ PhyCtrl |= PHY_CT_RESET;
+ }
+ }
+ else {
+- /* Set Auto-negotiation advertisement */
+-
++ /* set Auto-negotiation advertisement */
++
+ if (pAC->GIni.GICopperType) {
+- /* Set Speed capabilities */
++ /* set Speed capabilities */
+ switch (pPrt->PLinkSpeed) {
+ case SK_LSPEED_AUTO:
+- C1000BaseT |= PHY_M_1000C_AHD | PHY_M_1000C_AFD;
++ if ((pPrt->PLinkSpeedCap & SK_LSPEED_CAP_1000MBPS) != 0) {
++ C1000BaseT |= PHY_M_1000C_AFD;
++#ifdef xSK_DIAG
++ C1000BaseT |= PHY_M_1000C_AHD;
++#endif /* SK_DIAG */
++ }
+ 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;
++ if ((pPrt->PLinkSpeedCap & SK_LSPEED_CAP_1000MBPS) != 0) {
++ C1000BaseT |= PHY_M_1000C_AFD;
++#ifdef xSK_DIAG
++ C1000BaseT |= PHY_M_1000C_AHD;
++#endif /* SK_DIAG */
++ }
+ break;
+ case SK_LSPEED_100MBPS:
+- AutoNegAdv |= PHY_M_AN_100_FD | PHY_M_AN_100_HD |
+- /* advertise 10Base-T also */
+- PHY_M_AN_10_FD | PHY_M_AN_10_HD;
++ if ((pPrt->PLinkSpeedCap & SK_LSPEED_CAP_100MBPS) != 0) {
++ AutoNegAdv |= PHY_M_AN_100_FD | PHY_M_AN_100_HD |
++ /* advertise 10Base-T also */
++ 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;
++ if ((pPrt->PLinkSpeedCap & SK_LSPEED_CAP_10MBPS) != 0) {
++ 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);
+ }
+
+- /* Set Full/half duplex capabilities */
++ /* set Full/half duplex capabilities */
+ switch (pPrt->PLinkMode) {
+ case SK_LMODE_AUTOHALF:
+ C1000BaseT &= ~PHY_M_1000C_AFD;
+@@ -2524,8 +2867,8 @@
+ SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
+ SKERR_HWI_E015MSG);
+ }
+-
+- /* Set Flow-control capabilities */
++
++ /* set Flow-control capabilities */
+ switch (pPrt->PFlowCtrlMode) {
+ case SK_FLOW_MODE_NONE:
+ AutoNegAdv |= PHY_B_P_NO_PAUSE;
+@@ -2545,8 +2888,8 @@
+ }
+ }
+ else { /* special defines for FIBER (88E1011S only) */
+-
+- /* Set Full/half duplex capabilities */
++
++ /* set Full/half duplex capabilities */
+ switch (pPrt->PLinkMode) {
+ case SK_LMODE_AUTOHALF:
+ AutoNegAdv |= PHY_M_AN_1000X_AHD;
+@@ -2561,8 +2904,8 @@
+ SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015,
+ SKERR_HWI_E015MSG);
+ }
+-
+- /* Set Flow-control capabilities */
++
++ /* set Flow-control capabilities */
+ switch (pPrt->PFlowCtrlMode) {
+ case SK_FLOW_MODE_NONE:
+ AutoNegAdv |= PHY_M_P_NO_PAUSE_X;
+@@ -2587,52 +2930,51 @@
+ PhyCtrl |= PHY_CT_ANE | PHY_CT_RE_CFG;
+ }
+ }
+-
++
+ #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, 0x0700 /* 0x0708 */);
+-
++
+ VCpuWait(2000);
+
+ #else /* VCPU */
+-
+- /* Write 1000Base-T Control Register */
+- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_1000T_CTRL, C1000BaseT);
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+- ("Set 1000B-T Ctrl =0x%04X\n", C1000BaseT));
+-
++
++ if (pAC->GIni.GIChipId != CHIP_ID_YUKON_FE) {
++ /* Write 1000Base-T Control Register */
++ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_1000T_CTRL, C1000BaseT);
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
++ ("Set 1000B-T Ctrl =0x%04X\n", C1000BaseT));
++ }
++
+ /* Write AutoNeg Advertisement Register */
+ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_AUNE_ADV, AutoNegAdv);
+ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+ ("Set Auto-Neg.Adv.=0x%04X\n", AutoNegAdv));
+ #endif /* VCPU */
+-
++
+ if (DoLoop) {
+- /* Set the PHY Loopback bit */
++ /* set the PHY Loopback bit */
+ PhyCtrl |= PHY_CT_LOOP;
+
+ #ifdef XXX
+ /* Program PHY register 16 as 16'h0400 to force link good */
+ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, PHY_M_PC_FL_GOOD);
+-#endif /* XXX */
+
+-#ifndef VCPU
+ 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));
+ }
+-#endif /* VCPU */
++#endif /* XXX */
+ }
+ #ifdef TEST_ONLY
+ 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);
++ /* Write PHY Specific Control */
++ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, PHY_M_PC_EN_DET_MSK);
+ }
+ #endif
+
+@@ -2645,27 +2987,83 @@
+ VCpuWait(2000);
+ #else
+
+- LedCtrl = PHY_M_LED_PULS_DUR(PULS_170MS) | PHY_M_LED_BLINK_RT(BLINK_84MS);
++ LedCtrl = PHY_M_LED_PULS_DUR(PULS_170MS);
++
++ LedOver = 0;
++
++ if ((pAC->GIni.GILedBlinkCtrl & SK_ACT_LED_BLINK) != 0) {
++
++ if (pAC->GIni.GIChipId == CHIP_ID_YUKON_FE) {
++ /* on 88E3082 these bits are at 11..9 (shifted left) */
++ LedCtrl |= PHY_M_LED_BLINK_RT(BLINK_84MS) << 1;
++
++ SkGmPhyRead(pAC, IoC, Port, PHY_MARV_FE_LED_PAR, &SWord);
++
++ /* delete ACT LED control bits */
++ SWord &= ~PHY_M_FELP_LED1_MSK;
++ /* change ACT LED control to blink mode */
++ SWord |= PHY_M_FELP_LED1_CTRL(LED_PAR_CTRL_ACT_BL);
++
++ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_FE_LED_PAR, SWord);
++ }
++ else if (pAC->GIni.GIChipId == CHIP_ID_YUKON_XL) {
++ /* save page register */
++ SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_ADR, &PageReg);
++
++ /* select page 3 to access LED control register */
++ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 3);
++
++ /* set LED Function Control register */
++ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, (SK_U16)
++ (PHY_M_LEDC_LOS_CTRL(1) | /* LINK/ACT */
++ PHY_M_LEDC_INIT_CTRL(7) | /* 10 Mbps */
++ PHY_M_LEDC_STA1_CTRL(7) | /* 100 Mbps */
++ PHY_M_LEDC_STA0_CTRL(7))); /* 1000 Mbps */
++
++ /* set Polarity Control register */
++ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_STAT, (SK_U16)
++ (PHY_M_POLC_LS1_P_MIX(4) | PHY_M_POLC_IS0_P_MIX(4) |
++ PHY_M_POLC_LOS_CTRL(2) | PHY_M_POLC_INIT_CTRL(2) |
++ PHY_M_POLC_STA1_CTRL(2) | PHY_M_POLC_STA0_CTRL(2)));
++
++ /* restore page register */
++ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, PageReg);
++ }
++ else {
++ /* set Tx LED (LED_TX) to blink mode on Rx OR Tx activity */
++ LedCtrl |= PHY_M_LED_BLINK_RT(BLINK_84MS) | PHY_M_LEDC_TX_CTRL;
+
+- if ((pAC->GIni.GILedBlinkCtrl & SK_ACT_LED_BLINK) != 0) {
+- LedCtrl |= PHY_M_LEDC_RX_CTRL | PHY_M_LEDC_TX_CTRL;
++ /* on PHY 88E1111 there is a change for LED control */
++ if (pAC->GIni.GIChipId == CHIP_ID_YUKON_EC &&
++ (pAC->GIni.GILedBlinkCtrl & SK_DUAL_LED_ACT_LNK) != 0) {
++ /* Yukon-EC needs setting of 2 bits: 0,6=11) */
++ LedCtrl |= PHY_M_LEDC_TX_C_LSB;
++ }
++ /* turn off the Rx LED (LED_RX) */
++ LedOver |= PHY_M_LED_MO_RX(MO_LED_OFF);
++ }
+ }
+
+ if ((pAC->GIni.GILedBlinkCtrl & SK_DUP_LED_NORMAL) != 0) {
++ /* disable blink mode (LED_DUPLEX) on collisions */
+ LedCtrl |= PHY_M_LEDC_DP_CTRL;
+ }
+-
++
+ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_LED_CTRL, LedCtrl);
+
+ if ((pAC->GIni.GILedBlinkCtrl & SK_LED_LINK100_ON) != 0) {
+ /* only in forced 100 Mbps mode */
+ if (!AutoNeg && pPrt->PLinkSpeed == SK_LSPEED_100MBPS) {
+-
+- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_LED_OVER,
+- PHY_M_LED_MO_100(MO_LED_ON));
++ /* turn on 100 Mbps LED (LED_LINK100) */
++ LedOver |= PHY_M_LED_MO_100(MO_LED_ON);
+ }
+ }
+
++ if (LedOver != 0) {
++ /* set Manual LED Override */
++ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_LED_OVER, LedOver);
++ }
++
+ #ifdef SK_DIAG
+ c_print("Set PHY Ctrl=0x%04X\n", PhyCtrl);
+ c_print("Set 1000 B-T=0x%04X\n", C1000BaseT);
+@@ -2678,30 +3076,33 @@
+ 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));
+-
+- /* 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.Adv.=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));
+-
++
++ if (pAC->GIni.GIChipId != CHIP_ID_YUKON_FE) {
++ /* 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 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, &PhySpecStat);
+ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+@@ -2718,6 +3119,8 @@
+ c_print("PHY Spec Reg=0x%04X\n", PhySpecStat);
+ #endif /* SK_DIAG */
+
++ /* enable all PHY interrupts */
++ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, (SK_U16)PHY_M_DEF_MSK);
+ #endif /* VCPU */
+
+ } /* SkGmInitPhyMarv */
+@@ -2737,8 +3140,8 @@
+ * nothing
+ */
+ static void SkXmInitPhyLone(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ int Port, /* Port Index (MAC_1 + n) */
+ SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
+ {
+@@ -2756,7 +3159,7 @@
+ /* 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;
+ }
+@@ -2769,7 +3172,7 @@
+ */
+ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+ ("InitPhyLone: no auto-negotiation Port %d\n", Port));
+- /* Set DuplexMode in Config register */
++ /* set DuplexMode in Config register */
+ if (pPrt->PLinkMode == SK_LMODE_FULL) {
+ Ctrl1 |= PHY_CT_DUP_MD;
+ }
+@@ -2778,7 +3181,6 @@
+ if (pPrt->PMSMode == SK_MS_MODE_AUTO) {
+ Ctrl2 |= PHY_L_1000C_MSE; /* set it to Slave */
+ }
+-
+ /*
+ * Do NOT enable Auto-negotiation here. This would hold
+ * the link down because no IDLES are transmitted
+@@ -2787,9 +3189,9 @@
+ else {
+ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+ ("InitPhyLone: with auto-negotiation Port %d\n", Port));
+- /* Set Auto-negotiation advertisement */
++ /* set Auto-negotiation advertisement */
+
+- /* Set Full/half duplex capabilities */
++ /* set Full/half duplex capabilities */
+ switch (pPrt->PLinkMode) {
+ case SK_LMODE_AUTOHALF:
+ Ctrl2 |= PHY_L_1000C_AHD;
+@@ -2805,7 +3207,7 @@
+ SKERR_HWI_E015MSG);
+ }
+
+- /* Set Flow-control capabilities */
++ /* set Flow-control capabilities */
+ switch (pPrt->PFlowCtrlMode) {
+ case SK_FLOW_MODE_NONE:
+ Ctrl3 |= PHY_L_P_NO_PAUSE;
+@@ -2827,19 +3229,19 @@
+ /* Restart Auto-negotiation */
+ Ctrl1 = PHY_CT_ANE | PHY_CT_RE_CFG;
+ }
+-
++
+ /* Write 1000Base-T Control Register */
+ 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 */
+ 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) {
+- /* Set the Phy Loopback bit, too */
++ /* set the Phy Loopback bit, too */
+ Ctrl1 |= PHY_CT_LOOP;
+ }
+
+@@ -2862,8 +3264,8 @@
+ * nothing
+ */
+ static void SkXmInitPhyNat(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ int Port, /* Port Index (MAC_1 + n) */
+ SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
+ {
+@@ -2884,8 +3286,8 @@
+ * nothing
+ */
+ void SkMacInitPhy(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ int Port, /* Port Index (MAC_1 + n) */
+ SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */
+ {
+@@ -2895,7 +3297,7 @@
+
+ #ifdef GENESIS
+ if (pAC->GIni.GIGenesis) {
+-
++
+ switch (pPrt->PhyType) {
+ case SK_PHY_XMAC:
+ SkXmInitPhyXmac(pAC, IoC, Port, DoLoop);
+@@ -2914,10 +3316,10 @@
+ }
+ }
+ #endif /* GENESIS */
+-
++
+ #ifdef YUKON
+ if (pAC->GIni.GIYukon) {
+-
++
+ SkGmInitPhyMarv(pAC, IoC, Port, DoLoop);
+ }
+ #endif /* YUKON */
+@@ -2935,12 +3337,12 @@
+ *
+ * Returns:
+ * SK_AND_OK o.k.
+- * SK_AND_DUP_CAP Duplex capability error happened
+- * SK_AND_OTHER Other error happened
++ * SK_AND_DUP_CAP Duplex capability error happened
++ * SK_AND_OTHER Other error happened
+ */
+ static int SkXmAutoNegDoneXmac(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ int Port) /* Port Index (MAC_1 + n) */
+ {
+ SK_GEPORT *pPrt;
+@@ -2958,10 +3360,10 @@
+
+ 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_ERR,
+ ("AutoNegFail: Remote fault bit set Port %d\n", Port));
+ pPrt->PAutoNegFail = SK_TRUE;
++
+ return(SK_AND_OTHER);
+ }
+
+@@ -2974,9 +3376,10 @@
+ }
+ else {
+ /* Error */
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR,
+ ("AutoNegFail: Duplex mode mismatch Port %d\n", Port));
+ pPrt->PAutoNegFail = SK_TRUE;
++
+ return(SK_AND_DUP_CAP);
+ }
+
+@@ -2984,19 +3387,19 @@
+ /* We are NOT using chapter 4.23 of the Xaqti manual */
+ /* We are using IEEE 802.3z/D5.0 Table 37-4 */
+ if ((pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYMMETRIC ||
+- pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM) &&
+- (LPAb & PHY_X_P_SYM_MD) != 0) {
++ pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM) &&
++ (LPAb & PHY_X_P_SYM_MD) != 0) {
+ /* Symmetric PAUSE */
+ pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
+ }
+ else if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM &&
+- (LPAb & PHY_X_RS_PAUSE) == PHY_X_P_ASYM_MD) {
+- /* Enable PAUSE receive, disable PAUSE transmit */
++ (LPAb & PHY_X_RS_PAUSE) == PHY_X_P_ASYM_MD) {
++ /* enable PAUSE receive, disable PAUSE transmit */
+ pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
+ }
+ else if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_LOC_SEND &&
+- (LPAb & PHY_X_RS_PAUSE) == PHY_X_P_BOTH_MD) {
+- /* Disable PAUSE receive, enable PAUSE transmit */
++ (LPAb & PHY_X_RS_PAUSE) == PHY_X_P_BOTH_MD) {
++ /* disable PAUSE receive, enable PAUSE transmit */
+ pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
+ }
+ else {
+@@ -3018,12 +3421,12 @@
+ *
+ * Returns:
+ * SK_AND_OK o.k.
+- * SK_AND_DUP_CAP Duplex capability error happened
+- * SK_AND_OTHER Other error happened
++ * SK_AND_DUP_CAP Duplex capability error happened
++ * SK_AND_OTHER Other error happened
+ */
+ static int SkXmAutoNegDoneBcom(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ int Port) /* Port Index (MAC_1 + n) */
+ {
+ SK_GEPORT *pPrt;
+@@ -3031,9 +3434,8 @@
+ SK_U16 AuxStat; /* Auxiliary Status */
+
+ #ifdef TEST_ONLY
+-01-Sep-2000 RA;:;:
+ SK_U16 ResAb; /* Resolved Ability */
+-#endif /* 0 */
++#endif
+
+ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+ ("AutoNegDoneBcom, Port %d\n", Port));
+@@ -3042,17 +3444,17 @@
+ /* Get PHY parameters */
+ SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &LPAb);
+ #ifdef TEST_ONLY
+-01-Sep-2000 RA;:;:
+ SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb);
+-#endif /* 0 */
+-
++#endif
++
+ SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &AuxStat);
+
+ if ((LPAb & PHY_B_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_ERR,
+ ("AutoNegFail: Remote fault bit set Port %d\n", Port));
+ pPrt->PAutoNegFail = SK_TRUE;
++
+ return(SK_AND_OTHER);
+ }
+
+@@ -3065,26 +3467,26 @@
+ }
+ else {
+ /* Error */
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR,
+ ("AutoNegFail: Duplex mode mismatch Port %d\n", Port));
+ pPrt->PAutoNegFail = SK_TRUE;
++
+ return(SK_AND_DUP_CAP);
+ }
+-
++
+ #ifdef TEST_ONLY
+-01-Sep-2000 RA;:;:
+ /* Check Master/Slave resolution */
+ if ((ResAb & PHY_B_1000S_MSF) != 0) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR,
+ ("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_MS_STAT_MASTER : SK_MS_STAT_SLAVE;
+-#endif /* 0 */
++#endif
+
+ /* Check PAUSE mismatch ??? */
+ /* We are using IEEE 802.3z/D5.0 Table 37-4 */
+@@ -3093,11 +3495,11 @@
+ pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
+ }
+ else if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PRR) {
+- /* Enable PAUSE receive, disable PAUSE transmit */
++ /* 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 */
++ /* disable PAUSE receive, enable PAUSE transmit */
+ pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
+ }
+ else {
+@@ -3121,18 +3523,22 @@
+ *
+ * Returns:
+ * SK_AND_OK o.k.
+- * SK_AND_DUP_CAP Duplex capability error happened
+- * SK_AND_OTHER Other error happened
++ * 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 */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O 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_U8 PauseMode; /* Pause Mode */
++
++ /* set Pause On */
++ PauseMode = (SK_U8)GMC_PAUSE_ON;
+
+ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+ ("AutoNegDoneMarv, Port %d\n", Port));
+@@ -3142,78 +3548,107 @@
+ SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_LP, &LPAb);
+ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+ ("Link P.Abil.=0x%04X\n", LPAb));
+-
++
+ if ((LPAb & PHY_M_AN_RF) != 0) {
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR,
+ ("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);
++ if ((pPrt->PLinkSpeedCap & SK_LSPEED_CAP_1000MBPS) != 0) {
++
++ 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_ERR,
++ ("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;
+ }
+-
+- 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,
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR,
+ ("AutoNegFail: Speed & Duplex not resolved, Port %d\n", Port));
+ pPrt->PAutoNegFail = SK_TRUE;
+ pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN;
++
+ return(SK_AND_DUP_CAP);
+ }
+-
+- if ((AuxStat & PHY_M_PS_FULL_DUP) != 0) {
+- pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL;
+- }
+- else {
+- pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF;
+- }
+-
+- /* 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_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_M_PS_PAUSE_MSK) == PHY_M_PS_TX_P_EN) {
+- /* Disable PAUSE receive, enable PAUSE transmit */
+- pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
++
++ pPrt->PLinkModeStatus = (SK_U8)(((AuxStat & PHY_M_PS_FULL_DUP) != 0) ?
++ SK_LMODE_STAT_AUTOFULL : SK_LMODE_STAT_AUTOHALF);
++
++ if (pAC->GIni.GIChipId == CHIP_ID_YUKON_FE) {
++ /* set used link speed */
++ pPrt->PLinkSpeedUsed = (SK_U8)(((AuxStat & PHY_M_PS_SPEED_100) != 0) ?
++ SK_LSPEED_STAT_100MBPS : SK_LSPEED_STAT_10MBPS);
+ }
+ else {
+- /* 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_U8)SK_LSPEED_STAT_1000MBPS;
++ break;
++ case PHY_M_PS_SPEED_100:
++ pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_100MBPS;
++ break;
++ default:
++ pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_10MBPS;
++ }
++
++ if (pAC->GIni.GIChipId == CHIP_ID_YUKON_XL) {
++ /* Tx & Rx Pause Enabled bits are at 9..8 */
++ AuxStat >>= 6;
++
++ if (!pAC->GIni.GICopperType) {
++ /* always 1000 Mbps on fiber */
++ pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS;
++ }
++ }
++
++ AuxStat &= PHY_M_PS_PAUSE_MSK;
++ /* We are using IEEE 802.3z/D5.0 Table 37-4 */
++ if (AuxStat == PHY_M_PS_PAUSE_MSK) {
++ /* Symmetric PAUSE */
++ pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC;
++ }
++ else if (AuxStat == PHY_M_PS_RX_P_EN) {
++ /* enable PAUSE receive, disable PAUSE transmit */
++ pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
++ }
++ else if (AuxStat == PHY_M_PS_TX_P_EN) {
++ /* disable PAUSE receive, enable PAUSE transmit */
++ pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
++ }
++ else {
++ /* 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_U8)SK_LSPEED_STAT_1000MBPS;
+- break;
+- case PHY_M_PS_SPEED_100:
+- pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_100MBPS;
+- break;
+- default:
+- pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_10MBPS;
++
++ if ((pPrt->PFlowCtrlStatus == SK_FLOW_STAT_NONE) ||
++ /* disable Pause also for 10/100 Mbps in half duplex mode */
++ ((pPrt->PLinkSpeedUsed < (SK_U8)SK_LSPEED_STAT_1000MBPS) &&
++ pPrt->PLinkModeStatus == (SK_U8)SK_LMODE_STAT_AUTOHALF)) {
++
++ /* set Pause Off */
++ PauseMode = (SK_U8)GMC_PAUSE_OFF;
+ }
+
++ SK_OUT8(IoC, MR_ADDR(Port, GMAC_CTRL), PauseMode);
++
+ return(SK_AND_OK);
+ } /* SkGmAutoNegDoneMarv */
+ #endif /* YUKON */
+@@ -3229,12 +3664,12 @@
+ *
+ * Returns:
+ * SK_AND_OK o.k.
+- * SK_AND_DUP_CAP Duplex capability error happened
+- * SK_AND_OTHER Other error happened
++ * SK_AND_DUP_CAP Duplex capability error happened
++ * SK_AND_OTHER Other error happened
+ */
+ static int SkXmAutoNegDoneLone(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ int Port) /* Port Index (MAC_1 + n) */
+ {
+ SK_GEPORT *pPrt;
+@@ -3253,10 +3688,10 @@
+
+ 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_ERR,
+ ("AutoNegFail: Remote fault bit set Port %d\n", Port));
+ pPrt->PAutoNegFail = SK_TRUE;
++
+ return(SK_AND_OTHER);
+ }
+
+@@ -3267,28 +3702,25 @@
+ else {
+ pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF;
+ }
+-
++
+ /* Check Master/Slave resolution */
+ if ((ResAb & PHY_L_1000S_MSF) != 0) {
+ /* Error */
+- SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR,
+ ("Master/Slave Fault Port %d\n", Port));
+ pPrt->PAutoNegFail = SK_TRUE;
+ pPrt->PMSStatus = SK_MS_STAT_FAULT;
+ return(SK_AND_OTHER);
+ }
+- else if (ResAb & PHY_L_1000S_MSR) {
+- pPrt->PMSStatus = SK_MS_STAT_MASTER;
+- }
+- else {
+- pPrt->PMSStatus = SK_MS_STAT_SLAVE;
+- }
++
++ pPrt->PMSStatus = ((ResAb & PHY_L_1000S_MSR) != 0) ?
++ (SK_U8)SK_MS_STAT_MASTER : (SK_U8)SK_MS_STAT_SLAVE;
+
+ /* Check PAUSE mismatch */
+ /* We are using IEEE 802.3z/D5.0 Table 37-4 */
+ /* we must manually resolve the abilities here */
+ pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE;
+-
++
+ switch (pPrt->PFlowCtrlMode) {
+ case SK_FLOW_MODE_NONE:
+ /* default */
+@@ -3296,7 +3728,7 @@
+ case SK_FLOW_MODE_LOC_SEND:
+ if ((QuickStat & (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) ==
+ (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) {
+- /* Disable PAUSE receive, enable PAUSE transmit */
++ /* disable PAUSE receive, enable PAUSE transmit */
+ pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND;
+ }
+ break;
+@@ -3309,7 +3741,7 @@
+ case SK_FLOW_MODE_SYM_OR_REM:
+ if ((QuickStat & (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) ==
+ PHY_L_QS_AS_PAUSE) {
+- /* Enable PAUSE receive, disable PAUSE transmit */
++ /* enable PAUSE receive, disable PAUSE transmit */
+ pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND;
+ }
+ else if ((QuickStat & PHY_L_QS_PAUSE) != 0) {
+@@ -3321,7 +3753,7 @@
+ SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016,
+ SKERR_HWI_E016MSG);
+ }
+-
++
+ return(SK_AND_OK);
+ } /* SkXmAutoNegDoneLone */
+
+@@ -3335,12 +3767,12 @@
+ *
+ * Returns:
+ * SK_AND_OK o.k.
+- * SK_AND_DUP_CAP Duplex capability error happened
+- * SK_AND_OTHER Other error happened
++ * SK_AND_DUP_CAP Duplex capability error happened
++ * SK_AND_OTHER Other error happened
+ */
+ static int SkXmAutoNegDoneNat(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ int Port) /* Port Index (MAC_1 + n) */
+ {
+ /* todo: National */
+@@ -3357,12 +3789,12 @@
+ *
+ * Returns:
+ * SK_AND_OK o.k.
+- * SK_AND_DUP_CAP Duplex capability error happened
+- * SK_AND_OTHER Other error happened
++ * 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 SkMacAutoNegDone(
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ int Port) /* Port Index (MAC_1 + n) */
+ {
+ SK_GEPORT *pPrt;
+@@ -3374,9 +3806,9 @@
+
+ #ifdef GENESIS
+ if (pAC->GIni.GIGenesis) {
+-
++
+ switch (pPrt->PhyType) {
+-
++
+ case SK_PHY_XMAC:
+ Rtv = SkXmAutoNegDoneXmac(pAC, IoC, Port);
+ break;
+@@ -3396,26 +3828,26 @@
+ }
+ }
+ #endif /* GENESIS */
+-
++
+ #ifdef YUKON
+ if (pAC->GIni.GIYukon) {
+-
++
+ Rtv = SkGmAutoNegDoneMarv(pAC, IoC, Port);
+ }
+ #endif /* YUKON */
+-
++
+ if (Rtv != SK_AND_OK) {
+ return(Rtv);
+ }
+
+ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+ ("AutoNeg done Port %d\n", Port));
+-
++
+ /* We checked everything and may now enable the link */
+ pPrt->PAutoNegFail = SK_FALSE;
+
+ SkMacRxTxEnable(pAC, IoC, Port);
+-
++
+ return(SK_AND_OK);
+ } /* SkMacAutoNegDone */
+
+@@ -3433,7 +3865,7 @@
+ */
+ static void SkXmSetRxTxEn(
+ SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* IO context */
++SK_IOC IoC, /* I/O Context */
+ int Port, /* Port Index (MAC_1 + n) */
+ int Para) /* Parameter to set: MAC or PHY LoopBack, Duplex Mode */
+ {
+@@ -3458,7 +3890,7 @@
+ 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;
+@@ -3467,7 +3899,7 @@
+ 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 */
+@@ -3490,12 +3922,12 @@
+ */
+ static void SkGmSetRxTxEn(
+ SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* IO context */
++SK_IOC IoC, /* I/O 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)) {
+@@ -3515,12 +3947,13 @@
+ Ctrl &= ~GM_GPCR_DUP_FULL;
+ break;
+ }
+-
+- GM_OUT16(IoC, Port, GM_GP_CTRL, (SK_U16)(Ctrl | GM_GPCR_RX_ENA |
+- GM_GPCR_TX_ENA));
+
++ GM_OUT16(IoC, Port, GM_GP_CTRL, Ctrl | GM_GPCR_RX_ENA | GM_GPCR_TX_ENA);
++
++#ifdef XXX
+ /* dummy read to ensure writing */
+ GM_IN16(IoC, Port, GM_GP_CTRL, &Ctrl);
++#endif /* XXX */
+
+ } /* SkGmSetRxTxEn */
+ #endif /* YUKON */
+@@ -3537,20 +3970,20 @@
+ */
+ void SkMacSetRxTxEn(
+ SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* IO context */
++SK_IOC IoC, /* I/O Context */
+ int Port, /* Port Index (MAC_1 + n) */
+ int Para)
+ {
+ #ifdef GENESIS
+ if (pAC->GIni.GIGenesis) {
+-
++
+ SkXmSetRxTxEn(pAC, IoC, Port, Para);
+ }
+ #endif /* GENESIS */
+-
++
+ #ifdef YUKON
+ if (pAC->GIni.GIYukon) {
+-
++
+ SkGmSetRxTxEn(pAC, IoC, Port, Para);
+ }
+ #endif /* YUKON */
+@@ -3570,8 +4003,8 @@
+ * != 0 Error happened
+ */
+ int SkMacRxTxEnable(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ int Port) /* Port Index (MAC_1 + n) */
+ {
+ SK_GEPORT *pPrt;
+@@ -3589,9 +4022,9 @@
+ }
+
+ if ((pPrt->PLinkMode == SK_LMODE_AUTOHALF ||
+- pPrt->PLinkMode == SK_LMODE_AUTOFULL ||
+- pPrt->PLinkMode == SK_LMODE_AUTOBOTH) &&
+- pPrt->PAutoNegFail) {
++ pPrt->PLinkMode == SK_LMODE_AUTOFULL ||
++ pPrt->PLinkMode == SK_LMODE_AUTOBOTH) &&
++ pPrt->PAutoNegFail) {
+ /* Auto-negotiation is not done or failed */
+ return(0);
+ }
+@@ -3600,9 +4033,9 @@
+ 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
+@@ -3618,23 +4051,23 @@
+ /* 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:
+ /*
+@@ -3644,7 +4077,7 @@
+ 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,
++ SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK,
+ (SK_U16)PHY_B_DEF_MSK);
+ break;
+ #ifdef OTHER_PHY
+@@ -3658,12 +4091,12 @@
+ break;
+ #endif /* OTHER_PHY */
+ }
+-
++
+ /* enable Rx/Tx */
+ XM_OUT16(IoC, Port, XM_MMU_CMD, Reg | XM_MMU_ENA_RX | XM_MMU_ENA_TX);
+ }
+ #endif /* GENESIS */
+-
++
+ #ifdef YUKON
+ if (pAC->GIni.GIYukon) {
+ /*
+@@ -3674,34 +4107,34 @@
+ */
+ IntMask = GMAC_DEF_MSK;
+
+-#ifdef DEBUG
++#if defined(DEBUG) || defined(YUK2)
+ /* add IRQ for Receive FIFO Overrun */
+ IntMask |= GM_IS_RX_FF_OR;
+-#endif /* DEBUG */
+-
+- SK_OUT8(IoC, GMAC_IRQ_MSK, (SK_U8)IntMask);
+-
++#endif /* DEBUG || YUK2 */
++
++ SK_OUT8(IoC, MR_ADDR(Port, 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, (SK_U16)(Reg | GM_GPCR_RX_ENA |
+- GM_GPCR_TX_ENA));
++ 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,
+- (SK_U16)PHY_M_DEF_MSK);
+-#endif /* VCPU */
++#ifdef XXX
++ /* dummy read to ensure writing */
++ GM_IN16(IoC, Port, GM_GP_CTRL, &Reg);
++#endif /* XXX */
+ }
+ #endif /* YUKON */
+-
++
++ pAC->GIni.GP[Port].PState = SK_PRT_RUN;
++
+ return(0);
+
+ } /* SkMacRxTxEnable */
+@@ -3717,33 +4150,38 @@
+ */
+ void SkMacRxTxDisable(
+ SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* IO context */
++SK_IOC IoC, /* I/O Context */
+ int Port) /* Port Index (MAC_1 + n) */
+ {
+ SK_U16 Word;
+
+ #ifdef GENESIS
+ 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));
+-
++
++ Word &= ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX);
++
++ XM_OUT16(IoC, Port, XM_MMU_CMD, Word);
++
+ /* dummy read to ensure writing */
+ XM_IN16(IoC, Port, XM_MMU_CMD, &Word);
+ }
+ #endif /* GENESIS */
+-
++
+ #ifdef YUKON
+ if (pAC->GIni.GIYukon) {
+-
++
+ GM_IN16(IoC, Port, GM_GP_CTRL, &Word);
+
+- GM_OUT16(IoC, Port, GM_GP_CTRL, (SK_U16)(Word & ~(GM_GPCR_RX_ENA |
+- GM_GPCR_TX_ENA)));
++ Word &= ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA);
+
++ GM_OUT16(IoC, Port, GM_GP_CTRL, Word);
++
++#ifdef XXX
+ /* dummy read to ensure writing */
+ GM_IN16(IoC, Port, GM_GP_CTRL, &Word);
++#endif /* XXX */
+ }
+ #endif /* YUKON */
+
+@@ -3760,7 +4198,7 @@
+ */
+ void SkMacIrqDisable(
+ SK_AC *pAC, /* Adapter Context */
+-SK_IOC IoC, /* IO context */
++SK_IOC IoC, /* I/O Context */
+ int Port) /* Port Index (MAC_1 + n) */
+ {
+ SK_GEPORT *pPrt;
+@@ -3772,18 +4210,18 @@
+
+ #ifdef GENESIS
+ if (pAC->GIni.GIGenesis) {
+-
++
+ /* disable all XMAC IRQs */
+- XM_OUT16(IoC, Port, XM_IMSK, 0xffff);
+-
+- /* Disable all PHY interrupts */
++ 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 */
++ /* 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));
+@@ -3802,16 +4240,16 @@
+ }
+ }
+ #endif /* GENESIS */
+-
++
+ #ifdef YUKON
+ if (pAC->GIni.GIYukon) {
+ /* disable all GMAC IRQs */
+- SK_OUT8(IoC, GMAC_IRQ_MSK, 0);
+-
++ SK_OUT8(IoC, MR_ADDR(Port, GMAC_IRQ_MSK), 0);
++
+ #ifndef VCPU
+- /* Disable all PHY interrupts */
++ /* disable all PHY interrupts */
+ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, 0);
+-#endif /* VCPU */
++#endif /* !VCPU */
+ }
+ #endif /* YUKON */
+
+@@ -3823,29 +4261,72 @@
+ *
+ * SkXmSendCont() - Enable / Disable Send Continuous Mode
+ *
+- * Description: enable / disable Send Continuous Mode on XMAC
++ * Description: enable / disable Send Continuous Mode on XMAC resp.
++ * Packet Generation on GPHY
+ *
+ * Returns:
+ * nothing
+ */
+ void SkXmSendCont(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ int Port, /* Port Index (MAC_1 + n) */
+ SK_BOOL Enable) /* Enable / Disable */
+ {
++ SK_U16 Reg;
++ SK_U16 Save;
+ SK_U32 MdReg;
+
+- XM_IN32(IoC, Port, XM_MODE, &MdReg);
++ if (pAC->GIni.GIGenesis) {
++ XM_IN32(IoC, Port, XM_MODE, &MdReg);
+
+- if (Enable) {
+- MdReg |= XM_MD_TX_CONT;
++ if (Enable) {
++ MdReg |= XM_MD_TX_CONT;
++ }
++ else {
++ MdReg &= ~XM_MD_TX_CONT;
++ }
++ /* setup Mode Register */
++ XM_OUT32(IoC, Port, XM_MODE, MdReg);
+ }
+ else {
+- MdReg &= ~XM_MD_TX_CONT;
++ if (pAC->GIni.GIChipId == CHIP_ID_YUKON_EC) {
++ /* select page 18 */
++ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PAGE_ADDR, 18);
++
++ SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PAGE_DATA, &Reg);
++
++ Reg &= ~0x003c; /* clear bits 5..2 */
++
++ if (Enable) {
++ /* enable packet generation, 1518 byte length */
++ Reg |= (BIT_5S | BIT_3S);
++ }
++
++ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PAGE_DATA, Reg);
++ }
++ else if (pAC->GIni.GIChipId == CHIP_ID_YUKON_XL) {
++ /* save page register */
++ SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_ADR, &Save);
++
++ /* select page 6 to access Packet Generation register */
++ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 6);
++
++ SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_CTRL, &Reg);
++
++ Reg &= ~0x003f; /* clear bits 5..0 */
++
++ if (Enable) {
++ /* enable packet generation, 1518 byte length */
++ Reg |= (BIT_3S | BIT_1S);
++ }
++
++ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, Reg);
++
++ /* restore page register */
++ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, Save);
++ }
+ }
+- /* setup Mode Register */
+- XM_OUT32(IoC, Port, XM_MODE, MdReg);
+
+ } /* SkXmSendCont */
+
+@@ -3860,8 +4341,8 @@
+ * nothing
+ */
+ void SkMacTimeStamp(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ int Port, /* Port Index (MAC_1 + n) */
+ SK_BOOL Enable) /* Enable / Disable */
+ {
+@@ -3906,8 +4387,8 @@
+ * is set true.
+ */
+ void SkXmAutoNegLipaXmac(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ int Port, /* Port Index (MAC_1 + n) */
+ SK_U16 IStatus) /* Interrupt Status word to analyse */
+ {
+@@ -3921,6 +4402,7 @@
+ 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;
+ }
+ } /* SkXmAutoNegLipaXmac */
+@@ -3936,8 +4418,8 @@
+ * is set true.
+ */
+ void SkMacAutoNegLipaPhy(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ int Port, /* Port Index (MAC_1 + n) */
+ SK_U16 PhyStat) /* PHY Status word to analyse */
+ {
+@@ -3951,6 +4433,7 @@
+ 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;
+ }
+ } /* SkMacAutoNegLipaPhy */
+@@ -3965,7 +4448,7 @@
+ *
+ * Note:
+ * With an external PHY, some interrupt bits are not meaningfull any more:
+- * - LinkAsyncEvent (bit #14) XM_IS_LNK_AE
++ * - LinkAsyncEvent (bit #14) XM_IS_LNK_AE
+ * - LinkPartnerReqConfig (bit #10) XM_IS_LIPA_RC
+ * - Page Received (bit #9) XM_IS_RX_PAGE
+ * - NextPageLoadedForXmt (bit #8) XM_IS_TX_PAGE
+@@ -3977,8 +4460,8 @@
+ * nothing
+ */
+ void SkXmIrq(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ int Port) /* Port Index (MAC_1 + n) */
+ {
+ SK_GEPORT *pPrt;
+@@ -3986,13 +4469,13 @@
+ SK_U16 IStatus; /* Interrupt status read from the XMAC */
+ SK_U16 IStatus2;
+ #ifdef SK_SLIM
+- SK_U64 OverflowStatus;
+-#endif
++ SK_U64 OverflowStatus;
++#endif
+
+ pPrt = &pAC->GIni.GP[Port];
+-
++
+ XM_IN16(IoC, Port, XM_ISRC, &IStatus);
+-
++
+ /* LinkPartner Auto-negable? */
+ if (pPrt->PhyType == SK_PHY_XMAC) {
+ SkXmAutoNegLipaXmac(pAC, IoC, Port, IStatus);
+@@ -4003,7 +4486,7 @@
+ XM_IS_RX_PAGE | XM_IS_TX_PAGE |
+ XM_IS_AND | XM_IS_INP_ASS);
+ }
+-
++
+ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+ ("XmacIrq Port %d Isr 0x%04X\n", Port, IStatus));
+
+@@ -4113,45 +4596,49 @@
+ * nothing
+ */
+ void SkGmIrq(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ int Port) /* Port Index (MAC_1 + n) */
+ {
+ SK_GEPORT *pPrt;
+ SK_U8 IStatus; /* Interrupt status */
+ #ifdef SK_SLIM
+- SK_U64 OverflowStatus;
++ SK_U64 OverflowStatus;
+ #else
+ SK_EVPARA Para;
+-#endif
++#endif
+
+ pPrt = &pAC->GIni.GP[Port];
+-
+- SK_IN8(IoC, GMAC_IRQ_SRC, &IStatus);
+-
++
++ SK_IN8(IoC, MR_ADDR(Port, GMAC_IRQ_SRC), &IStatus);
++
+ #ifdef XXX
+ /* LinkPartner Auto-negable? */
+ SkMacAutoNegLipaPhy(pAC, IoC, Port, IStatus);
+ #endif /* XXX */
+-
++
+ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ,
+- ("GmacIrq Port %d Isr 0x%04X\n", Port, IStatus));
++ ("GmacIrq Port %d Isr 0x%02X\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 */
+ #ifdef SK_SLIM
+- SkGmOverflowStatus(pAC, IoC, Port, IStatus, &OverflowStatus);
++ SkGmOverflowStatus(pAC, IoC, Port, (SK_U16)IStatus, &OverflowStatus);
+ #else
+ Para.Para32[0] = (SK_U32)Port;
+ Para.Para32[1] = (SK_U32)IStatus;
+ SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_SIRQ_OVERFLOW, Para);
+-#endif
++#endif
+ }
+
+ 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);
++
++ Para.Para64 = Port;
++ SkEventQueue(pAC, SKGE_DRV, SK_DRV_RX_OVERFLOW, Para);
++
+ #ifdef DEBUG
+ pPrt->PRxOverCnt++;
+ #endif /* DEBUG */
+@@ -4185,8 +4672,8 @@
+ * nothing
+ */
+ void SkMacIrq(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ int Port) /* Port Index (MAC_1 + n) */
+ {
+ #ifdef GENESIS
+@@ -4195,7 +4682,7 @@
+ SkXmIrq(pAC, IoC, Port);
+ }
+ #endif /* GENESIS */
+-
++
+ #ifdef YUKON
+ if (pAC->GIni.GIYukon) {
+ /* IRQ from GMAC */
+@@ -4222,8 +4709,8 @@
+ * 1: something went wrong
+ */
+ int SkXmUpdateStats(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ unsigned int Port) /* Port Index (MAC_1 + n) */
+ {
+ SK_GEPORT *pPrt;
+@@ -4245,7 +4732,7 @@
+ 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);
+@@ -4253,7 +4740,7 @@
+ return(1);
+ }
+ } while ((StatReg & (XM_SC_SNP_TXC | XM_SC_SNP_RXC)) != 0);
+-
++
+ return(0);
+ } /* SkXmUpdateStats */
+
+@@ -4272,19 +4759,19 @@
+ * 1: something went wrong
+ */
+ int SkXmMacStatistic(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ unsigned int Port, /* Port Index (MAC_1 + n) */
+ SK_U16 StatAddr, /* MIB counter base address */
+-SK_U32 SK_FAR *pVal) /* ptr to return statistic value */
++SK_U32 SK_FAR *pVal) /* Pointer 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);
+@@ -4303,12 +4790,12 @@
+ * 1: something went wrong
+ */
+ int SkXmResetCounter(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O 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 */
++ /* Clear two times according to XMAC Errata #3 */
+ XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_CLR_RXC | XM_SC_CLR_TXC);
+
+ return(0);
+@@ -4335,11 +4822,11 @@
+ * 1: something went wrong
+ */
+ int SkXmOverflowStatus(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ unsigned int Port, /* Port Index (MAC_1 + n) */
+-SK_U16 IStatus, /* Interupt Status from MAC */
+-SK_U64 SK_FAR *pStatus) /* ptr for return overflow status value */
++SK_U16 IStatus, /* Interrupt Status from MAC */
++SK_U64 SK_FAR *pStatus) /* Pointer for return overflow status value */
+ {
+ SK_U64 Status; /* Overflow status */
+ SK_U32 RegVal;
+@@ -4351,7 +4838,7 @@
+ 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);
+@@ -4378,8 +4865,8 @@
+ * 1: something went wrong
+ */
+ int SkGmUpdateStats(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ unsigned int Port) /* Port Index (MAC_1 + n) */
+ {
+ return(0);
+@@ -4400,24 +4887,27 @@
+ * 1: something went wrong
+ */
+ int SkGmMacStatistic(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ unsigned int Port, /* Port Index (MAC_1 + n) */
+ SK_U16 StatAddr, /* MIB counter base address */
+-SK_U32 SK_FAR *pVal) /* ptr to return statistic value */
++SK_U32 SK_FAR *pVal) /* Pointer 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,
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR,
+ ("SkGmMacStat: wrong MIB counter 0x%04X\n", StatAddr));
+ return(1);
+ }
+-
++
+ GM_IN32(IoC, Port, StatAddr, pVal);
+
++ /* dummy read */
++ SK_IN16(IoC, B0_RAP, &StatAddr);
++
+ return(0);
+ } /* SkGmMacStatistic */
+
+@@ -4434,8 +4924,8 @@
+ * 1: something went wrong
+ */
+ int SkGmResetCounter(
+-SK_AC *pAC, /* adapter context */
+-SK_IOC IoC, /* IO context */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ unsigned int Port) /* Port Index (MAC_1 + n) */
+ {
+ SK_U16 Reg; /* Phy Address Register */
+@@ -4446,16 +4936,16 @@
+
+ /* 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);
+-
++
+ return(0);
+ } /* SkGmResetCounter */
+
+@@ -4469,48 +4959,62 @@
+ * 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
++ * 55:48 - TxRx interrupt register bit 7:0
++ * 47:32 - Rx interrupt register
+ * 31:24 - unused
+- * 23:16 - TxRx interrupt register bit15:8
+- * 15:0 - Tx interrupt register
++ * 23:16 - TxRx interrupt register bit 15: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 */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ unsigned int Port, /* Port Index (MAC_1 + n) */
+-SK_U16 IStatus, /* Interupt Status from MAC */
+-SK_U64 SK_FAR *pStatus) /* ptr for return overflow status value */
++SK_U16 IStatus, /* Interrupt Status from MAC */
++SK_U64 SK_FAR *pStatus) /* Pointer for return overflow status value */
+ {
+- SK_U64 Status; /* Overflow status */
+ SK_U16 RegVal;
++#ifndef SK_SLIM
++ SK_U64 Status; /* Overflow status */
+
+ Status = 0;
++#endif /* !SK_SLIM */
+
+ if ((IStatus & GM_IS_RX_CO_OV) != 0) {
+ /* this register is self-clearing after read */
+ GM_IN16(IoC, Port, GM_RX_IRQ_SRC, &RegVal);
++
++#ifndef SK_SLIM
+ Status |= (SK_U64)RegVal << 32;
++#endif /* !SK_SLIM */
+ }
+-
++
+ if ((IStatus & GM_IS_TX_CO_OV) != 0) {
+ /* this register is self-clearing after read */
+ GM_IN16(IoC, Port, GM_TX_IRQ_SRC, &RegVal);
++
++#ifndef SK_SLIM
+ Status |= (SK_U64)RegVal;
++#endif /* !SK_SLIM */
+ }
+-
++
+ /* this register is self-clearing after read */
+ GM_IN16(IoC, Port, GM_TR_IRQ_SRC, &RegVal);
++
++#ifndef SK_SLIM
+ /* 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;
++#endif /* !SK_SLIM */
++
++ /* dummy read */
++ SK_IN16(IoC, B0_RAP, &RegVal);
+
+ return(0);
+ } /* SkGmOverflowStatus */
+@@ -4526,57 +5030,114 @@
+ * 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 */
++SK_AC *pAC, /* Adapter Context */
++SK_IOC IoC, /* I/O Context */
+ int Port, /* Port Index (MAC_1 + n) */
+ SK_BOOL StartTest) /* flag for start / get result */
+ {
+ int i;
++ int CableDiagOffs;
++ int MdiPairs;
++ SK_BOOL FastEthernet;
++ SK_BOOL Yukon2;
+ SK_U16 RegVal;
+ SK_GEPORT *pPrt;
+
+ pPrt = &pAC->GIni.GP[Port];
+
+ if (pPrt->PhyType != SK_PHY_MARV_COPPER) {
+-
++
+ return(1);
+ }
+
++ Yukon2 = (pAC->GIni.GIChipId == CHIP_ID_YUKON_XL);
++
++ if (pAC->GIni.GIChipId == CHIP_ID_YUKON_FE) {
++
++ CableDiagOffs = PHY_MARV_FE_VCT_TX;
++ FastEthernet = SK_TRUE;
++ MdiPairs = 2;
++ }
++ else {
++ CableDiagOffs = Yukon2 ? PHY_MARV_PHY_CTRL : PHY_MARV_CABLE_DIAG;
++ FastEthernet = SK_FALSE;
++ MdiPairs = 4;
++ }
++
+ if (StartTest) {
++
++ /* set to RESET to avoid PortCheckUp */
++ pPrt->PState = SK_PRT_RESET;
++
+ /* 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);
++ if (!FastEthernet) {
++
++ if ((((pPrt->PhyId1 & PHY_I1_MOD_NUM) >> 4) == 2) &&
++ ((pPrt->PhyId1 & PHY_I1_REV_MSK) < 4)) {
++ /* apply TDR workaround for model 2, rev. < 4 */
++ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PAGE_ADDR, 0x001e);
++
++ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PAGE_DATA, 0xcc00);
++ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PAGE_DATA, 0xc800);
++ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PAGE_DATA, 0xc400);
++ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PAGE_DATA, 0xc000);
++ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PAGE_DATA, 0xc100);
++ }
++
++#ifdef YUKON_DBG
++ if (pAC->GIni.GIChipId == CHIP_ID_YUKON_EC) {
++ /* set address to 1 for page 1 */
++ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 1);
++
++ /* disable waiting period */
++ SkGmPhyWrite(pAC, IoC, Port, CableDiagOffs,
++ PHY_M_CABD_DIS_WAIT);
++ }
++#endif
++ if (Yukon2) {
++ /* set address to 5 for page 5 */
++ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 5);
++
++#ifdef YUKON_DBG
++ /* disable waiting period */
++ SkGmPhyWrite(pAC, IoC, Port, CableDiagOffs + 1,
++ PHY_M_CABD_DIS_WAIT);
++#endif
++ }
++ else {
++ /* set address to 0 for MDI[0] (Page 0) */
++ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 0);
++ }
+ }
++ else {
++ RegVal = PHY_CT_RESET | PHY_CT_SP100;
+
+- /* set address to 0 for MDI[0] */
+- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 0);
++ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, RegVal);
+
+- /* Read Cable Diagnostic Reg */
+- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal);
++#ifdef xYUKON_DBG
++ SkGmPhyRead(pAC, IoC, Port, PHY_MARV_FE_SPEC_2, &RegVal);
++ /* disable waiting period */
++ RegVal |= PHY_M_FESC_DIS_WAIT;
++
++ SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_FE_SPEC_2, RegVal);
++#endif
++ }
+
+ /* start Cable Diagnostic Test */
+- SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CABLE_DIAG,
+- (SK_U16)(RegVal | PHY_M_CABD_ENA_TEST));
+-
++ SkGmPhyWrite(pAC, IoC, Port, CableDiagOffs, PHY_M_CABD_ENA_TEST);
++
+ return(0);
+ }
+-
++
+ /* Read Cable Diagnostic Reg */
+- SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal);
++ SkGmPhyRead(pAC, IoC, Port, CableDiagOffs, &RegVal);
+
+ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL,
+ ("PHY Cable Diag.=0x%04X\n", RegVal));
+@@ -4587,16 +5148,24 @@
+ }
+
+ /* 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);
++ for (i = 0; i < MdiPairs; i++) {
++
++ if (!FastEthernet && !Yukon2) {
++ /* 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);
++ SkGmPhyRead(pAC, IoC, Port, CableDiagOffs, &RegVal);
+
+ pPrt->PMdiPairLen[i] = (SK_U8)(RegVal & PHY_M_CABD_DIST_MSK);
+
+ pPrt->PMdiPairSts[i] = (SK_U8)((RegVal & PHY_M_CABD_STAT_MSK) >> 13);
++
++ if (FastEthernet || Yukon2) {
++ /* get next register */
++ CableDiagOffs++;
++ }
+ }
+
+ return(0);
+@@ -4605,3 +5174,4 @@
+ #endif /* YUKON */
+
+ /* End of file */
++
+diff -ruN linux/drivers/net/sk98lin/sky2.c linux-new/drivers/net/sk98lin/sky2.c
+--- linux/drivers/net/sk98lin/sky2.c 1970-01-01 03:00:00.000000000 +0300
++++ linux-new/drivers/net/sk98lin/sky2.c 2005-08-09 17:15:51.000000000 +0400
+@@ -0,0 +1,2714 @@
++/******************************************************************************
++ *
++ * Name: sky2.c
++ * Project: Yukon2 specific functions and implementations
++ * Version: $Revision: 1.35.2.37 $
++ * Date: $Date: 2005/08/09 13:14:56 $
++ * Purpose: The main driver source module
++ *
++ *****************************************************************************/
++
++/******************************************************************************
++ *
++ * (C)Copyright 1998-2002 SysKonnect GmbH.
++ * (C)Copyright 2002-2005 Marvell.
++ *
++ * Driver for Marvell Yukon/2 chipset and SysKonnect Gigabit Ethernet
++ * Server Adapters.
++ *
++ * Author: Ralph Roesler (rroesler@syskonnect.de)
++ * Mirko Lindner (mlindner@syskonnect.de)
++ *
++ * Address all question to: linux@syskonnect.de
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * The information in this file is provided "AS IS" without warranty.
++ *
++ *****************************************************************************/
++
++#include "h/skdrv1st.h"
++#include "h/skdrv2nd.h"
++#include <linux/tcp.h>
++
++/******************************************************************************
++ *
++ * Local Function Prototypes
++ *
++ *****************************************************************************/
++
++static void InitPacketQueues(SK_AC *pAC,int Port);
++static void GiveTxBufferToHw(SK_AC *pAC,SK_IOC IoC,int Port);
++static void GiveRxBufferToHw(SK_AC *pAC,SK_IOC IoC,int Port,SK_PACKET *pPacket);
++static SK_BOOL HandleReceives(SK_AC *pAC,int Port,SK_U16 Len,SK_U32 FrameStatus,SK_U16 Tcp1,SK_U16 Tcp2,SK_U32 Tist,SK_U16 Vlan);
++static void CheckForSendComplete(SK_AC *pAC,SK_IOC IoC,int Port,SK_PKT_QUEUE *pPQ,SK_LE_TABLE *pLETab,unsigned int Done);
++static void UnmapAndFreeTxPktBuffer(SK_AC *pAC,SK_PACKET *pSkPacket,int TxPort);
++static SK_BOOL AllocateAndInitLETables(SK_AC *pAC);
++static SK_BOOL AllocatePacketBuffersYukon2(SK_AC *pAC);
++static void FreeLETables(SK_AC *pAC);
++static void FreePacketBuffers(SK_AC *pAC);
++static SK_BOOL AllocAndMapRxBuffer(SK_AC *pAC,SK_PACKET *pSkPacket,int Port);
++#ifdef CONFIG_SK98LIN_NAPI
++static SK_BOOL HandleStatusLEs(SK_AC *pAC,int *WorkDone,int WorkToDo);
++#else
++static SK_BOOL HandleStatusLEs(SK_AC *pAC);
++#endif
++
++extern void SkGeCheckTimer (DEV_NET *pNet);
++extern void SkLocalEventQueue( SK_AC *pAC,
++ SK_U32 Class,
++ SK_U32 Event,
++ SK_U32 Param1,
++ SK_U32 Param2,
++ SK_BOOL Flag);
++extern void SkLocalEventQueue64( SK_AC *pAC,
++ SK_U32 Class,
++ SK_U32 Event,
++ SK_U64 Param,
++ SK_BOOL Flag);
++
++/******************************************************************************
++ *
++ * Local Variables
++ *
++ *****************************************************************************/
++
++#define MAX_NBR_RX_BUFFERS_IN_HW 0x15
++static SK_U8 NbrRxBuffersInHW;
++#define FLUSH_OPC(le)
++
++/******************************************************************************
++ *
++ * Global Functions
++ *
++ *****************************************************************************/
++
++int SkY2Xmit( struct sk_buff *skb, struct SK_NET_DEVICE *dev);
++void FillReceiveTableYukon2(SK_AC *pAC,SK_IOC IoC,int Port);
++
++/*****************************************************************************
++ *
++ * SkY2RestartStatusUnit - restarts teh status unit
++ *
++ * Description:
++ * Reenables the status unit after any De-Init (e.g. when altering
++ * the sie of the MTU via 'ifconfig a.b.c.d mtu xxx')
++ *
++ * Returns: N/A
++ */
++void SkY2RestartStatusUnit(
++SK_AC *pAC) /* pointer to adapter control context */
++{
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,
++ ("==> SkY2RestartStatusUnit\n"));
++
++ /*
++ ** It might be that the TX timer is not started. Therefore
++ ** it is initialized here -> to be more investigated!
++ */
++ SK_OUT32(pAC->IoBase, STAT_TX_TIMER_INI, HW_MS_TO_TICKS(pAC,10));
++
++ pAC->StatusLETable.Done = 0;
++ pAC->StatusLETable.Put = 0;
++ pAC->StatusLETable.HwPut = 0;
++ SkGeY2InitStatBmu(pAC, pAC->IoBase, &pAC->StatusLETable);
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,
++ ("<== SkY2RestartStatusUnit\n"));
++}
++
++/*****************************************************************************
++ *
++ * SkY2RlmtSend - sends out a single RLMT notification
++ *
++ * Description:
++ * This function sends out an RLMT frame
++ *
++ * Returns:
++ * > 0 - on succes: the number of bytes in the message
++ * = 0 - on resource shortage: this frame sent or dropped, now
++ * the ring is full ( -> set tbusy)
++ * < 0 - on failure: other problems ( -> return failure to upper layers)
++ */
++int SkY2RlmtSend (
++SK_AC *pAC, /* pointer to adapter control context */
++int PortNr, /* index of port the packet(s) shall be send to */
++struct sk_buff *pMessage) /* pointer to send-message */
++{
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,
++ ("=== SkY2RlmtSend\n"));
++#if 0
++ return -1; // temporarily do not send out RLMT frames
++#endif
++ skb_shinfo(pMessage)->nr_frags = (2*MAX_SKB_FRAGS) + PortNr;
++ return(SkY2Xmit(pMessage, pAC->dev[PortNr])); // SkY2Xmit needs device
++}
++
++/*****************************************************************************
++ *
++ * SkY2AllocateResources - Allocates all required resources for Yukon2
++ *
++ * Description:
++ * This function allocates all memory needed for the Yukon2.
++ * It maps also RX buffers to the LETables and initializes the
++ * status list element table.
++ *
++ * Returns:
++ * SK_TRUE, if all resources could be allocated and setup succeeded
++ * SK_FALSE, if an error
++ */
++SK_BOOL SkY2AllocateResources (
++SK_AC *pAC) /* pointer to adapter control context */
++{
++ int CurrMac;
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT,
++ ("==> SkY2AllocateResources\n"));
++
++ /*
++ ** Initialize the packet queue variables first
++ */
++ for (CurrMac = 0; CurrMac < pAC->GIni.GIMacsFound; CurrMac++) {
++ InitPacketQueues(pAC, CurrMac);
++ }
++
++ /*
++ ** Get sufficient memory for the LETables
++ */
++ if (!AllocateAndInitLETables(pAC)) {
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV,
++ SK_DBGCAT_INIT | SK_DBGCAT_DRV_ERROR,
++ ("No memory for LETable.\n"));
++ return(SK_FALSE);
++ }
++
++ /*
++ ** Allocate and intialize memory for both RX and TX
++ ** packet and fragment buffers. On an error, free
++ ** previously allocated LETable memory and quit.
++ */
++ if (!AllocatePacketBuffersYukon2(pAC)) {
++ FreeLETables(pAC);
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV,
++ SK_DBGCAT_INIT | SK_DBGCAT_DRV_ERROR,
++ ("No memory for Packetbuffers.\n"));
++ return(SK_FALSE);
++ }
++
++ /*
++ ** Rx and Tx LE tables will be initialized in SkGeOpen()
++ **
++ ** It might be that the TX timer is not started. Therefore
++ ** it is initialized here -> to be more investigated!
++ */
++ SK_OUT32(pAC->IoBase, STAT_TX_TIMER_INI, HW_MS_TO_TICKS(pAC,10));
++ SkGeY2InitStatBmu(pAC, pAC->IoBase, &pAC->StatusLETable);
++
++ pAC->MaxUnusedRxLeWorking = MAX_UNUSED_RX_LE_WORKING;
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT,
++ ("<== SkY2AllocateResources\n"));
++
++ return (SK_TRUE);
++}
++
++/*****************************************************************************
++ *
++ * SkY2FreeResources - Frees previously allocated resources of Yukon2
++ *
++ * Description:
++ * This function frees all previously allocated memory of the Yukon2.
++ *
++ * Returns: N/A
++ */
++void SkY2FreeResources (
++SK_AC *pAC) /* pointer to adapter control context */
++{
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,
++ ("==> SkY2FreeResources\n"));
++
++ FreeLETables(pAC);
++ FreePacketBuffers(pAC);
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,
++ ("<== SkY2FreeResources\n"));
++}
++
++/*****************************************************************************
++ *
++ * SkY2AllocateRxBuffers - Allocates the receive buffers for a port
++ *
++ * Description:
++ * This function allocated all the RX buffers of the Yukon2.
++ *
++ * Returns: N/A
++ */
++void SkY2AllocateRxBuffers (
++SK_AC *pAC, /* pointer to adapter control context */
++SK_IOC IoC, /* I/O control context */
++int Port) /* port index of RX */
++{
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT,
++ ("==> SkY2AllocateRxBuffers (Port %c)\n", Port));
++
++ FillReceiveTableYukon2(pAC, IoC, Port);
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT,
++ ("<== SkY2AllocateRxBuffers\n"));
++}
++
++/*****************************************************************************
++ *
++ * SkY2FreeRxBuffers - Free's all allocates RX buffers of
++ *
++ * Description:
++ * This function frees all RX buffers of the Yukon2 for a single port
++ *
++ * Returns: N/A
++ */
++void SkY2FreeRxBuffers (
++SK_AC *pAC, /* pointer to adapter control context */
++SK_IOC IoC, /* I/O control context */
++int Port) /* port index of RX */
++{
++ SK_PACKET *pSkPacket;
++ unsigned long Flags; /* for POP/PUSH macros */
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,
++ ("==> SkY2FreeRxBuffers (Port %c)\n", Port));
++
++ if (pAC->RxPort[Port].ReceivePacketTable != NULL) {
++ POP_FIRST_PKT_FROM_QUEUE(&pAC->RxPort[Port].RxQ_working, pSkPacket);
++ while (pSkPacket != NULL) {
++ if ((pSkPacket->pFrag) != NULL) {
++ pci_unmap_page(pAC->PciDev,
++ (dma_addr_t) pSkPacket->pFrag->pPhys,
++ pSkPacket->pFrag->FragLen - 2,
++ PCI_DMA_FROMDEVICE);
++
++ DEV_KFREE_SKB_ANY(pSkPacket->pMBuf);
++ pSkPacket->pMBuf = NULL;
++ pSkPacket->pFrag->pPhys = (SK_U64) 0;
++ pSkPacket->pFrag->pVirt = NULL;
++ }
++ PUSH_PKT_AS_LAST_IN_QUEUE(&pAC->RxPort[Port].RxQ_waiting, pSkPacket);
++ POP_FIRST_PKT_FROM_QUEUE(&pAC->RxPort[Port].RxQ_working, pSkPacket);
++ }
++ }
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,
++ ("<== SkY2FreeRxBuffers\n"));
++}
++
++/*****************************************************************************
++ *
++ * SkY2FreeTxBuffers - Free's any currently maintained Tx buffer
++ *
++ * Description:
++ * This function frees the TX buffers of the Yukon2 for a single port
++ * which might be in use by a transmit action
++ *
++ * Returns: N/A
++ */
++void SkY2FreeTxBuffers (
++SK_AC *pAC, /* pointer to adapter control context */
++SK_IOC IoC, /* I/O control context */
++int Port) /* port index of TX */
++{
++ SK_PACKET *pSkPacket;
++ SK_FRAG *pSkFrag;
++ unsigned long Flags;
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,
++ ("==> SkY2FreeTxBuffers (Port %c)\n", Port));
++
++ if (pAC->TxPort[Port][0].TransmitPacketTable != NULL) {
++ POP_FIRST_PKT_FROM_QUEUE(&pAC->TxPort[Port][0].TxAQ_working, pSkPacket);
++ while (pSkPacket != NULL) {
++ if ((pSkFrag = pSkPacket->pFrag) != NULL) {
++ UnmapAndFreeTxPktBuffer(pAC, pSkPacket, Port);
++ }
++ PUSH_PKT_AS_LAST_IN_QUEUE(&pAC->TxPort[Port][0].TxQ_free, pSkPacket);
++ POP_FIRST_PKT_FROM_QUEUE(&pAC->TxPort[Port][0].TxAQ_working, pSkPacket);
++ }
++#if USE_SYNC_TX_QUEUE
++ POP_FIRST_PKT_FROM_QUEUE(&pAC->TxPort[Port][0].TxSQ_working, pSkPacket);
++ while (pSkPacket != NULL) {
++ if ((pSkFrag = pSkPacket->pFrag) != NULL) {
++ UnmapAndFreeTxPktBuffer(pAC, pSkPacket, Port);
++ }
++ PUSH_PKT_AS_LAST_IN_QUEUE(&pAC->TxPort[Port][0].TxQ_free, pSkPacket);
++ POP_FIRST_PKT_FROM_QUEUE(&pAC->TxPort[Port][0].TxSQ_working, pSkPacket);
++ }
++#endif
++ }
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,
++ ("<== SkY2FreeTxBuffers\n"));
++}
++
++/*****************************************************************************
++ *
++ * SkY2Isr - handle a receive IRQ for all yukon2 cards
++ *
++ * Description:
++ * This function is called when a receive IRQ is set. (only for yukon2)
++ * HandleReceives does the deferred processing of all outstanding
++ * interrupt operations.
++ *
++ * Returns: N/A
++ */
++SkIsrRetVar SkY2Isr (
++int irq, /* the irq we have received (might be shared!) */
++void *dev_id, /* current device id */
++struct pt_regs *ptregs) /* not used by our driver */
++{
++ struct SK_NET_DEVICE *dev = (struct SK_NET_DEVICE *)dev_id;
++ DEV_NET *pNet = (DEV_NET*) dev->priv;
++ SK_AC *pAC = pNet->pAC;
++ SK_U32 IntSrc;
++ unsigned long Flags;
++#ifndef CONFIG_SK98LIN_NAPI
++ SK_BOOL handledStatLE = SK_FALSE;
++#else
++ SK_BOOL SetIntMask = SK_FALSE;
++#endif
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,
++ ("==> SkY2Isr\n"));
++
++ SK_IN32(pAC->IoBase, B0_Y2_SP_ISRC2, &IntSrc);
++
++ if ((IntSrc == 0) && (!pNet->NetConsoleMode)){
++ SK_OUT32(pAC->IoBase, B0_Y2_SP_ICR, 2);
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,
++ ("No Interrupt\n ==> SkY2Isr\n"));
++ return SkIsrRetNone;
++
++ }
++
++#ifdef Y2_RECOVERY
++ if (pNet->InRecover) {
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,
++ ("Already in recover\n ==> SkY2Isr\n"));
++ SK_OUT32(pAC->IoBase, B0_Y2_SP_ICR, 2);
++ return SkIsrRetNone;
++ }
++#endif
++
++#ifdef CONFIG_SK98LIN_NAPI
++ if (netif_rx_schedule_prep(pAC->dev[0])) {
++ pAC->GIni.GIValIrqMask &= ~(Y2_IS_STAT_BMU);
++ SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask);
++ SetIntMask = SK_TRUE;
++ __netif_rx_schedule(pAC->dev[0]);
++ }
++
++ if (netif_rx_schedule_prep(pAC->dev[1])) {
++ if (!SetIntMask) {
++ pAC->GIni.GIValIrqMask &= ~(Y2_IS_STAT_BMU);
++ SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask);
++ }
++ __netif_rx_schedule(pAC->dev[1]);
++ }
++#else
++ handledStatLE = HandleStatusLEs(pAC);
++#endif
++
++ /*
++ ** Check for Special Interrupts
++ */
++ if ((IntSrc & ~Y2_IS_STAT_BMU) || pAC->CheckQueue || pNet->TimerExpired) {
++ pAC->CheckQueue = SK_FALSE;
++ spin_lock_irqsave(&pAC->SlowPathLock, Flags);
++ SkGeSirqIsr(pAC, pAC->IoBase, IntSrc);
++ SkEventDispatcher(pAC, pAC->IoBase);
++ spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
++ }
++
++ /* Speed enhancement for a2 chipsets */
++ if (HW_FEATURE(pAC, HWF_WA_DEV_42)) {
++ spin_lock_irqsave(&pAC->SetPutIndexLock, Flags);
++ SkGeY2SetPutIndex(pAC, pAC->IoBase, Y2_PREF_Q_ADDR(Q_XA1,0), &pAC->TxPort[0][0].TxALET);
++ SkGeY2SetPutIndex(pAC, pAC->IoBase, Y2_PREF_Q_ADDR(Q_R1,0), &pAC->RxPort[0].RxLET);
++ spin_unlock_irqrestore(&pAC->SetPutIndexLock, Flags);
++ }
++
++ /*
++ ** Reenable interrupts and signal end of ISR
++ */
++ SK_OUT32(pAC->IoBase, B0_Y2_SP_ICR, 2);
++
++ /*
++ ** Stop and restart TX timer in case a Status LE was handled
++ */
++#ifndef CONFIG_SK98LIN_NAPI
++ if ((HW_FEATURE(pAC, HWF_WA_DEV_43_418)) && (handledStatLE)) {
++ SK_OUT8(pAC->IoBase, STAT_TX_TIMER_CTRL, TIM_STOP);
++ SK_OUT8(pAC->IoBase, STAT_TX_TIMER_CTRL, TIM_START);
++ }
++#endif
++
++ if (!(IS_Q_EMPTY(&(pAC->TxPort[0][TX_PRIO_LOW].TxAQ_waiting)))) {
++ GiveTxBufferToHw(pAC, pAC->IoBase, 0);
++ }
++ if (!(IS_Q_EMPTY(&(pAC->TxPort[1][TX_PRIO_LOW].TxAQ_waiting)))) {
++ GiveTxBufferToHw(pAC, pAC->IoBase, 1);
++ }
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,
++ ("<== SkY2Isr\n"));
++
++ return SkIsrRetHandled;
++} /* SkY2Isr */
++
++/*****************************************************************************
++ *
++ * SkY2Xmit - Linux frame transmit function for Yukon2
++ *
++ * Description:
++ * The system calls this function to send frames onto the wire.
++ * It puts the frame in the tx descriptor ring. If the ring is
++ * full then, the 'tbusy' flag is set.
++ *
++ * Returns:
++ * 0, if everything is ok
++ * !=0, on error
++ *
++ * WARNING:
++ * returning 1 in 'tbusy' case caused system crashes (double
++ * allocated skb's) !!!
++ */
++int SkY2Xmit(
++struct sk_buff *skb, /* socket buffer to be sent */
++struct SK_NET_DEVICE *dev) /* via which device? */
++{
++ DEV_NET *pNet = (DEV_NET*) dev->priv;
++ SK_AC *pAC = pNet->pAC;
++ SK_U8 FragIdx = 0;
++ SK_PACKET *pSkPacket;
++ SK_FRAG *PrevFrag;
++ SK_FRAG *CurrFrag;
++ SK_PKT_QUEUE *pWorkQueue; /* corresponding TX queue */
++ SK_PKT_QUEUE *pWaitQueue;
++ SK_PKT_QUEUE *pFreeQueue;
++ SK_LE_TABLE *pLETab; /* corresponding LETable */
++ skb_frag_t *sk_frag;
++ SK_U64 PhysAddr;
++ unsigned long Flags;
++ unsigned int Port;
++ int CurrFragCtr;
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
++ ("==> SkY2Xmit\n"));
++
++ /*
++ ** Get port and return if no free packet is available
++ */
++ if (skb_shinfo(skb)->nr_frags > MAX_SKB_FRAGS) {
++ Port = skb_shinfo(skb)->nr_frags - (2*MAX_SKB_FRAGS);
++ skb_shinfo(skb)->nr_frags = 0;
++ } else {
++ Port = (pAC->RlmtNets == 2) ? pNet->PortNr : pAC->ActivePort;
++ }
++
++ if (IS_Q_EMPTY(&(pAC->TxPort[Port][TX_PRIO_LOW].TxQ_free))) {
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV,
++ SK_DBGCAT_DRV_TX_PROGRESS | SK_DBGCAT_DRV_ERROR,
++ ("Not free packets available for send\n"));
++ return 1; /* zero bytes sent! */
++ }
++
++ /*
++ ** Put any new packet to be sent in the waiting queue and
++ ** handle also any possible fragment of that packet.
++ */
++ pWorkQueue = &(pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_working);
++ pWaitQueue = &(pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_waiting);
++ pFreeQueue = &(pAC->TxPort[Port][TX_PRIO_LOW].TxQ_free);
++ pLETab = &(pAC->TxPort[Port][TX_PRIO_LOW].TxALET);
++
++ /*
++ ** Normal send operations require only one fragment, because
++ ** only one sk_buff data area is passed.
++ ** In contradiction to this, scatter-gather (zerocopy) send
++ ** operations might pass one or more additional fragments
++ ** where each fragment needs a separate fragment info packet.
++ */
++ if (((skb_shinfo(skb)->nr_frags + 1) * MAX_FRAG_OVERHEAD) >
++ NUM_FREE_LE_IN_TABLE(pLETab)) {
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV,
++ SK_DBGCAT_DRV_TX_PROGRESS | SK_DBGCAT_DRV_ERROR,
++ ("Not enough LE available for send\n"));
++ return 1; /* zero bytes sent! */
++ }
++
++ if ((skb_shinfo(skb)->nr_frags + 1) > MAX_NUM_FRAGS) {
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV,
++ SK_DBGCAT_DRV_TX_PROGRESS | SK_DBGCAT_DRV_ERROR,
++ ("Not even one fragment available for send\n"));
++ return 1; /* zero bytes sent! */
++ }
++
++ /*
++ ** Get first packet from free packet queue
++ */
++ POP_FIRST_PKT_FROM_QUEUE(pFreeQueue, pSkPacket);
++ if(pSkPacket == NULL) {
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV,
++ SK_DBGCAT_DRV_TX_PROGRESS | SK_DBGCAT_DRV_ERROR,
++ ("Could not obtain free packet used for xmit\n"));
++ return 1; /* zero bytes sent! */
++ }
++
++ pSkPacket->pFrag = &(pSkPacket->FragArray[FragIdx]);
++
++ /*
++ ** map the sk_buff to be available for the adapter
++ */
++ PhysAddr = (SK_U64) pci_map_page(pAC->PciDev,
++ virt_to_page(skb->data),
++ ((unsigned long) skb->data & ~PAGE_MASK),
++ skb_headlen(skb),
++ PCI_DMA_TODEVICE);
++ pSkPacket->pMBuf = skb;
++ pSkPacket->pFrag->pPhys = PhysAddr;
++ pSkPacket->pFrag->FragLen = skb_headlen(skb);
++ pSkPacket->pFrag->pNext = NULL; /* initial has no next default */
++ pSkPacket->NumFrags = skb_shinfo(skb)->nr_frags + 1;
++
++ PrevFrag = pSkPacket->pFrag;
++
++ /*
++ ** Each scatter-gather fragment need to be mapped...
++ */
++ for ( CurrFragCtr = 0;
++ CurrFragCtr < skb_shinfo(skb)->nr_frags;
++ CurrFragCtr++) {
++ FragIdx++;
++ sk_frag = &skb_shinfo(skb)->frags[CurrFragCtr];
++ CurrFrag = &(pSkPacket->FragArray[FragIdx]);
++
++ /*
++ ** map the sk_buff to be available for the adapter
++ */
++ PhysAddr = (SK_U64) pci_map_page(pAC->PciDev,
++ sk_frag->page,
++ sk_frag->page_offset,
++ sk_frag->size,
++ PCI_DMA_TODEVICE);
++
++ CurrFrag->pPhys = PhysAddr;
++ CurrFrag->FragLen = sk_frag->size;
++ CurrFrag->pNext = NULL;
++
++ /*
++ ** Add the new fragment to the list of fragments
++ */
++ PrevFrag->pNext = CurrFrag;
++ PrevFrag = CurrFrag;
++ }
++
++ /*
++ ** Add packet to waiting packets queue
++ */
++ PUSH_PKT_AS_LAST_IN_QUEUE(pWaitQueue, pSkPacket);
++ GiveTxBufferToHw(pAC, pAC->IoBase, Port);
++ dev->trans_start = jiffies;
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
++ ("<== SkY2Xmit(return 0)\n"));
++ return (0);
++} /* SkY2Xmit */
++
++#ifdef CONFIG_SK98LIN_NAPI
++/*****************************************************************************
++ *
++ * SkY2Poll - NAPI Rx polling callback for Yukon2 chipsets
++ *
++ * Description:
++ * Called by the Linux system in case NAPI polling is activated
++ *
++ * Returns
++ * The number of work data still to be handled
++ *
++ * Notes
++ * The slowpath lock needs to be set because HW accesses may
++ * interfere with slowpath events (e.g. TWSI)
++ */
++int SkY2Poll(
++struct net_device *dev, /* device that needs to be polled */
++int *budget) /* how many budget do we have? */
++{
++ SK_AC *pAC = ((DEV_NET*)(dev->priv))->pAC;
++ int WorkToDo = min(*budget, dev->quota);
++ int WorkDone = 0;
++ SK_BOOL handledStatLE = SK_FALSE;
++ unsigned long Flags;
++
++ spin_lock_irqsave(&pAC->SlowPathLock, Flags);
++ handledStatLE = HandleStatusLEs(pAC, &WorkDone, WorkToDo);
++
++ *budget -= WorkDone;
++ dev->quota -= WorkDone;
++
++ if(WorkDone < WorkToDo) {
++ netif_rx_complete(dev);
++ pAC->GIni.GIValIrqMask |= (Y2_IS_STAT_BMU);
++ SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask);
++ if ((HW_FEATURE(pAC, HWF_WA_DEV_43_418)) && (handledStatLE)) {
++ SK_OUT8(pAC->IoBase, STAT_TX_TIMER_CTRL, TIM_STOP);
++ SK_OUT8(pAC->IoBase, STAT_TX_TIMER_CTRL, TIM_START);
++ }
++ }
++ spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
++ return (WorkDone >= WorkToDo);
++} /* SkY2Poll */
++#endif
++
++/******************************************************************************
++ *
++ * SkY2PortStop - stop a port on Yukon2
++ *
++ * Description:
++ * This function stops a port of the Yukon2 chip. This stop
++ * stop needs to be performed in a specific order:
++ *
++ * a) Stop the Prefetch unit
++ * b) Stop the Port (MAC, PHY etc.)
++ *
++ * Returns: N/A
++ */
++void SkY2PortStop(
++SK_AC *pAC, /* adapter control context */
++SK_IOC IoC, /* I/O control context (address of adapter registers) */
++int Port, /* port to stop (MAC_1 + n) */
++int Dir, /* StopDirection (SK_STOP_RX, SK_STOP_TX, SK_STOP_ALL) */
++int RstMode) /* Reset Mode (SK_SOFT_RST, SK_HARD_RST) */
++{
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,
++ ("==> SkY2PortStop (Port %c)\n", 'A' + Port));
++
++ /*
++ ** Stop the HW
++ */
++ SkGeStopPort(pAC, IoC, Port, Dir, RstMode);
++
++ /*
++ ** Move any TX packet from work queues into the free queue again
++ ** and initialize the TX LETable variables
++ */
++ SkY2FreeTxBuffers(pAC, pAC->IoBase, Port);
++ pAC->TxPort[Port][TX_PRIO_LOW].TxALET.Bmu.RxTx.TcpWp = 0;
++ pAC->TxPort[Port][TX_PRIO_LOW].TxALET.Bmu.RxTx.MssValue = 0;
++ pAC->TxPort[Port][TX_PRIO_LOW].TxALET.BufHighAddr = 0;
++ pAC->TxPort[Port][TX_PRIO_LOW].TxALET.Done = 0;
++ pAC->TxPort[Port][TX_PRIO_LOW].TxALET.Put = 0;
++ // pAC->GIni.GP[Port].PState = SK_PRT_STOP;
++
++ /*
++ ** Move any RX packet from work queue into the waiting queue
++ ** and initialize the RX LETable variables
++ */
++ SkY2FreeRxBuffers(pAC, pAC->IoBase, Port);
++ pAC->RxPort[Port].RxLET.BufHighAddr = 0;
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,
++ ("<== SkY2PortStop()\n"));
++}
++
++/******************************************************************************
++ *
++ * SkY2PortStart - start a port on Yukon2
++ *
++ * Description:
++ * This function starts a port of the Yukon2 chip. This start
++ * action needs to be performed in a specific order:
++ *
++ * a) Initialize the LET indices (PUT/GET to 0)
++ * b) Initialize the LET in HW (enables also prefetch unit)
++ * c) Move all RX buffers from waiting queue to working queue
++ * which involves also setting up of RX list elements
++ * d) Initialize the FIFO settings of Yukon2 (Watermark etc.)
++ * e) Initialize the Port (MAC, PHY etc.)
++ * f) Initialize the MC addresses
++ *
++ * Returns: N/A
++ */
++void SkY2PortStart(
++SK_AC *pAC, /* adapter control context */
++SK_IOC IoC, /* I/O control context (address of adapter registers) */
++int Port) /* port to start */
++{
++ // SK_GEPORT *pPrt = &pAC->GIni.GP[Port];
++ SK_HWLE *pLE;
++ SK_U32 DWord;
++ SK_U32 PrefetchReg; /* register for Put index */
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,
++ ("==> SkY2PortStart (Port %c)\n", 'A' + Port));
++
++ /*
++ ** Initialize the LET indices
++ */
++ pAC->RxPort[Port].RxLET.Done = 0;
++ pAC->RxPort[Port].RxLET.Put = 0;
++ pAC->RxPort[Port].RxLET.HwPut = 0;
++ pAC->TxPort[Port][TX_PRIO_LOW].TxALET.Done = 0;
++ pAC->TxPort[Port][TX_PRIO_LOW].TxALET.Put = 0;
++ pAC->TxPort[Port][TX_PRIO_LOW].TxALET.HwPut = 0;
++ if (HW_SYNC_TX_SUPPORTED(pAC)) {
++ pAC->TxPort[Port][TX_PRIO_LOW].TxSLET.Done = 0;
++ pAC->TxPort[Port][TX_PRIO_LOW].TxSLET.Put = 0;
++ pAC->TxPort[Port][TX_PRIO_LOW].TxSLET.HwPut = 0;
++ }
++
++ if (HW_FEATURE(pAC, HWF_WA_DEV_420)) {
++ /*
++ ** It might be that we have to limit the RX buffers
++ ** effectively passed to HW. Initialize the start
++ ** value in that case...
++ */
++ NbrRxBuffersInHW = 0;
++ }
++
++ /*
++ ** TODO on dual net adapters we need to check if
++ ** StatusLETable need to be set...
++ **
++ ** pAC->StatusLETable.Done = 0;
++ ** pAC->StatusLETable.Put = 0;
++ ** pAC->StatusLETable.HwPut = 0;
++ ** SkGeY2InitPrefetchUnit(pAC, pAC->IoBase, Q_ST, &pAC->StatusLETable);
++ */
++
++ /*
++ ** Initialize the LET in HW (enables also prefetch unit)
++ */
++ SkGeY2InitPrefetchUnit(pAC, IoC,(Port == 0) ? Q_R1 : Q_R2,
++ &pAC->RxPort[Port].RxLET);
++ SkGeY2InitPrefetchUnit( pAC, IoC,(Port == 0) ? Q_XA1 : Q_XA2,
++ &pAC->TxPort[Port][TX_PRIO_LOW].TxALET);
++ if (HW_SYNC_TX_SUPPORTED(pAC)) {
++ SkGeY2InitPrefetchUnit( pAC, IoC, (Port == 0) ? Q_XS1 : Q_XS2,
++ &pAC->TxPort[Port][TX_PRIO_HIGH].TxSLET);
++ }
++
++
++ /*
++ ** Using new values for the watermarks and the timer for
++ ** low latency optimization
++ */
++ if (pAC->LowLatency) {
++ SK_OUT8(IoC, STAT_FIFO_WM, 1);
++ SK_OUT8(IoC, STAT_FIFO_ISR_WM, 1);
++ SK_OUT32(IoC, STAT_LEV_TIMER_INI, 50);
++ SK_OUT32(IoC, STAT_ISR_TIMER_INI, 10);
++ }
++
++
++ /*
++ ** Initialize the Port (MAC, PHY etc.)
++ */
++ if (SkGeInitPort(pAC, IoC, Port)) {
++ if (Port == 0) {
++ printk("%s: SkGeInitPort A failed.\n",pAC->dev[0]->name);
++ } else {
++ printk("%s: SkGeInitPort B failed.\n",pAC->dev[1]->name);
++ }
++ }
++
++ if (IS_GMAC(pAC)) {
++ /* disable Rx GMAC FIFO Flush Mode */
++ SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8) GMF_RX_F_FL_OFF);
++ }
++
++ /*
++ ** Initialize the MC addresses
++ */
++ SkAddrMcUpdate(pAC,IoC, Port);
++
++ SkMacRxTxEnable(pAC, IoC,Port);
++
++ if (pAC->RxPort[Port].UseRxCsum) {
++ SkGeRxCsum(pAC, IoC, Port, SK_TRUE);
++
++ GET_RX_LE(pLE, &pAC->RxPort[Port].RxLET);
++ RXLE_SET_STACS1(pLE, pAC->CsOfs1);
++ RXLE_SET_STACS2(pLE, pAC->CsOfs2);
++ RXLE_SET_CTRL(pLE, 0);
++
++ RXLE_SET_OPC(pLE, OP_TCPSTART | HW_OWNER);
++ FLUSH_OPC(pLE);
++ if (Port == 0) {
++ PrefetchReg=Y2_PREF_Q_ADDR(Q_R1,PREF_UNIT_PUT_IDX_REG);
++ } else {
++ PrefetchReg=Y2_PREF_Q_ADDR(Q_R2,PREF_UNIT_PUT_IDX_REG);
++ }
++ DWord = GET_PUT_IDX(&pAC->RxPort[Port].RxLET);
++ SK_OUT32(IoC, PrefetchReg, DWord);
++ UPDATE_HWPUT_IDX(&pAC->RxPort[Port].RxLET);
++ }
++
++ pAC->GIni.GP[Port].PState = SK_PRT_RUN;
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,
++ ("<== SkY2PortStart()\n"));
++}
++
++/******************************************************************************
++ *
++ * Local Functions
++ *
++ *****************************************************************************/
++
++/*****************************************************************************
++ *
++ * InitPacketQueues - initialize SW settings of packet queues
++ *
++ * Description:
++ * This function will initialize the packet queues for a port.
++ *
++ * Returns: N/A
++ */
++static void InitPacketQueues(
++SK_AC *pAC, /* pointer to adapter control context */
++int Port) /* index of port to be initialized */
++{
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT,
++ ("==> InitPacketQueues(Port %c)\n", 'A' + Port));
++
++ pAC->RxPort[Port].RxQ_working.pHead = NULL;
++ pAC->RxPort[Port].RxQ_working.pTail = NULL;
++ spin_lock_init(&pAC->RxPort[Port].RxQ_working.QueueLock);
++
++ pAC->RxPort[Port].RxQ_waiting.pHead = NULL;
++ pAC->RxPort[Port].RxQ_waiting.pTail = NULL;
++ spin_lock_init(&pAC->RxPort[Port].RxQ_waiting.QueueLock);
++
++ pAC->TxPort[Port][TX_PRIO_LOW].TxQ_free.pHead = NULL;
++ pAC->TxPort[Port][TX_PRIO_LOW].TxQ_free.pTail = NULL;
++ spin_lock_init(&pAC->TxPort[Port][TX_PRIO_LOW].TxQ_free.QueueLock);
++
++ pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_working.pHead = NULL;
++ pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_working.pTail = NULL;
++ spin_lock_init(&pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_working.QueueLock);
++
++ pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_waiting.pHead = NULL;
++ pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_waiting.pTail = NULL;
++ spin_lock_init(&pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_waiting.QueueLock);
++
++#if USE_SYNC_TX_QUEUE
++ pAC->TxPort[Port][TX_PRIO_LOW].TxSQ_working.pHead = NULL;
++ pAC->TxPort[Port][TX_PRIO_LOW].TxSQ_working.pTail = NULL;
++ spin_lock_init(&pAC->TxPort[Port][TX_PRIO_LOW].TxSQ_working.QueueLock);
++
++ pAC->TxPort[Port][TX_PRIO_LOW].TxSQ_waiting.pHead = NULL;
++ pAC->TxPort[Port][TX_PRIO_LOW].TxSQ_waiting.pTail = NULL;
++ spin_lock_init(&pAC->TxPort[Port][TX_PRIO_LOW].TxSQ_waiting.QueueLock);
++#endif
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT,
++ ("<== InitPacketQueues(Port %c)\n", 'A' + Port));
++} /* InitPacketQueues */
++
++/*****************************************************************************
++ *
++ * GiveTxBufferToHw - commits a previously allocated DMA area to HW
++ *
++ * Description:
++ * This functions gives transmit buffers to HW. If no list elements
++ * are available the buffers will be queued.
++ *
++ * Notes:
++ * This function can run only once in a system at one time.
++ *
++ * Returns: N/A
++ */
++static void GiveTxBufferToHw(
++SK_AC *pAC, /* pointer to adapter control context */
++SK_IOC IoC, /* I/O control context (address of registers) */
++int Port) /* port index for which the buffer is used */
++{
++ SK_HWLE *pLE;
++ SK_PACKET *pSkPacket;
++ SK_FRAG *pFrag;
++ SK_PKT_QUEUE *pWorkQueue; /* corresponding TX queue */
++ SK_PKT_QUEUE *pWaitQueue;
++ SK_LE_TABLE *pLETab; /* corresponding LETable */
++ SK_BOOL SetOpcodePacketFlag;
++ SK_U32 HighAddress;
++ SK_U32 LowAddress;
++ SK_U16 TcpSumStart;
++ SK_U16 TcpSumWrite;
++ SK_U8 OpCode;
++ SK_U8 Ctrl;
++ unsigned long Flags;
++ unsigned long LockFlag;
++ int Protocol;
++#ifdef NETIF_F_TSO
++ SK_U16 Mss;
++ int TcpOptLen;
++ int IpTcpLen;
++#endif
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
++ ("==> GiveTxBufferToHw\n"));
++
++ if (IS_Q_EMPTY(&(pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_waiting))) {
++ return;
++ }
++
++ spin_lock_irqsave(&pAC->TxQueueLock, LockFlag);
++
++ /*
++ ** Initialize queue settings
++ */
++ pWorkQueue = &(pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_working);
++ pWaitQueue = &(pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_waiting);
++ pLETab = &(pAC->TxPort[Port][TX_PRIO_LOW].TxALET);
++
++ POP_FIRST_PKT_FROM_QUEUE(pWaitQueue, pSkPacket);
++ while (pSkPacket != NULL) {
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
++ ("\tWe have a packet to send %p\n", pSkPacket));
++
++ /*
++ ** the first frag of a packet gets opcode OP_PACKET
++ */
++ SetOpcodePacketFlag = SK_TRUE;
++ pFrag = pSkPacket->pFrag;
++
++ /*
++ ** fill list elements with data from fragments
++ */
++ while (pFrag != NULL) {
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
++ ("\tGet LE\n"));
++#ifdef NETIF_F_TSO
++ Mss = skb_shinfo(pSkPacket->pMBuf)->tso_size;
++ if (Mss) {
++ TcpOptLen = ((pSkPacket->pMBuf->h.th->doff - 5) * 4);
++ IpTcpLen = ((pSkPacket->pMBuf->nh.iph->ihl * 4) +
++ sizeof(struct tcphdr));
++ Mss += (TcpOptLen + IpTcpLen + C_LEN_ETHERMAC_HEADER);
++ }
++ if (pLETab->Bmu.RxTx.MssValue != Mss) {
++ pLETab->Bmu.RxTx.MssValue = Mss;
++ /* Take a new LE for TSO from the table */
++ GET_TX_LE(pLE, pLETab);
++
++#if 0
++ if(pSkPacket->VlanId) {
++ TXLE_SET_OPC(pLE, OP_LRGLENVLAN | HW_OWNER);
++ TXLE_SET_VLAN(pLE, pSkPacket->VlanId);
++ pSkPacket->VlanId = 0;
++ Ctrl |= INS_VLAN;
++ } else {
++#endif
++ TXLE_SET_OPC(pLE, OP_LRGLEN | HW_OWNER);
++#if 0
++ }
++#endif
++ /* set maximum segment size for new packet */
++ TXLE_SET_LSLEN(pLE, pLETab->Bmu.RxTx.MssValue);
++ FLUSH_OPC(pLE) ;
++ }
++#endif
++ GET_TX_LE(pLE, pLETab);
++ Ctrl = 0;
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
++ ("\tGot empty LE %p idx %d\n", pLE, GET_PUT_IDX(pLETab)));
++
++ SK_DBG_DUMP_TX_LE(pLE);
++
++ LowAddress = (SK_U32) (pFrag->pPhys & 0xffffffff);
++ HighAddress = (SK_U32) (pFrag->pPhys >> 32);
++
++ if (HighAddress != pLETab->BufHighAddr) {
++ /* set opcode high part of the address in one LE */
++ OpCode = OP_ADDR64 | HW_OWNER;
++
++ /* Set now the 32 high bits of the address */
++ TXLE_SET_ADDR( pLE, HighAddress);
++
++ /* Set the opcode into the LE */
++ TXLE_SET_OPC(pLE, OpCode);
++
++ /* Flush the LE to memory */
++ FLUSH_OPC(pLE);
++
++ /* remember the HighAddress we gave to the Hardware */
++ pLETab->BufHighAddr = HighAddress;
++
++ /* get a new LE because we filled one with high address */
++ GET_TX_LE(pLE, pLETab);
++ }
++
++ /*
++ ** TCP checksum offload
++ */
++ if ((pSkPacket->pMBuf->ip_summed == CHECKSUM_HW) &&
++ (SetOpcodePacketFlag == SK_TRUE)) {
++ Protocol = ((SK_U8)pSkPacket->pMBuf->data[C_OFFSET_IPPROTO] & 0xff);
++ /* if (Protocol & C_PROTO_ID_IP) { Ctrl = 0; } */
++ if (Protocol & C_PROTO_ID_TCP) {
++ Ctrl = CALSUM | WR_SUM | INIT_SUM | LOCK_SUM;
++ /* TCP Checksum Calculation Start Position */
++ TcpSumStart = C_LEN_ETHERMAC_HEADER + IP_HDR_LEN;
++ /* TCP Checksum Write Position */
++ TcpSumWrite = TcpSumStart + TCP_CSUM_OFFS;
++ } else {
++ Ctrl = UDPTCP | CALSUM | WR_SUM | INIT_SUM | LOCK_SUM;
++ /* TCP Checksum Calculation Start Position */
++ TcpSumStart = ETHER_MAC_HDR_LEN + IP_HDR_LEN;
++ /* UDP Checksum Write Position */
++ TcpSumWrite = TcpSumStart + UDP_CSUM_OFFS;
++ }
++
++ if ((Ctrl) && (pLETab->Bmu.RxTx.TcpWp != TcpSumWrite)) {
++ /* Update the last value of the write position */
++ pLETab->Bmu.RxTx.TcpWp = TcpSumWrite;
++
++ /* Set the Lock field for this LE: */
++ /* Checksum calculation for one packet only */
++ TXLE_SET_LCKCS(pLE, 1);
++
++ /* Set the start position for checksum. */
++ TXLE_SET_STACS(pLE, TcpSumStart);
++
++ /* Set the position where the checksum will be writen */
++ TXLE_SET_WRICS(pLE, TcpSumWrite);
++
++ /* Set the initial value for checksum */
++ /* PseudoHeader CS passed from Linux -> 0! */
++ TXLE_SET_INICS(pLE, 0);
++
++ /* Set the opcode for tcp checksum */
++ TXLE_SET_OPC(pLE, OP_TCPLISW | HW_OWNER);
++
++ /* Flush the LE to memory */
++ FLUSH_OPC(pLE);
++
++ /* get a new LE because we filled one with data for checksum */
++ GET_TX_LE(pLE, pLETab);
++ }
++ } /* end TCP offload handling */
++
++ TXLE_SET_ADDR(pLE, LowAddress);
++ TXLE_SET_LEN(pLE, pFrag->FragLen);
++
++ if (SetOpcodePacketFlag){
++#ifdef NETIF_F_TSO
++ if (Mss) {
++ OpCode = OP_LARGESEND | HW_OWNER;
++ } else {
++#endif
++ OpCode = OP_PACKET| HW_OWNER;
++#ifdef NETIF_F_TSO
++ }
++#endif
++ SetOpcodePacketFlag = SK_FALSE;
++ } else {
++ /* Follow packet in a sequence has always OP_BUFFER */
++ OpCode = OP_BUFFER | HW_OWNER;
++ }
++
++ /* Check if the low address is near the upper limit. */
++ CHECK_LOW_ADDRESS(pLETab->BufHighAddr, LowAddress, pFrag->FragLen);
++
++ pFrag = pFrag->pNext;
++ if (pFrag == NULL) {
++ /* mark last fragment */
++ Ctrl |= EOP;
++ }
++ TXLE_SET_CTRL(pLE, Ctrl);
++ TXLE_SET_OPC(pLE, OpCode);
++ FLUSH_OPC(pLE);
++
++ SK_DBG_DUMP_TX_LE(pLE);
++ }
++
++ /*
++ ** Remember next LE for tx complete
++ */
++ pSkPacket->NextLE = GET_PUT_IDX(pLETab);
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
++ ("\tNext LE for pkt %p is %d\n", pSkPacket, pSkPacket->NextLE));
++
++ /*
++ ** Add packet to working packets queue
++ */
++ PUSH_PKT_AS_LAST_IN_QUEUE(pWorkQueue, pSkPacket);
++
++ /*
++ ** give transmit start command
++ */
++ if (HW_FEATURE(pAC, HWF_WA_DEV_42)) {
++ spin_lock(&pAC->SetPutIndexLock);
++ SkGeY2SetPutIndex(pAC, pAC->IoBase, Y2_PREF_Q_ADDR(Q_XA1,0), &pAC->TxPort[0][0].TxALET);
++ spin_unlock(&pAC->SetPutIndexLock);
++ } else {
++ /* write put index */
++ if (Port == 0) {
++ SK_OUT32(pAC->IoBase,
++ Y2_PREF_Q_ADDR(Q_XA1,PREF_UNIT_PUT_IDX_REG),
++ GET_PUT_IDX(&pAC->TxPort[0][0].TxALET));
++ UPDATE_HWPUT_IDX(&pAC->TxPort[0][0].TxALET);
++ } else {
++ SK_OUT32(pAC->IoBase,
++ Y2_PREF_Q_ADDR(Q_XA2, PREF_UNIT_PUT_IDX_REG),
++ GET_PUT_IDX(&pAC->TxPort[1][0].TxALET));
++ UPDATE_HWPUT_IDX(&pAC->TxPort[1][0].TxALET);
++ }
++ }
++
++ if (IS_Q_EMPTY(&(pAC->TxPort[Port][TX_PRIO_LOW].TxAQ_waiting))) {
++ break; /* get out of while */
++ }
++ POP_FIRST_PKT_FROM_QUEUE(pWaitQueue, pSkPacket);
++ } /* while (pSkPacket != NULL) */
++
++ spin_unlock_irqrestore(&pAC->TxQueueLock, LockFlag);
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
++ ("<== GiveTxBufferToHw\n"));
++ return;
++} /* GiveTxBufferToHw */
++
++/***********************************************************************
++ *
++ * GiveRxBufferToHw - commits a previously allocated DMA area to HW
++ *
++ * Description:
++ * This functions gives receive buffers to HW. If no list elements
++ * are available the buffers will be queued.
++ *
++ * Notes:
++ * This function can run only once in a system at one time.
++ *
++ * Returns: N/A
++ */
++static void GiveRxBufferToHw(
++SK_AC *pAC, /* pointer to adapter control context */
++SK_IOC IoC, /* I/O control context (address of registers) */
++int Port, /* port index for which the buffer is used */
++SK_PACKET *pPacket) /* receive buffer(s) */
++{
++ SK_HWLE *pLE;
++ SK_LE_TABLE *pLETab;
++ SK_BOOL Done = SK_FALSE; /* at least on LE changed? */
++ SK_U32 LowAddress;
++ SK_U32 HighAddress;
++ SK_U32 PrefetchReg; /* register for Put index */
++ unsigned NumFree;
++ unsigned Required;
++ unsigned long Flags;
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,
++ ("==> GiveRxBufferToHw(Port %c, Packet %p)\n", 'A' + Port, pPacket));
++
++ pLETab = &pAC->RxPort[Port].RxLET;
++
++ if (Port == 0) {
++ PrefetchReg = Y2_PREF_Q_ADDR(Q_R1, PREF_UNIT_PUT_IDX_REG);
++ } else {
++ PrefetchReg = Y2_PREF_Q_ADDR(Q_R2, PREF_UNIT_PUT_IDX_REG);
++ }
++
++ if (pPacket != NULL) {
++ /*
++ ** For the time being, we have only one packet passed
++ ** to this function which might be changed in future!
++ */
++ PUSH_PKT_AS_LAST_IN_QUEUE(&pAC->RxPort[Port].RxQ_waiting, pPacket);
++ }
++
++ /*
++ ** now pPacket contains the very first waiting packet
++ */
++ POP_FIRST_PKT_FROM_QUEUE(&pAC->RxPort[Port].RxQ_waiting, pPacket);
++ while (pPacket != NULL) {
++ if (HW_FEATURE(pAC, HWF_WA_DEV_420)) {
++ if (NbrRxBuffersInHW >= MAX_NBR_RX_BUFFERS_IN_HW) {
++ PUSH_PKT_AS_FIRST_IN_QUEUE(&pAC->RxPort[Port].RxQ_waiting, pPacket);
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,
++ ("<== GiveRxBufferToHw()\n"));
++ return;
++ }
++ NbrRxBuffersInHW++;
++ }
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,
++ ("Try to add packet %p\n", pPacket));
++
++ /*
++ ** Check whether we have enough listelements:
++ **
++ ** we have to take into account that each fragment
++ ** may need an additional list element for the high
++ ** part of the address here I simplified it by
++ ** using MAX_FRAG_OVERHEAD maybe it's worth to split
++ ** this constant for Rx and Tx or to calculate the
++ ** real number of needed LE's
++ */
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,
++ ("\tNum %d Put %d Done %d Free %d %d\n",
++ pLETab->Num, pLETab->Put, pLETab->Done,
++ NUM_FREE_LE_IN_TABLE(pLETab),
++ (NUM_FREE_LE_IN_TABLE(pLETab))));
++
++ Required = pPacket->NumFrags + MAX_FRAG_OVERHEAD;
++ NumFree = NUM_FREE_LE_IN_TABLE(pLETab);
++ if (NumFree) {
++ NumFree--;
++ }
++
++ if (Required > NumFree ) {
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV,
++ SK_DBGCAT_DRV_RX_PROGRESS | SK_DBGCAT_DRV_ERROR,
++ ("\tOut of LEs have %d need %d\n",
++ NumFree, Required));
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,
++ ("\tWaitQueue starts with packet %p\n", pPacket));
++ PUSH_PKT_AS_FIRST_IN_QUEUE(&pAC->RxPort[Port].RxQ_waiting, pPacket);
++ if (Done) {
++ /*
++ ** write Put index to BMU or Polling Unit and make the LE's
++ ** available for the hardware
++ */
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,
++ ("\tWrite new Put Idx\n"));
++
++ SK_OUT32(IoC, PrefetchReg, GET_PUT_IDX(pLETab));
++ UPDATE_HWPUT_IDX(pLETab);
++ }
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,
++ ("<== GiveRxBufferToHw()\n"));
++ return;
++ } else {
++ if (!AllocAndMapRxBuffer(pAC, pPacket, Port)) {
++ /*
++ ** Failure while allocating sk_buff might
++ ** be due to temporary short of resources
++ ** Maybe next time buffers are available.
++ ** Until this, the packet remains in the
++ ** RX waiting queue...
++ */
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV,
++ SK_DBGCAT_DRV_RX_PROGRESS | SK_DBGCAT_DRV_ERROR,
++ ("Failed to allocate Rx buffer\n"));
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,
++ ("WaitQueue starts with packet %p\n", pPacket));
++ PUSH_PKT_AS_FIRST_IN_QUEUE(&pAC->RxPort[Port].RxQ_waiting, pPacket);
++ if (Done) {
++ /*
++ ** write Put index to BMU or Polling
++ ** Unit and make the LE's
++ ** available for the hardware
++ */
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,
++ ("\tWrite new Put Idx\n"));
++
++ SK_OUT32(IoC, PrefetchReg, GET_PUT_IDX(pLETab));
++ UPDATE_HWPUT_IDX(pLETab);
++ }
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,
++ ("<== GiveRxBufferToHw()\n"));
++ return;
++ }
++ }
++ Done = SK_TRUE;
++
++ LowAddress = (SK_U32) (pPacket->pFrag->pPhys & 0xffffffff);
++ HighAddress = (SK_U32) (pPacket->pFrag->pPhys >> 32);
++ if (HighAddress != pLETab->BufHighAddr) {
++ /* get a new LE for high address */
++ GET_RX_LE(pLE, pLETab);
++
++ /* Set now the 32 high bits of the address */
++ RXLE_SET_ADDR(pLE, HighAddress);
++
++ /* Set the control bits of the address */
++ RXLE_SET_CTRL(pLE, 0);
++
++ /* Set the opcode into the LE */
++ RXLE_SET_OPC(pLE, (OP_ADDR64 | HW_OWNER));
++
++ /* Flush the LE to memory */
++ FLUSH_OPC(pLE);
++
++ /* remember the HighAddress we gave to the Hardware */
++ pLETab->BufHighAddr = HighAddress;
++ }
++
++ /*
++ ** Fill data into listelement
++ */
++ GET_RX_LE(pLE, pLETab);
++ RXLE_SET_ADDR(pLE, LowAddress);
++ RXLE_SET_LEN(pLE, pPacket->pFrag->FragLen);
++ RXLE_SET_CTRL(pLE, 0);
++ RXLE_SET_OPC(pLE, (OP_PACKET | HW_OWNER));
++ FLUSH_OPC(pLE);
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,
++ ("=== LE filled\n"));
++
++ SK_DBG_DUMP_RX_LE(pLE);
++
++ /*
++ ** Remember next LE for rx complete
++ */
++ pPacket->NextLE = GET_PUT_IDX(pLETab);
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,
++ ("\tPackets Next LE is %d\n", pPacket->NextLE));
++
++ /*
++ ** Add packet to working receive buffer queue and get
++ ** any next packet out of the waiting queue
++ */
++ PUSH_PKT_AS_LAST_IN_QUEUE(&pAC->RxPort[Port].RxQ_working, pPacket);
++ if (IS_Q_EMPTY(&(pAC->RxPort[Port].RxQ_waiting))) {
++ break; /* get out of while processing */
++ }
++ POP_FIRST_PKT_FROM_QUEUE(&pAC->RxPort[Port].RxQ_waiting, pPacket);
++ }
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,
++ ("\tWaitQueue is empty\n"));
++
++ if (Done) {
++ /*
++ ** write Put index to BMU or Polling Unit and make the LE's
++ ** available for the hardware
++ */
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,
++ ("\tWrite new Put Idx\n"));
++
++ /* Speed enhancement for a2 chipsets */
++ if (HW_FEATURE(pAC, HWF_WA_DEV_42)) {
++ spin_lock_irqsave(&pAC->SetPutIndexLock, Flags);
++ SkGeY2SetPutIndex(pAC, pAC->IoBase, Y2_PREF_Q_ADDR(Q_R1,0), pLETab);
++ spin_unlock_irqrestore(&pAC->SetPutIndexLock, Flags);
++ } else {
++ /* write put index */
++ if (Port == 0) {
++ SK_OUT32(IoC,
++ Y2_PREF_Q_ADDR(Q_R1, PREF_UNIT_PUT_IDX_REG),
++ GET_PUT_IDX(pLETab));
++ } else {
++ SK_OUT32(IoC,
++ Y2_PREF_Q_ADDR(Q_R2, PREF_UNIT_PUT_IDX_REG),
++ GET_PUT_IDX(pLETab));
++ }
++
++ /* Update put index */
++ UPDATE_HWPUT_IDX(pLETab);
++ }
++ }
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,
++ ("<== GiveRxBufferToHw()\n"));
++} /* GiveRxBufferToHw */
++
++/***********************************************************************
++ *
++ * FillReceiveTableYukon2 - map any waiting RX buffers to HW
++ *
++ * Description:
++ * If the list element table contains more empty elements than
++ * specified this function tries to refill them.
++ *
++ * Notes:
++ * This function can run only once per port in a system at one time.
++ *
++ * Returns: N/A
++ */
++void FillReceiveTableYukon2(
++SK_AC *pAC, /* pointer to adapter control context */
++SK_IOC IoC, /* I/O control context */
++int Port) /* port index of RX */
++{
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,
++ ("==> FillReceiveTableYukon2 (Port %c)\n", 'A' + Port));
++
++ if (NUM_FREE_LE_IN_TABLE(&pAC->RxPort[Port].RxLET) >
++ pAC->MaxUnusedRxLeWorking) {
++
++ /*
++ ** Give alle waiting receive buffers down
++ ** The queue holds all RX packets that
++ ** need a fresh allocation of the sk_buff.
++ */
++ if (pAC->RxPort[Port].RxQ_waiting.pHead != NULL) {
++ SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,
++ ("Waiting queue is not empty -> give it to HW"));
++ GiveRxBufferToHw(pAC, IoC, Port, NULL);
++ }
++ }
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,
++ ("<== FillReceiveTableYukon2 ()\n"));
++} /* FillReceiveTableYukon2 */
++
++/******************************************************************************
++ *
++ *
++ * HandleReceives - will pass any ready RX packet to kernel
++ *
++ * Description:
++ * This functions handles a received packet. It checks wether it is
++ * valid, updates the receive list element table and gives the receive
++ * buffer to Linux
++ *
++ * Notes:
++ * This function can run only once per port at one time in the system.
++ *
++ * Returns: N/A
++ */
++static SK_BOOL HandleReceives(
++SK_AC *pAC, /* adapter control context */
++int Port, /* port on which a packet has been received */
++SK_U16 Len, /* number of bytes which was actually received */
++SK_U32 FrameStatus, /* MAC frame status word */
++SK_U16 Tcp1, /* first hw checksum */
++SK_U16 Tcp2, /* second hw checksum */
++SK_U32 Tist, /* timestamp */
++SK_U16 Vlan) /* Vlan Id */
++{
++
++ SK_PACKET *pSkPacket;
++ SK_LE_TABLE *pLETab;
++ SK_MBUF *pRlmtMbuf; /* buffer for giving RLMT frame */
++ struct sk_buff *pMsg; /* ptr to message holding frame */
++#ifdef __ia64__
++ struct sk_buff *pNewMsg; /* used when IP aligning */
++#endif
++
++#ifdef CONFIG_SK98LIN_NAPI
++ SK_BOOL SlowPathLock = SK_FALSE;
++#else
++ SK_BOOL SlowPathLock = SK_TRUE;
++#endif
++ SK_BOOL IsGoodPkt;
++ SK_BOOL IsBc;
++ SK_BOOL IsMc;
++ SK_EVPARA EvPara; /* an event parameter union */
++ SK_I16 LenToFree; /* must be signed integer */
++
++ unsigned long Flags; /* for spin lock */
++ unsigned int RlmtNotifier;
++ unsigned short Type;
++ int IpFrameLength;
++ int FrameLength; /* total length of recvd frame */
++ int HeaderLength;
++ int NumBytes;
++ int Result;
++ int Offset = 0;
++
++#ifdef Y2_SYNC_CHECK
++ SK_U16 MyTcp;
++#endif
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,
++ ("==> HandleReceives (Port %c)\n", 'A' + Port));
++
++ /*
++ ** initialize vars for selected port
++ */
++ pLETab = &pAC->RxPort[Port].RxLET;
++
++ /*
++ ** check whether we want to receive this packet
++ */
++ SK_Y2_RXSTAT_CHECK_PKT(Len, FrameStatus, IsGoodPkt);
++
++ /*
++ ** Remember length to free (in case of RxBuffer overruns;
++ ** unlikely, but might happen once in a while)
++ */
++ LenToFree = (SK_I16) Len;
++
++ /*
++ ** maybe we put these two checks into the SK_RXDESC_CHECK_PKT macro too
++ */
++ if (Len > pAC->RxPort[Port].RxBufSize) {
++ IsGoodPkt = SK_FALSE;
++ }
++
++ /*
++ ** take first receive buffer out of working queue
++ */
++ POP_FIRST_PKT_FROM_QUEUE(&pAC->RxPort[Port].RxQ_working, pSkPacket);
++ if (pSkPacket == NULL) {
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV,
++ SK_DBGCAT_DRV_ERROR,
++ ("Packet not available. NULL pointer.\n"));
++ return(SK_TRUE);
++ }
++
++ if (HW_FEATURE(pAC, HWF_WA_DEV_420)) {
++ NbrRxBuffersInHW--;
++ }
++
++ /*
++ ** Verify the received length of the frame! Note that having
++ ** multiple RxBuffers being aware of one single receive packet
++ ** (one packet spread over multiple RxBuffers) is not supported
++ ** by this driver!
++ */
++ if ((Len > pAC->RxPort[Port].RxBufSize) ||
++ (Len > (SK_U16) pSkPacket->PacketLen)) {
++ IsGoodPkt = SK_FALSE;
++ }
++
++ /*
++ ** Reset own bit in LE's between old and new Done index
++ ** This is not really necessary but makes debugging easier
++ */
++ CLEAR_LE_OWN_FROM_DONE_TO(pLETab, pSkPacket->NextLE);
++
++ /*
++ ** Free the list elements for new Rx buffers
++ */
++ SET_DONE_INDEX(pLETab, pSkPacket->NextLE);
++ pMsg = pSkPacket->pMBuf;
++ FrameLength = Len;
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,
++ ("Received frame of length %d on port %d\n",FrameLength, Port));
++
++ if (!IsGoodPkt) {
++ /*
++ ** release the DMA mapping
++ */
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5)
++ pci_dma_sync_single(pAC->PciDev,
++ (dma_addr_t) pSkPacket->pFrag->pPhys,
++ pSkPacket->pFrag->FragLen,
++ PCI_DMA_FROMDEVICE);
++
++#else
++ pci_dma_sync_single_for_cpu(pAC->PciDev,
++ (dma_addr_t) pSkPacket->pFrag->pPhys,
++ pSkPacket->pFrag->FragLen,
++ PCI_DMA_FROMDEVICE);
++#endif
++
++ DEV_KFREE_SKB_ANY(pSkPacket->pMBuf);
++ PUSH_PKT_AS_LAST_IN_QUEUE(&pAC->RxPort[Port].RxQ_waiting, pSkPacket);
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,
++ ("<== HandleReceives (Port %c)\n", 'A' + Port));
++
++ /*
++ ** Sanity check for RxBuffer overruns...
++ */
++ LenToFree = LenToFree - (pSkPacket->pFrag->FragLen);
++ while (LenToFree > 0) {
++ POP_FIRST_PKT_FROM_QUEUE(&pAC->RxPort[Port].RxQ_working, pSkPacket);
++ if (HW_FEATURE(pAC, HWF_WA_DEV_420)) {
++ NbrRxBuffersInHW--;
++ }
++ CLEAR_LE_OWN_FROM_DONE_TO(pLETab, pSkPacket->NextLE);
++ SET_DONE_INDEX(pLETab, pSkPacket->NextLE);
++#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5)
++ pci_dma_sync_single(pAC->PciDev,
++ (dma_addr_t) pSkPacket->pFrag->pPhys,
++ pSkPacket->pFrag->FragLen,
++ PCI_DMA_FROMDEVICE);
++#else
++ pci_dma_sync_single_for_device(pAC->PciDev,
++ (dma_addr_t) pSkPacket->pFrag->pPhys,
++ pSkPacket->pFrag->FragLen,
++ PCI_DMA_FROMDEVICE);
++#endif
++
++ DEV_KFREE_SKB_ANY(pSkPacket->pMBuf);
++ PUSH_PKT_AS_LAST_IN_QUEUE(&pAC->RxPort[Port].RxQ_waiting, pSkPacket);
++ LenToFree = LenToFree - ((SK_I16)(pSkPacket->pFrag->FragLen));
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV,
++ SK_DBGCAT_DRV_RX_PROGRESS | SK_DBGCAT_DRV_ERROR,
++ ("<==HandleReceives (Port %c) drop faulty len pkt(2)\n",'A'+Port));
++ }
++ return(SK_TRUE);
++ } else {
++ /*
++ ** Release the DMA mapping
++ */
++ pci_unmap_single(pAC->PciDev,
++ pSkPacket->pFrag->pPhys,
++ pAC->RxPort[Port].RxBufSize,
++ PCI_DMA_FROMDEVICE);
++
++ skb_put(pMsg, FrameLength); /* set message len */
++ pMsg->ip_summed = CHECKSUM_NONE; /* initial default */
++
++#ifdef Y2_SYNC_CHECK
++ pAC->FramesWithoutSyncCheck++;
++ if (pAC->FramesWithoutSyncCheck > Y2_RESYNC_WATERMARK) {
++ if ((Tcp1 != 1) && (Tcp2 != 0)) {
++ pAC->FramesWithoutSyncCheck = 0;
++ MyTcp = (SK_U16) SkCsCalculateChecksum(
++ &pMsg->data[14],
++ FrameLength - 14);
++ if (MyTcp != Tcp1) {
++ /* Queue port reset event */
++ SkLocalEventQueue(pAC, SKGE_DRV,
++ SK_DRV_RECOVER,Port,-1,SK_FALSE);
++ }
++ }
++ }
++#endif
++
++ if (pAC->RxPort[Port].UseRxCsum) {
++ Type = ntohs(*((short*)&pMsg->data[12]));
++ if (Type == 0x800) {
++ *((char *)&(IpFrameLength)) = pMsg->data[16];
++ *(((char *)&(IpFrameLength))+1) = pMsg->data[17];
++ IpFrameLength = ntohs(IpFrameLength);
++ HeaderLength = FrameLength - IpFrameLength;
++ if (HeaderLength == 0xe) {
++ Result =
++ SkCsGetReceiveInfo(pAC,&pMsg->data[14],Tcp1,Tcp2, Port);
++ if ((Result == SKCS_STATUS_IP_FRAGMENT) ||
++ (Result == SKCS_STATUS_IP_CSUM_OK) ||
++ (Result == SKCS_STATUS_TCP_CSUM_OK) ||
++ (Result == SKCS_STATUS_UDP_CSUM_OK)) {
++ pMsg->ip_summed = CHECKSUM_UNNECESSARY;
++ } else if ((Result == SKCS_STATUS_TCP_CSUM_ERROR) ||
++ (Result == SKCS_STATUS_UDP_CSUM_ERROR) ||
++ (Result == SKCS_STATUS_IP_CSUM_ERROR_UDP) ||
++ (Result == SKCS_STATUS_IP_CSUM_ERROR_TCP) ||
++ (Result == SKCS_STATUS_IP_CSUM_ERROR)) {
++ SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
++ SK_DBGCAT_DRV_RX_PROGRESS | SK_DBGCAT_DRV_ERROR,
++ ("skge: CRC error. Frame dropped!\n"));
++ DEV_KFREE_SKB_ANY(pMsg);
++ PUSH_PKT_AS_LAST_IN_QUEUE(&pAC->RxPort[Port].RxQ_waiting, pSkPacket);
++ SK_DBG_MSG(pAC,SK_DBGMOD_DRV,SK_DBGCAT_DRV_RX_PROGRESS,
++ ("<==HandleReceives(Port %c)\n",'A'+Port));
++ return(SK_TRUE);
++ } else {
++ pMsg->ip_summed = CHECKSUM_NONE;
++ }
++ } /* end if (HeaderLength == valid) */
++ } /* end if (Type == 0x800) -> IP frame */
++ } /* end if (pRxPort->UseRxCsum) */
++
++ SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
++ SK_DBGCAT_DRV_RX_PROGRESS,("V"));
++ RlmtNotifier = SK_RLMT_RX_PROTOCOL;
++
++ IsBc = (FrameStatus & GMR_FS_BC) ? SK_TRUE : SK_FALSE;
++ SK_RLMT_PRE_LOOKAHEAD(pAC,Port,FrameLength,
++ IsBc,&Offset,&NumBytes);
++ if (NumBytes != 0) {
++ IsMc = (FrameStatus & GMR_FS_MC) ? SK_TRUE : SK_FALSE;
++ SK_RLMT_LOOKAHEAD(pAC,Port,&pMsg->data[Offset],
++ IsBc,IsMc,&RlmtNotifier);
++ }
++
++ if (RlmtNotifier == SK_RLMT_RX_PROTOCOL) {
++ SK_DBG_MSG(NULL,SK_DBGMOD_DRV,
++ SK_DBGCAT_DRV_RX_PROGRESS,("W"));
++ if ((Port == pAC->ActivePort)||(pAC->RlmtNets == 2)) {
++ /* send up only frames from active port */
++ SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
++ SK_DBGCAT_DRV_RX_PROGRESS,("U"));
++#ifdef xDEBUG
++ DumpMsg(pMsg, "Rx");
++#endif
++ SK_PNMI_CNT_RX_OCTETS_DELIVERED(pAC,
++ FrameLength, Port);
++#ifdef __ia64__
++ pNewMsg = alloc_skb(pMsg->len, GFP_ATOMIC);
++ skb_reserve(pNewMsg, 2); /* to align IP */
++ SK_MEMCPY(pNewMsg->data,pMsg->data,pMsg->len);
++ pNewMsg->ip_summed = pMsg->ip_summed;
++ skb_put(pNewMsg, pMsg->len);
++ DEV_KFREE_SKB_ANY(pMsg);
++ pMsg = pNewMsg;
++#endif
++ pMsg->dev = pAC->dev[Port];
++ pMsg->protocol = eth_type_trans(pMsg,
++ pAC->dev[Port]);
++ netif_rx(pMsg);
++ pAC->dev[Port]->last_rx = jiffies;
++ } else { /* drop frame */
++ SK_DBG_MSG(NULL,SK_DBGMOD_DRV,
++ SK_DBGCAT_DRV_RX_PROGRESS,("D"));
++ DEV_KFREE_SKB_ANY(pMsg);
++ }
++ } else { /* This is an RLMT-packet! */
++ SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
++ SK_DBGCAT_DRV_RX_PROGRESS,("R"));
++ pRlmtMbuf = SkDrvAllocRlmtMbuf(pAC,
++ pAC->IoBase, FrameLength);
++ if (pRlmtMbuf != NULL) {
++ pRlmtMbuf->pNext = NULL;
++ pRlmtMbuf->Length = FrameLength;
++ pRlmtMbuf->PortIdx = Port;
++ EvPara.pParaPtr = pRlmtMbuf;
++ SK_MEMCPY((char*)(pRlmtMbuf->pData),
++ (char*)(pMsg->data),FrameLength);
++
++ if (SlowPathLock == SK_TRUE) {
++ spin_lock_irqsave(&pAC->SlowPathLock, Flags);
++ SkEventQueue(pAC, SKGE_RLMT,
++ SK_RLMT_PACKET_RECEIVED,
++ EvPara);
++ pAC->CheckQueue = SK_TRUE;
++ spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
++ } else {
++ SkEventQueue(pAC, SKGE_RLMT,
++ SK_RLMT_PACKET_RECEIVED,
++ EvPara);
++ pAC->CheckQueue = SK_TRUE;
++ }
++
++ SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
++ SK_DBGCAT_DRV_RX_PROGRESS,("Q"));
++ }
++ if (pAC->dev[Port]->flags & (IFF_PROMISC | IFF_ALLMULTI)) {
++#ifdef __ia64__
++ pNewMsg = alloc_skb(pMsg->len, GFP_ATOMIC);
++ skb_reserve(pNewMsg, 2); /* to align IP */
++ SK_MEMCPY(pNewMsg->data,pMsg->data,pMsg->len);
++ pNewMsg->ip_summed = pMsg->ip_summed;
++ pNewMsg->len = pMsg->len;
++ DEV_KFREE_SKB_ANY(pMsg);
++ pMsg = pNewMsg;
++#endif
++ pMsg->dev = pAC->dev[Port];
++ pMsg->protocol = eth_type_trans(pMsg,pAC->dev[Port]);
++ netif_rx(pMsg);
++ pAC->dev[Port]->last_rx = jiffies;
++ } else {
++ DEV_KFREE_SKB_ANY(pMsg);
++ }
++ } /* if packet for rlmt */
++ PUSH_PKT_AS_LAST_IN_QUEUE(&pAC->RxPort[Port].RxQ_waiting, pSkPacket);
++ } /* end if-else (IsGoodPkt) */
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,
++ ("<== HandleReceives (Port %c)\n", 'A' + Port));
++ return(SK_TRUE);
++
++} /* HandleReceives */
++
++/***********************************************************************
++ *
++ * CheckForSendComplete - Frees any freeable Tx bufffer
++ *
++ * Description:
++ * This function checks the queues of a port for completed send
++ * packets and returns these packets back to the OS.
++ *
++ * Notes:
++ * This function can run simultaneously for both ports if
++ * the OS function OSReturnPacket() can handle this,
++ *
++ * Such a send complete does not mean, that the packet is really
++ * out on the wire. We just know that the adapter has copied it
++ * into its internal memory and the buffer in the systems memory
++ * is no longer needed.
++ *
++ * Returns: N/A
++ */
++static void CheckForSendComplete(
++SK_AC *pAC, /* pointer to adapter control context */
++SK_IOC IoC, /* I/O control context */
++int Port, /* port index */
++SK_PKT_QUEUE *pPQ, /* tx working packet queue to check */
++SK_LE_TABLE *pLETab, /* corresponding list element table */
++unsigned int Done) /* done index reported for this LET */
++{
++ SK_PACKET *pSkPacket;
++ SK_PKT_QUEUE SendCmplPktQ = { NULL, NULL, SPIN_LOCK_UNLOCKED };
++ SK_BOOL DoWakeQueue = SK_FALSE;
++ unsigned long Flags;
++ unsigned Put;
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
++ ("==> CheckForSendComplete(Port %c)\n", 'A' + Port));
++
++ /*
++ ** Reset own bit in LE's between old and new Done index
++ ** This is not really necessairy but makes debugging easier
++ */
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
++ ("Clear Own Bits in TxTable from %d to %d\n",
++ pLETab->Done, (Done == 0) ?
++ NUM_LE_IN_TABLE(pLETab) :
++ (Done - 1)));
++
++ spin_lock_irqsave(&(pPQ->QueueLock), Flags);
++
++ CLEAR_LE_OWN_FROM_DONE_TO(pLETab, Done);
++
++ Put = GET_PUT_IDX(pLETab);
++
++ /*
++ ** Check whether some packets have been completed
++ */
++ PLAIN_POP_FIRST_PKT_FROM_QUEUE(pPQ, pSkPacket);
++ while (pSkPacket != NULL) {
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
++ ("Check Completion of Tx packet %p\n", pSkPacket));
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
++ ("Put %d NewDone %d NextLe of Packet %d\n", Put, Done,
++ pSkPacket->NextLE));
++
++ if ((Put > Done) &&
++ ((pSkPacket->NextLE > Put) || (pSkPacket->NextLE <= Done))) {
++ PLAIN_PUSH_PKT_AS_LAST_IN_QUEUE(&SendCmplPktQ, pSkPacket);
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
++ ("Packet finished (a)\n"));
++ } else if ((Done > Put) &&
++ (pSkPacket->NextLE > Put) && (pSkPacket->NextLE <= Done)) {
++ PLAIN_PUSH_PKT_AS_LAST_IN_QUEUE(&SendCmplPktQ, pSkPacket);
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
++ ("Packet finished (b)\n"));
++ } else if ((Done == TXA_MAX_LE-1) && (Put == 0) && (pSkPacket->NextLE == 0)) {
++ PLAIN_PUSH_PKT_AS_LAST_IN_QUEUE(&SendCmplPktQ, pSkPacket);
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
++ ("Packet finished (b)\n"));
++ DoWakeQueue = SK_TRUE;
++ } else if (Done == Put) {
++ /* all packets have been sent */
++ PLAIN_PUSH_PKT_AS_LAST_IN_QUEUE(&SendCmplPktQ, pSkPacket);
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
++ ("Packet finished (c)\n"));
++ } else {
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
++ ("Packet not yet finished\n"));
++ PLAIN_PUSH_PKT_AS_FIRST_IN_QUEUE(pPQ, pSkPacket);
++ break;
++ }
++ PLAIN_POP_FIRST_PKT_FROM_QUEUE(pPQ, pSkPacket);
++ }
++ spin_unlock_irqrestore(&(pPQ->QueueLock), Flags);
++
++ /*
++ ** Set new done index in list element table
++ */
++ SET_DONE_INDEX(pLETab, Done);
++
++ /*
++ ** All TX packets that are send complete should be added to
++ ** the free queue again for new sents to come
++ */
++ pSkPacket = SendCmplPktQ.pHead;
++ while (pSkPacket != NULL) {
++ while (pSkPacket->pFrag != NULL) {
++ pci_unmap_page(pAC->PciDev,
++ (dma_addr_t) pSkPacket->pFrag->pPhys,
++ pSkPacket->pFrag->FragLen,
++ PCI_DMA_FROMDEVICE);
++ pSkPacket->pFrag = pSkPacket->pFrag->pNext;
++ }
++
++ DEV_KFREE_SKB_ANY(pSkPacket->pMBuf);
++ pSkPacket->pMBuf = NULL;
++ pSkPacket = pSkPacket->pNext; /* get next packet */
++ }
++
++ /*
++ ** Append the available TX packets back to free queue
++ */
++ if (SendCmplPktQ.pHead != NULL) {
++ spin_lock_irqsave(&(pAC->TxPort[Port][0].TxQ_free.QueueLock), Flags);
++ if (pAC->TxPort[Port][0].TxQ_free.pTail != NULL) {
++ pAC->TxPort[Port][0].TxQ_free.pTail->pNext = SendCmplPktQ.pHead;
++ pAC->TxPort[Port][0].TxQ_free.pTail = SendCmplPktQ.pTail;
++ if (pAC->TxPort[Port][0].TxQ_free.pHead->pNext == NULL) {
++ netif_wake_queue(pAC->dev[Port]);
++ }
++ } else {
++ pAC->TxPort[Port][0].TxQ_free.pHead = SendCmplPktQ.pHead;
++ pAC->TxPort[Port][0].TxQ_free.pTail = SendCmplPktQ.pTail;
++ netif_wake_queue(pAC->dev[Port]);
++ }
++ if (Done == Put) {
++ netif_wake_queue(pAC->dev[Port]);
++ }
++ if (DoWakeQueue) {
++ netif_wake_queue(pAC->dev[Port]);
++ DoWakeQueue = SK_FALSE;
++ }
++ spin_unlock_irqrestore(&pAC->TxPort[Port][0].TxQ_free.QueueLock, Flags);
++ }
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
++ ("<== CheckForSendComplete()\n"));
++
++ return;
++} /* CheckForSendComplete */
++
++/*****************************************************************************
++ *
++ * UnmapAndFreeTxPktBuffer
++ *
++ * Description:
++ * This function free any allocated space of receive buffers
++ *
++ * Arguments:
++ * pAC - A pointer to the adapter context struct.
++ *
++ */
++static void UnmapAndFreeTxPktBuffer(
++SK_AC *pAC, /* pointer to adapter context */
++SK_PACKET *pSkPacket, /* pointer to port struct of ring to fill */
++int TxPort) /* TX port index */
++{
++ SK_FRAG *pFrag = pSkPacket->pFrag;
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
++ ("--> UnmapAndFreeTxPktBuffer\n"));
++
++ while (pFrag != NULL) {
++ pci_unmap_page(pAC->PciDev,
++ (dma_addr_t) pFrag->pPhys,
++ pFrag->FragLen,
++ PCI_DMA_FROMDEVICE);
++ pFrag = pFrag->pNext;
++ }
++
++ DEV_KFREE_SKB_ANY(pSkPacket->pMBuf);
++ pSkPacket->pMBuf = NULL;
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS,
++ ("<-- UnmapAndFreeTxPktBuffer\n"));
++}
++
++/*****************************************************************************
++ *
++ * HandleStatusLEs
++ *
++ * Description:
++ * This function checks for any new status LEs that may have been
++ * received. Those status LEs may either be Rx or Tx ones.
++ *
++ * Returns: N/A
++ */
++static SK_BOOL HandleStatusLEs(
++#ifdef CONFIG_SK98LIN_NAPI
++SK_AC *pAC, /* pointer to adapter context */
++int *WorkDone, /* Done counter needed for NAPI */
++int WorkToDo) /* ToDo counter for NAPI */
++#else
++SK_AC *pAC) /* pointer to adapter context */
++#endif
++{
++ int DoneTxA[SK_MAX_MACS];
++ int DoneTxS[SK_MAX_MACS];
++ int Port;
++ SK_BOOL handledStatLE = SK_FALSE;
++ SK_BOOL NewDone = SK_FALSE;
++ SK_HWLE *pLE;
++ SK_U16 HighVal;
++ SK_U32 LowVal;
++ SK_U8 OpCode;
++ int i;
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,
++ ("==> HandleStatusLEs\n"));
++
++ do {
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,
++ ("Check next Own Bit of ST-LE[%d]: 0x%li \n",
++ (pAC->StatusLETable.Done + 1) % NUM_LE_IN_TABLE(&pAC->StatusLETable),
++ OWN_OF_FIRST_LE(&pAC->StatusLETable)));
++
++ while (OWN_OF_FIRST_LE(&pAC->StatusLETable) == HW_OWNER) {
++ GET_ST_LE(pLE, &pAC->StatusLETable);
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,
++ ("Working on finished status LE[%d]:\n",
++ GET_DONE_INDEX(&pAC->StatusLETable)));
++ SK_DBG_DUMP_ST_LE(pLE);
++ handledStatLE = SK_TRUE;
++ OpCode = STLE_GET_OPC(pLE) & ~HW_OWNER;
++ Port = STLE_GET_LINK(pLE);
++
++#ifdef USE_TIST_FOR_RESET
++ if (SK_ADAPTER_WAITING_FOR_TIST(pAC)) {
++ /* do we just have a tist LE ? */
++ if ((OpCode & OP_RXTIMESTAMP) == OP_RXTIMESTAMP) {
++ for (i = 0; i < pAC->GIni.GIMacsFound; i++) {
++ if (SK_PORT_WAITING_FOR_ANY_TIST(pAC, i)) {
++ /* if a port is waiting for any tist it is done */
++ SK_CLR_STATE_FOR_PORT(pAC, i);
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DUMP,
++ ("Got any Tist on port %c (now 0x%X!!!)\n",
++ 'A' + i, pAC->AdapterResetState));
++ }
++ if (SK_PORT_WAITING_FOR_SPECIFIC_TIST(pAC, i)) {
++ Y2_GET_TIST_LOW_VAL(pAC->IoBase, &LowVal);
++ if ((pAC->MinTistHi != pAC->GIni.GITimeStampCnt) ||
++ (pAC->MinTistLo < LowVal)) {
++ /* time is up now */
++ SK_CLR_STATE_FOR_PORT(pAC, i);
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DUMP,
++ ("Got expected Tist on Port %c (now 0x%X)!!!\n",
++ 'A' + i, pAC->AdapterResetState));
++#ifdef Y2_SYNC_CHECK
++ pAC->FramesWithoutSyncCheck =
++ Y2_RESYNC_WATERMARK;
++#endif
++ } else {
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DUMP,
++ ("Got Tist %l:%l on Port %c but still waiting\n",
++ pAC->GIni.GITimeStampCnt, pAC->MinTistLo,
++ 'A' + i));
++ }
++ }
++ }
++#ifndef Y2_RECOVERY
++ if (!SK_ADAPTER_WAITING_FOR_TIST(pAC)) {
++ /* nobody needs tist anymore - turn it off */
++ Y2_DISABLE_TIST(pAC->IoBase);
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DUMP,
++ ("Turn off Tist !!!\n"));
++ }
++#endif
++ } else if (OpCode == OP_TXINDEXLE) {
++ /*
++ * change OpCode to notify the folowing code
++ * to ignore the done index from this LE
++ * unfortunately tist LEs will be generated only
++ * for RxStat LEs
++ * so in order to get a safe Done index for a
++ * port currently waiting for a tist we have to
++ * get the done index directly from the BMU
++ */
++ OpCode = OP_MOD_TXINDEX;
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DUMP,
++ ("Mark unusable TX_INDEX LE!!!\n"));
++ } else {
++ if (SK_PORT_WAITING_FOR_TIST(pAC, Port)) {
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DUMP,
++ ("Ignore LE 0x%X on Port %c!!!\n",
++ OpCode, 'A' + Port));
++ OpCode = OP_MOD_LE;
++#ifdef Y2_LE_CHECK
++ /* mark entries invalid */
++ pAC->LastOpc = 0xFF;
++ pAC->LastPort = 3;
++#endif
++ }
++ }
++ } /* if (SK_ADAPTER_WAITING_FOR_TIST(pAC)) */
++#endif
++
++
++
++
++
++#ifdef Y2_LE_CHECK
++ if (pAC->LastOpc != 0xFF) {
++ /* last opc is valid
++ * check if current opcode follows last opcode
++ */
++ if ((((OpCode & OP_RXTIMESTAMP) == OP_RXTIMESTAMP) && (pAC->LastOpc != OP_RXSTAT)) ||
++ (((OpCode & OP_RXCHKS) == OP_RXCHKS) && (pAC->LastOpc != OP_RXTIMESTAMP)) ||
++ ((OpCode == OP_RXSTAT) && (pAC->LastOpc != OP_RXCHKS))) {
++
++ /* opcode sequence broken
++ * current LE is invalid
++ */
++
++ if (pAC->LastOpc == OP_RXTIMESTAMP) {
++ /* force invalid checksum */
++ pLE->St.StUn.StRxTCPCSum.RxTCPSum1 = 1;
++ pLE->St.StUn.StRxTCPCSum.RxTCPSum2 = 0;
++ OpCode = pAC->LastOpc = OP_RXCHKS;
++ Port = pAC->LastPort;
++ } else if (pAC->LastOpc == OP_RXCHKS) {
++ /* force invalid frame */
++ Port = pAC->LastPort;
++ pLE->St.Stat.BufLen = 64;
++ pLE->St.StUn.StRxStatWord = GMR_FS_CRC_ERR;
++ OpCode = pAC->LastOpc = OP_RXSTAT;
++#ifdef Y2_SYNC_CHECK
++ /* force rx sync check */
++ pAC->FramesWithoutSyncCheck = Y2_RESYNC_WATERMARK;
++#endif
++ } else if (pAC->LastOpc == OP_RXSTAT) {
++ /* create dont care tist */
++ pLE->St.StUn.StRxTimeStamp = 0;
++ OpCode = pAC->LastOpc = OP_RXTIMESTAMP;
++ /* dont know the port yet */
++ } else {
++#ifdef DEBUG
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,
++ ("Unknown LastOpc %X for Timestamp on port %c.\n",
++ pAC->LastOpc, Port));
++#endif
++ }
++ }
++ }
++#endif
++
++ switch (OpCode) {
++ case OP_RXSTAT:
++#ifdef Y2_RECOVERY
++ pAC->LastOpc = OP_RXSTAT;
++#endif
++ /*
++ ** This is always the last Status LE belonging
++ ** to a received packet -> handle it...
++ */
++ if ((Port != 0) && (Port != 1)) {
++ /* Unknown port */
++ panic("sk98lin: Unknown port %d\n",
++ Port);
++ }
++
++ HandleReceives(
++ pAC,
++ Port,
++ STLE_GET_LEN(pLE),
++ STLE_GET_FRSTATUS(pLE),
++ pAC->StatusLETable.Bmu.Stat.TcpSum1,
++ pAC->StatusLETable.Bmu.Stat.TcpSum2,
++ pAC->StatusLETable.Bmu.Stat.RxTimeStamp,
++ pAC->StatusLETable.Bmu.Stat.VlanId);
++#ifdef CONFIG_SK98LIN_NAPI
++ if (*WorkDone >= WorkToDo) {
++ break;
++ }
++ (*WorkDone)++;
++#endif
++ break;
++ case OP_RXVLAN:
++ /* this value will be used for next RXSTAT */
++ pAC->StatusLETable.Bmu.Stat.VlanId = STLE_GET_VLAN(pLE);
++ break;
++ case OP_RXTIMEVLAN:
++ /* this value will be used for next RXSTAT */
++ pAC->StatusLETable.Bmu.Stat.VlanId = STLE_GET_VLAN(pLE);
++ /* fall through */
++ case OP_RXTIMESTAMP:
++ /* this value will be used for next RXSTAT */
++ pAC->StatusLETable.Bmu.Stat.RxTimeStamp = STLE_GET_TIST(pLE);
++#ifdef Y2_RECOVERY
++ pAC->LastOpc = OP_RXTIMESTAMP;
++ pAC->LastPort = Port;
++#endif
++ break;
++ case OP_RXCHKSVLAN:
++ /* this value will be used for next RXSTAT */
++ pAC->StatusLETable.Bmu.Stat.VlanId = STLE_GET_VLAN(pLE);
++ /* fall through */
++ case OP_RXCHKS:
++ /* this value will be used for next RXSTAT */
++ pAC->StatusLETable.Bmu.Stat.TcpSum1 = STLE_GET_TCP1(pLE);
++ pAC->StatusLETable.Bmu.Stat.TcpSum2 = STLE_GET_TCP2(pLE);
++#ifdef Y2_RECOVERY
++ pAC->LastPort = Port;
++ pAC->LastOpc = OP_RXCHKS;
++#endif
++ break;
++ case OP_RSS_HASH:
++ /* this value will be used for next RXSTAT */
++#if 0
++ pAC->StatusLETable.Bmu.Stat.RssHashValue = STLE_GET_RSS(pLE);
++#endif
++ break;
++ case OP_TXINDEXLE:
++ /*
++ ** :;:; TODO
++ ** it would be possible to check for which queues
++ ** the index has been changed and call
++ ** CheckForSendComplete() only for such queues
++ */
++ STLE_GET_DONE_IDX(pLE,LowVal,HighVal);
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,
++ ("LowVal: 0x%x HighVal: 0x%x\n", LowVal, HighVal));
++
++ /*
++ ** It would be possible to check whether we really
++ ** need the values for second port or sync queue,
++ ** but I think checking whether we need them is
++ ** more expensive than the calculation
++ */
++ DoneTxA[0] = STLE_GET_DONE_IDX_TXA1(LowVal,HighVal);
++ DoneTxS[0] = STLE_GET_DONE_IDX_TXS1(LowVal,HighVal);
++ DoneTxA[1] = STLE_GET_DONE_IDX_TXA2(LowVal,HighVal);
++ DoneTxS[1] = STLE_GET_DONE_IDX_TXS2(LowVal,HighVal);
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,
++ ("DoneTxa1 0x%x DoneTxS1: 0x%x DoneTxa2 0x%x DoneTxS2: 0x%x\n",
++ DoneTxA[0], DoneTxS[0], DoneTxA[1], DoneTxS[1]));
++
++ NewDone = SK_TRUE;
++ break;
++#ifdef USE_TIST_FOR_RESET
++ case OP_MOD_TXINDEX:
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DUMP,
++ ("OP_MOD_TXINDEX\n"));
++ SK_IN16(pAC->IoBase, Q_ADDR(Q_XA1, Q_DONE), &DoneTxA[0]);
++ if (pAC->GIni.GIMacsFound > 1) {
++ SK_IN16(pAC->IoBase, Q_ADDR(Q_XA2, Q_DONE), &DoneTxA[1]);
++ }
++ NewDone = SK_TRUE;
++ break;
++ case OP_MOD_LE:
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DUMP,
++ ("Ignore marked LE on port in Reset\n"));
++ break;
++#endif
++
++ default:
++ /*
++ ** Have to handle the illegal Opcode in Status LE
++ */
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,
++ ("Unexpected OpCode\n"));
++ break;
++ }
++
++#ifdef Y2_RECOVERY
++ OpCode = STLE_GET_OPC(pLE) & ~HW_OWNER;
++ STLE_SET_OPC(pLE, OpCode);
++#else
++ /*
++ ** Reset own bit we have to do this in order to detect a overflow
++ */
++ STLE_SET_OPC(pLE, SW_OWNER);
++#endif
++ } /* while (OWN_OF_FIRST_LE(&pAC->StatusLETable) == HW_OWNER) */
++
++ /*
++ ** Now handle any new transmit complete
++ */
++ if (NewDone) {
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,
++ ("Done Index for Tx BMU has been changed\n"));
++ for (Port = 0; Port < pAC->GIni.GIMacsFound; Port++) {
++ /*
++ ** Do we have a new Done idx ?
++ */
++ if (DoneTxA[Port] != GET_DONE_INDEX(&pAC->TxPort[Port][0].TxALET)) {
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,
++ ("Check TxA%d\n", Port + 1));
++ CheckForSendComplete(pAC, pAC->IoBase, Port,
++ &(pAC->TxPort[Port][0].TxAQ_working),
++ &pAC->TxPort[Port][0].TxALET,
++ DoneTxA[Port]);
++ } else {
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,
++ ("No changes for TxA%d\n", Port + 1));
++ }
++#if USE_SYNC_TX_QUEUE
++ if (HW_SYNC_TX_SUPPORTED(pAC)) {
++ /*
++ ** Do we have a new Done idx ?
++ */
++ if (DoneTxS[Port] !=
++ GET_DONE_INDEX(&pAC->TxPort[Port][0].TxSLET)) {
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV,
++ SK_DBGCAT_DRV_INT_SRC,
++ ("Check TxS%d\n", Port));
++ CheckForSendComplete(pAC, pAC->IoBase, Port,
++ &(pAC->TxPort[Port][0].TxSQ_working),
++ &pAC->TxPort[Port][0].TxSLET,
++ DoneTxS[Port]);
++ } else {
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV,
++ SK_DBGCAT_DRV_INT_SRC,
++ ("No changes for TxS%d\n", Port));
++ }
++ }
++#endif
++ }
++ }
++ NewDone = SK_FALSE;
++
++ /*
++ ** Check whether we have to refill our RX table
++ */
++ if (HW_FEATURE(pAC, HWF_WA_DEV_420)) {
++ if (NbrRxBuffersInHW < MAX_NBR_RX_BUFFERS_IN_HW) {
++ for (Port = 0; Port < pAC->GIni.GIMacsFound; Port++) {
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,
++ ("Check for refill of RxBuffers on Port %c\n", 'A' + Port));
++ FillReceiveTableYukon2(pAC, pAC->IoBase, Port);
++ }
++ }
++ } else {
++ for (Port = 0; Port < pAC->GIni.GIMacsFound; Port++) {
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC,
++ ("Check for refill of RxBuffers on Port %c\n", 'A' + Port));
++ if (NUM_FREE_LE_IN_TABLE(&pAC->RxPort[Port].RxLET) >= 64) {
++ FillReceiveTableYukon2(pAC, pAC->IoBase, Port);
++ }
++ }
++ }
++#ifdef CONFIG_SK98LIN_NAPI
++ if (*WorkDone >= WorkToDo) {
++ break;
++ }
++#endif
++ } while (OWN_OF_FIRST_LE(&pAC->StatusLETable) == HW_OWNER);
++
++ /*
++ ** Clear status BMU
++ */
++ SK_OUT32(pAC->IoBase, STAT_CTRL, SC_STAT_CLR_IRQ);
++
++ return(handledStatLE);
++} /* HandleStatusLEs */
++
++/*****************************************************************************
++ *
++ * AllocateAndInitLETables - allocate memory for the LETable and init
++ *
++ * Description:
++ * This function will allocate space for the LETable and will also
++ * initialize them. The size of the tables must have been specified
++ * before.
++ *
++ * Arguments:
++ * pAC - A pointer to the adapter context struct.
++ *
++ * Returns:
++ * SK_TRUE - all LETables initialized
++ * SK_FALSE - failed
++ */
++static SK_BOOL AllocateAndInitLETables(
++SK_AC *pAC) /* pointer to adapter context */
++{
++ char *pVirtMemAddr;
++ dma_addr_t pPhysMemAddr = 0;
++ SK_U32 CurrMac;
++ unsigned Size;
++ unsigned Aligned;
++ unsigned Alignment;
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT,
++ ("==> AllocateAndInitLETables()\n"));
++
++ /*
++ ** Determine how much memory we need with respect to alignment
++ */
++ Alignment = MAX_LEN_OF_LE_TAB;
++ Size = 0;
++ for (CurrMac = 0; CurrMac < pAC->GIni.GIMacsFound; CurrMac++) {
++ SK_ALIGN_SIZE(LE_TAB_SIZE(RX_MAX_LE), Alignment, Aligned);
++ Size += Aligned;
++ SK_ALIGN_SIZE(LE_TAB_SIZE(TXA_MAX_LE), Alignment, Aligned);
++ Size += Aligned;
++ SK_ALIGN_SIZE(LE_TAB_SIZE(TXS_MAX_LE), Alignment, Aligned);
++ Size += Aligned;
++ }
++ SK_ALIGN_SIZE(LE_TAB_SIZE(ST_MAX_LE), Alignment, Aligned);
++ Size += Aligned;
++ Size += Alignment;
++ pAC->SizeOfAlignedLETables = Size;
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT,
++ ("Need %08x bytes in total\n", Size));
++
++ /*
++ ** Allocate the memory
++ */
++ pVirtMemAddr = pci_alloc_consistent(pAC->PciDev, Size, &pPhysMemAddr);
++ if (pVirtMemAddr == NULL) {
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV,
++ SK_DBGCAT_INIT | SK_DBGCAT_DRV_ERROR,
++ ("AllocateAndInitLETables: kernel malloc failed!\n"));
++ return (SK_FALSE);
++ }
++
++ /*
++ ** Initialize the memory
++ */
++ SK_MEMSET(pVirtMemAddr, 0, Size);
++ ALIGN_ADDR(pVirtMemAddr, Alignment); /* Macro defined in skgew.h */
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT,
++ ("Virtual address of LETab is %8p!\n", pVirtMemAddr));
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT,
++ ("Phys address of LETab is %8p!\n", (void *) pPhysMemAddr));
++
++ for (CurrMac = 0; CurrMac < pAC->GIni.GIMacsFound; CurrMac++) {
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT,
++ ("RxLeTable for Port %c", 'A' + CurrMac));
++ SkGeY2InitSingleLETable(
++ pAC,
++ &pAC->RxPort[CurrMac].RxLET,
++ RX_MAX_LE,
++ pVirtMemAddr,
++ (SK_U32) (pPhysMemAddr & 0xffffffff),
++ (SK_U32) (((SK_U64) pPhysMemAddr) >> 32));
++
++ SK_ALIGN_SIZE(LE_TAB_SIZE(RX_MAX_LE), Alignment, Aligned);
++ pVirtMemAddr += Aligned;
++ pPhysMemAddr += Aligned;
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT,
++ ("TxALeTable for Port %c", 'A' + CurrMac));
++ SkGeY2InitSingleLETable(
++ pAC,
++ &pAC->TxPort[CurrMac][0].TxALET,
++ TXA_MAX_LE,
++ pVirtMemAddr,
++ (SK_U32) (pPhysMemAddr & 0xffffffff),
++ (SK_U32) (((SK_U64) pPhysMemAddr) >> 32));
++
++ SK_ALIGN_SIZE(LE_TAB_SIZE(TXA_MAX_LE), Alignment, Aligned);
++ pVirtMemAddr += Aligned;
++ pPhysMemAddr += Aligned;
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT,
++ ("TxSLeTable for Port %c", 'A' + CurrMac));
++ SkGeY2InitSingleLETable(
++ pAC,
++ &pAC->TxPort[CurrMac][0].TxSLET,
++ TXS_MAX_LE,
++ pVirtMemAddr,
++ (SK_U32) (pPhysMemAddr & 0xffffffff),
++ (SK_U32) (((SK_U64) pPhysMemAddr) >> 32));
++
++ SK_ALIGN_SIZE(LE_TAB_SIZE(TXS_MAX_LE), Alignment, Aligned);
++ pVirtMemAddr += Aligned;
++ pPhysMemAddr += Aligned;
++ }
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,("StLeTable"));
++
++ SkGeY2InitSingleLETable(
++ pAC,
++ &pAC->StatusLETable,
++ ST_MAX_LE,
++ pVirtMemAddr,
++ (SK_U32) (pPhysMemAddr & 0xffffffff),
++ (SK_U32) (((SK_U64) pPhysMemAddr) >> 32));
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT,
++ ("<== AllocateAndInitLETables(OK)\n"));
++ return(SK_TRUE);
++} /* AllocateAndInitLETables */
++
++/*****************************************************************************
++ *
++ * AllocatePacketBuffersYukon2 - allocate packet and fragment buffers
++ *
++ * Description:
++ * This function will allocate space for the packets and fragments
++ *
++ * Arguments:
++ * pAC - A pointer to the adapter context struct.
++ *
++ * Returns:
++ * SK_TRUE - Memory was allocated correctly
++ * SK_FALSE - An error occured
++ */
++static SK_BOOL AllocatePacketBuffersYukon2(
++SK_AC *pAC) /* pointer to adapter context */
++{
++ SK_PACKET *pRxPacket;
++ SK_PACKET *pTxPacket;
++ SK_U32 CurrBuff;
++ SK_U32 CurrMac;
++ unsigned long Flags; /* needed for POP/PUSH functions */
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT,
++ ("==> AllocatePacketBuffersYukon2()"));
++
++ for (CurrMac = 0; CurrMac < pAC->GIni.GIMacsFound; CurrMac++) {
++ /*
++ ** Allocate RX packet space, initialize the packets and
++ ** add them to the RX waiting queue. Waiting queue means
++ ** that packet and fragment are initialized, but no sk_buff
++ ** has been assigned to it yet.
++ */
++ pAC->RxPort[CurrMac].ReceivePacketTable =
++ kmalloc((RX_MAX_NBR_BUFFERS * sizeof(SK_PACKET)), GFP_KERNEL);
++
++ if (pAC->RxPort[CurrMac].ReceivePacketTable == NULL) {
++ SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_INIT | SK_DBGCAT_DRV_ERROR,
++ ("AllocatePacketBuffersYukon2: no mem RxPkts (port %i)",CurrMac));
++ break;
++ } else {
++ SK_MEMSET(pAC->RxPort[CurrMac].ReceivePacketTable, 0,
++ (RX_MAX_NBR_BUFFERS * sizeof(SK_PACKET)));
++
++ pRxPacket = pAC->RxPort[CurrMac].ReceivePacketTable;
++
++ for (CurrBuff=0;CurrBuff<RX_MAX_NBR_BUFFERS;CurrBuff++) {
++ pRxPacket->pFrag = &(pRxPacket->FragArray[0]);
++ pRxPacket->NumFrags = 1;
++ PUSH_PKT_AS_LAST_IN_QUEUE(&pAC->RxPort[CurrMac].RxQ_waiting, pRxPacket);
++ pRxPacket++;
++ }
++ }
++
++ /*
++ ** Allocate TX packet space, initialize the packets and
++ ** add them to the TX free queue. Free queue means that
++ ** packet is available and initialized, but no fragment
++ ** has been assigned to it. (Must be done at TX side)
++ */
++ pAC->TxPort[CurrMac][0].TransmitPacketTable =
++ kmalloc((TX_MAX_NBR_BUFFERS * sizeof(SK_PACKET)), GFP_KERNEL);
++
++ if (pAC->TxPort[CurrMac][0].TransmitPacketTable == NULL) {
++ SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_INIT | SK_DBGCAT_DRV_ERROR,
++ ("AllocatePacketBuffersYukon2: no mem TxPkts (port %i)",CurrMac));
++ kfree(pAC->RxPort[CurrMac].ReceivePacketTable);
++ return(SK_FALSE);
++ } else {
++ SK_MEMSET(pAC->TxPort[CurrMac][0].TransmitPacketTable, 0,
++ (TX_MAX_NBR_BUFFERS * sizeof(SK_PACKET)));
++
++ pTxPacket = pAC->TxPort[CurrMac][0].TransmitPacketTable;
++
++ for (CurrBuff=0;CurrBuff<TX_MAX_NBR_BUFFERS;CurrBuff++) {
++ PUSH_PKT_AS_LAST_IN_QUEUE(&pAC->TxPort[CurrMac][0].TxQ_free, pTxPacket);
++ pTxPacket++;
++ }
++ }
++ } /* end for (CurrMac = 0; CurrMac < pAC->GIni.GIMacsFound; CurrMac++) */
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_INIT,
++ ("<== AllocatePacketBuffersYukon2 (OK)\n"));
++ return(SK_TRUE);
++
++} /* AllocatePacketBuffersYukon2 */
++
++/*****************************************************************************
++ *
++ * FreeLETables - release allocated memory of LETables
++ *
++ * Description:
++ * This function will free all resources of the LETables
++ *
++ * Arguments:
++ * pAC - A pointer to the adapter context struct.
++ *
++ * Returns: N/A
++ */
++static void FreeLETables(
++SK_AC *pAC) /* pointer to adapter control context */
++{
++ dma_addr_t pPhysMemAddr;
++ char *pVirtMemAddr;
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,
++ ("==> FreeLETables()\n"));
++
++ /*
++ ** The RxLETable is the first of all LET.
++ ** Therefore we can use its address for the input
++ ** of the free function.
++ */
++ pVirtMemAddr = (char *) pAC->RxPort[0].RxLET.pLETab;
++ pPhysMemAddr = (((SK_U64) pAC->RxPort[0].RxLET.pPhyLETABHigh << (SK_U64) 32) |
++ ((SK_U64) pAC->RxPort[0].RxLET.pPhyLETABLow));
++
++ /* free continuous memory */
++ pci_free_consistent(pAC->PciDev, pAC->SizeOfAlignedLETables,
++ pVirtMemAddr, pPhysMemAddr);
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,
++ ("<== FreeLETables()\n"));
++} /* FreeLETables */
++
++/*****************************************************************************
++ *
++ * FreePacketBuffers - free's all packet buffers of an adapter
++ *
++ * Description:
++ * This function will free all previously allocated memory of the
++ * packet buffers.
++ *
++ * Arguments:
++ * pAC - A pointer to the adapter context struct.
++ *
++ * Returns: N/A
++ */
++static void FreePacketBuffers(
++SK_AC *pAC) /* pointer to adapter control context */
++{
++ int Port;
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,
++ ("==> FreePacketBuffers()\n"));
++
++ for (Port = 0; Port < pAC->GIni.GIMacsFound; Port++) {
++ kfree(pAC->RxPort[Port].ReceivePacketTable);
++ kfree(pAC->TxPort[Port][0].TransmitPacketTable);
++ }
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MSG,
++ ("<== FreePacketBuffers()\n"));
++} /* FreePacketBuffers */
++
++/*****************************************************************************
++ *
++ * AllocAndMapRxBuffer - fill one buffer into the receive packet/fragment
++ *
++ * Description:
++ * The function allocates a new receive buffer and assigns it to the
++ * the passsed receive packet/fragment
++ *
++ * Returns:
++ * SK_TRUE - a buffer was allocated and assigned
++ * SK_FALSE - a buffer could not be added
++ */
++static SK_BOOL AllocAndMapRxBuffer(
++SK_AC *pAC, /* pointer to the adapter control context */
++SK_PACKET *pSkPacket, /* pointer to packet that is to fill */
++int Port) /* port the packet belongs to */
++{
++ struct sk_buff *pMsgBlock; /* pointer to a new message block */
++ SK_U64 PhysAddr; /* physical address of a rx buffer */
++
++ SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,
++ ("--> AllocAndMapRxBuffer (Port: %i)\n", Port));
++
++ pMsgBlock = alloc_skb(pAC->RxPort[Port].RxBufSize, GFP_ATOMIC);
++ if (pMsgBlock == NULL) {
++ SK_DBG_MSG(NULL, SK_DBGMOD_DRV,
++ SK_DBGCAT_DRV_RX_PROGRESS | SK_DBGCAT_DRV_ERROR,
++ ("%s: Allocation of rx buffer failed !\n",
++ pAC->dev[Port]->name));
++ SK_PNMI_CNT_NO_RX_BUF(pAC, pAC->RxPort[Port].PortIndex);
++ return(SK_FALSE);
++ }
++ skb_reserve(pMsgBlock, 8);
++
++ PhysAddr = (SK_U64) pci_map_page(pAC->PciDev,
++ virt_to_page(pMsgBlock->data),
++ ((unsigned long) pMsgBlock->data &
++ ~PAGE_MASK),
++ pAC->RxPort[Port].RxBufSize,
++ PCI_DMA_FROMDEVICE);
++
++ pSkPacket->pFrag->pVirt = pMsgBlock->data;
++ pSkPacket->pFrag->pPhys = PhysAddr;
++ pSkPacket->pFrag->FragLen = pAC->RxPort[Port].RxBufSize; /* for correct unmap */
++ pSkPacket->pMBuf = pMsgBlock;
++ pSkPacket->PacketLen = pAC->RxPort[Port].RxBufSize;
++
++ SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_RX_PROGRESS,
++ ("<-- AllocAndMapRxBuffer\n"));
++
++ return (SK_TRUE);
++} /* AllocAndMapRxBuffer */
++
++/*******************************************************************************
++ *
++ * End of file
++ *
++ ******************************************************************************/
+diff -ruN linux/drivers/net/sk98lin/sky2le.c linux-new/drivers/net/sk98lin/sky2le.c
+--- linux/drivers/net/sk98lin/sky2le.c 1970-01-01 03:00:00.000000000 +0300
++++ linux-new/drivers/net/sk98lin/sky2le.c 2005-08-09 17:15:51.000000000 +0400
+@@ -0,0 +1,510 @@
++/*****************************************************************************
++ *
++ * Name: sky2le.c
++ * Project: Gigabit Ethernet Adapters, Common Modules
++ * Version: $Revision: 1.11 $
++ * Date: $Date: 2004/11/22 14:21:58 $
++ * Purpose: Functions for handling List Element Tables
++ *
++ *****************************************************************************/
++
++/******************************************************************************
++ *
++ * (C)Copyright 2002-2004 Marvell.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ * The information in this file is provided "AS IS" without warranty.
++ *
++ ******************************************************************************/
++
++/*****************************************************************************
++ *
++ * Description:
++ *
++ * This module contains the code necessary for handling List Elements.
++ *
++ * Supported Gigabit Ethernet Chipsets:
++ * Yukon-2 (PCI, PCI-X, PCI-Express)
++ *
++ * Include File Hierarchy:
++ *
++ *
++ *****************************************************************************/
++#include "h/skdrv1st.h"
++#include "h/skdrv2nd.h"
++
++/* defines *******************************************************************/
++/* typedefs ******************************************************************/
++/* global variables **********************************************************/
++/* local variables ***********************************************************/
++
++#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM))))
++static const char SysKonnectFileId[] =
++ "@(#) $Id: sky2le.c,v 1.11 2004/11/22 14:21:58 malthoff Exp $ (C) Marvell.";
++#endif /* DEBUG || (!LINT && !SK_SLIM) */
++
++/* function prototypes *******************************************************/
++
++/*****************************************************************************
++ *
++ * SkGeY2InitSingleLETable() - initializes a list element table
++ *
++ * Description:
++ * This function will initialize the selected list element table.
++ * Should be called once during DriverInit. No InitLevel required.
++ *
++ * Arguments:
++ * pAC - pointer to the adapter context struct.
++ * pLETab - pointer to list element table structure
++ * NumLE - number of list elements in this table
++ * pVMem - virtual address of memory allocated for this LE table
++ * PMemLowAddr - physical address of memory to be used for the LE table
++ * PMemHighAddr
++ *
++ * Returns:
++ * nothing
++ */
++void SkGeY2InitSingleLETable(
++SK_AC *pAC, /* pointer to adapter context */
++SK_LE_TABLE *pLETab, /* pointer to list element table to be initialized */
++unsigned int NumLE, /* number of list elements to be filled in tab */
++void *pVMem, /* virtual address of memory used for list elements */
++SK_U32 PMemLowAddr, /* physical addr of mem used for LE */
++SK_U32 PMemHighAddr)
++{
++ unsigned int i;
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
++ ("==> SkGeY2InitSingleLETable()\n"));
++
++#ifdef DEBUG
++ if (NumLE != 2) { /* not table for polling unit */
++ if ((NumLE % MIN_LEN_OF_LE_TAB) != 0 || NumLE > MAX_LEN_OF_LE_TAB) {
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR,
++ ("ERROR: Illegal number of list elements %d\n", NumLE));
++ }
++ }
++#endif /* DEBUG */
++
++ /* special case: unused list element table */
++ if (NumLE == 0) {
++ PMemLowAddr = 0;
++ PMemHighAddr = 0;
++ pVMem = 0;
++ }
++
++ /*
++ * in order to get the best possible performance the macros to access
++ * list elements use & instead of %
++ * this requires the length of LE tables to be a power of 2
++ */
++
++ /*
++ * this code guarantees that we use the next power of 2 below the
++ * value specified for NumLe - this way some LEs in the table may
++ * not be used but the macros work correctly
++ * this code does not check for bad values below 128 because in such a
++ * case we cannot do anything here
++ */
++
++ if ((NumLE != 2) && (NumLE != 0)) {
++ /* no check for polling unit and unused sync Tx */
++ i = MIN_LEN_OF_LE_TAB;
++ while (NumLE > i) {
++ i *= 2;
++ if (i > MAX_LEN_OF_LE_TAB) {
++ break;
++ }
++ }
++ if (NumLE != i) {
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR,
++ ("ERROR: Illegal number of list elements %d adjusted to %d\n",
++ NumLE, (i / 2)));
++ NumLE = i / 2;
++ }
++ }
++
++ /* set addresses */
++ pLETab->pPhyLETABLow = PMemLowAddr;
++ pLETab->pPhyLETABHigh = PMemHighAddr;
++ pLETab->pLETab = pVMem;
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
++ ("contains %d LEs", NumLE));
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
++ (" and starts at virt %08lx and phys %08lx:%08lx\n",
++ pVMem, PMemHighAddr, PMemLowAddr));
++
++ /* initialize indexes */
++ pLETab->Done = 0;
++ pLETab->Put = 0;
++ pLETab->HwPut = 0;
++ /* initialize size */
++ pLETab->Num = NumLE;
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
++ ("<== SkGeY2InitSingleLETable()\n"));
++} /* SkGeY2InitSingleLETable */
++
++/*****************************************************************************
++ *
++ * SkGeY2InitPrefetchUnit() - Initialize a Prefetch Unit
++ *
++ * Description:
++ * Calling this function requires an already configured list element
++ * table. The prefetch unit to be configured is specified in the parameter
++ * 'Queue'. The function is able to initialze the prefetch units of
++ * the following queues: Q_R1, Q_R2, Q_XS1, Q_XS2, Q_XA1, Q_XA2.
++ * The funcution should be called before SkGeInitPort().
++ *
++ * Arguments:
++ * pAC - pointer to the adapter context struct.
++ * IoC - I/O context.
++ * Queue - I/O offset of queue e.g. Q_XA1.
++ * pLETab - pointer to list element table to be initialized
++ *
++ * Returns: N/A
++ */
++void SkGeY2InitPrefetchUnit(
++SK_AC *pAC, /* pointer to adapter context */
++SK_IOC IoC, /* I/O context */
++unsigned int Queue, /* Queue offset for finding the right registers */
++SK_LE_TABLE *pLETab) /* pointer to list element table to be initialized */
++{
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
++ ("==> SkGeY2InitPrefetchUnit()\n"));
++
++#ifdef DEBUG
++ if (Queue != Q_R1 && Queue != Q_R2 && Queue != Q_XS1 &&
++ Queue != Q_XS2 && Queue != Q_XA1 && Queue != Q_XA2) {
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_ERR,
++ ("ERROR: Illegal queue identifier %x\n", Queue));
++ }
++#endif /* DEBUG */
++
++ /* disable the prefetch unit */
++ SK_OUT32(IoC, Y2_PREF_Q_ADDR(Queue, PREF_UNIT_CTRL_REG), PREF_UNIT_RST_SET);
++ SK_OUT32(IoC, Y2_PREF_Q_ADDR(Queue, PREF_UNIT_CTRL_REG), PREF_UNIT_RST_CLR);
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
++ ("Base address: %08lx:%08lx\n", pLETab->pPhyLETABHigh,
++ pLETab->pPhyLETABLow));
++
++ /* Set the list base address high part*/
++ SK_OUT32(IoC, Y2_PREF_Q_ADDR(Queue, PREF_UNIT_ADDR_HI_REG),
++ pLETab->pPhyLETABHigh);
++
++ /* Set the list base address low part */
++ SK_OUT32(IoC, Y2_PREF_Q_ADDR(Queue, PREF_UNIT_ADDR_LOW_REG),
++ pLETab->pPhyLETABLow);
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
++ ("Last index: %d\n", pLETab->Num-1));
++
++ /* Set the list last index */
++ SK_OUT16(IoC, Y2_PREF_Q_ADDR(Queue, PREF_UNIT_LAST_IDX_REG),
++ (SK_U16)(pLETab->Num - 1));
++
++ /* turn on prefetch unit */
++ SK_OUT32(IoC, Y2_PREF_Q_ADDR(Queue, PREF_UNIT_CTRL_REG), PREF_UNIT_OP_ON);
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
++ ("<== SkGeY2InitPrefetchUnit()\n"));
++} /* SkGeY2InitPrefetchUnit */
++
++
++/*****************************************************************************
++ *
++ * SkGeY2InitStatBmu() - Initialize the Status BMU
++ *
++ * Description:
++ * Calling this function requires an already configured list element
++ * table. Ensure the status BMU is only initialized once during
++ * DriverInit - InitLevel2 required.
++ *
++ * Arguments:
++ * pAC - pointer to the adapter context struct.
++ * IoC - I/O context.
++ * pLETab - pointer to status LE table to be initialized
++ *
++ * Returns: N/A
++ */
++void SkGeY2InitStatBmu(
++SK_AC *pAC, /* pointer to adapter context */
++SK_IOC IoC, /* I/O context */
++SK_LE_TABLE *pLETab) /* pointer to status LE table */
++{
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
++ ("==> SkGeY2InitStatBmu()\n"));
++
++ /* disable the prefetch unit */
++ SK_OUT32(IoC, STAT_CTRL, SC_STAT_RST_SET);
++ SK_OUT32(IoC, STAT_CTRL, SC_STAT_RST_CLR);
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
++ ("Base address Low: %08lX\n", pLETab->pPhyLETABLow));
++
++ /* Set the list base address */
++ SK_OUT32(IoC, STAT_LIST_ADDR_LO, pLETab->pPhyLETABLow);
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
++ ("Base address High: %08lX\n", pLETab->pPhyLETABHigh));
++
++ SK_OUT32(IoC, STAT_LIST_ADDR_HI, pLETab->pPhyLETABHigh);
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
++ ("Last index: %d\n", pLETab->Num - 1));
++
++ /* Set the list last index */
++ SK_OUT16(IoC, STAT_LAST_IDX, (SK_U16)(pLETab->Num - 1));
++
++ if (HW_FEATURE(pAC, HWF_WA_DEV_43_418)) {
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
++ ("Set Tx index threshold\n"));
++ /* WA for dev. #4.3 */
++ SK_OUT16(IoC, STAT_TX_IDX_TH, ST_TXTH_IDX_MASK);
++
++ /* set Status-FIFO watermark */
++ SK_OUT8(IoC, STAT_FIFO_WM, 0x21); /* WA for dev. #4.18 */
++
++ /* set Status-FIFO ISR watermark */
++ SK_OUT8(IoC, STAT_FIFO_ISR_WM, 0x07); /* WA for dev. #4.18 */
++
++ /* WA for dev. #4.3 and #4.18 */
++ /* set Status-FIFO Tx timer init value */
++ SK_OUT32(IoC, STAT_TX_TIMER_INI, HW_MS_TO_TICKS(pAC, 10));
++ }
++ else {
++ /*
++ * Further settings may be added if required...
++ * 1) Status-FIFO watermark (STAT_FIFO_WM, STAT_FIFO_ISR_WM)
++ * 2) Status-FIFO timer values (STAT_TX_TIMER_INI,
++ * STAT_LEV_TIMER_INI and STAT_ISR_TIMER_INI)
++ * but tests shows that the default values give the best results,
++ * therefore the defaults are used.
++ */
++
++ /*
++ * Theses settings should avoid the
++ * temporary hanging of the status BMU.
++ * May be not all required... still under investigation...
++ */
++ SK_OUT16(IoC, STAT_TX_IDX_TH, 0x000a);
++
++ /* set Status-FIFO watermark */
++ SK_OUT8(IoC, STAT_FIFO_WM, 0x10);
++
++
++ /* set Status-FIFO ISR watermark */
++ if (HW_FEATURE(pAC, HWF_WA_DEV_4109)) {
++ SK_OUT8(IoC, STAT_FIFO_ISR_WM, 0x10);
++ }
++ else {
++ SK_OUT8(IoC, STAT_FIFO_ISR_WM, 0x04);
++ }
++
++ SK_OUT32(IoC, STAT_ISR_TIMER_INI, 0x0190);
++ }
++
++ /* start Status-FIFO timer */
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
++ ("Start Status FiFo timer\n"));
++
++ /* enable the prefetch unit */
++ /* operational bit not functional for Yukon-EC, but fixed in Yukon-2 */
++ SK_OUT32(IoC, STAT_CTRL, SC_STAT_OP_ON);
++
++ /* start Status-FIFO timer */
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
++ ("Start Status FiFo timer\n"));
++
++ SK_OUT8(IoC, STAT_TX_TIMER_CTRL, TIM_START);
++ SK_OUT8(IoC, STAT_LEV_TIMER_CTRL, TIM_START);
++ SK_OUT8(IoC, STAT_ISR_TIMER_CTRL, TIM_START);
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
++ ("<== SkGeY2InitStatBmu()\n"));
++} /* SkGeY2InitStatBmu */
++
++#ifdef USE_POLLING_UNIT
++/*****************************************************************************
++ *
++ * SkGeY2InitPollUnit() - Initialize the Polling Unit
++ *
++ * Description:
++ * This function will write the data of one polling LE table into the
++ * adapter.
++ *
++ * Arguments:
++ * pAC - pointer to the adapter context struct.
++ * IoC - I/O context.
++ * pLETab - pointer to polling LE table to be initialized
++ *
++ * Returns: N/A
++ */
++void SkGeY2InitPollUnit(
++SK_AC *pAC, /* pointer to adapter context */
++SK_IOC IoC, /* I/O context */
++SK_LE_TABLE *pLETab) /* pointer to polling LE table */
++{
++ SK_HWLE *pLE;
++ int i;
++#ifdef VCPU
++ VCPU_VARS();
++#endif /* VCPU */
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
++ ("==> SkGeY2InitPollUnit()\n"));
++
++#ifdef VCPU
++ for (i = 0; i < SK_MAX_MACS; i++) {
++ GET_PO_LE(pLE, pLETab, i);
++ VCPU_START_AND_COPY_LE();
++ /* initialize polling LE but leave indexes invalid */
++ POLE_SET_OPC(pLE, OP_PUTIDX | HW_OWNER);
++ POLE_SET_LINK(pLE, i);
++ POLE_SET_RXIDX(pLE, 0);
++ POLE_SET_TXAIDX(pLE, 0);
++ POLE_SET_TXSIDX(pLE, 0);
++ VCPU_WRITE_LE();
++ SK_DBG_DUMP_PO_LE(pLE);
++ }
++#endif /* VCPU */
++
++ /* disable the polling unit */
++ SK_OUT32(IoC, POLL_CTRL, PC_POLL_RST_SET);
++ SK_OUT32(IoC, POLL_CTRL, PC_POLL_RST_CLR);
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
++ ("Base address Low: %08lX\n", pLETab->pPhyLETABLow));
++
++ /* Set the list base address */
++ SK_OUT32(IoC, POLL_LIST_ADDR_LO, pLETab->pPhyLETABLow);
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
++ ("Base address High: %08lX\n", pLETab->pPhyLETABHigh));
++
++ SK_OUT32(IoC, POLL_LIST_ADDR_HI, pLETab->pPhyLETABHigh);
++
++ /* we don't need to write the last index - it is hardwired to 1 */
++
++ /* enable the prefetch unit */
++ SK_OUT32(IoC, POLL_CTRL, PC_POLL_OP_ON);
++
++ /*
++ * now we have to start the descriptor poll timer because it triggers
++ * the polling unit
++ */
++
++ /*
++ * still playing with the value (timer runs at 125 MHz)
++ * descriptor poll timer is enabled by GeInit
++ */
++ SK_OUT32(IoC, B28_DPT_INI,
++ (SK_DPOLL_DEF_Y2 * (SK_U32)pAC->GIni.GIHstClkFact / 100));
++
++ SK_OUT8(IoC, B28_DPT_CTRL, TIM_START);
++
++ SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT,
++ ("<== SkGeY2InitPollUnit()\n"));
++} /* SkGeY2InitPollUnit */
++#endif /* USE_POLLING_UNIT */
++
++
++/******************************************************************************
++ *
++ * SkGeY2SetPutIndex
++ *
++ * Description:
++ * This function is writing the Done index of a transmit
++ * list element table.
++ *
++ * Notes:
++ * Dev. Issue 4.2
++ *
++ * Returns: N/A
++ */
++void SkGeY2SetPutIndex(
++SK_AC *pAC, /* pointer to adapter context */
++SK_IOC IoC, /* pointer to the IO context */
++SK_U32 StartAddrPrefetchUnit, /* start address of the prefetch unit */
++SK_LE_TABLE *pLETab) /* list element table to work with */
++{
++ unsigned int Put;
++ SK_U16 EndOfListIndex;
++ SK_U16 HwGetIndex;
++ SK_U16 HwPutIndex;
++
++ /* set put index we would like to write */
++ Put = GET_PUT_IDX(pLETab);
++
++ /*
++ * in this case we wrap around
++ * new put is lower than last put given to hw
++ */
++ if (Put < pLETab->HwPut) {
++
++ /* set put index = last index of list */
++ EndOfListIndex = (NUM_LE_IN_TABLE(pLETab)-1);
++
++ /* read get index of hw prefetch unit */
++ SK_IN16(IoC, (StartAddrPrefetchUnit + PREF_UNIT_GET_IDX_REG),
++ &HwGetIndex);
++
++ /* read put index of hw prefetch unit */
++ SK_IN16(IoC, (StartAddrPrefetchUnit + PREF_UNIT_PUT_IDX_REG),
++ &HwPutIndex);
++
++ /* prefetch unit reached end of list */
++ /* prefetch unit reached first list element */
++ if (HwGetIndex == 0) {
++ /* restore watermark */
++ SK_OUT8(IoC, StartAddrPrefetchUnit + PREF_UNIT_FIFO_WM_REG, 0xe0U);
++ /* write put index */
++ SK_OUT16(IoC, StartAddrPrefetchUnit + PREF_UNIT_PUT_IDX_REG,
++ (SK_U16)Put);
++
++ /* remember put index we wrote to hw */
++ pLETab->HwPut = Put;
++ }
++ else if (HwGetIndex == EndOfListIndex) {
++ /* set watermark to one list element */
++ SK_OUT8(IoC, StartAddrPrefetchUnit + PREF_UNIT_FIFO_WM_REG, 8);
++ /* set put index to first list element */
++ SK_OUT16(IoC, StartAddrPrefetchUnit + PREF_UNIT_PUT_IDX_REG, 0);
++ }
++ /* prefetch unit did not reach end of list yet */
++ /* and we did not write put index to end of list yet */
++ else if ((HwPutIndex != EndOfListIndex) &&
++ (HwGetIndex != EndOfListIndex)) {
++ /* write put index */
++ SK_OUT16(IoC, StartAddrPrefetchUnit + PREF_UNIT_PUT_IDX_REG,
++ EndOfListIndex);
++ }
++ else {
++ /* do nothing */
++ }
++ }
++ else {
++#ifdef XXX /* leads in to problems in the Windows Driver */
++ if (Put != pLETab->HwPut) {
++ /* write put index */
++ SK_OUT16(IoC, StartAddrPrefetchUnit + PREF_UNIT_PUT_IDX_REG,
++ (SK_U16)Put);
++ /* update put index */
++ UPDATE_HWPUT_IDX(pLETab);
++ }
++#else
++ /* write put index */
++ SK_OUT16(IoC, StartAddrPrefetchUnit + PREF_UNIT_PUT_IDX_REG,
++ (SK_U16)Put);
++ /* update put index */
++ UPDATE_HWPUT_IDX(pLETab);
++#endif
++ }
++} /* SkGeY2SetPutIndex */
++
+diff -ruN linux/Documentation/networking/sk98lin.txt linux-new/Documentation/networking/sk98lin.txt
+--- linux/Documentation/networking/sk98lin.txt 2005-09-26 13:33:56.000000000 +0400
++++ linux-new/drivers/net/sk98lin/sk98lin.txt 2005-08-09 17:15:51.000000000 +0400
+@@ -1,38 +1,56 @@
+-(C)Copyright 1999-2004 Marvell(R).
+-All rights reserved
+-===========================================================================
++(C)Copyright 1999-2005 Marvell(R).
++All rights reserved.
++================================================================================
+
+-sk98lin.txt created 13-Feb-2004
++sk98lin.txt created 09-Aug-2005
+
+-Readme File for sk98lin v6.23
+-Marvell Yukon/SysKonnect SK-98xx Gigabit Ethernet Adapter family driver for LINUX
++Readme File for sk98lin v8.24.1.3
++Marvell Yukon/SysKonnect SK-98xx Gigabit Ethernet Adapter driver for LINUX
+
+ This file contains
+ 1 Overview
+- 2 Required Files
+- 3 Installation
+- 3.1 Driver Installation
+- 3.2 Inclusion of adapter at system start
+- 4 Driver Parameters
+- 4.1 Per-Port Parameters
+- 4.2 Adapter Parameters
+- 5 Large Frame Support
+- 6 VLAN and Link Aggregation Support (IEEE 802.1, 802.1q, 802.3ad)
+- 7 Troubleshooting
++ 2 Supported Functions
++ 3 Required Files
++ 4 Installation
++ 4.1 Driver Installation
++ 4.2 Inclusion of adapter at system start
++ 5 Driver Parameters
++ 5.1 Per-Port Parameters
++ 5.2 Adapter Parameters
++ 6 Ethtool Support
++ 7 Large Frame Support
++ 8 VLAN and Link Aggregation Support (IEEE 802.1, 802.1q, 802.3ad)
++ 9 Wake on Lan support
++10 Troubleshooting
+
+-===========================================================================
++================================================================================
+
+
+ 1 Overview
+ ===========
+
+-The sk98lin driver supports the Marvell Yukon and SysKonnect
+-SK-98xx/SK-95xx compliant Gigabit Ethernet Adapter on Linux. It has
+-been tested with Linux on Intel/x86 machines.
++The sk98lin driver supports the Marvell Yukon, Yukon EC/FE, Yukon 2
++and SysKonnect SK-98xx/SK-95xx compliant Gigabit Ethernet Adapter on Linux.
++It has been tested with Linux on Intel/x86, x86_64 and IA64 machines.
+ ***
+
++2 Supported Functions
++======================
++
++The following functions are supported by the driver:
+
+-2 Required Files
++ NOTE 1: The hardware support depends on the used card
++
++ - RX/TX HW Checksum
++ - Hardware interrupt moderation (static/dynamic)
++ - Transmit poll
++ - Zerocopy/Scatter-Gather
++ - Ethtool support
++ - Wake on Lan (Magic Packet only) (From suspend and APM only)
++ - DualNet
++
++
++3 Required Files
+ =================
+
+ The linux kernel source.
+@@ -40,16 +58,14 @@
+ ***
+
+
+-3 Installation
++4 Installation
+ ===============
+
+ It is recommended to download the latest version of the driver from the
+-SysKonnect web site www.syskonnect.com. If you have downloaded the latest
+-driver, the Linux kernel has to be patched before the driver can be
+-installed. For details on how to patch a Linux kernel, refer to the
+-patch.txt file.
++SysKonnect web site www.syskonnect.com. For details on Installation
++Instructions for sk98lin Driver, please refer to the README.txt file.
+
+-3.1 Driver Installation
++4.1 Driver Installation
+ ------------------------
+
+ The following steps describe the actions that are required to install
+@@ -110,13 +126,13 @@
+
+ NOTE 1: If you have more than one Marvell Yukon or SysKonnect SK-98xx
+ adapter installed, the adapters will be listed as 'eth0',
+- 'eth1', 'eth2', etc.
+- For each adapter, repeat steps 3 and 4 below.
++ 'eth1', 'eth2', etc.
++ For each adapter, repeat steps 3 and 4 below.
+
+ NOTE 2: If you have other Ethernet adapters installed, your Marvell
+ Yukon or SysKonnect SK-98xx adapter will be mapped to the
+- next available number, e.g. 'eth1'. The mapping is executed
+- automatically.
++ next available number, e.g. 'eth1'. The mapping is executed
++ automatically.
+ The module installation message (displayed either in a system
+ log file or on the console) prints a line for each adapter
+ found containing the corresponding 'ethX'.
+@@ -153,7 +169,7 @@
+ 1. Execute the command "ifconfig eth0 down".
+ 2. Execute the command "rmmod sk98lin".
+
+-3.2 Inclusion of adapter at system start
++4.2 Inclusion of adapter at system start
+ -----------------------------------------
+
+ Since a large number of different Linux distributions are
+@@ -165,7 +181,8 @@
+
+ ***
+
+-4 Driver Parameters
++
++5 Driver Parameters
+ ====================
+
+ Parameters can be set at the command line after the module has been
+@@ -174,7 +191,7 @@
+ to the driver module.
+
+ If you use the kernel module loader, you can set driver parameters
+-in the file /etc/modprobe.conf (or /etc/modules.conf in 2.4 or earlier).
++in the file /etc/modules.conf (or old name: /etc/conf.modules).
+ To set the driver parameters in this file, proceed as follows:
+
+ 1. Insert a line of the form :
+@@ -208,7 +225,7 @@
+ more adapters, adjust this and recompile.
+
+
+-4.1 Per-Port Parameters
++5.1 Per-Port Parameters
+ ------------------------
+
+ These settings are available for each port on the adapter.
+@@ -282,7 +299,7 @@
+ with this parameter.
+
+
+-4.2 Adapter Parameters
++5.2 Adapter Parameters
+ -----------------------
+
+ Connection Type (SK-98xx V2.0 copper adapters only)
+@@ -379,7 +396,6 @@
+ is tremendous. On the other hand, selecting a very short moderation time might
+ compensate the use of any moderation being applied.
+
+-
+ Preferred Port
+ --------------
+ Parameter: PrefPort
+@@ -394,7 +410,7 @@
+ ------------------------------------------------
+ Parameter: RlmtMode
+ Values: CheckLinkState,CheckLocalPort, CheckSeg, DualNet
+-Default: CheckLinkState
++Default: CheckLinkState (DualNet on dual port adapters)
+
+ RLMT monitors the status of the port. If the link of the active port
+ fails, RLMT switches immediately to the standby link. The virtual link is
+@@ -429,10 +445,94 @@
+ where a network path between the ports on one adapter exists.
+ Moreover, they are not designed to work where adapters are connected
+ back-to-back.
++
++LowLatency
++----------
++Parameter: LowLatency
++Values: On, Off
++Default: Off
++
++This is used to reduce the packet latency time of the adapter. Setting the
++LowLatency parameter to 'On' forces the adapter to pass any received packet
++immediately to upper network layers and to send out any transmit packet as
++fast as possible.
++
++NOTE 1: The system load increases if LowLatency is set to 'On' and a lot
++ of data packets are transmitted and received.
++
++NOTE 2: This parameter is only used on adapters which are based on
++ PCI Express compatible chipsets.
+ ***
+
+
+-5 Large Frame Support
++6 Ethtool Support
++==================
++
++The sk98lin driver provides built-in ethtool support. The ethtool
++can be used to display or modify interface specific configurations.
++
++Ethtool commands are invoked using a single parameter which reflects
++the requested ethtool command plus an optional number of parameters
++which belong to the desired command.
++
++It is not the intention of this section to explain the ethtool command
++line tool and all its options. For further information refer to the
++manpage of the ethtool. This sections describes only the sk98lin
++driver supported ethtool commands.
++
++Pause Parameters
++----------------
++Query command: -a
++Set command: -A [autoneg on|off] [rx on|off] [tx on|off]
++Sample: ethtool -A eth0 rx off tx off
++
++Coalescing Parameters
++---------------------
++Query command: -c
++Set command: -C [sample-interval I]
++ [rx-usecs N] [tx-usecs N]
++ [rx-usecs-low N] [tx-usecs-low N]
++ [rx-usecs-high N] [tx-usecs-high N]
++Parameter: I = Length of sample interval, in seconds
++ (supported values range from 1...10)
++ N = Length of coalescing interval, in microseconds
++ (supported values range from 25...33,333)
++Sample: ethtool -C eth2 rx-usecs 500 tx-usecs 500
++
++NOTE: The sk98lin driver does not support different settings
++ for the rx and tx interrupt coalescing parameters.
++
++Driver Information
++------------------
++Query command: -i
++Sample: ethtool -i eth1
++
++Checksumming Parameters
++-----------------------
++Query command: -k
++Set command: -K [rx on|off] [tx on|off] [sg on|off]
++Sample: ethtool -K eth0 sg off
++
++Locate NIC Command
++------------------
++Query command: -p [N]
++Parameter: N = Amount of time to perform locate NIC command, in seconds
++Sample: ethtool -p 10 eth1
++
++Driver-specific Statistics
++--------------------------
++Query command: -S
++Sample: ethtool -S eth0
++
++Setting Parameters
++------------------
++Set command: -s [speed 10|100|1000] [duplex half|full]
++ [autoneg on|off] [wol gd]
++Sample: ethtool -s eth2 wol d
++***
++
++
++7 Large Frame Support
+ ======================
+
+ The driver supports large frames (also called jumbo frames). Using large
+@@ -444,10 +544,10 @@
+ ifconfig eth0 mtu 9000
+ This will only work if you have two adapters connected back-to-back
+ or if you use a switch that supports large frames. When using a switch,
+-it should be configured to allow large frames and auto-negotiation should
+-be set to OFF. The setting must be configured on all adapters that can be
+-reached by the large frames. If one adapter is not set to receive large
+-frames, it will simply drop them.
++it should be configured to allow large frames. The setting must be
++configured on all adapters that can be reached by the large frames.
++If one adapter is not set to receive large frames, it will simply drop
++them.
+
+ You can switch back to the standard ethernet frame size by executing the
+ following command:
+@@ -459,7 +559,7 @@
+ ***
+
+
+-6 VLAN and Link Aggregation Support (IEEE 802.1, 802.1q, 802.3ad)
++8 VLAN and Link Aggregation Support (IEEE 802.1, 802.1q, 802.3ad)
+ ==================================================================
+
+ The Marvell Yukon/SysKonnect Linux drivers are able to support VLAN and
+@@ -477,8 +577,21 @@
+ cause problems when unloading the driver.
+
+
+-7 Troubleshooting
+-==================
++9 Wake on Lan support
++======================
++
++The sk98lin driver supports wake up from suspend mode with MagicPacket
++on APM systems. Wake on Lan support is enabled by default. To disable it
++please use the ethtool.
++
++NOTE 1: APM support has to be enabled in BIOS and in the kernel.
++
++NOTE 2: Refer to the kernel documentation for additional requirements
++ regarding APM support.
++
++
++10 Troubleshooting
++===================
+
+ If any problems occur during the installation process, check the
+ following list:
+diff -ruN linux/drivers/net/Kconfig linux-new/drivers/net/Kconfig
+--- linux/drivers/net/Kconfig 2005-09-26 13:32:55.000000000 +0400
++++ linux-new/drivers/net/Kconfig 2005-10-21 11:35:52.000267280 +0400
+@@ -2043,6 +2043,7 @@
+ To compile this driver as a module, choose M here: the module
+ will be called r8169. This is recommended.
+
++
+ config SK98LIN
+ tristate "Marvell Yukon Chipset / SysKonnect SK-98xx Support"
+ depends on PCI
+@@ -2052,6 +2053,22 @@
+ by this driver:
+ - 3Com 3C940 Gigabit LOM Ethernet Adapter
+ - 3Com 3C941 Gigabit LOM Ethernet Adapter
++ - 88E8021 Marvell 1000 Mbit PCI-X, single Port Copper
++ - 88E8021 Marvell 1000 Mbit PCI-X, single Port Fiber LX
++ - 88E8021 Marvell 1000 Mbit PCI-X, single Port Fiber SX
++ - 88E8022 Marvell 1000 Mbit PCI-X, dual Port Copper
++ - 88E8022 Marvell 1000 Mbit PCI-X, dual Port Copper (Gateway)
++ - 88E8022 Marvell 1000 Mbit PCI-X, dual Port Fiber LX
++ - 88E8022 Marvell 1000 Mbit PCI-X, dual Port Fiber SX
++ - 88E8061 Marvell 1000 Mbit PCI-E, single Port Copper
++ - 88E8061 Marvell 1000 Mbit PCI-E, single Port Fiber LX
++ - 88E8061 Marvell 1000 Mbit PCI-E, single Port Fiber SX
++ - 88E8062 Marvell 1000 Mbit PCI-E, dual Port Copper
++ - 88E8062 Marvell 1000 Mbit PCI-E, dual Port Copper (Gateway)
++ - 88E8062 Marvell 1000 Mbit PCI-E, dual Port Fiber LX
++ - 88E8062 Marvell 1000 Mbit PCI-E, dual Port Fiber SX
++ - Abocom EFE3K - 10/100 Ethernet Expresscard
++ - Abocom EGE5K - Giga Ethernet Expresscard
+ - Allied Telesyn AT-2970LX Gigabit Ethernet Adapter
+ - Allied Telesyn AT-2970LX/2SC Gigabit Ethernet Adapter
+ - Allied Telesyn AT-2970SX Gigabit Ethernet Adapter
+@@ -2062,31 +2079,81 @@
+ - Allied Telesyn AT-2971T Gigabit Ethernet Adapter
+ - Belkin Gigabit Desktop Card 10/100/1000Base-T Adapter, Copper RJ-45
+ - DGE-530T Gigabit Ethernet Adapter
++ - DGE-560T Gigabit Ethernet Adapter
+ - EG1032 v2 Instant Gigabit Network Adapter
+ - EG1064 v2 Instant Gigabit Network Adapter
+- - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Abit)
+- - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Albatron)
+- - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Asus)
+- - Marvell 88E8001 Gigabit LOM Ethernet Adapter (ECS)
+- - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Epox)
+- - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Foxconn)
+- - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Gigabyte)
+- - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Iwill)
+- - Marvell 88E8050 Gigabit LOM Ethernet Adapter (Intel)
++ - Marvell 88E8001 Gigabit Ethernet Controller (Abit)
++ - Marvell 88E8001 Gigabit Ethernet Controller (Albatron)
++ - Marvell 88E8001 Gigabit Ethernet Controller (Asus)
++ - Marvell 88E8001 Gigabit Ethernet Controller (Chaintech)
++ - Marvell 88E8001 Gigabit Ethernet Controller (ECS)
++ - Marvell 88E8001 Gigabit Ethernet Controller (Epox)
++ - Marvell 88E8001 Gigabit Ethernet Controller (Foxconn)
++ - Marvell 88E8001 Gigabit Ethernet Controller (Gigabyte)
++ - Marvell 88E8001 Gigabit Ethernet Controller (Iwill)
++ - Marvell 88E8035 Fast Ethernet Controller (LGE)
++ - Marvell 88E8035 Fast Ethernet Controller (Toshiba)
++ - Marvell 88E8036 Fast Ethernet Controller (Arima)
++ - Marvell 88E8036 Fast Ethernet Controller (Compal)
++ - Marvell 88E8036 Fast Ethernet Controller (Inventec)
++ - Marvell 88E8036 Fast Ethernet Controller (LGE)
++ - Marvell 88E8036 Fast Ethernet Controller (Mitac)
++ - Marvell 88E8036 Fast Ethernet Controller (Panasonic)
++ - Marvell 88E8036 Fast Ethernet Controller (Quanta)
++ - Marvell 88E8036 Fast Ethernet Controller (Toshiba)
++ - Marvell 88E8036 Fast Ethernet Controller (Wistron)
++ - Marvell 88E8050 Gigabit Ethernet Controller (Gateway)
++ - Marvell 88E8050 Gigabit Ethernet Controller (Intel)
++ - Marvell 88E8052 Gigabit Ethernet Controller (ASRock)
++ - Marvell 88E8052 Gigabit Ethernet Controller (Aopen)
++ - Marvell 88E8052 Gigabit Ethernet Controller (Asus)
++ - Marvell 88E8052 Gigabit Ethernet Controller (Gateway)
++ - Marvell 88E8052 Gigabit Ethernet Controller (Gigabyte)
++ - Marvell 88E8052 Gigabit Ethernet Controller (MSI)
++ - Marvell 88E8052 Gigabit Ethernet Controller (Wistron)
++ - Marvell 88E8053 Gigabit Ethernet Controller (ASRock)
++ - Marvell 88E8053 Gigabit Ethernet Controller (Albatron)
++ - Marvell 88E8053 Gigabit Ethernet Controller (Aopen)
++ - Marvell 88E8053 Gigabit Ethernet Controller (Arima)
++ - Marvell 88E8053 Gigabit Ethernet Controller (Asus)
++ - Marvell 88E8053 Gigabit Ethernet Controller (Chaintech)
++ - Marvell 88E8053 Gigabit Ethernet Controller (Clevo)
++ - Marvell 88E8053 Gigabit Ethernet Controller (Compal)
++ - Marvell 88E8053 Gigabit Ethernet Controller (DFI)
++ - Marvell 88E8053 Gigabit Ethernet Controller (ECS)
++ - Marvell 88E8053 Gigabit Ethernet Controller (Epox)
++ - Marvell 88E8053 Gigabit Ethernet Controller (Gigabyte)
++ - Marvell 88E8053 Gigabit Ethernet Controller (Inventec)
++ - Marvell 88E8053 Gigabit Ethernet Controller (LGE)
++ - Marvell 88E8053 Gigabit Ethernet Controller (MSI)
++ - Marvell 88E8053 Gigabit Ethernet Controller (Mitac)
++ - Marvell 88E8053 Gigabit Ethernet Controller (Panasonic)
++ - Marvell 88E8053 Gigabit Ethernet Controller (Quanta)
++ - Marvell 88E8053 Gigabit Ethernet Controller (SOYO)
++ - Marvell 88E8053 Gigabit Ethernet Controller (Shuttle)
++ - Marvell 88E8053 Gigabit Ethernet Controller (Toshiba)
++ - Marvell 88E8053 Gigabit Ethernet Controller (Trigem)
++ - Marvell RDK-8001
+ - Marvell RDK-8001 Adapter
+ - Marvell RDK-8002 Adapter
++ - Marvell RDK-8003
+ - Marvell RDK-8003 Adapter
+ - Marvell RDK-8004 Adapter
+ - Marvell RDK-8006 Adapter
+ - Marvell RDK-8007 Adapter
+ - Marvell RDK-8008 Adapter
+ - Marvell RDK-8009 Adapter
+- - Marvell RDK-8010 Adapter
++ - Marvell RDK-8010
+ - Marvell RDK-8011 Adapter
+ - Marvell RDK-8012 Adapter
+- - Marvell RDK-8052 Adapter
+- - Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Adapter (32 bit)
+- - Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Adapter (64 bit)
++ - Marvell RDK-8035
++ - Marvell RDK-8036
++ - Marvell RDK-8052
++ - Marvell RDK-8053
++ - Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Controller (32 bit)
++ - Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Controller (64 bit)
++ - Marvell Yukon-EC Ultra, no ASF (Battery Power Service Support)
++ - Marvell Yukon-FE Fast Ethernet, Reduced Battery Power Service Support)
+ - N-Way PCI-Bus Giga-Card 1000/100/10Mbps(L)
+ - SK-9521 10/100/1000Base-T Adapter
+ - SK-9521 V2.0 10/100/1000Base-T Adapter
+@@ -2106,6 +2173,14 @@
+ - SK-9871 Gigabit Ethernet Server Adapter (SK-NET GE-ZX)
+ - SK-9871 V2.0 Gigabit Ethernet 1000Base-ZX Adapter
+ - SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link)
++ - SK-9S21 Server Adapter
++ - SK-9S22 Server Adapter
++ - SK-9S24 Server Adapter
++ - SK-9S34 Server Adapter
++ - SK-9S81 Server Adapter
++ - SK-9S82 Server Adapter
++ - SK-9S91 Server Adapter
++ - SK-9S92 Server Adapter
+ - SMC EZ Card 1000 (SMC9452TXV.2)
+
+ The adapters support Jumbo Frames.
+@@ -2119,8 +2194,16 @@
+
+ If you want to compile this driver as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want),
+- say M here and read Documentation/kbuild/modules.txt. The module will
+- be called sk98lin. This is recommended.
++ say M here and read Documentation/modules.txt. This is recommended.
++ The module will be called sk98lin. This is recommended.
++
++config SK98LIN_NAPI
++ bool "Use Rx polling (NAPI)"
++ depends on SK98LIN
++ help
++ NAPI is a new driver API designed to reduce CPU and interrupt load
++ when the driver is receiving lots of packets from the card.
++
+
+ config TIGON3
+ tristate "Broadcom Tigon3 support"