/******************************************************************************
 *
 * Name:	skgipnmi.c
 * Project:	SysKonnect SK-9Dxx Gigabit Ethernet
 * Version:	$Revision: 1.6 $
 * Date:	$Date: 2001/09/24 09:54:11 $
 * Purpose:	Private Network Management Interface
 *
 ******************************************************************************/

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

/******************************************************************************
 *
 * History:
 *
 *	$Log: skgipnmi.c,v $
 *	Revision 1.6  2001/09/24 09:54:11  mmoser
 *	NdisStat(): allow Instance == -1
 *	
 *	Revision 1.5  2001/09/21 11:50:46  mmoser
 *	make module runnable for W2K
 *	
 *	Revision 1.4  2001/08/14 14:29:31  rschmidt
 *	Added line speed info and counter for Rx errors.
 *	Editorial changes.
 *	
 *	Revision 1.3  2001/08/08 13:32:45  rschmidt
 *	Replaced printk with SK_DBG_MSG
 *	
 *	Revision 1.2  2001/06/05 08:50:56  rassmann
 *	Changed SysKonnectFileId.
 *	
 *	Revision 1.1  2001/06/05 08:28:24  rassmann
 *	First public version.
 *	
 *
 ******************************************************************************/

/******************************************************************************
 *
 * Description:
 *
 ******************************************************************************/

static const char SysKonnectFileId[] =
	"@(#) $Id: skgipnmi.c,v 1.6 2001/09/24 09:54:11 mmoser Exp $ (C) SysKonnect.";

#include "h/skdrv1st.h"
#include "h/skdrv2nd.h"
#include "h/sktypes.h"
#include "h/skgihw.h"
#include "h/skgipnmi.h"
#include "h/skgipnm2.h"


/*
 * Private Function prototypes
 */
static int OidStruct(
	SK_AC		*pAC,
	SK_IOC		IoC,
	int			Action,
	SK_U32		Id,
	char		*pBuf,
	unsigned	*pLen,
	SK_U32		Instance,
	unsigned	TableIndex);
static int NdisStat(
	SK_AC		*pAC,
	SK_IOC		IoC,
	int			Action,
	SK_U32		Id,
	char		*pBuf,
	unsigned	*pLen,
	SK_U32		Instance,
	unsigned	TableIndex);
static int General(
	SK_AC		*pAC,
	SK_IOC		IoC,
	int			Action,
	SK_U32		Id,
	char		*pBuf,
	unsigned	*pLen,
	SK_U32		Instance,
	unsigned	TableIndex);
static int PrivateStat(
	SK_AC		*pAC,
	SK_IOC		IoC,
	int			Action,
	SK_U32		Id,
	char		*pBuf,
	unsigned	*pLen,
	SK_U32		Instance,
	unsigned	TableIndex);
static int LookupId(
	SK_U32		Id);
static int PnmiStruct(
	SK_AC		*pAC,
	SK_IOC		IoC,
	int			Action,
	char		*pBuf,
	unsigned	*pLen);
static int PnmiVar(
	SK_AC		*pAC,
	SK_IOC		IoC,
	int			Action,
	SK_U32		Id,
	char		*pBuf,
	unsigned	*pLen,
	SK_U32		Instance);

/******************************************************************************
 *
 * Global variables
 */

/*
 * Table to correlate OID with handler function and index to
 * hardware register stored in StatAddress if applicable.
 */
static const SK_PNMI_TAB_ENTRY IdTable[] = {
	{OID_GEN_XMIT_OK,
		0,
		0,
		0,
		SK_PNMI_RO, NdisStat},
	{OID_GEN_RCV_OK,
		0,
		0,
		0,
		SK_PNMI_RO, NdisStat},
	{OID_GEN_XMIT_ERROR,
		0,
		0,
		0,
		SK_PNMI_RO, NdisStat},
	{OID_GEN_RCV_ERROR,
		0,
		0,
		0,
		SK_PNMI_RO, NdisStat},
	{OID_GEN_DIRECTED_FRAMES_XMIT,
		0,
		0,
		0,
		SK_PNMI_RO, NdisStat},
	{OID_GEN_MULTICAST_FRAMES_XMIT,
		0,
		0,
		0,
		SK_PNMI_RO, NdisStat},
	{OID_GEN_BROADCAST_FRAMES_XMIT,
		0,
		0,
		0,
		SK_PNMI_RO, NdisStat},
	{OID_GEN_DIRECTED_FRAMES_RCV,
		0,
		0,
		0,
		SK_PNMI_RO, NdisStat},
	{OID_GEN_MULTICAST_FRAMES_RCV,
		0,
		0,
		0,
		SK_PNMI_RO, NdisStat},
	{OID_GEN_BROADCAST_FRAMES_RCV,
		0,
		0,
		0,
		SK_PNMI_RO, NdisStat},
	{OID_GEN_RCV_CRC_ERROR,
		0,
		0,
		0,
		SK_PNMI_RO, NdisStat},
	{OID_802_3_RCV_ERROR_ALIGNMENT,
		0,
		0,
		0,
		SK_PNMI_RO, NdisStat},
	{OID_802_3_XMIT_ONE_COLLISION,
		0,
		0,
		0,
		SK_PNMI_RO, NdisStat},
	{OID_802_3_XMIT_MORE_COLLISIONS,
		0,
		0,
		0,
		SK_PNMI_RO, NdisStat},
	{OID_802_3_XMIT_DEFERRED,
		0,
		0,
		0,
		SK_PNMI_RO, NdisStat},
	{OID_802_3_XMIT_MAX_COLLISIONS,
		0,
		0,
		0,
		SK_PNMI_RO, NdisStat},
	{OID_802_3_RCV_OVERRUN,
		0,
		0,
		0,
		SK_PNMI_RO, NdisStat},
	{OID_802_3_XMIT_UNDERRUN,
		0,
		0,
		0,
		SK_PNMI_RO, NdisStat},
	{OID_802_3_XMIT_TIMES_CRS_LOST,
		0,
		0,
		0,
		SK_PNMI_RO, NdisStat},
	{OID_802_3_XMIT_LATE_COLLISIONS,
		0,
		0,
		0,
		SK_PNMI_RO, NdisStat},
	{OID_SKGE_MDB_VERSION,
		1,
		0,
		SK_PNMI_MAI_OFF(MgmtDBVersion),
		SK_PNMI_RO, General},
	{OID_SKGE_SUPPORTED_LIST,
		0,
		0,
		0,
		SK_PNMI_RO, General},
	{OID_SKGE_ALL_DATA,
		0,
		0,
		0,
		SK_PNMI_RW, OidStruct},
	{OID_SKGE_PORT_NUMBER,		
		1,
		0,
		SK_PNMI_MAI_OFF(PortNumber),
		SK_PNMI_RO, General},
	{OID_SKGE_DEVICE_TYPE,
		1,
		0,
		SK_PNMI_MAI_OFF(DeviceType),
		SK_PNMI_RO, General},
	{OID_SKGE_DRIVER_DESCR,
		1,
		0,
		SK_PNMI_MAI_OFF(DriverDescr),
		SK_PNMI_RO, General},
	{OID_SKGE_DRIVER_VERSION,
		1,
		0,
		SK_PNMI_MAI_OFF(DriverVersion),
		SK_PNMI_RO, General},
	{OID_SKGE_BUS_TYPE,
		1,
		0,
		SK_PNMI_MAI_OFF(BusType),
		SK_PNMI_RO, General},
	{OID_SKGE_BUS_SPEED,
		1,
		0,
		SK_PNMI_MAI_OFF(BusSpeed),
		SK_PNMI_RO, General},
	{OID_SKGE_BUS_WIDTH,
		1,
		0,
		SK_PNMI_MAI_OFF(BusWidth),
		SK_PNMI_RO, General},
	{OID_SKGE_LINK_SPEED,
		1,
		0,
		SK_PNMI_MAI_OFF(EthSpeed),
		SK_PNMI_RO, General},
	{OID_SKGE_TX_RETRY,
		1,
		0,
		SK_PNMI_MAI_OFF(TxRetryCts),
		SK_PNMI_RO, General},
	{OID_SKGE_RX_INTR_CTS,
		1,
		0,
		SK_PNMI_MAI_OFF(RxIntrCts),
		SK_PNMI_RO, General},
	{OID_SKGE_TX_INTR_CTS,
		1,
		0,
		SK_PNMI_MAI_OFF(TxIntrCts),
		SK_PNMI_RO, General},
	{OID_SKGE_RX_NO_BUF_CTS,
		1,
		0,
		SK_PNMI_MAI_OFF(RxNoBufCts),
		SK_PNMI_RO, General},
	{OID_SKGE_TX_NO_BUF_CTS,
		1,
		0,
		SK_PNMI_MAI_OFF(TxNoBufCts),
		SK_PNMI_RO, General},
	{OID_SKGE_TX_USED_DESCR_NO,
		1,
		0,
		SK_PNMI_MAI_OFF(TxUsedDescrNo),
		SK_PNMI_RO, General},
	{OID_SKGE_RX_DELIVERED_CTS,
		1,
		0,
		SK_PNMI_MAI_OFF(RxDeliveredCts),
		SK_PNMI_RO, General},
	{OID_SKGE_RX_OCTETS_DELIV_CTS,
		1,
		0,
		SK_PNMI_MAI_OFF(RxOctetsDeliveredCts),
		SK_PNMI_RO, General},
	{OID_SKGE_RX_HW_ERROR_CTS,
		1,
		0,
		SK_PNMI_MAI_OFF(RxHwErrorsCts),
		SK_PNMI_RO, General},
	{OID_SKGE_TX_HW_ERROR_CTS,
		1,
		0,
		SK_PNMI_MAI_OFF(TxHwErrorsCts),
		SK_PNMI_RO, General},
	{OID_SKGE_IN_ERRORS_CTS,
		1,
		0,
		SK_PNMI_MAI_OFF(InErrorsCts),
		SK_PNMI_RO, General},
	{OID_SKGE_OUT_ERROR_CTS,
		1,
		0,
		SK_PNMI_MAI_OFF(OutErrorsCts),
		SK_PNMI_RO, General},
	{OID_SKGE_ERR_RECOVERY_CTS,
		1,
		0,
		SK_PNMI_MAI_OFF(ErrRecoveryCts),
		SK_PNMI_RO, General},
	{OID_SKGE_SYSUPTIME,
		1,
		0,
		SK_PNMI_MAI_OFF(SysUpTime),
		SK_PNMI_RO, General},
	{OID_SKGE_STAT_TX,
		SK_PNMI_MAC_ENTRIES,
		sizeof(SK_PNMI_STAT),
		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(COSIfHCOutPkts),
		SK_PNMI_RO, PrivateStat},
	{OID_SKGE_STAT_TX_OCTETS,
		SK_PNMI_MAC_ENTRIES,
		sizeof(SK_PNMI_STAT),
		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(ifHCOutOctets),
		SK_PNMI_RO, PrivateStat},
	{OID_SKGE_STAT_TX_BROADCAST,
		SK_PNMI_MAC_ENTRIES,
		sizeof(SK_PNMI_STAT),
		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(ifHCOutBroadcastPkts),
		SK_PNMI_RO, PrivateStat},
	{OID_SKGE_STAT_TX_MULTICAST,
		SK_PNMI_MAC_ENTRIES,
		sizeof(SK_PNMI_STAT),
		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(ifHCOutMulticastPkts),
		SK_PNMI_RO, PrivateStat},
	{OID_SKGE_STAT_TX_UNICAST,
		SK_PNMI_MAC_ENTRIES,
		sizeof(SK_PNMI_STAT),
		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(ifHCOutUcastPkts),
		SK_PNMI_RO, PrivateStat},
	{OID_SKGE_STAT_TX_SINGLE_COL,
		SK_PNMI_MAC_ENTRIES,
		sizeof(SK_PNMI_STAT),
		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(dot3StatsSingleCollisionFrames),
		SK_PNMI_RO, PrivateStat},
	{OID_SKGE_STAT_TX_MULTI_COL,
		SK_PNMI_MAC_ENTRIES,
		sizeof(SK_PNMI_STAT),
		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(dot3StatsMultipleCollisionFrames),
		SK_PNMI_RO, PrivateStat},
	{OID_SKGE_STAT_TX_EXCESS_COL,
		SK_PNMI_MAC_ENTRIES,
		sizeof(SK_PNMI_STAT),
		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(dot3StatsExcessiveCollisions),
		SK_PNMI_RO, PrivateStat},
	{OID_SKGE_STAT_TX_LATE_COL,
		SK_PNMI_MAC_ENTRIES,
		sizeof(SK_PNMI_STAT),
		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(dot3StatsLateCollisions),
		SK_PNMI_RO, PrivateStat},
	{OID_SKGE_STAT_TX_DEFFERAL,
		SK_PNMI_MAC_ENTRIES,
		sizeof(SK_PNMI_STAT),
		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(dot3StatsDeferredTransmissions),
		SK_PNMI_RO, PrivateStat},
	{OID_SKGE_STAT_TX_UNDERRUN,
		SK_PNMI_MAC_ENTRIES,
		sizeof(SK_PNMI_STAT),
		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(dot3StatsInternalMacTransmitErrors),
		SK_PNMI_RO, PrivateStat},
	{OID_SKGE_STAT_TX_CARRIER,
		SK_PNMI_MAC_ENTRIES,
		sizeof(SK_PNMI_STAT),
		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(dot3StatsCarrierSenseErrors),
		SK_PNMI_RO, PrivateStat},
	{OID_SKGE_STAT_RX,
		SK_PNMI_MAC_ENTRIES,
		sizeof(SK_PNMI_STAT),
		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(COSIfHCInPkts),
		SK_PNMI_RO, PrivateStat},
	{OID_SKGE_STAT_RX_OCTETS,
		SK_PNMI_MAC_ENTRIES,
		sizeof(SK_PNMI_STAT),
		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(ifHCInOctets),
		SK_PNMI_RO, PrivateStat},
	{OID_SKGE_STAT_RX_BROADCAST,
		SK_PNMI_MAC_ENTRIES,
		sizeof(SK_PNMI_STAT),
		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(ifHCInBroadcastPkts),
		SK_PNMI_RO, PrivateStat},
	{OID_SKGE_STAT_RX_MULTICAST,
		SK_PNMI_MAC_ENTRIES,
		sizeof(SK_PNMI_STAT),
		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(ifHCInMulticastPkts),
		SK_PNMI_RO, PrivateStat},
	{OID_SKGE_STAT_RX_UNICAST,
		SK_PNMI_MAC_ENTRIES,
		sizeof(SK_PNMI_STAT),
		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(ifHCInUcastPkts),
		SK_PNMI_RO, PrivateStat},
	{OID_SKGE_STAT_RX_MISSED,
		SK_PNMI_MAC_ENTRIES,
		sizeof(SK_PNMI_STAT),
		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(ifInDiscards),
		SK_PNMI_RO, PrivateStat},
	{OID_SKGE_STAT_RX_FRAMING,
		SK_PNMI_MAC_ENTRIES,
		sizeof(SK_PNMI_STAT),
		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(dot3StatsAlignmentErrors),
		SK_PNMI_RO, PrivateStat},
	{OID_SKGE_STAT_RX_OVERFLOW,
		SK_PNMI_MAC_ENTRIES,
		sizeof(SK_PNMI_STAT),
		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(nicNoMoreRxBDs),
		SK_PNMI_RO, PrivateStat},
	{OID_SKGE_STAT_RX_JABBER,
		SK_PNMI_MAC_ENTRIES,
		sizeof(SK_PNMI_STAT),
		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(etherStatsJabbers),
		SK_PNMI_RO, PrivateStat},
	{OID_SKGE_STAT_RX_RUNT,
		SK_PNMI_MAC_ENTRIES,
		sizeof(SK_PNMI_STAT),
		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(etherStatsUndersizePkts),
		SK_PNMI_RO, PrivateStat},
	{OID_SKGE_STAT_RX_CEXT,
		SK_PNMI_MAC_ENTRIES,
		sizeof(SK_PNMI_STAT),
		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(ifInErrors),
		SK_PNMI_RO, PrivateStat},
	{OID_SKGE_STAT_RX_TOO_LONG,
		SK_PNMI_MAC_ENTRIES,
		sizeof(SK_PNMI_STAT),
		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(dot3StatsFramesTooLong),
		SK_PNMI_RO, PrivateStat},
	{OID_SKGE_STAT_RX_FRAGMENTS,
		SK_PNMI_MAC_ENTRIES,
		sizeof(SK_PNMI_STAT),
		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(etherStatsFragments),
		SK_PNMI_RO, PrivateStat},
	{OID_SKGE_STAT_RX_FCS,
		SK_PNMI_MAC_ENTRIES,
		sizeof(SK_PNMI_STAT),
		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(dot3StatsFCSErrors),
		SK_PNMI_RO, PrivateStat},
	{OID_SKGE_STAT_RX_64,
		SK_PNMI_MAC_ENTRIES,
		sizeof(SK_PNMI_STAT),
		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(etherStatsPkts64Octets),
		SK_PNMI_RO, PrivateStat},
	{OID_SKGE_STAT_RX_127,
		SK_PNMI_MAC_ENTRIES,
		sizeof(SK_PNMI_STAT),
		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(etherStatsPkts65Octetsto127Octets),
		SK_PNMI_RO, PrivateStat},
	{OID_SKGE_STAT_RX_255,
		SK_PNMI_MAC_ENTRIES,
		sizeof(SK_PNMI_STAT),
		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(etherStatsPkts128Octetsto255Octets),
		SK_PNMI_RO, PrivateStat},
	{OID_SKGE_STAT_RX_511,
		SK_PNMI_MAC_ENTRIES,
		sizeof(SK_PNMI_STAT),
		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(etherStatsPkts256Octetsto511Octets),
		SK_PNMI_RO, PrivateStat},
	{OID_SKGE_STAT_RX_1023,
		SK_PNMI_MAC_ENTRIES,
		sizeof(SK_PNMI_STAT),
		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(etherStatsPkts512Octetsto1023Octets),
		SK_PNMI_RO, PrivateStat},
	{OID_SKGE_STAT_RX_MAX,
		SK_PNMI_MAC_ENTRIES,
		sizeof(SK_PNMI_STAT),
		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(etherStatsPkts1024Octetsto9022Octets),
		SK_PNMI_RO, PrivateStat},
};

/*****************************************************************************
 *
 * Public functions
 *
 */

/*****************************************************************************
 *
 * SkPnmiInit - Init function of PNMI
 *
 * Description:
 *	SK_INIT_DATA: Initialises the data structures
 *	SK_INIT_IO:   Resets the XMAC statistics, determines the device and
 *	              connector type.
 *	SK_INIT_RUN:  Starts a timer event for port switch per hour
 *	              calculation.
 *
 * Returns:
 *	Always 0
 */

void SkPnmiInit(
SK_AC	*pAC,	/* the adapter context */
SK_IOC	IoC,	/* I/O context */
int		Level)	/* initialization level */
{
//	SK_U32	Data32;
//	SK_U16	Data16;

	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
		("PNMI: SkPnmiInit: Called"));

	switch (Level) {
	case SK_INIT_DATA:
		memset((char *)&pAC->Pnmi, 0, sizeof(pAC->Pnmi));
		/*
		 * Save StartUpTime
		 */
		pAC->Pnmi.StartUpTime = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC));
		break;

	case SK_INIT_IO:
		/*
		 * Determine the adapter type
		 */
//		SK_PCI_IN16(pAC, PCI_SUBDEVICE_ID, &Data16);
//		pAC->Pnmi.DeviceType = Data16;
		pAC->Pnmi.DeviceType = (SK_U16)(pAC->Hw.SubsystemVendorId >> 16);
		/*
		 * Get bus mode, 1 is PCI, 2 means PCI-X
		 */
//		SK_PCI_IN32(pAC, PCI_STATE_REG, &Data32);
		
//		if ((Data32 & CONVENTIONAL_PCI_MODE) != 0) {
		if ((pAC->Hw.PciState & CONVENTIONAL_PCI_MODE) != 0) {
			pAC->Pnmi.PciBusType = 1;
		}
		else{
			pAC->Pnmi.PciBusType = 2;
		}

		/*
		 * Get bus speed 33, 66, 133
		 */
//		if ((Data32 & BUS_SPEED_HIGH) == 0) {
		if ((pAC->Hw.PciState & BUS_SPEED_HIGH) == 0) {
			pAC->Pnmi.PciBusSpeed = 33;
		}
		else{
			pAC->Pnmi.PciBusSpeed = 66;
		}

		/*
		 * Get bus width, 32Bit or 64Bit
		 */
//		if ((Data32 & PCI_BUS_32_BIT) == 0) {
		if ((pAC->Hw.PciState & PCI_BUS_32_BIT) == 0) {
			pAC->Pnmi.PciBusWidth = 64;	
		}
		else {
			pAC->Pnmi.PciBusWidth = 32;	
		}
		break;

	case SK_INIT_RUN:
		pAC->Pnmi.EthLinkSpeed = pAC->Hw.LineSpeed;
		break;

	default:
		break;
	}
}

/*****************************************************************************
 *
 * SkPnmiGetVar - Retrieves the value of a single OID
 *
 * Description:
 *	Calls a general sub-function for all this stuff. If the instance
 *	-1 is passed, the values of all instances are returned in an
 *	array of values.
 *
 * 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 take
 *	                         the data.
 *	SK_PNMI_ERR_UNKNOWN_OID  The requested OID is unknown
 *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
 *                               exist (e.g. port instance 3 on a two port
 *	                         adapter.
 */

int SkPnmiGetVar(
SK_AC		*pAC,		/* Pointer to adapter context */
SK_IOC		IoC,		/* IO context handle */
SK_U32		Id,			/* Object ID that is to be processed */
void		*pBuf,		/* Buffer to which to mgmt data will be retrieved */
unsigned	*pLen,		/* On call: buffer length. On return: used buffer */
SK_U32		Instance)	/* Instance (1..n) that is to be queried or -1 */
{
	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
		("PNMI: SkPnmiGetVar: Called, Id=0x%x, BufLen=%d, Instance=%d\n",
			Id, *pLen, Instance));

	return (PnmiVar(pAC, IoC, SK_PNMI_GET, Id, (char *)pBuf, pLen, Instance));
}

/*****************************************************************************
 *
 * SkPnmiPreSetVar - Presets the value of a single OID
 *
 * Description:
 *	Calls a general sub-function for all this stuff. The preset does
 *	the same as a set, but returns just before finally setting the
 *	new value. This is usefull to check if a set might be successfull.
 *	If as instance a -1 is passed, an array of values is supposed and
 *	all instance of the OID will be set.
 *
 * 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_BAD_VALUE    The passed value is not in the valid
 *	                         value range.
 *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
 *	SK_PNMI_ERR_UNKNOWN_OID  The requested OID is unknown.
 *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
 *                               exist (e.g. port instance 3 on a two port
 *	                         adapter.
 */

int SkPnmiPreSetVar(
SK_AC		*pAC,		/* Pointer to adapter context */
SK_IOC		IoC,		/* IO context handle */
SK_U32		Id,			/* Object ID that is to be processed */
void		*pBuf,		/* Buffer which stores the mgmt data to be set */
unsigned	*pLen,		/* Total length of mgmt data */
SK_U32		Instance)	/* Instance (1..n) that is to be set or -1 */
{
	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
		("PNMI: SkPnmiPreSetVar: Called, Id=0x%x, BufLen=%d, Instance=%d\n",
			Id, *pLen, Instance));

	return (PnmiVar(pAC, IoC, SK_PNMI_PRESET, Id, (char *)pBuf, pLen, Instance));
}

/*****************************************************************************
 *
 * SkPnmiSetVar - Sets the value of a single OID
 *
 * Description:
 *	Calls a general sub-function for all this stuff. The preset does
 *	the same as a set, but returns just before finally setting the
 *	new value. This is usefull to check if a set might be successfull.
 *	If as instance a -1 is passed, an array of values is supposed and
 *	all instance of the OID will be set.
 *
 * 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_BAD_VALUE    The passed value is not in the valid
 *	                         value range.
 *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
 *	SK_PNMI_ERR_UNKNOWN_OID  The requested OID is unknown.
 *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
 *                               exist (e.g. port instance 3 on a two port
 *	                         adapter.
 */

int SkPnmiSetVar(
SK_AC		*pAC,		/* Pointer to adapter context */
SK_IOC		IoC,		/* IO context handle */
SK_U32		Id,			/* Object ID that is to be processed */
void		*pBuf,		/* Buffer which stores the mgmt data to be set */
unsigned	*pLen,		/* Total length of mgmt data */
SK_U32		Instance)	/* Instance (1..n) that is to be set or -1 */
{
	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
		("PNMI: SkPnmiSetVar: Called, Id=0x%x, BufLen=%d, Instance=%d\n",
			Id, *pLen, Instance));

	return (PnmiVar(pAC, IoC, SK_PNMI_SET, Id, (char *)pBuf, pLen, Instance));
}

/*****************************************************************************
 *
 * SkPnmiGetStruct - Retrieves the management database in SK_PNMI_STRUCT_DATA
 *
 * Description:
 *	Runs through the IdTable, queries the single OIDs and stores the
 *	returned data into the management database structure
 *	SK_PNMI_STRUCT_DATA. The offset of the OID in the structure
 *	is stored in the IdTable. The return value of the function will also
 *	be stored in SK_PNMI_STRUCT_DATA if the passed buffer has the
 *	minimum size of SK_PNMI_MIN_STRUCT_SIZE.
 *
 * 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 take
 *	                         the data.
 *	SK_PNMI_ERR_UNKNOWN_NET  The requested NetIndex doesn't exist
 */

int SkPnmiGetStruct(
SK_AC		*pAC,		/* Pointer to adapter context */
SK_IOC		IoC,		/* IO context handle */
void		*pBuf,		/* Buffer which will store the retrieved data */
unsigned	*pLen)		/* Length of buffer */
{
	int			Ret;
	unsigned	TableIndex;
	unsigned	DstOffset;
	unsigned	InstanceNo;
	unsigned	InstanceCnt;
	SK_U32		Instance;
	unsigned	TmpLen;


	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
		("PNMI: SkPnmiGetStruct: Called, BufLen=%d\n",
			*pLen));

	if (*pLen < SK_PNMI_STRUCT_SIZE) {
		*pLen = SK_PNMI_STRUCT_SIZE;
		return (SK_PNMI_ERR_TOO_SHORT);
	}

	/* Retrieve values */
	memset((char *)pBuf, 0, SK_PNMI_STRUCT_SIZE);

	for (TableIndex = 0; TableIndex < sizeof(IdTable) / sizeof(IdTable[0]);
		TableIndex ++) {

		InstanceNo = IdTable[TableIndex].InstanceNo;
		for (InstanceCnt = 1; InstanceCnt <= InstanceNo; InstanceCnt ++) {
			DstOffset = IdTable[TableIndex].Offset +
				(InstanceCnt - 1) * IdTable[TableIndex].StructSize;

			Instance = (SK_U32)InstanceCnt;

			TmpLen = *pLen - DstOffset;
			Ret = IdTable[TableIndex].Func(pAC, IoC, SK_PNMI_GET,
				IdTable[TableIndex].Id, (char *)pBuf +
				DstOffset, &TmpLen, Instance, TableIndex);

			/*
			 * An unknown instance error means that we reached
			 * the last instance of that variable. Proceed with
			 * the next OID in the table and ignore the return
			 * code.
			 */
			if (Ret == SK_PNMI_ERR_UNKNOWN_INST) {
                break;
			}

			if (Ret != SK_PNMI_ERR_OK) {
				return (Ret);
			}
		}
	}

	*pLen = SK_PNMI_STRUCT_SIZE;
	SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_OK, (SK_U32)(-1));
	return (SK_PNMI_ERR_OK);
}

/*****************************************************************************
 *
 * SkPnmiPreSetStruct - Presets the management database in SK_PNMI_STRUCT_DATA
 *
 * Description:
 *	Calls a general sub-function for all this set stuff. The preset does
 *	the same as a set, but returns just before finally setting the
 *	new value. This is usefull to check if a set might be successfull.
 *	The sub-function runs through the IdTable, checks which OIDs are able
 *	to set, and calls the handler function of the OID to perform the
 *	preset. The return value of the function will also be stored in
 *	SK_PNMI_STRUCT_DATA if the passed buffer has the minimum size of
 *	SK_PNMI_MIN_STRUCT_SIZE.
 *
 * 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_BAD_VALUE    The passed value is not in the valid
 *	                         value range.
 */

int SkPnmiPreSetStruct(
SK_AC		*pAC,		/* Pointer to adapter context */
SK_IOC		IoC,		/* IO context handle */
void		*pBuf,		/* Buffer which contains the data to be set */
unsigned	*pLen)		/* Length of buffer */
{
	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
		("PNMI: SkPnmiPreSetStruct: Called, BufLen=%d\n",
			*pLen));

	return (PnmiStruct(pAC, IoC, SK_PNMI_PRESET, (char *)pBuf, pLen));
}

/*****************************************************************************
 *
 * SkPnmiSetStruct - Sets the management database in SK_PNMI_STRUCT_DATA
 *
 * Description:
 *	Calls a general sub-function for all this set stuff. The return value
 *	of the function will also be stored in SK_PNMI_STRUCT_DATA if the
 *	passed buffer has the minimum size of SK_PNMI_MIN_STRUCT_SIZE.
 *	The sub-function runs through the IdTable, checks which OIDs are able
 *	to set, and calls the handler function of the OID to perform the
 *	set. The return value of the function will also be stored in
 *	SK_PNMI_STRUCT_DATA if the passed buffer has the minimum size of
 *	SK_PNMI_MIN_STRUCT_SIZE.
 *
 * 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_BAD_VALUE    The passed value is not in the valid
 *	                         value range.
 */

int SkPnmiSetStruct(
SK_AC *pAC,		/* Pointer to adapter context */
SK_IOC IoC,		/* IO context handle */
void *pBuf,		/* Buffer which contains the data to be set */
unsigned int *pLen)	/* Length of buffer */
{
	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
		("PNMI: SkPnmiSetStruct: Called, BufLen=%d\n",
			*pLen));

	return (PnmiStruct(pAC, IoC, SK_PNMI_SET, (char *)pBuf, pLen));
}


/******************************************************************************
 *
 * Private functions
 *
 */

/*****************************************************************************
 *
 * PnmiVar - Gets, presets, and sets single OIDs
 *
 * Description:
 *	Looks up the requested OID, calls the corresponding handler
 *	function, and passes the parameters with the get, preset, or
 *	set command. The function is called by SkGePnmiGetVar,
 *	SkGePnmiPreSetVar, or SkGePnmiSetVar.
 *
 * Returns:
 *	SK_PNMI_ERR_XXX. For details have a look to the description of the
 *	calling functions.
 *	SK_PNMI_ERR_UNKNOWN_NET  The requested NetIndex doesn't exist
 */

static int PnmiVar(
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 which stores the mgmt data to be set */
unsigned	*pLen,		/* Total length of mgmt data */
SK_U32		Instance)	/* Instance (1..n) that is to be set or -1 */
{
	unsigned int	TableIndex;
	int		Ret;


	if ((TableIndex = LookupId(Id)) == (unsigned int)(-1)) {
		*pLen = 0;
		return (SK_PNMI_ERR_UNKNOWN_OID);
	}
	
	SK_PNMI_CHECKFLAGS("PnmiVar: On call");

	Ret = IdTable[TableIndex].Func(pAC, IoC, Action, Id, pBuf, pLen,
		Instance, TableIndex);

	SK_PNMI_CHECKFLAGS("PnmiVar: On return");

	return (Ret);
}

/*****************************************************************************
 *
 * PnmiStruct - Presets and Sets data in structure SK_PNMI_STRUCT_DATA
 *
 * Description:
 *	The return value of the function will also be stored in
 *	SK_PNMI_STRUCT_DATA if the passed buffer has the minimum size of
 *	SK_PNMI_MIN_STRUCT_SIZE. The sub-function runs through the IdTable,
 *	checks which OIDs are able to set, and calls the handler function of
 *	the OID to perform the set. The return value of the function will
 *	also be stored in SK_PNMI_STRUCT_DATA if the passed buffer has the
 *	minimum size of SK_PNMI_MIN_STRUCT_SIZE. The function is called
 *	by SkGePnmiPreSetStruct and SkGePnmiSetStruct.
 *
 * Returns:
 *	SK_PNMI_ERR_XXX. The codes are described in the calling functions.
 *	SK_PNMI_ERR_UNKNOWN_NET  The requested NetIndex doesn't exist
 */

static int PnmiStruct(
SK_AC		*pAC,		/* Pointer to adapter context */
SK_IOC		IoC,		/* IO context handle */
int			Action,		/* Set action to be performed */
char		*pBuf,		/* Buffer which contains the data to be set */
unsigned	*pLen)		/* Length of buffer */
{
	int		Ret;
	unsigned int	TableIndex;
	unsigned int	DstOffset;
	unsigned int	Len;
	unsigned int	InstanceNo;
	unsigned int	InstanceCnt;
	SK_U32		Instance;
	SK_U32		Id;


	/* Check if the passed buffer has the right size */
	if (*pLen < SK_PNMI_STRUCT_SIZE) {
		*pLen = SK_PNMI_STRUCT_SIZE;
		return (SK_PNMI_ERR_TOO_SHORT);
	}
	
	SK_PNMI_CHECKFLAGS("PnmiStruct: On call");

	/* Preset/Set values */
	for (TableIndex = 0; TableIndex < sizeof(IdTable)/sizeof(IdTable[0]);
		TableIndex ++) {

		if (IdTable[TableIndex].Access != SK_PNMI_RW) {
			continue;
		}

		InstanceNo = IdTable[TableIndex].InstanceNo;
		Id = IdTable[TableIndex].Id;

		for (InstanceCnt = 1; InstanceCnt <= InstanceNo; InstanceCnt ++) {
			DstOffset = IdTable[TableIndex].Offset +
				(InstanceCnt - 1) * IdTable[TableIndex].StructSize;

			Instance = (SK_U32)InstanceCnt;

			/*
			 * Evaluate needed buffer length
			 */
			Len = 0;
			Ret = IdTable[TableIndex].Func(pAC, IoC, SK_PNMI_GET,
				IdTable[TableIndex].Id, NULL, &Len, Instance, TableIndex);

			if (Ret == SK_PNMI_ERR_UNKNOWN_INST) {
				break;
			}
			if (Ret != SK_PNMI_ERR_TOO_SHORT) {
				return (SK_PNMI_ERR_GENERAL);
			}

			/* Call the OID handler function */
			Ret = IdTable[TableIndex].Func(pAC, IoC, Action,
				IdTable[TableIndex].Id, pBuf + DstOffset,
				&Len, Instance, TableIndex);

			if (Ret != SK_PNMI_ERR_OK) {
				return (SK_PNMI_ERR_BAD_VALUE);
			}
		}
	}

	return (SK_PNMI_ERR_OK);
}

/*****************************************************************************
 *
 * LookupId - Lookup an OID in the IdTable
 *
 * Description:
 *	Scans the IdTable to find the table entry of an OID.
 *
 * Returns:
 *	The table index or -1 if not found.
 */

static int LookupId(
SK_U32	Id)		/* Object identifier to be searched */
{
	int i;
	int Len = sizeof(IdTable)/sizeof(IdTable[0]);

	for (i = 0; i < Len; i++) {
		if (IdTable[i].Id == Id) {
			return i;
		}
	}

	return (-1);
}
/*****************************************************************************
 *
 * OidStruct - Handler of OID_SKGE_ALL_DATA
 *
 * Description:
 *	This OID performs a Get/Preset/SetStruct call and returns all data
 *	in a SK_PNMI_STRUCT_DATA structure.
 *
 * 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_BAD_VALUE    The passed value is not in the valid
 *	                         value range.
 *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
 *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
 *                               exist (e.g. port instance 3 on a two port
 *	                         adapter.
 */

static int OidStruct(
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 to which to mgmt data will be retrieved */
unsigned	*pLen,		/* On call: buffer length. On return: used buffer */
SK_U32		Instance,	/* Instance (1..n) that is to be queried or -1 */
unsigned	TableIndex)	/* Index to the Id table */
{

	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
		("PNMI: OidStruct: Called, BufLen=%d, Id=0x%x, Instance=%d\n",
			*pLen, Id, Instance));

	if (Id != OID_SKGE_ALL_DATA) {
		*pLen = 0;
		return (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);
	}

	switch (Action) {
	case SK_PNMI_GET:
		return (SkPnmiGetStruct(pAC, IoC, pBuf, pLen));

	case SK_PNMI_PRESET:
		return (SkPnmiPreSetStruct(pAC, IoC, pBuf, pLen));

	case SK_PNMI_SET:
		return (SkPnmiSetStruct(pAC, IoC, pBuf, pLen));
	}

	*pLen = 0;
	return (SK_PNMI_ERR_GENERAL);
}

/*****************************************************************************
 *
 * NdisStat - OID handler of OID_GEN_XXX and OID_802_3_XXX
 *
 * Description:
 *	Retrieves the statistic values of the virtual port (logical
 *	index 0). Only special OIDs of NDIS are handled which consist
 *	of a 32 bit instead of a 64 bit value. The OIDs are public
 *	because perhaps some other platform can use them too.
 *
 * 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.
 */

static int NdisStat(
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 to which to mgmt data will be retrieved */
unsigned	*pLen,		/* On call: buffer length. On return: used buffer */
SK_U32		Instance,	/* Instance (1..n) that is to be queried or -1 */
unsigned	TableIndex)	/* Index to the Id table */
{
	SK_U64			Val64;

	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
		("PNMI: NdisStat: Called, BufLen=%d, Id=0x%x, Instance=%d\n",
			*pLen, Id, Instance));
	/*
	 * Check instance
	 */
	if (Instance != (SK_U32)-1 &&
		Instance != 1 ) {
		*pLen = 0;
		return (SK_PNMI_ERR_UNKNOWN_INST);
	}

	/*
	 * Check action type, we only handle read access
	 */
	if (Action != SK_PNMI_GET) {
		*pLen = 0;
		return (SK_PNMI_ERR_READ_ONLY);
	}

	/*
	 * Check length
	 */
	if (*pLen < sizeof(SK_U64)) {
		*pLen = sizeof(SK_U64);
		return (SK_PNMI_ERR_TOO_SHORT);
	}
		
	/*
	 * Get value
	 */
	switch (Id) {
	case OID_GEN_XMIT_OK:
		Val64 = pAC->Pnmi.TxPacketGoodCnt ;
		break;
		
	case OID_GEN_RCV_OK:
		Val64 = pAC->Pnmi.RxPacketGoodCnt;
		break;
		
	case OID_GEN_XMIT_ERROR:
		Val64 = (SK_U64)pAC->pPnmiStatBlock->ifOutErrors.Low +
			((SK_U64)pAC->pPnmiStatBlock->ifOutErrors.High << 32);
		break;

	case OID_GEN_RCV_ERROR:
		Val64 = pAC->Pnmi.RxPacketErrCnt;
		break;
		
	case OID_GEN_DIRECTED_FRAMES_XMIT:
		Val64 = (SK_U64)pAC->pPnmiStatBlock->ifHCOutUcastPkts.Low +
			((SK_U64)pAC->pPnmiStatBlock->ifHCOutUcastPkts.High << 32);
		break;
		
	case OID_GEN_MULTICAST_FRAMES_XMIT:
		Val64 = pAC->pPnmiStatBlock->ifHCOutMulticastPkts.Low +
			((SK_U64)pAC->pPnmiStatBlock->ifHCOutMulticastPkts.High << 32);
		break;
		
	case OID_GEN_BROADCAST_FRAMES_XMIT:
		Val64 = pAC->pPnmiStatBlock->ifHCOutBroadcastPkts.Low +
			((SK_U64)pAC->pPnmiStatBlock->ifHCOutBroadcastPkts.High << 32);
		break;
		
	case OID_GEN_DIRECTED_FRAMES_RCV:
		Val64 = pAC->pPnmiStatBlock->ifHCInUcastPkts.Low +
			((SK_U64)pAC->pPnmiStatBlock->ifHCInUcastPkts.High << 32);
		break;
		
	case OID_GEN_MULTICAST_FRAMES_RCV:
		Val64 = pAC->pPnmiStatBlock->ifHCInMulticastPkts.Low +
			((SK_U64)pAC->pPnmiStatBlock->ifHCInMulticastPkts.High << 32);
		break;
		
	case OID_GEN_BROADCAST_FRAMES_RCV:
		Val64 = pAC->pPnmiStatBlock->ifHCInBroadcastPkts.Low +
			((SK_U64)pAC->pPnmiStatBlock->ifHCInBroadcastPkts.High << 32);
		break;
		
	case OID_GEN_RCV_CRC_ERROR:
		Val64 = pAC->pPnmiStatBlock->dot3StatsFCSErrors.Low +
			((SK_U64)pAC->pPnmiStatBlock->dot3StatsFCSErrors.High << 32);
		break;

	case OID_802_3_RCV_ERROR_ALIGNMENT:
		Val64 = pAC->pPnmiStatBlock->dot3StatsAlignmentErrors.Low +
			((SK_U64)pAC->pPnmiStatBlock->dot3StatsAlignmentErrors.High << 32);
		break;
		
	case OID_802_3_XMIT_ONE_COLLISION:
		Val64 =
			pAC->pPnmiStatBlock->dot3StatsSingleCollisionFrames.Low +
			((SK_U64)pAC->pPnmiStatBlock->dot3StatsSingleCollisionFrames.High << 32);
		break;
		
	case OID_802_3_XMIT_MORE_COLLISIONS:
		Val64 =
			pAC->pPnmiStatBlock->dot3StatsMultipleCollisionFrames.Low +
			((SK_U64)pAC->pPnmiStatBlock->dot3StatsMultipleCollisionFrames.High << 32);
		break;
		
	case OID_802_3_XMIT_DEFERRED:
		Val64 =
			pAC->pPnmiStatBlock->dot3StatsDeferredTransmissions.Low +
			((SK_U64)pAC->pPnmiStatBlock->dot3StatsDeferredTransmissions.High << 32);
		break;
		
	case OID_802_3_XMIT_MAX_COLLISIONS:
		Val64 = pAC->pPnmiStatBlock->dot3StatsExcessiveCollisions.Low +
			((SK_U64)pAC->pPnmiStatBlock->dot3StatsExcessiveCollisions.High << 32);
		break;
		
	case OID_802_3_RCV_OVERRUN:
		Val64 = pAC->pPnmiStatBlock->nicNoMoreRxBDs.Low +
			((SK_U64)pAC->pPnmiStatBlock->nicNoMoreRxBDs.High << 32);
		break;
		
	case OID_802_3_XMIT_UNDERRUN:
		Val64 =
			pAC->pPnmiStatBlock->dot3StatsInternalMacTransmitErrors.Low +
			((SK_U64)pAC->pPnmiStatBlock->dot3StatsInternalMacTransmitErrors.High << 32);
		break;
		
	case OID_802_3_XMIT_TIMES_CRS_LOST:
		Val64 = 0;
		break;
		
	case OID_802_3_XMIT_LATE_COLLISIONS:
		Val64 = pAC->pPnmiStatBlock->dot3StatsLateCollisions.Low +
			((SK_U64)pAC->pPnmiStatBlock->dot3StatsLateCollisions.High << 32);
		break;	
		
	default:
		/* unknown oid */
		break;
	}

	SK_PNMI_STORE_U64(pBuf, Val64);
	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
		("PNMI: NdisStat: Val64.Low=%d, Val64.High=%d\n",
			(SK_U32)(Val64 & 0xFFFFFFFF), (SK_U32)((Val64 & 0xFFFFFFFF) >> 32)));

	*pLen = sizeof(SK_U64);
	return (SK_PNMI_ERR_OK);
}

/*****************************************************************************
 *
 * General - OID handler function of various single instance OIDs
 *
 * 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.
 */

static int General(
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 to which to mgmt data will be retrieved */
unsigned	*pLen,		/* On call: buffer length. On return: used buffer */
SK_U32		Instance,	/* Instance (1..n) that is to be queried or -1 */
unsigned	TableIndex)	/* Index to the Id table */
{
	SK_U64		Val64;
	unsigned	Len;
	unsigned	Offset;
	unsigned	Index;
	SK_U32		Val32;

	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
		("PNMI: General: Called, BufLen=%d, Id=0x%x, Instance=%d\n",
			*pLen, Id, Instance));

	/*
	 * 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.
	 */
	if (Action != SK_PNMI_GET) {
		*pLen = 0;
		return (SK_PNMI_ERR_READ_ONLY);
	}

	/*
	 * Check length
	 */
	switch (Id) {
	case OID_SKGE_DEVICE_TYPE:
	case OID_SKGE_RESULT:
	case OID_SKGE_RLMT_MONITOR_NUMBER:
	case OID_GEN_TRANSMIT_QUEUE_LENGTH:
	case OID_SKGE_TRAP_NUMBER:
		if (*pLen < sizeof(SK_U32)) {

			*pLen = sizeof(SK_U32);
			return (SK_PNMI_ERR_TOO_SHORT);
		}
		break;

	case OID_SKGE_BUS_TYPE:
	case OID_SKGE_BUS_SPEED:
	case OID_SKGE_BUS_WIDTH:
		if (*pLen < sizeof(SK_U8)) {

			*pLen = sizeof(SK_U8);
			return (SK_PNMI_ERR_TOO_SHORT);
		}
		break;

	case OID_SKGE_LINK_SPEED:
		if (*pLen < sizeof(SK_U16)) {

			*pLen = sizeof(SK_U16);
			return (SK_PNMI_ERR_TOO_SHORT);
		}
		break;

	case OID_SKGE_PORT_NUMBER:
	case OID_SKGE_MDB_VERSION:
		if (*pLen < sizeof(SK_U32)) {
			*pLen = sizeof(SK_U32);
			return (SK_PNMI_ERR_TOO_SHORT);
		}
		break;

	case OID_SKGE_TX_RETRY:
	case OID_SKGE_RX_INTR_CTS:
	case OID_SKGE_TX_INTR_CTS:
	case OID_SKGE_RX_NO_BUF_CTS:
	case OID_SKGE_TX_NO_BUF_CTS:
	case OID_SKGE_TX_USED_DESCR_NO:
	case OID_SKGE_RX_DELIVERED_CTS:
	case OID_SKGE_RX_OCTETS_DELIV_CTS:
	case OID_SKGE_RX_HW_ERROR_CTS:
	case OID_SKGE_TX_HW_ERROR_CTS:
	case OID_SKGE_IN_ERRORS_CTS:
	case OID_SKGE_OUT_ERROR_CTS:
	case OID_SKGE_ERR_RECOVERY_CTS:
	case OID_SKGE_SYSUPTIME:
		if (*pLen < sizeof(SK_U64)) {
			*pLen = sizeof(SK_U64);
			return (SK_PNMI_ERR_TOO_SHORT);
		}
	}
	/*
	 * Retrieve value
	 */
	switch (Id) {

	case OID_SKGE_SUPPORTED_LIST:
		Len = sizeof(IdTable)/sizeof(IdTable[0]) * sizeof(SK_U32);
		if (*pLen < Len) {
			*pLen = Len;
			return (SK_PNMI_ERR_TOO_SHORT);
		}
		for (Offset = 0, Index = 0; Offset < Len;
			Offset += sizeof(SK_U32), Index ++) {

			Val32 = (SK_U32)IdTable[Index].Id;
			SK_PNMI_STORE_U32(pBuf + Offset, Val32);
		}
		*pLen = Len;
		break;

	case OID_SKGE_PORT_NUMBER:
		Val32 = 1;
		SK_PNMI_STORE_U32(pBuf, Val32);
		*pLen = sizeof(SK_U32);
		break;

	case OID_SKGE_DEVICE_TYPE:
		Val32 = (SK_U32)pAC->Pnmi.DeviceType;
		SK_PNMI_STORE_U32(pBuf, Val32);
		*pLen = sizeof(SK_U32);
		break;

	case OID_SKGE_DRIVER_DESCR:
		if (pAC->Pnmi.pDriverDescription == NULL) {
			*pLen = 0;
			return (SK_PNMI_ERR_GENERAL);
		}

		Len = strlen((char*)(pAC->Pnmi.pDriverDescription)) + 1;
		if (Len > SK_PNMI_STRINGLEN1) {
			*pLen = 0;
			return (SK_PNMI_ERR_GENERAL);
		}

		if (*pLen < Len) {
			*pLen = Len;
			return (SK_PNMI_ERR_TOO_SHORT);
		}
		*pBuf = (char)(Len - 1);
		memcpy(pBuf + 1, pAC->Pnmi.pDriverDescription, Len - 1);
		*pLen = Len;
		break;

	case OID_SKGE_DRIVER_VERSION:
		Len = strlen((char*)(pAC->Pnmi.pDriverVersion)) + 1;
		if (Len > SK_PNMI_STRINGLEN1) {
			*pLen = 0;
			return (SK_PNMI_ERR_GENERAL);
		}

		if (*pLen < Len) {
			*pLen = Len;
			return (SK_PNMI_ERR_TOO_SHORT);
		}
		*pBuf = (char)(Len - 1);
		memcpy(pBuf + 1, pAC->Pnmi.pDriverVersion, Len - 1);
		*pLen = Len;
		break;

	case OID_SKGE_BUS_TYPE:
		*pBuf = pAC->Pnmi.PciBusType;
		*pLen = sizeof(char);
		break;

	case OID_SKGE_BUS_SPEED:
		*pBuf = pAC->Pnmi.PciBusSpeed;
		*pLen = sizeof(char);
		break;

	case OID_SKGE_BUS_WIDTH:
		*pBuf = pAC->Pnmi.PciBusWidth;
		*pLen = sizeof(char);
		break;

	case OID_SKGE_LINK_SPEED:
		*pBuf = pAC->Pnmi.EthLinkSpeed;
		*pLen = sizeof(SK_U16);
		break;

	case OID_SKGE_TX_RETRY:
		Val64 = pAC->Pnmi.TxRetryCts;
		SK_PNMI_STORE_U64(pBuf, Val64);
		*pLen = sizeof(SK_U64);
		break;
		
	case OID_SKGE_RX_INTR_CTS:
		Val64 = pAC->Pnmi.RxIntrCts;
		SK_PNMI_STORE_U64(pBuf, Val64);
		*pLen = sizeof(SK_U64);
		break;
		
	case OID_SKGE_TX_INTR_CTS:
		Val64 = pAC->Pnmi.TxIntrCts;
		SK_PNMI_STORE_U64(pBuf, Val64);
		*pLen = sizeof(SK_U64);
		break;
		
	case OID_SKGE_RX_NO_BUF_CTS:
		Val64 = pAC->Pnmi.RxNoBufCts;
		SK_PNMI_STORE_U64(pBuf, Val64);
		*pLen = sizeof(SK_U64);
		break;
		
	case OID_SKGE_TX_NO_BUF_CTS:
		Val64 = pAC->Pnmi.TxNoBufCts;
		SK_PNMI_STORE_U64(pBuf, Val64);
		*pLen = sizeof(SK_U64);
		break;
		
	case OID_SKGE_TX_USED_DESCR_NO:
		Val64 = pAC->Pnmi.TxUsedDescrNo;
		SK_PNMI_STORE_U64(pBuf, Val64);
		*pLen = sizeof(SK_U64);
		break;
		
	case OID_SKGE_RX_DELIVERED_CTS:
		Val64 = pAC->Pnmi.RxDeliveredCts;
		SK_PNMI_STORE_U64(pBuf, Val64);
		*pLen = sizeof(SK_U64);
		break;
		
	case OID_SKGE_RX_OCTETS_DELIV_CTS:
		Val64 = pAC->Pnmi.RxOctetsDeliveredCts;
		SK_PNMI_STORE_U64(pBuf, Val64);
		*pLen = sizeof(SK_U64);
		break;
		
	case OID_SKGE_RX_HW_ERROR_CTS:
		Val64 = pAC->pPnmiStatBlock->dot3StatsAlignmentErrors.Low +
			pAC->pPnmiStatBlock->nicNoMoreRxBDs.Low +
			pAC->pPnmiStatBlock->etherStatsJabbers.Low +
			pAC->pPnmiStatBlock->etherStatsUndersizePkts.Low +
			pAC->pPnmiStatBlock->dot3StatsFramesTooLong.Low +
			pAC->pPnmiStatBlock->dot3StatsFCSErrors.Low +
			((SK_U64)pAC->pPnmiStatBlock->dot3StatsAlignmentErrors.High << 32) +
			((SK_U64)pAC->pPnmiStatBlock->nicNoMoreRxBDs.High << 32) +
			((SK_U64)pAC->pPnmiStatBlock->etherStatsJabbers.High << 32) +
			((SK_U64)pAC->pPnmiStatBlock->etherStatsUndersizePkts.High << 32) +
			((SK_U64)pAC->pPnmiStatBlock->dot3StatsFramesTooLong.High << 32) +
			((SK_U64)pAC->pPnmiStatBlock->dot3StatsFCSErrors.High << 32);
		SK_PNMI_STORE_U64(pBuf, Val64);
		*pLen = sizeof(SK_U64);
		break;
		
	case OID_SKGE_TX_HW_ERROR_CTS:
		Val64 = pAC->pPnmiStatBlock->dot3StatsExcessiveCollisions.Low +
			pAC->pPnmiStatBlock->dot3StatsLateCollisions.Low +
			pAC->pPnmiStatBlock->dot3StatsInternalMacTransmitErrors.Low +
			pAC->pPnmiStatBlock->dot3StatsCarrierSenseErrors.Low +
			((SK_U64)pAC->pPnmiStatBlock->dot3StatsExcessiveCollisions.High << 32) +
			((SK_U64)pAC->pPnmiStatBlock->dot3StatsLateCollisions.High << 32) +
			((SK_U64)pAC->pPnmiStatBlock->dot3StatsInternalMacTransmitErrors.High << 32) +
			((SK_U64)pAC->pPnmiStatBlock->dot3StatsCarrierSenseErrors.High << 32);
		SK_PNMI_STORE_U64(pBuf, Val64);
		*pLen = sizeof(SK_U64);
		break;
		
	case OID_SKGE_IN_ERRORS_CTS:
		Val64 = pAC->Pnmi.RxNoBufCts;
		SK_PNMI_STORE_U64(pBuf, Val64);
		*pLen = sizeof(SK_U64);
		break;
		
	case OID_SKGE_OUT_ERROR_CTS:
		Val64 = pAC->Pnmi.TxNoBufCts;
		SK_PNMI_STORE_U64(pBuf, Val64);
		*pLen = sizeof(SK_U64);
		break;
		
	case OID_SKGE_ERR_RECOVERY_CTS:
		Val64 = pAC->Pnmi.ErrRecoveryCts;
		SK_PNMI_STORE_U64(pBuf, Val64);
		*pLen = sizeof(SK_U64);
		break;

	case OID_SKGE_SYSUPTIME:
		Val64 = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC));
		Val64 -= pAC->Pnmi.StartUpTime;
		SK_PNMI_STORE_U64(pBuf, Val64);
		*pLen = sizeof(SK_U64);
		break;

	case OID_SKGE_MDB_VERSION:
		Val32 = SK_PNMI_MDB_VERSION;
		SK_PNMI_STORE_U32(pBuf, Val32);
		*pLen = sizeof(SK_U32);
		break;

	default:
		/* unknown oid */
		*pLen = 0;
		return (SK_PNMI_ERR_GENERAL);
	}

	return (SK_PNMI_ERR_OK);
}

/*****************************************************************************
 *
 * PrivateStat - OID handler function of OID_SKGE_STAT_XXX
 *
 * Description:
 *	Retrieves the XMAC statistic data.
 *
 * 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.
 */

static int PrivateStat(
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 to which to mgmt data will be retrieved */
unsigned	*pLen,		/* On call: buffer length. On return: used buffer */
SK_U32		Instance,	/* Instance (1..n) that is to be queried or -1 */
unsigned	TableIndex)	/* Index to the Id table */
{
	unsigned int	LogPortMax;
	unsigned int	LogPortIndex;
	unsigned int	PhysPortMax;
	unsigned int	Limit;
	unsigned int	Offset;
	unsigned int	i;
	SK_U64			Val64;

	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
		("PNMI: PrivateStat: Called, BufLen=%d, Id=0x%x, Instance=%d\n",
			*pLen, Id, Instance));
	/*
	 * Calculate instance if wished. MAC index 0 is the virtual
	 * MAC.
	 */
	PhysPortMax = 1;
	LogPortMax = 2;

	if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried */
		/* Check instance range */
		if ((Instance < 1) || (Instance > LogPortMax)) {
			*pLen = 0;
			return (SK_PNMI_ERR_UNKNOWN_INST);
		}
		LogPortIndex = Instance - 1;
		Limit = LogPortIndex + 1;
	}

	else { /* Instance == (SK_U32)(-1), get all Instances of that OID */
		LogPortIndex = 0;
		Limit = LogPortMax;
	}

	/*
	 * Check action
	 */
	if (Action != SK_PNMI_GET) {
		*pLen = 0;
		return (SK_PNMI_ERR_READ_ONLY);
	}

	/*
	 * Check length
	 */
	if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U64)) {
		*pLen = (Limit - LogPortIndex) * sizeof(SK_U64);
		return (SK_PNMI_ERR_TOO_SHORT);
	}

	/*
	 * Get value
	 */
	Offset = 0;
	Val64 = 0;
	for (; LogPortIndex < Limit; LogPortIndex ++) {
		switch (Id) {
		case OID_SKGE_STAT_TX:
			for (i = 0; i < 16; i++) {
				Val64 += pAC->pPnmiStatBlock->COSIfHCOutPkts[i].Low +
					((SK_U64)pAC->pPnmiStatBlock->COSIfHCOutPkts[i].High << 32);
			}
			break;
			
		case OID_SKGE_STAT_TX_OCTETS:
			Val64 = pAC->pPnmiStatBlock->ifHCOutOctets.Low +
				((SK_U64)pAC->pPnmiStatBlock->ifHCOutOctets.High << 32);
			break;
			
		case OID_SKGE_STAT_TX_BROADCAST:
			Val64 = pAC->pPnmiStatBlock->ifHCOutBroadcastPkts.Low +
				((SK_U64)pAC->pPnmiStatBlock->ifHCOutBroadcastPkts.High << 32);
			break;
			
		case OID_SKGE_STAT_TX_MULTICAST:
			Val64 = pAC->pPnmiStatBlock->ifHCOutMulticastPkts.Low +
				((SK_U64)pAC->pPnmiStatBlock->ifHCOutMulticastPkts.High << 32);
			break;
			
		case OID_SKGE_STAT_TX_UNICAST:
			Val64 = pAC->pPnmiStatBlock->ifHCOutUcastPkts.Low +
				((SK_U64)pAC->pPnmiStatBlock->ifHCOutUcastPkts.High << 32);
			break;
			
		case OID_SKGE_STAT_TX_SINGLE_COL:
			Val64 =
				pAC->pPnmiStatBlock->dot3StatsSingleCollisionFrames.Low +
				((SK_U64)pAC->pPnmiStatBlock->dot3StatsSingleCollisionFrames.High << 32);
			break;
			
		case OID_SKGE_STAT_TX_MULTI_COL:
			Val64 =
				pAC->pPnmiStatBlock->dot3StatsMultipleCollisionFrames.Low +
				((SK_U64)pAC->pPnmiStatBlock->dot3StatsMultipleCollisionFrames.High << 32);
			break;
			
		case OID_SKGE_STAT_TX_EXCESS_COL:
			Val64 =
				pAC->pPnmiStatBlock->dot3StatsExcessiveCollisions.Low +
				((SK_U64)pAC->pPnmiStatBlock->dot3StatsExcessiveCollisions.High << 32);
			break;
			
		case OID_SKGE_STAT_TX_LATE_COL:
			Val64 = pAC->pPnmiStatBlock->dot3StatsLateCollisions.Low +
				((SK_U64)pAC->pPnmiStatBlock->dot3StatsLateCollisions.High << 32);
			break;
			
		case OID_SKGE_STAT_TX_DEFFERAL:
			Val64 =
				pAC->pPnmiStatBlock->dot3StatsDeferredTransmissions.Low +
				((SK_U64)pAC->pPnmiStatBlock->dot3StatsDeferredTransmissions.High << 32);
			break;
			
		case OID_SKGE_STAT_TX_UNDERRUN:
			Val64 =
				pAC->pPnmiStatBlock->dot3StatsInternalMacTransmitErrors.Low +
				((SK_U64)pAC->pPnmiStatBlock->dot3StatsInternalMacTransmitErrors.High << 32);
			break;
			
		case OID_SKGE_STAT_TX_CARRIER:
			Val64 =
				pAC->pPnmiStatBlock->dot3StatsCarrierSenseErrors.Low +
				((SK_U64)pAC->pPnmiStatBlock->dot3StatsCarrierSenseErrors.High << 32);
			break;
			
		case OID_SKGE_STAT_RX:
			for (i = 0; i < 16; i++) {
				Val64 += pAC->pPnmiStatBlock->COSIfHCInPkts[i].Low +
					((SK_U64)pAC->pPnmiStatBlock->COSIfHCInPkts[i].High << 32);
			}
			break;
			
		case OID_SKGE_STAT_RX_OCTETS:
			Val64 = pAC->pPnmiStatBlock->ifHCInOctets.Low +
				((SK_U64)pAC->pPnmiStatBlock->ifHCInOctets.High << 32);
			break;
			
		case OID_SKGE_STAT_RX_BROADCAST:
			Val64 = pAC->pPnmiStatBlock->ifHCInBroadcastPkts.Low +
				((SK_U64)pAC->pPnmiStatBlock->ifHCInBroadcastPkts.High << 32);
			break;
			
		case OID_SKGE_STAT_RX_MULTICAST:
			Val64 = pAC->pPnmiStatBlock->ifHCInMulticastPkts.Low +
				((SK_U64)pAC->pPnmiStatBlock->ifHCInMulticastPkts.High << 32);
			break;
			
		case OID_SKGE_STAT_RX_UNICAST:
			Val64 = pAC->pPnmiStatBlock->ifHCInUcastPkts.Low +
				((SK_U64)pAC->pPnmiStatBlock->ifHCInUcastPkts.High << 32);
			break;
			
		case OID_SKGE_STAT_RX_MISSED:
			Val64 = pAC->pPnmiStatBlock->ifInDiscards.Low +
				((SK_U64)pAC->pPnmiStatBlock->ifInDiscards.High << 32);
			break;
			
		case OID_SKGE_STAT_RX_FRAMING:
			Val64 = pAC->pPnmiStatBlock->dot3StatsAlignmentErrors.Low +
				((SK_U64)pAC->pPnmiStatBlock->dot3StatsAlignmentErrors.High << 32);
			break;
			
		case OID_SKGE_STAT_RX_OVERFLOW:
			Val64 = pAC->pPnmiStatBlock->nicNoMoreRxBDs.Low +
				((SK_U64)pAC->pPnmiStatBlock->nicNoMoreRxBDs.High << 32);
			break;
			
		case OID_SKGE_STAT_RX_JABBER:
			Val64 = pAC->pPnmiStatBlock->etherStatsJabbers.Low +
				((SK_U64)pAC->pPnmiStatBlock->etherStatsJabbers.High << 32);
			break;
			
		case OID_SKGE_STAT_RX_RUNT:
			Val64 = pAC->pPnmiStatBlock->etherStatsUndersizePkts.Low +
				((SK_U64)pAC->pPnmiStatBlock->etherStatsUndersizePkts.High << 32);
			break;
			
		case OID_SKGE_STAT_RX_CEXT:
			Val64 = pAC->pPnmiStatBlock->ifInErrors.Low +
				((SK_U64)pAC->pPnmiStatBlock->ifInErrors.High << 32);
			break;
			
		case OID_SKGE_STAT_RX_TOO_LONG:
			Val64 = pAC->pPnmiStatBlock->dot3StatsFramesTooLong.Low +
				((SK_U64)pAC->pPnmiStatBlock->dot3StatsFramesTooLong.High << 32);
			break;
			
		case OID_SKGE_STAT_RX_FRAGMENTS:
			Val64 = pAC->pPnmiStatBlock->etherStatsFragments.Low +
				((SK_U64)pAC->pPnmiStatBlock->etherStatsFragments.High << 32);
			break;
			
		case OID_SKGE_STAT_RX_FCS:
			Val64 = pAC->pPnmiStatBlock->dot3StatsFCSErrors.Low +
				((SK_U64)pAC->pPnmiStatBlock->dot3StatsFCSErrors.High << 32);
			break;
			
		case OID_SKGE_STAT_RX_64:
			Val64 = pAC->pPnmiStatBlock->etherStatsPkts64Octets.Low +
				((SK_U64)pAC->pPnmiStatBlock->etherStatsPkts64Octets.High << 32);
			break;
			
		case OID_SKGE_STAT_RX_127:
			Val64 =
				pAC->pPnmiStatBlock->etherStatsPkts65Octetsto127Octets.Low +
				((SK_U64)pAC->pPnmiStatBlock->etherStatsPkts65Octetsto127Octets.High << 32);
			break;
			
		case OID_SKGE_STAT_RX_255:
			Val64 =
				pAC->pPnmiStatBlock->etherStatsPkts128Octetsto255Octets.Low +
				((SK_U64)pAC->pPnmiStatBlock->etherStatsPkts128Octetsto255Octets.High << 32);
			break;
			
		case OID_SKGE_STAT_RX_511:
			Val64 =
				pAC->pPnmiStatBlock->etherStatsPkts256Octetsto511Octets.Low +
				((SK_U64)pAC->pPnmiStatBlock->etherStatsPkts256Octetsto511Octets.High << 32);
			break;
			
		case OID_SKGE_STAT_RX_1023:
			Val64 =
				pAC->pPnmiStatBlock->etherStatsPkts512Octetsto1023Octets.Low +
				((SK_U64)pAC->pPnmiStatBlock->etherStatsPkts512Octetsto1023Octets.High << 32);
			break;

		case OID_SKGE_STAT_RX_MAX:
			Val64 =
				pAC->pPnmiStatBlock->etherStatsPkts1024Octetsto1522Octets.Low +
				pAC->pPnmiStatBlock->etherStatsPkts1523Octetsto2047Octets.Low +
				pAC->pPnmiStatBlock->etherStatsPkts2048Octetsto4095Octets.Low +
				pAC->pPnmiStatBlock->etherStatsPkts4096Octetsto8191Octets.Low +
				pAC->pPnmiStatBlock->etherStatsPkts8192Octetsto9022Octets.Low +
				((SK_U64)pAC->pPnmiStatBlock->etherStatsPkts1024Octetsto1522Octets.High << 32) +
				((SK_U64)pAC->pPnmiStatBlock->etherStatsPkts1523Octetsto2047Octets.High << 32) +
				((SK_U64)pAC->pPnmiStatBlock->etherStatsPkts2048Octetsto4095Octets.High << 32) +
				((SK_U64)pAC->pPnmiStatBlock->etherStatsPkts4096Octetsto8191Octets.High << 32) +
				((SK_U64)pAC->pPnmiStatBlock->etherStatsPkts8192Octetsto9022Octets.High << 32);
			break;

		default:
			/* unknown oid */
			break;
		}

		SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
			("PNMI: PrivateStat: Val64.Low=%d, Val64.High=%d\n",
				(SK_U32)(Val64 & 0xFFFFFFFF), (SK_U32)(Val64 >> 32)));

		SK_PNMI_STORE_U64(pBuf + Offset, Val64);
		Offset += sizeof(SK_U64);
	}
	*pLen = Offset;
	return (SK_PNMI_ERR_OK);
}

/*****************************************************************************
 *
 *	SkPnmiEvent - handle PNMI events
 *
 * Description:
 *	This routine handles events for PNMI.
 *
 *
 * Returns:
 *	0
 */
int	SkPnmiEvent(
SK_AC		*pAC,	/* Pointer to Adapter Context */
SK_IOC		IoC,	/* I/O Context */
SK_U32		Event,
SK_EVPARA	Para)
{
	switch (Event) {
	case SK_PNMI_EVT_MAC_RESET:
		SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_QUEUE,
		("SkPnmiEvent: SK_PNMI_EVT_MAC_RESET.\n"));
		break;

	case SK_PNMI_EVT_RLMT_PORT_UP:
		SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_QUEUE,
		("SkPnmiEvent: SK_PNMI_EVT_RLMT_PORT_UP.\n"));
		break;

	case SK_PNMI_EVT_RLMT_PORT_DOWN:
		SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_QUEUE,
		("SkPnmiEvent: SK_PNMI_EVT_RLMT_PORT_DOWN.\n"));
		break;

	default:
		SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_QUEUE,
		("SkPnmiEvent %d.\n", Event));
		break;
	}

	return (0);
} /* SkPnmiEvent */

