blob: b5d32b04c1f5841382bef852eb0264ec77642ab8 [file] [log] [blame]
/*****************************************************************************
*
* Name: skgepnmi.c
* Project: GEnesis, PCI Gigabit Ethernet Adapter
* Version: $Revision: 1.102 $
* Date: $Date: 2002/12/16 14:03:24 $
* Purpose: Private Network Management Interface
*
****************************************************************************/
/******************************************************************************
*
* (C)Copyright 1998-2002 SysKonnect GmbH.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* 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: skgepnmi.c,v $
* Revision 1.102 2002/12/16 14:03:24 tschilli
* VCT code in Vct() changed.
*
* Revision 1.101 2002/12/16 09:04:10 tschilli
* Code for VCT handling added.
*
* Revision 1.100 2002/09/26 14:28:13 tschilli
* For XMAC the values in the SK_PNMI_PORT Port struct are copied to
* the new SK_PNMI_PORT BufPort struct during a MacUpdate() call.
* These values are used when GetPhysStatVal() is called. With this
* mechanism you get the best results when software corrections for
* counters are needed. Example: RX_LONGFRAMES.
*
* Revision 1.99 2002/09/17 12:31:19 tschilli
* OID_SKGE_TX_HW_ERROR_CTS, OID_SKGE_OUT_ERROR_CTS, OID_GEN_XMIT_ERROR:
* Double count of SK_PNMI_HTX_EXCESS_COL in function General() removed.
* OID_PNP_CAPABILITIES: sizeof(SK_PM_WAKE_UP_CAPABILITIES) changed to
* sizeof(SK_PNP_CAPABILITIES) in function PowerManagement().
*
* Revision 1.98 2002/09/10 09:00:03 rwahl
* Adapted boolean definitions according sktypes.
*
* Revision 1.97 2002/09/05 15:07:03 rwahl
* Editorial changes.
*
* Revision 1.96 2002/09/05 11:04:14 rwahl
* - Rx/Tx packets statistics of virtual port were zero on link down (#10750)
* - For GMAC the overflow IRQ for Rx longframe counter was not counted.
* - Incorrect calculation for oids OID_SKGE_RX_HW_ERROR_CTS,
* OID_SKGE_IN_ERRORS_CTS, OID_GEN_RCV_ERROR.
* - Moved correction for OID_SKGE_STAT_RX_TOO_LONG to GetPhysStatVal().
* - Editorial changes.
*
* Revision 1.95 2002/09/04 08:53:37 rwahl
* - Incorrect statistics for Rx_too_long counter with jumbo frame (#10751)
* - StatRxFrameTooLong & StatRxPMaccErr counters were not reset.
* - Fixed compiler warning for debug msg arg types.
*
* Revision 1.94 2002/08/09 15:42:14 rwahl
* - Fixed StatAddr table for GMAC.
* - VirtualConf(): returned indeterminated status for speed oids if no
* active port.
*
* Revision 1.93 2002/08/09 11:04:59 rwahl
* Added handler for link speed caps.
*
* Revision 1.92 2002/08/09 09:43:03 rwahl
* - Added handler for NDIS OID_PNP_xxx ids.
*
* Revision 1.91 2002/07/17 19:53:03 rwahl
* - Added StatOvrflwBit table for XMAC & GMAC.
* - Extended StatAddr table for GMAC. Added check of number of counters
* in enumeration and size of StatAddr table on init level.
* - Added use of GIFunc table.
* - ChipSet is not static anymore,
* - Extended SIRQ event handler for both mac types.
* - Fixed rx short counter bug (#10620)
* - Added handler for oids SKGE_SPEED_MODE & SKGE_SPEED_STATUS.
* - Extendet GetPhysStatVal() for GMAC.
* - Editorial changes.
*
* Revision 1.90 2002/05/22 08:56:25 rwahl
* - Moved OID table to separate source file.
* - Fix: TX_DEFFERAL counter incremented in full-duplex mode.
* - Use string definitions for error msgs.
*
* Revision 1.89 2001/09/18 10:01:30 mkunz
* some OID's fixed for dualnetmode
*
* Revision 1.88 2001/08/02 07:58:08 rwahl
* - Fixed NetIndex to csum module at ResetCounter().
*
* Revision 1.87 2001/04/06 13:35:09 mkunz
* -Bugs fixed in handling of OID_SKGE_MTU and the VPD OID's
*
* Revision 1.86 2001/03/09 09:18:03 mkunz
* Changes in SK_DBG_MSG
*
* Revision 1.85 2001/03/08 09:37:31 mkunz
* Bugfix in ResetCounter for Pnmi.Port structure
*
* Revision 1.84 2001/03/06 09:04:55 mkunz
* Made some changes in instance calculation
*
* Revision 1.83 2001/02/15 09:15:32 mkunz
* Necessary changes for dual net mode added
*
* Revision 1.82 2001/02/07 08:24:19 mkunz
* -Made changes in handling of OID_SKGE_MTU
*
* Revision 1.81 2001/02/06 09:58:00 mkunz
* -Vpd bug fixed
* -OID_SKGE_MTU added
* -pnmi support for dual net mode. Interface function and macros extended
*
* Revision 1.80 2001/01/22 13:41:35 rassmann
* Supporting two nets on dual-port adapters.
*
* Revision 1.79 2000/12/05 14:57:40 cgoos
* SetStruct failed before first Link Up (link mode of virtual
* port "INDETERMINATED").
*
* Revision 1.78 2000/09/12 10:44:58 cgoos
* Fixed SK_PNMI_STORE_U32 calls with typecasted argument.
*
* Revision 1.77 2000/09/07 08:10:19 rwahl
* - Modified algorithm for 64bit NDIS statistic counters;
* returns 64bit or 32bit value depending on passed buffer
* size. Indicate capability for 64bit NDIS counter, if passed
* buffer size is zero. OID_GEN_XMIT_ERROR, OID_GEN_RCV_ERROR,
* and OID_GEN_RCV_NO_BUFFER handled as 64bit counter, too.
* - corrected OID_SKGE_RLMT_PORT_PREFERRED.
*
* Revision 1.76 2000/08/03 15:23:39 rwahl
* - Correction for FrameTooLong counter has to be moved to OID handling
* routines (instead of statistic counter routine).
* - Fix in XMAC Reset Event handling: Only offset counter for hardware
* statistic registers are updated.
*
* Revision 1.75 2000/08/01 16:46:05 rwahl
* - Added StatRxLongFrames counter and correction of FrameTooLong counter.
* - Added directive to control width (default = 32bit) of NDIS statistic
* counters (SK_NDIS_64BIT_CTR).
*
* Revision 1.74 2000/07/04 11:41:53 rwahl
* - Added volition connector type.
*
* Revision 1.73 2000/03/15 16:33:10 rwahl
* Fixed bug 10510; wrong reset of virtual port statistic counters.
*
* Revision 1.72 1999/12/06 16:15:53 rwahl
* Fixed problem of instance range for current and factory MAC address.
*
* Revision 1.71 1999/12/06 10:14:20 rwahl
* Fixed bug 10476; set operation for PHY_OPERATION_MODE.
*
* Revision 1.70 1999/11/22 13:33:34 cgoos
* Changed license header to GPL.
*
* Revision 1.69 1999/10/18 11:42:15 rwahl
* Added typecasts for checking event dependent param (debug only).
*
* Revision 1.68 1999/10/06 09:35:59 cgoos
* Added state check to PHY_READ call (hanged if called during startup).
*
* Revision 1.67 1999/09/22 09:53:20 rwahl
* - Read Broadcom register for updating fcs error counter (1000Base-T).
*
* Revision 1.66 1999/08/26 13:47:56 rwahl
* Added SK_DRIVER_SENDEVENT when queueing RLMT_CHANGE_THRES trap.
*
* Revision 1.65 1999/07/26 07:49:35 cgoos
* Added two typecasts to avoid compiler warnings.
*
* Revision 1.64 1999/05/20 09:24:12 cgoos
* Changes for 1000Base-T (sensors, Master/Slave).
*
* Revision 1.63 1999/04/13 15:11:58 mhaveman
* Moved include of rlmt.h to header skgepnmi.h because some macros
* are needed there.
*
* Revision 1.62 1999/04/13 15:08:07 mhaveman
* Replaced again SK_RLMT_CHECK_LINK with SK_PNMI_RLMT_MODE_CHK_LINK
* to grant unified interface by only using the PNMI header file.
* SK_PNMI_RLMT_MODE_CHK_LINK is defined the same as SK_RLMT_CHECK_LINK.
*
* Revision 1.61 1999/04/13 15:02:48 mhaveman
* Changes caused by review:
* -Changed some comments
* -Removed redundant check for OID_SKGE_PHYS_FAC_ADDR
* -Optimized PRESET check.
* -Meaning of error SK_ADDR_DUPLICATE_ADDRESS changed. Set of same
* address will now not cause this error. Removed corresponding check.
*
* Revision 1.60 1999/03/23 10:41:23 mhaveman
* Added comments.
*
* Revision 1.59 1999/02/19 08:01:28 mhaveman
* Fixed bug 10372 that after counter reset all ports were displayed
* as inactive.
*
* Revision 1.58 1999/02/16 18:04:47 mhaveman
* Fixed problem of twisted OIDs SENSOR_WAR_TIME and SENSOR_ERR_TIME.
*
* Revision 1.56 1999/01/27 12:29:11 mhaveman
* SkTimerStart was called with time value in milli seconds but needs
* micro seconds.
*
* Revision 1.55 1999/01/25 15:00:38 mhaveman
* Added support to allow multiple ports to be active. If this feature in
* future will be used, the Management Data Base variables PORT_ACTIVE
* and PORT_PREFERED should be moved to the port specific part of RLMT.
* Currently they return the values of the first active physical port
* found. A set to the virtual port will actually change all active
* physical ports. A get returns the melted values of all active physical
* ports. If the port values differ a return value INDETERMINATED will
* be returned. This effects especially the CONF group.
*
* Revision 1.54 1999/01/19 10:10:22 mhaveman
* -Fixed bug 10354: Counter values of virtual port were wrong after port
* switches
* -Added check if a switch to the same port is notified.
*
* Revision 1.53 1999/01/07 09:25:21 mhaveman
* Forgot to initialize a variable.
*
* Revision 1.52 1999/01/05 10:34:33 mhaveman
* Fixed little error in RlmtChangeEstimate calculation.
*
* Revision 1.51 1999/01/05 09:59:07 mhaveman
* -Moved timer start to init level 2
* -Redesigned port switch average calculation to avoid 64bit
* arithmetic.
*
* Revision 1.50 1998/12/10 15:13:59 mhaveman
* -Fixed: PHYS_CUR_ADDR returned wrong addresses
* -Fixed: RLMT_PORT_PREFERED and RLMT_CHANGE_THRES preset returned
* always BAD_VALUE.
* -Fixed: TRAP buffer seemed to sometimes suddenly empty
*
* Revision 1.49 1998/12/09 16:17:07 mhaveman
* Fixed: Couldnot delete VPD keys on UNIX.
*
* Revision 1.48 1998/12/09 14:11:10 mhaveman
* -Add: Debugmessage for XMAC_RESET supressed to minimize output.
* -Fixed: RlmtChangeThreshold will now be initialized.
* -Fixed: VPD_ENTRIES_LIST extended value with unnecessary space char.
* -Fixed: On VPD key creation an invalid key name could be created
* (e.g. A5)
* -Some minor changes in comments and code.
*
* Revision 1.47 1998/12/08 16:00:31 mhaveman
* -Fixed: For RLMT_PORT_ACTIVE will now be returned a 0 if no port
* is active.
* -Fixed: For the RLMT statistics group only the last value was
* returned and the rest of the buffer was filled with 0xff
* -Fixed: Mysteriously the preset on RLMT_MODE still returned
* BAD_VALUE.
* Revision 1.46 1998/12/08 10:04:56 mhaveman
* -Fixed: Preset on RLMT_MODE returned always BAD_VALUE error.
* -Fixed: Alignment error in GetStruct
* -Fixed: If for Get/Preset/SetStruct the buffer size is equal or
* larger than SK_PNMI_MIN_STRUCT_SIZE the return value is stored
* to the buffer. In this case the caller should always return
* ok to its upper routines. Only if the buffer size is less
* than SK_PNMI_MIN_STRUCT_SIZE and the return value is unequal
* to 0, an error should be returned by the caller.
* -Fixed: Wrong number of instances with RLMT statistic.
* -Fixed: Return now SK_LMODE_STAT_UNKNOWN if the LinkModeStatus is 0.
*
* Revision 1.45 1998/12/03 17:17:24 mhaveman
* -Removed for VPD create action the buffer size limitation to 4 bytes.
* -Pass now physical/active physical port to ADDR for CUR_ADDR set
*
* Revision 1.44 1998/12/03 15:14:35 mhaveman
* Another change to Vpd instance evaluation.
*
* Revision 1.43 1998/12/03 14:18:10 mhaveman
* -Fixed problem in PnmiSetStruct. It was impossible to set any value.
* -Removed VPD key evaluation for VPD_FREE_BYTES and VPD_ACTION.
*
* Revision 1.42 1998/12/03 11:31:47 mhaveman
* Inserted cast to satisfy lint.
*
* Revision 1.41 1998/12/03 11:28:16 mhaveman
* Removed SK_PNMI_CHECKPTR
*
* Revision 1.40 1998/12/03 11:19:07 mhaveman
* Fixed problems
* -A set to virtual port will now be ignored. A set with broadcast
* address to any port will be ignored.
* -GetStruct function made VPD instance calculation wrong.
* -Prefered port returned -1 instead of 0.
*
* Revision 1.39 1998/11/26 15:30:29 mhaveman
* Added sense mode to link mode.
*
* Revision 1.38 1998/11/23 15:34:00 mhaveman
* -Fixed bug for RX counters. On an RX overflow interrupt the high
* words of all RX counters were incremented.
* -SET operations on FLOWCTRL_MODE and LINK_MODE accept now the
* value 0, which has no effect. It is usefull for multiple instance
* SETs.
*
* Revision 1.37 1998/11/20 08:02:04 mhaveman
* -Fixed: Ports were compared with MAX_SENSORS
* -Fixed: Crash in GetTrapEntry with MEMSET macro
* -Fixed: Conversions between physical, logical port index and instance
*
* Revision 1.36 1998/11/16 07:48:53 mhaveman
* Casted SK_DRIVER_SENDEVENT with (void) to eleminate compiler warnings
* on Solaris.
*
* Revision 1.35 1998/11/16 07:45:34 mhaveman
* SkAddrOverride now returns value and will be checked.
*
* Revision 1.34 1998/11/10 13:40:37 mhaveman
* Needed to change interface, because NT driver needs a return value
* of needed buffer space on TOO_SHORT errors. Therefore all
* SkPnmiGet/Preset/Set functions now have a pointer to the length
* parameter, where the needed space on error is returned.
*
* Revision 1.33 1998/11/03 13:52:46 mhaveman
* Made file lint conform.
*
* Revision 1.32 1998/11/03 13:19:07 mhaveman
* The events SK_HWEV_SET_LMODE and SK_HWEV_SET_FLOWMODE pass now in
* Para32[0] the physical MAC index and in Para32[1] the new mode.
*
* Revision 1.31 1998/11/03 12:30:40 gklug
* fix: compiler warning memset
*
* Revision 1.30 1998/11/03 12:04:46 mhaveman
* Fixed problem in SENSOR_VALUE, which wrote beyond the buffer end
* Fixed alignment problem with CHIPSET.
*
* Revision 1.29 1998/11/02 11:23:54 mhaveman
* Corrected SK_ERROR_LOG to SK_ERR_LOG. Sorry.
*
* Revision 1.28 1998/11/02 10:47:16 mhaveman
* Added syslog messages for internal errors.
*
* Revision 1.27 1998/10/30 15:48:06 mhaveman
* Fixed problems after simulation of SK_PNMI_EVT_CHG_EST_TIMER and
* RlmtChangeThreshold calculation.
*
* Revision 1.26 1998/10/29 15:36:55 mhaveman
* -Fixed bug in trap buffer handling.
* -OID_SKGE_DRIVER_DESCR, OID_SKGE_DRIVER_VERSION, OID_SKGE_HW_DESCR,
* OID_SKGE_HW_VERSION, OID_SKGE_VPD_ENTRIES_LIST, OID_SKGE_VPD_KEY,
* OID_SKGE_VPD_VALUE, and OID_SKGE_SENSOR_DESCR return values with
* a leading octet before each string storing the string length.
* -Perform a RlmtUpdate during SK_PNMI_EVT_XMAC_RESET to minimize
* RlmtUpdate calls in GetStatVal.
* -Inserted SK_PNMI_CHECKFLAGS macro increase readability.
*
* Revision 1.25 1998/10/29 08:50:36 mhaveman
* Fixed problems after second event simulation.
*
* Revision 1.24 1998/10/28 08:44:37 mhaveman
* -Fixed alignment problem
* -Fixed problems during event simulation
* -Fixed sequence of error return code (INSTANCE -> ACCESS -> SHORT)
* -Changed type of parameter Instance back to SK_U32 because of VPD
* -Updated new VPD function calls
*
* Revision 1.23 1998/10/23 10:16:37 mhaveman
* Fixed bugs after buffer test simulation.
*
* Revision 1.22 1998/10/21 13:23:52 mhaveman
* -Call syntax of SkOsGetTime() changed to SkOsGetTime(pAc).
* -Changed calculation of hundrets of seconds.
*
* Revision 1.20 1998/10/20 07:30:45 mhaveman
* Made type changes to unsigned integer where possible.
*
* Revision 1.19 1998/10/19 10:51:30 mhaveman
* -Made Bug fixes after simulation run
* -Renamed RlmtMAC... to RlmtPort...
* -Marked workarounds with Errata comments
*
* Revision 1.18 1998/10/14 07:50:08 mhaveman
* -For OID_SKGE_LINK_STATUS the link down detection has moved from RLMT
* to HWACCESS.
* -Provided all MEMCPY/MEMSET macros with (char *) pointers, because
* Solaris throwed warnings when mapping to bcopy/bset.
*
* Revision 1.17 1998/10/13 07:42:01 mhaveman
* -Added OIDs OID_SKGE_TRAP_NUMBER and OID_SKGE_ALL_DATA
* -Removed old cvs history entries
* -Renamed MacNumber to PortNumber
*
* Revision 1.16 1998/10/07 10:52:49 mhaveman
* -Inserted handling of some OID_GEN_ Ids for windows
* -Fixed problem with 803.2 statistic.
*
* Revision 1.15 1998/10/01 09:16:29 mhaveman
* Added Debug messages for function call and UpdateFlag tracing.
*
* Revision 1.14 1998/09/30 13:39:09 mhaveman
* -Reduced namings of 'MAC' by replacing them with 'PORT'.
* -Completed counting of OID_SKGE_RX_HW_ERROR_CTS,
* OID_SKGE_TX_HW_ERROR_CTS,
* OID_SKGE_IN_ERRORS_CTS, and OID_SKGE_OUT_ERROR_CTS.
* -SET check for RlmtMode
*
* Revision 1.13 1998/09/28 13:13:08 mhaveman
* Hide strcmp, strlen, and strncpy behind macros SK_STRCMP, SK_STRLEN,
* and SK_STRNCPY. (Same reasons as for mem.. and MEM..)
*
* Revision 1.12 1998/09/16 08:18:36 cgoos
* Fix: XM_INxx and XM_OUTxx called with different parameter order:
* sometimes IoC,Mac,... sometimes Mac,IoC,... Now always first variant.
* Fix: inserted "Pnmi." into some pAC->pDriverDescription / Version.
* Change: memset, memcpy to makros SK_MEMSET, SK_MEMCPY
*
* Revision 1.11 1998/09/04 17:01:45 mhaveman
* Added SyncCounter as macro and OID_SKGE_.._NO_DESCR_CTS to
* OID_SKGE_RX_NO_BUF_CTS.
*
* Revision 1.10 1998/09/04 14:35:35 mhaveman
* Added macro counters, that are counted by driver.
*
****************************************************************************/
#include <config.h>
#ifdef CONFIG_SK98
static const char SysKonnectFileId[] =
"@(#) $Id: skgepnmi.c,v 1.102 2002/12/16 14:03:24 tschilli Exp $"
" (C) SysKonnect.";
#include "h/skdrv1st.h"
#include "h/sktypes.h"
#include "h/xmac_ii.h"
#include "h/skdebug.h"
#include "h/skqueue.h"
#include "h/skgepnmi.h"
#include "h/skgesirq.h"
#include "h/skcsum.h"
#include "h/skvpd.h"
#include "h/skgehw.h"
#include "h/skgeinit.h"
#include "h/skdrv2nd.h"
#include "h/skgepnm2.h"
#ifdef SK_POWER_MGMT
#include "h/skgepmgt.h"
#endif
/* defines *******************************************************************/
#ifndef DEBUG
#define PNMI_STATIC static
#else /* DEBUG */
#define PNMI_STATIC
#endif /* DEBUG */
/*
* Public Function prototypes
*/
int SkPnmiInit(SK_AC *pAC, SK_IOC IoC, int level);
int SkPnmiGetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, void *pBuf,
unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex);
int SkPnmiPreSetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, void *pBuf,
unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex);
int SkPnmiSetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, void *pBuf,
unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex);
int SkPnmiGetStruct(SK_AC *pAC, SK_IOC IoC, void *pBuf,
unsigned int *pLen, SK_U32 NetIndex);
int SkPnmiPreSetStruct(SK_AC *pAC, SK_IOC IoC, void *pBuf,
unsigned int *pLen, SK_U32 NetIndex);
int SkPnmiSetStruct(SK_AC *pAC, SK_IOC IoC, void *pBuf,
unsigned int *pLen, SK_U32 NetIndex);
int SkPnmiEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event, SK_EVPARA Param);
/*
* Private Function prototypes
*/
PNMI_STATIC SK_U8 CalculateLinkModeStatus(SK_AC *pAC, SK_IOC IoC, unsigned int
PhysPortIndex);
PNMI_STATIC SK_U8 CalculateLinkStatus(SK_AC *pAC, SK_IOC IoC, unsigned int
PhysPortIndex);
PNMI_STATIC void CopyMac(char *pDst, SK_MAC_ADDR *pMac);
PNMI_STATIC void CopyTrapQueue(SK_AC *pAC, char *pDstBuf);
PNMI_STATIC SK_U64 GetPhysStatVal(SK_AC *pAC, SK_IOC IoC,
unsigned int PhysPortIndex, unsigned int StatIndex);
PNMI_STATIC SK_U64 GetStatVal(SK_AC *pAC, SK_IOC IoC, unsigned int LogPortIndex,
unsigned int StatIndex, SK_U32 NetIndex);
PNMI_STATIC char* GetTrapEntry(SK_AC *pAC, SK_U32 TrapId, unsigned int Size);
PNMI_STATIC void GetTrapQueueLen(SK_AC *pAC, unsigned int *pLen,
unsigned int *pEntries);
PNMI_STATIC int GetVpdKeyArr(SK_AC *pAC, SK_IOC IoC, char *pKeyArr,
unsigned int KeyArrLen, unsigned int *pKeyNo);
PNMI_STATIC int LookupId(SK_U32 Id);
PNMI_STATIC int MacUpdate(SK_AC *pAC, SK_IOC IoC, unsigned int FirstMac,
unsigned int LastMac);
PNMI_STATIC int PnmiStruct(SK_AC *pAC, SK_IOC IoC, int Action, char *pBuf,
unsigned int *pLen, SK_U32 NetIndex);
PNMI_STATIC int PnmiVar(SK_AC *pAC, SK_IOC IoC, int Action, SK_U32 Id,
char *pBuf, unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex);
PNMI_STATIC void QueueRlmtNewMacTrap(SK_AC *pAC, unsigned int ActiveMac);
PNMI_STATIC void QueueRlmtPortTrap(SK_AC *pAC, SK_U32 TrapId,
unsigned int PortIndex);
PNMI_STATIC void QueueSensorTrap(SK_AC *pAC, SK_U32 TrapId,
unsigned int SensorIndex);
PNMI_STATIC void QueueSimpleTrap(SK_AC *pAC, SK_U32 TrapId);
PNMI_STATIC void ResetCounter(SK_AC *pAC, SK_IOC IoC, SK_U32 NetIndex);
PNMI_STATIC int RlmtUpdate(SK_AC *pAC, SK_IOC IoC, SK_U32 NetIndex);
PNMI_STATIC int SirqUpdate(SK_AC *pAC, SK_IOC IoC);
PNMI_STATIC void VirtualConf(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, char *pBuf);
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);
/*
* Table to correlate OID with handler function and index to
* hardware register stored in StatAddress if applicable.
*/
#include "skgemib.c"
/* global variables **********************************************************/
/*
* Overflow status register bit table and corresponding counter
* dependent on MAC type - the number relates to the size of overflow
* mask returned by the pFnMacOverflow function
*/
PNMI_STATIC const SK_U16 StatOvrflwBit[][SK_PNMI_MAC_TYPES] = {
/* Bit0 */ { SK_PNMI_HTX, SK_PNMI_HTX_UNICAST},
/* Bit1 */ { SK_PNMI_HTX_OCTETHIGH, SK_PNMI_HTX_BROADCAST},
/* Bit2 */ { SK_PNMI_HTX_OCTETLOW, SK_PNMI_HTX_PMACC},
/* Bit3 */ { SK_PNMI_HTX_BROADCAST, SK_PNMI_HTX_MULTICAST},
/* Bit4 */ { SK_PNMI_HTX_MULTICAST, SK_PNMI_HTX_OCTETLOW},
/* Bit5 */ { SK_PNMI_HTX_UNICAST, SK_PNMI_HTX_OCTETHIGH},
/* Bit6 */ { SK_PNMI_HTX_LONGFRAMES, SK_PNMI_HTX_64},
/* Bit7 */ { SK_PNMI_HTX_BURST, SK_PNMI_HTX_127},
/* Bit8 */ { SK_PNMI_HTX_PMACC, SK_PNMI_HTX_255},
/* Bit9 */ { SK_PNMI_HTX_MACC, SK_PNMI_HTX_511},
/* Bit10 */ { SK_PNMI_HTX_SINGLE_COL, SK_PNMI_HTX_1023},
/* Bit11 */ { SK_PNMI_HTX_MULTI_COL, SK_PNMI_HTX_MAX},
/* Bit12 */ { SK_PNMI_HTX_EXCESS_COL, SK_PNMI_HTX_LONGFRAMES},
/* Bit13 */ { SK_PNMI_HTX_LATE_COL, SK_PNMI_HTX_RESERVED},
/* Bit14 */ { SK_PNMI_HTX_DEFFERAL, SK_PNMI_HTX_COL},
/* Bit15 */ { SK_PNMI_HTX_EXCESS_DEF, SK_PNMI_HTX_LATE_COL},
/* Bit16 */ { SK_PNMI_HTX_UNDERRUN, SK_PNMI_HTX_EXCESS_COL},
/* Bit17 */ { SK_PNMI_HTX_CARRIER, SK_PNMI_HTX_MULTI_COL},
/* Bit18 */ { SK_PNMI_HTX_UTILUNDER, SK_PNMI_HTX_SINGLE_COL},
/* Bit19 */ { SK_PNMI_HTX_UTILOVER, SK_PNMI_HTX_UNDERRUN},
/* Bit20 */ { SK_PNMI_HTX_64, SK_PNMI_HTX_RESERVED},
/* Bit21 */ { SK_PNMI_HTX_127, SK_PNMI_HTX_RESERVED},
/* Bit22 */ { SK_PNMI_HTX_255, SK_PNMI_HTX_RESERVED},
/* Bit23 */ { SK_PNMI_HTX_511, SK_PNMI_HTX_RESERVED},
/* Bit24 */ { SK_PNMI_HTX_1023, SK_PNMI_HTX_RESERVED},
/* Bit25 */ { SK_PNMI_HTX_MAX, SK_PNMI_HTX_RESERVED},
/* Bit26 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED},
/* Bit27 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED},
/* Bit28 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED},
/* Bit29 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED},
/* Bit30 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED},
/* Bit31 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED},
/* Bit32 */ { SK_PNMI_HRX, SK_PNMI_HRX_UNICAST},
/* Bit33 */ { SK_PNMI_HRX_OCTETHIGH, SK_PNMI_HRX_BROADCAST},
/* Bit34 */ { SK_PNMI_HRX_OCTETLOW, SK_PNMI_HRX_PMACC},
/* Bit35 */ { SK_PNMI_HRX_BROADCAST, SK_PNMI_HRX_MULTICAST},
/* Bit36 */ { SK_PNMI_HRX_MULTICAST, SK_PNMI_HRX_FCS},
/* Bit37 */ { SK_PNMI_HRX_UNICAST, SK_PNMI_HRX_RESERVED},
/* Bit38 */ { SK_PNMI_HRX_PMACC, SK_PNMI_HRX_OCTETLOW},
/* Bit39 */ { SK_PNMI_HRX_MACC, SK_PNMI_HRX_OCTETHIGH},
/* Bit40 */ { SK_PNMI_HRX_PMACC_ERR, SK_PNMI_HRX_BADOCTETLOW},
/* Bit41 */ { SK_PNMI_HRX_MACC_UNKWN, SK_PNMI_HRX_BADOCTETHIGH},
/* Bit42 */ { SK_PNMI_HRX_BURST, SK_PNMI_HRX_UNDERSIZE},
/* Bit43 */ { SK_PNMI_HRX_MISSED, SK_PNMI_HRX_RUNT},
/* Bit44 */ { SK_PNMI_HRX_FRAMING, SK_PNMI_HRX_64},
/* Bit45 */ { SK_PNMI_HRX_OVERFLOW, SK_PNMI_HRX_127},
/* Bit46 */ { SK_PNMI_HRX_JABBER, SK_PNMI_HRX_255},
/* Bit47 */ { SK_PNMI_HRX_CARRIER, SK_PNMI_HRX_511},
/* Bit48 */ { SK_PNMI_HRX_IRLENGTH, SK_PNMI_HRX_1023},
/* Bit49 */ { SK_PNMI_HRX_SYMBOL, SK_PNMI_HRX_MAX},
/* Bit50 */ { SK_PNMI_HRX_SHORTS, SK_PNMI_HRX_LONGFRAMES},
/* Bit51 */ { SK_PNMI_HRX_RUNT, SK_PNMI_HRX_TOO_LONG},
/* Bit52 */ { SK_PNMI_HRX_TOO_LONG, SK_PNMI_HRX_JABBER},
/* Bit53 */ { SK_PNMI_HRX_FCS, SK_PNMI_HRX_RESERVED},
/* Bit54 */ { SK_PNMI_HRX_RESERVED, SK_PNMI_HRX_OVERFLOW},
/* Bit55 */ { SK_PNMI_HRX_CEXT, SK_PNMI_HRX_RESERVED},
/* Bit56 */ { SK_PNMI_HRX_UTILUNDER, SK_PNMI_HRX_RESERVED},
/* Bit57 */ { SK_PNMI_HRX_UTILOVER, SK_PNMI_HRX_RESERVED},
/* Bit58 */ { SK_PNMI_HRX_64, SK_PNMI_HRX_RESERVED},
/* Bit59 */ { SK_PNMI_HRX_127, SK_PNMI_HRX_RESERVED},
/* Bit60 */ { SK_PNMI_HRX_255, SK_PNMI_HRX_RESERVED},
/* Bit61 */ { SK_PNMI_HRX_511, SK_PNMI_HRX_RESERVED},
/* Bit62 */ { SK_PNMI_HRX_1023, SK_PNMI_HRX_RESERVED},
/* Bit63 */ { SK_PNMI_HRX_MAX, SK_PNMI_HRX_RESERVED}
};
/*
* Table for hardware register saving on resets and port switches
*/
PNMI_STATIC const SK_PNMI_STATADDR StatAddr[SK_PNMI_MAX_IDX][SK_PNMI_MAC_TYPES] = {
/* SK_PNMI_HTX */
{{XM_TXF_OK, SK_TRUE}, {0, SK_FALSE}},
/* SK_PNMI_HTX_OCTETHIGH */
{{XM_TXO_OK_HI, SK_TRUE}, {GM_TXO_OK_HI, SK_TRUE}},
/* SK_PNMI_HTX_OCTETLOW */
{{XM_TXO_OK_LO, SK_FALSE}, {GM_TXO_OK_LO, SK_FALSE}},
/* SK_PNMI_HTX_BROADCAST */
{{XM_TXF_BC_OK, SK_TRUE}, {GM_TXF_BC_OK, SK_TRUE}},
/* SK_PNMI_HTX_MULTICAST */
{{XM_TXF_MC_OK, SK_TRUE}, {GM_TXF_MC_OK, SK_TRUE}},
/* SK_PNMI_HTX_UNICAST */
{{XM_TXF_UC_OK, SK_TRUE}, {GM_TXF_UC_OK, SK_TRUE}},
/* SK_PNMI_HTX_BURST */
{{XM_TXE_BURST, SK_TRUE}, {0, SK_FALSE}},
/* SK_PNMI_HTX_PMACC */
{{XM_TXF_MPAUSE, SK_TRUE}, {GM_TXF_MPAUSE, SK_TRUE}},
/* SK_PNMI_HTX_MACC */
{{XM_TXF_MCTRL, SK_TRUE}, {0, SK_FALSE}},
/* SK_PNMI_HTX_COL */
{{0, SK_FALSE}, {GM_TXF_COL, SK_TRUE}},
/* SK_PNMI_HTX_SINGLE_COL */
{{XM_TXF_SNG_COL, SK_TRUE}, {GM_TXF_SNG_COL, SK_TRUE}},
/* SK_PNMI_HTX_MULTI_COL */
{{XM_TXF_MUL_COL, SK_TRUE}, {GM_TXF_MUL_COL, SK_TRUE}},
/* SK_PNMI_HTX_EXCESS_COL */
{{XM_TXF_ABO_COL, SK_TRUE}, {GM_TXF_ABO_COL, SK_TRUE}},
/* SK_PNMI_HTX_LATE_COL */
{{XM_TXF_LAT_COL, SK_TRUE}, {GM_TXF_LAT_COL, SK_TRUE}},
/* SK_PNMI_HTX_DEFFERAL */
{{XM_TXF_DEF, SK_TRUE}, {0, SK_FALSE}},
/* SK_PNMI_HTX_EXCESS_DEF */
{{XM_TXF_EX_DEF, SK_TRUE}, {0, SK_FALSE}},
/* SK_PNMI_HTX_UNDERRUN */
{{XM_TXE_FIFO_UR, SK_TRUE}, {GM_TXE_FIFO_UR, SK_TRUE}},
/* SK_PNMI_HTX_CARRIER */
{{XM_TXE_CS_ERR, SK_TRUE}, {0, SK_FALSE}},
/* SK_PNMI_HTX_UTILUNDER */
{{0, SK_FALSE}, {0, SK_FALSE}},
/* SK_PNMI_HTX_UTILOVER */
{{0, SK_FALSE}, {0, SK_FALSE}},
/* SK_PNMI_HTX_64 */
{{XM_TXF_64B, SK_TRUE}, {GM_TXF_64B, SK_TRUE}},
/* SK_PNMI_HTX_127 */
{{XM_TXF_127B, SK_TRUE}, {GM_TXF_127B, SK_TRUE}},
/* SK_PNMI_HTX_255 */
{{XM_TXF_255B, SK_TRUE}, {GM_TXF_255B, SK_TRUE}},
/* SK_PNMI_HTX_511 */
{{XM_TXF_511B, SK_TRUE}, {GM_TXF_511B, SK_TRUE}},
/* SK_PNMI_HTX_1023 */
{{XM_TXF_1023B, SK_TRUE}, {GM_TXF_1023B, SK_TRUE}},
/* SK_PNMI_HTX_MAX */
{{XM_TXF_MAX_SZ, SK_TRUE}, {GM_TXF_1518B, SK_TRUE}},
/* SK_PNMI_HTX_LONGFRAMES */
{{XM_TXF_LONG, SK_TRUE}, {GM_TXF_MAX_SZ, SK_TRUE}},
/* SK_PNMI_HTX_SYNC */
{{0, SK_FALSE}, {0, SK_FALSE}},
/* SK_PNMI_HTX_SYNC_OCTET */
{{0, SK_FALSE}, {0, SK_FALSE}},
/* SK_PNMI_HTX_RESERVED */
{{0, SK_FALSE}, {0, SK_FALSE}},
/* SK_PNMI_HRX */
{{XM_RXF_OK, SK_TRUE}, {0, SK_FALSE}},
/* SK_PNMI_HRX_OCTETHIGH */
{{XM_RXO_OK_HI, SK_TRUE}, {GM_RXO_OK_HI, SK_TRUE}},
/* SK_PNMI_HRX_OCTETLOW */
{{XM_RXO_OK_LO, SK_FALSE}, {GM_RXO_OK_LO, SK_FALSE}},
/* SK_PNMI_HRX_BADOCTETHIGH */
{{0, SK_FALSE}, {GM_RXO_ERR_HI, SK_TRUE}},
/* SK_PNMI_HRX_BADOCTETLOW */
{{0, SK_FALSE}, {GM_RXO_ERR_LO, SK_TRUE}},
/* SK_PNMI_HRX_BROADCAST */
{{XM_RXF_BC_OK, SK_TRUE}, {GM_RXF_BC_OK, SK_TRUE}},
/* SK_PNMI_HRX_MULTICAST */
{{XM_RXF_MC_OK, SK_TRUE}, {GM_RXF_MC_OK, SK_TRUE}},
/* SK_PNMI_HRX_UNICAST */
{{XM_RXF_UC_OK, SK_TRUE}, {GM_RXF_UC_OK, SK_TRUE}},
/* SK_PNMI_HRX_PMACC */
{{XM_RXF_MPAUSE, SK_TRUE}, {GM_RXF_MPAUSE, SK_TRUE}},
/* SK_PNMI_HRX_MACC */
{{XM_RXF_MCTRL, SK_TRUE}, {0, SK_FALSE}},
/* SK_PNMI_HRX_PMACC_ERR */
{{XM_RXF_INV_MP, SK_TRUE}, {0, SK_FALSE}},
/* SK_PNMI_HRX_MACC_UNKWN */
{{XM_RXF_INV_MOC, SK_TRUE}, {0, SK_FALSE}},
/* SK_PNMI_HRX_BURST */
{{XM_RXE_BURST, SK_TRUE}, {0, SK_FALSE}},
/* SK_PNMI_HRX_MISSED */
{{XM_RXE_FMISS, SK_TRUE}, {0, SK_FALSE}},
/* SK_PNMI_HRX_FRAMING */
{{XM_RXF_FRA_ERR, SK_TRUE}, {0, SK_FALSE}},
/* SK_PNMI_HRX_UNDERSIZE */
{{0, SK_FALSE},{GM_RXF_SHT, SK_TRUE}},
/* SK_PNMI_HRX_OVERFLOW */
{{XM_RXE_FIFO_OV, SK_TRUE}, {GM_RXE_FIFO_OV, SK_TRUE}},
/* SK_PNMI_HRX_JABBER */
{{XM_RXF_JAB_PKT, SK_TRUE}, {GM_RXF_JAB_PKT, SK_TRUE}},
/* SK_PNMI_HRX_CARRIER */
{{XM_RXE_CAR_ERR, SK_TRUE}, {0, SK_FALSE}},
/* SK_PNMI_HRX_IRLENGTH */
{{XM_RXF_LEN_ERR, SK_TRUE}, {0, SK_FALSE}},
/* SK_PNMI_HRX_SYMBOL */
{{XM_RXE_SYM_ERR, SK_TRUE}, {0, SK_FALSE}},
/* SK_PNMI_HRX_SHORTS */
{{XM_RXE_SHT_ERR, SK_TRUE}, {0, SK_FALSE}},
/* SK_PNMI_HRX_RUNT */
{{XM_RXE_RUNT, SK_TRUE}, {GM_RXE_FRAG, SK_TRUE}},
/* SK_PNMI_HRX_TOO_LONG */
{{XM_RXF_LNG_ERR, SK_TRUE}, {GM_RXF_LNG_ERR, SK_TRUE}},
/* SK_PNMI_HRX_FCS */
{{XM_RXF_FCS_ERR, SK_TRUE}, {GM_RXF_FCS_ERR, SK_TRUE}},
/* SK_PNMI_HRX_CEXT */
{{XM_RXF_CEX_ERR, SK_TRUE}, {0, SK_FALSE}},
/* SK_PNMI_HRX_UTILUNDER */
{{0, SK_FALSE}, {0, SK_FALSE}},
/* SK_PNMI_HRX_UTILOVER */
{{0, SK_FALSE}, {0, SK_FALSE}},
/* SK_PNMI_HRX_64 */
{{XM_RXF_64B, SK_TRUE}, {GM_RXF_64B, SK_TRUE}},
/* SK_PNMI_HRX_127 */
{{XM_RXF_127B, SK_TRUE}, {GM_RXF_127B, SK_TRUE}},
/* SK_PNMI_HRX_255 */
{{XM_RXF_255B, SK_TRUE}, {GM_RXF_255B, SK_TRUE}},
/* SK_PNMI_HRX_511 */
{{XM_RXF_511B, SK_TRUE}, {GM_RXF_511B, SK_TRUE}},
/* SK_PNMI_HRX_1023 */
{{XM_RXF_1023B, SK_TRUE}, {GM_RXF_1023B, SK_TRUE}},
/* SK_PNMI_HRX_MAX */
{{XM_RXF_MAX_SZ, SK_TRUE}, {GM_RXF_1518B, SK_TRUE}},
/* SK_PNMI_HRX_LONGFRAMES */
{{0, SK_FALSE}, {GM_RXF_MAX_SZ, SK_TRUE}},
/* SK_PNMI_HRX_RESERVED */
{{0, SK_FALSE}, {0, SK_FALSE}}
};
/*****************************************************************************
*
* 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
*/
int SkPnmiInit(
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_GEPORT *pPrt;
SK_PNMI_VCT *pVctBackupData;
SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
("PNMI: SkPnmiInit: Called, level=%d\n", Level));
switch (Level) {
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;
}
#ifdef SK_PNMI_CHECK
if (SK_PNMI_MAX_IDX != SK_PNMI_CNT_NO) {
SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR049, SK_PNMI_ERR049MSG);
SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_INIT | SK_DBGCAT_FATAL,
("CounterOffset struct size (%d) differs from"
"SK_PNMI_MAX_IDX (%d)\n",
SK_PNMI_CNT_NO, SK_PNMI_MAX_IDX));
BRK;
}
if (SK_PNMI_MAX_IDX !=
(sizeof(StatAddr) / (sizeof(SK_PNMI_STATADDR) * SK_PNMI_MAC_TYPES))) {
SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR050, SK_PNMI_ERR050MSG);
SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_INIT | SK_DBGCAT_FATAL,
("StatAddr table size (%d) differs from "
"SK_PNMI_MAX_IDX (%d)\n",
(sizeof(StatAddr) /
(sizeof(SK_PNMI_STATADDR) * SK_PNMI_MAC_TYPES)),
SK_PNMI_MAX_IDX));
BRK;
}
#endif /* SK_PNMI_CHECK */
break;
case SK_INIT_IO:
/*
* 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 ++) {
pPrt = &pAC->GIni.GP[PortIndex];
pPrt->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;
}
else {
pAC->Pnmi.PciBusSpeed = 66;
}
/*
* Get pci bus width
*/
SK_IN16(IoC, B0_CTST, &Val16);
if ((Val16 & CS_BUS_SLOT_SZ) == 0) {
pAC->Pnmi.PciBusWidth = 32;
}
else {
pAC->Pnmi.PciBusWidth = 64;
}
/*
* Get chipset
*/
switch (pAC->GIni.GIChipId) {
case CHIP_ID_GENESIS:
pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_XMAC;
break;
case CHIP_ID_YUKON:
pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_YUKON;
break;
default:
break;
}
/*
* Get PMD and DeviceType
*/
SK_IN8(IoC, B2_PMD_TYP, &Val8);
switch (Val8) {
case 'S':
pAC->Pnmi.PMD = 3;
if (pAC->GIni.GIMacsFound > 1) {
pAC->Pnmi.DeviceType = 0x00020002;
}
else {
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;
}
break;
case 'C':
pAC->Pnmi.PMD = 4;
if (pAC->GIni.GIMacsFound > 1) {
pAC->Pnmi.DeviceType = 0x00020006;
}
else {
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;
}
break;
default :
pAC->Pnmi.PMD = 1;
pAC->Pnmi.DeviceType = 0;
break;
}
/*
* Get connector
*/
SK_IN8(IoC, B2_CONN_TYP, &Val8);
switch (Val8) {
case 'C':
pAC->Pnmi.Connector = 2;
break;
case 'D':
pAC->Pnmi.Connector = 3;
break;
case 'F':
pAC->Pnmi.Connector = 4;
break;
case 'J':
pAC->Pnmi.Connector = 5;
break;
case 'V':
pAC->Pnmi.Connector = 6;
break;
default:
pAC->Pnmi.Connector = 1;
break;
}
break;
case SK_INIT_RUN:
/*
* 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,
EventParam);
break;
default:
break; /* Nothing todo */
}
return (0);
}
/*****************************************************************************
*
* 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 int *pLen, /* On call: buffer length. On return: used buffer */
SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */
{
SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
("PNMI: SkPnmiGetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n",
Id, *pLen, Instance, NetIndex));
return (PnmiVar(pAC, IoC, SK_PNMI_GET, Id, (char *)pBuf, pLen,
Instance, NetIndex));
}
/*****************************************************************************
*
* 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 int *pLen, /* Total length of mgmt data */
SK_U32 Instance, /* Instance (1..n) that is to be set or -1 */
SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */
{
SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
("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));
}
/*****************************************************************************
*
* 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 int *pLen, /* Total length of mgmt data */
SK_U32 Instance, /* Instance (1..n) that is to be set or -1 */
SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */
{
SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
("PNMI: SkPnmiSetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n",
Id, *pLen, Instance, NetIndex));
return (PnmiVar(pAC, IoC, SK_PNMI_SET, Id, (char *)pBuf, pLen,
Instance, NetIndex));
}
/*****************************************************************************
*
* 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 int *pLen, /* Length of buffer */
SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */
{
int Ret;
unsigned int TableIndex;
unsigned int DstOffset;
unsigned int InstanceNo;
unsigned int InstanceCnt;
SK_U32 Instance;
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));
if (*pLen < SK_PNMI_STRUCT_SIZE) {
if (*pLen >= SK_PNMI_MIN_STRUCT_SIZE) {
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
*/
if (NetIndex >= pAC->Rlmt.NumNets) {
return (SK_PNMI_ERR_UNKNOWN_NET);
}
/* Update statistic */
SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On call");
if ((Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1)) !=
SK_PNMI_ERR_OK) {
SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
*pLen = SK_PNMI_MIN_STRUCT_SIZE;
return (Ret);
}
if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) {
SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
*pLen = SK_PNMI_MIN_STRUCT_SIZE;
return (Ret);
}
if ((Ret = SirqUpdate(pAC, IoC)) != SK_PNMI_ERR_OK) {
SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
*pLen = SK_PNMI_MIN_STRUCT_SIZE;
return (Ret);
}
/*
* 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) {
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);
}
/* 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 ++) {
DstOffset = IdTable[TableIndex].Offset +
(InstanceCnt - 1) *
IdTable[TableIndex].StructSize;
/*
* For the VPD the instance is not an index number
* but the key itself. Determin with the instance
* counter the VPD key to be used.
*/
if (IdTable[TableIndex].Id == OID_SKGE_VPD_KEY ||
IdTable[TableIndex].Id == OID_SKGE_VPD_VALUE ||
IdTable[TableIndex].Id == OID_SKGE_VPD_ACCESS ||
IdTable[TableIndex].Id == OID_SKGE_VPD_ACTION) {
SK_STRNCPY((char *)&Instance, KeyArr[InstanceCnt - 1], 4);
}
else {
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, NetIndex);
/*
* 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) {
pAC->Pnmi.MacUpdatedFlag --;
pAC->Pnmi.RlmtUpdatedFlag --;
pAC->Pnmi.SirqUpdatedFlag --;
SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return");
SK_PNMI_SET_STAT(pBuf, Ret, DstOffset);
*pLen = SK_PNMI_MIN_STRUCT_SIZE;
return (Ret);
}
}
}
pAC->Pnmi.MacUpdatedFlag --;
pAC->Pnmi.RlmtUpdatedFlag --;
pAC->Pnmi.SirqUpdatedFlag --;
*pLen = SK_PNMI_STRUCT_SIZE;
SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return");
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 int *pLen, /* Length of buffer */
SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */
{
SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
("PNMI: SkPnmiPreSetStruct: Called, BufLen=%d, NetIndex=%d\n",
*pLen, NetIndex));
return (PnmiStruct(pAC, IoC, SK_PNMI_PRESET, (char *)pBuf,
pLen, NetIndex));
}
/*****************************************************************************
*
* 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_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */
{
SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
("PNMI: SkPnmiSetStruct: Called, BufLen=%d, NetIndex=%d\n",
*pLen, NetIndex));
return (PnmiStruct(pAC, IoC, SK_PNMI_SET, (char *)pBuf,
pLen, NetIndex));
}
/*****************************************************************************
*
* SkPnmiEvent - Event handler
*
* Description:
* Handles the following events:
* SK_PNMI_EVT_SIRQ_OVERFLOW When a hardware counter overflows an
* interrupt will be generated which is
* first handled by SIRQ which generates a
* this event. The event increments the
* upper 32 bit of the 64 bit counter.
* SK_PNMI_EVT_SEN_XXX The event is generated by the I2C module
* when a sensor reports a warning or
* error. The event will store a trap
* message in the trap buffer.
* SK_PNMI_EVT_CHG_EST_TIMER The timer event was initiated by this
* module and is used to calculate the
* port switches per hour.
* SK_PNMI_EVT_CLEAR_COUNTER The event clears all counters and
* timestamps.
* SK_PNMI_EVT_XMAC_RESET The event is generated by the driver
* before a hard reset of the XMAC is
* performed. All counters will be saved
* and added to the hardware counter
* values after reset to grant continuous
* counter values.
* SK_PNMI_EVT_RLMT_PORT_UP Generated by RLMT to notify that a port
* went logically up. A trap message will
* be stored to the trap buffer.
* SK_PNMI_EVT_RLMT_PORT_DOWN Generated by RLMT to notify that a port
* went logically down. A trap message will
* be stored to the trap buffer.
* SK_PNMI_EVT_RLMT_SEGMENTATION Generated by RLMT to notify that two
* spanning tree root bridges were
* detected. A trap message will be stored
* to the trap buffer.
* SK_PNMI_EVT_RLMT_ACTIVE_DOWN Notifies PNMI that an active port went
* down. PNMI will not further add the
* statistic values to the virtual port.
* SK_PNMI_EVT_RLMT_ACTIVE_UP Notifies PNMI that a port went up and
* is now an active port. PNMI will now
* add the statistic data of this port to
* the virtual port.
* SK_PNMI_EVT_RLMT_SET_NETS Notifies PNMI about the net mode. The first Parameter
* contains the number of nets. 1 means single net, 2 means
* dual net. The second Parameter is -1
*
* Returns:
* Always 0
*/
int SkPnmiEvent(
SK_AC *pAC, /* Pointer to adapter context */
SK_IOC IoC, /* IO context handle */
SK_U32 Event, /* Event-Id */
SK_EVPARA Param) /* Event dependent parameter */
{
unsigned int PhysPortIndex;
unsigned int MaxNetNumber;
int CounterIndex;
int Ret;
SK_U16 MacStatus;
SK_U64 OverflowStatus;
SK_U64 Mask;
int MacType;
SK_U64 Value;
SK_U32 Val32;
SK_U16 Register;
SK_EVPARA EventParam;
SK_U64 NewestValue;
SK_U64 OldestValue;
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) {
SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
("PNMI: SkPnmiEvent: Called, Event=0x%x, Param=0x%x\n",
(unsigned int)Event, (unsigned int)Param.Para64));
}
#endif
SK_PNMI_CHECKFLAGS("SkPnmiEvent: On call");
MacType = pAC->GIni.GIMacType;
switch (Event) {
case SK_PNMI_EVT_SIRQ_OVERFLOW:
PhysPortIndex = (int)Param.Para32[0];
MacStatus = (SK_U16)Param.Para32[1];
#ifdef DEBUG
if (PhysPortIndex >= SK_MAX_MACS) {
SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SIRQ_OVERFLOW parameter"
" wrong, PhysPortIndex=0x%x\n",
PhysPortIndex));
return (0);
}
#endif
OverflowStatus = 0;
/*
* Check which source caused an overflow interrupt.
*/
if ((pAC->GIni.GIFunc.pFnMacOverflow(
pAC, IoC, PhysPortIndex, MacStatus, &OverflowStatus) != 0) ||
(OverflowStatus == 0)) {
SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
return (0);
}
/*
* Check the overflow status register and increment
* the upper dword of corresponding counter.
*/
for (CounterIndex = 0; CounterIndex < sizeof(Mask) * 8;
CounterIndex ++) {
Mask = (SK_U64)1 << CounterIndex;
if ((OverflowStatus & Mask) == 0) {
continue;
}
switch (StatOvrflwBit[CounterIndex][MacType]) {
case SK_PNMI_HTX_UTILUNDER:
case SK_PNMI_HTX_UTILOVER:
XM_IN16(IoC, PhysPortIndex, XM_TX_CMD,
&Register);
Register |= XM_TX_SAM_LINE;
XM_OUT16(IoC, PhysPortIndex, XM_TX_CMD,
Register);
break;
case SK_PNMI_HRX_UTILUNDER:
case SK_PNMI_HRX_UTILOVER:
XM_IN16(IoC, PhysPortIndex, XM_RX_CMD,
&Register);
Register |= XM_RX_SAM_LINE;
XM_OUT16(IoC, PhysPortIndex, XM_RX_CMD,
Register);
break;
case SK_PNMI_HTX_OCTETHIGH:
case SK_PNMI_HTX_OCTETLOW:
case SK_PNMI_HTX_RESERVED:
case SK_PNMI_HRX_OCTETHIGH:
case SK_PNMI_HRX_OCTETLOW:
case SK_PNMI_HRX_IRLENGTH:
case SK_PNMI_HRX_RESERVED:
/*
* the following counters aren't be handled (id > 63)
*/
case SK_PNMI_HTX_SYNC:
case SK_PNMI_HTX_SYNC_OCTET:
break;
case SK_PNMI_HRX_LONGFRAMES:
if (MacType == SK_MAC_GMAC) {
pAC->Pnmi.Port[PhysPortIndex].
CounterHigh[CounterIndex] ++;
}
break;
default:
pAC->Pnmi.Port[PhysPortIndex].
CounterHigh[CounterIndex] ++;
}
}
break;
case SK_PNMI_EVT_SEN_WAR_LOW:
#ifdef DEBUG
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_WAR_LOW parameter wrong, SensorIndex=%d\n",
(unsigned int)Param.Para64));
return (0);
}
#endif
/*
* Store a trap message in the trap buffer and generate
* an event for user space applications with the
* SK_DRIVER_SENDEVENT macro.
*/
QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_WAR_LOW,
(unsigned int)Param.Para64);
(void)SK_DRIVER_SENDEVENT(pAC, IoC);
break;
case SK_PNMI_EVT_SEN_WAR_UPP:
#ifdef DEBUG
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_WAR_UPP parameter wrong, SensorIndex=%d\n",
(unsigned int)Param.Para64));
return (0);
}
#endif
/*
* Store a trap message in the trap buffer and generate
* an event for user space applications with the
* SK_DRIVER_SENDEVENT macro.
*/
QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_WAR_UPP,
(unsigned int)Param.Para64);
(void)SK_DRIVER_SENDEVENT(pAC, IoC);
break;
case SK_PNMI_EVT_SEN_ERR_LOW:
#ifdef DEBUG
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_LOW parameter wrong, SensorIndex=%d\n",
(unsigned int)Param.Para64));
return (0);
}
#endif
/*
* Store a trap message in the trap buffer and generate
* an event for user space applications with the
* SK_DRIVER_SENDEVENT macro.
*/
QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_ERR_LOW,
(unsigned int)Param.Para64);
(void)SK_DRIVER_SENDEVENT(pAC, IoC);
break;
case SK_PNMI_EVT_SEN_ERR_UPP:
#ifdef DEBUG
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",
(unsigned int)Param.Para64));
return (0);
}
#endif
/*
* Store a trap message in the trap buffer and generate
* an event for user space applications with the
* SK_DRIVER_SENDEVENT macro.
*/
QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_ERR_UPP,
(unsigned int)Param.Para64);
(void)SK_DRIVER_SENDEVENT(pAC, IoC);
break;
case SK_PNMI_EVT_CHG_EST_TIMER:
/*
* Calculate port switch average on a per hour basis
* Time interval for check : 28125 ms
* 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 initilization SkTimerStart() in SkPnmiInit
* - Delta value below must be multiplicated with
* power of 2
*
*/
pEst = &pAC->Pnmi.RlmtChangeEstimate;
CounterIndex = pEst->EstValueIndex + 1;
if (CounterIndex == 7) {
CounterIndex = 0;
}
pEst->EstValueIndex = CounterIndex;
NewestValue = pAC->Pnmi.RlmtChangeCts;
OldestValue = pEst->EstValue[CounterIndex];
pEst->EstValue[CounterIndex] = NewestValue;
/*
* Calculate average. Delta stores the number of
* port switches per 28125 * 8 = 225000 ms
*/
if (NewestValue >= OldestValue) {
Delta = NewestValue - OldestValue;
}
else {
/* Overflow situation */
Delta = (SK_U64)(0 - OldestValue) + NewestValue;
}
/*
* Extrapolate delta to port switches per hour.
* Estimate = Delta * (3600000 / 225000)
* = Delta * 16
* = Delta << 4
*/
pAC->Pnmi.RlmtChangeEstimate.Estimate = Delta << 4;
/*
* Check if threshold is exceeded. If the threshold is
* permanently exceeded every 28125 ms an event will be
* generated to remind the user of this condition.
*/
if ((pAC->Pnmi.RlmtChangeThreshold != 0) &&
(pAC->Pnmi.RlmtChangeEstimate.Estimate >=
pAC->Pnmi.RlmtChangeThreshold)) {
QueueSimpleTrap(pAC, OID_SKGE_TRAP_RLMT_CHANGE_THRES);
(void)SK_DRIVER_SENDEVENT(pAC, IoC);
}
SK_MEMSET((char *) &EventParam, 0, sizeof(EventParam));
SkTimerStart(pAC, IoC, &pAC->Pnmi.RlmtChangeEstimate.EstTimer,
28125000, SKGE_PNMI, SK_PNMI_EVT_CHG_EST_TIMER,
EventParam);
break;
case SK_PNMI_EVT_CLEAR_COUNTER:
/*
* Param.Para32[0] contains the NetIndex (0 ..1).
* Param.Para32[1] is reserved, contains -1.
*/
NetIndex = (SK_U32)Param.Para32[0];
#ifdef DEBUG
if (NetIndex >= pAC->Rlmt.NumNets) {
SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_CLEAR_COUNTER parameter wrong, NetIndex=%d\n",
NetIndex));
return (0);
}
#endif
/*
* Set all counters and timestamps to zero
*/
ResetCounter(pAC, IoC, NetIndex); /* the according NetIndex is required
as a Parameter of the Event */
break;
case SK_PNMI_EVT_XMAC_RESET:
/*
* To grant continuous counter values store the current
* XMAC statistic values to the entries 1..n of the
* CounterOffset array. XMAC Errata #2
*/
#ifdef DEBUG
if ((unsigned int)Param.Para64 >= SK_MAX_MACS) {
SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_XMAC_RESET parameter wrong, PhysPortIndex=%d\n",
(unsigned int)Param.Para64));
return (0);
}
#endif
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) {
SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
return (0);
}
/*
* 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;
}
pAC->Pnmi.Port[PhysPortIndex].
CounterOffset[CounterIndex] = GetPhysStatVal(
pAC, IoC, PhysPortIndex, CounterIndex);
pAC->Pnmi.Port[PhysPortIndex].
CounterHigh[CounterIndex] = 0;
}
pAC->Pnmi.MacUpdatedFlag --;
break;
case SK_PNMI_EVT_RLMT_PORT_UP:
PhysPortIndex = (unsigned int)Param.Para32[0];
#ifdef DEBUG
if (PhysPortIndex >= SK_MAX_MACS) {
SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_PORT_UP parameter"
" wrong, PhysPortIndex=%d\n", PhysPortIndex));
return (0);
}
#endif
/*
* Store a trap message in the trap buffer and generate an event for
* user space applications with the SK_DRIVER_SENDEVENT macro.
*/
QueueRlmtPortTrap(pAC, OID_SKGE_TRAP_RLMT_PORT_UP, PhysPortIndex);
(void)SK_DRIVER_SENDEVENT(pAC, IoC);
/* Bugfix for XMAC errata (#10620)*/
if (pAC->GIni.GIMacType == SK_MAC_XMAC){
/* 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;
}
/* Tell VctStatus() that a link was up meanwhile. */
pAC->Pnmi.VctStatus[PhysPortIndex] |= SK_PNMI_VCT_LINK;
break;
case SK_PNMI_EVT_RLMT_PORT_DOWN:
PhysPortIndex = (unsigned int)Param.Para32[0];
#ifdef DEBUG
if (PhysPortIndex >= SK_MAX_MACS) {
SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_PORT_DOWN parameter"
" wrong, PhysPortIndex=%d\n", PhysPortIndex));
return (0);
}
#endif
/*
* Store a trap message in the trap buffer and generate an event for
* user space applications with the SK_DRIVER_SENDEVENT macro.
*/
QueueRlmtPortTrap(pAC, OID_SKGE_TRAP_RLMT_PORT_DOWN, PhysPortIndex);
(void)SK_DRIVER_SENDEVENT(pAC, IoC);
/* Bugfix #10620 - get zero level for incremental difference */
if ((pAC->GIni.GIMacType == SK_MAC_XMAC)) {
(void)pAC->GIni.GIFunc.pFnMacStatistic(pAC, IoC, PhysPortIndex,
XM_RXE_SHT_ERR, &Val32);
pAC->Pnmi.Port[PhysPortIndex].RxShortZeroMark =
(((SK_U64)pAC->Pnmi.Port[PhysPortIndex].
CounterHigh[SK_PNMI_HRX_SHORTS] << 32) | (SK_U64)Val32);
}
break;
case SK_PNMI_EVT_RLMT_ACTIVE_DOWN:
PhysPortIndex = (unsigned int)Param.Para32[0];
NetIndex = (SK_U32)Param.Para32[1];
#ifdef DEBUG
if (PhysPortIndex >= SK_MAX_MACS) {
SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_DOWN parameter too high, PhysPort=%d\n",
PhysPortIndex));
}
if (NetIndex >= pAC->Rlmt.NumNets) {
SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_DOWN parameter too high, NetIndex=%d\n",
NetIndex));
}
#endif
/*
* For now, ignore event if NetIndex != 0.
*/
if (Param.Para32[1] != 0) {
return (0);
}
/*
* Nothing to do if port is already inactive
*/
if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
return (0);
}
/*
* Update statistic counters to calculate new offset for the virtual
* port and increment semaphore to indicate that an update was already
* done.
*/
if (MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1) !=
SK_PNMI_ERR_OK) {
SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
return (0);
}
pAC->Pnmi.MacUpdatedFlag ++;
/*
* Calculate new counter offset for virtual port to grant continous
* counting on port switches. The virtual port consists of all currently
* active ports. The port down event indicates that a port is removed
* from the virtual port. Therefore add the counter value of the removed
* port to the CounterOffset for the virtual port to grant the same
* counter value.
*/
for (CounterIndex = 0; CounterIndex < SK_PNMI_MAX_IDX;
CounterIndex ++) {
if (!StatAddr[CounterIndex][MacType].GetOffset) {
continue;
}
Value = GetPhysStatVal(pAC, IoC, PhysPortIndex, CounterIndex);
pAC->Pnmi.VirtualCounterOffset[CounterIndex] += Value;
}
/*
* Set port to inactive
*/
pAC->Pnmi.Port[PhysPortIndex].ActiveFlag = SK_FALSE;
pAC->Pnmi.MacUpdatedFlag --;
break;
case SK_PNMI_EVT_RLMT_ACTIVE_UP:
PhysPortIndex = (unsigned int)Param.Para32[0];
NetIndex = (SK_U32)Param.Para32[1];
#ifdef DEBUG
if (PhysPortIndex >= SK_MAX_MACS) {
SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_UP parameter too high, PhysPort=%d\n",
PhysPortIndex));
}
if (NetIndex >= pAC->Rlmt.NumNets) {
SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_UP parameter too high, NetIndex=%d\n",
NetIndex));
}
#endif
/*
* For now, ignore event if NetIndex != 0.
*/
if (Param.Para32[1] != 0) {
return (0);
}
/*
* Nothing to do if port is already active
*/
if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
return (0);
}
/*
* Statistic maintenance
*/
pAC->Pnmi.RlmtChangeCts ++;
pAC->Pnmi.RlmtChangeTime = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC));
/*
* Store a trap message in the trap buffer and generate an event for
* user space applications with the SK_DRIVER_SENDEVENT macro.
*/
QueueRlmtNewMacTrap(pAC, PhysPortIndex);
(void)SK_DRIVER_SENDEVENT(pAC, IoC);
/*
* Update statistic counters to calculate new offset for the virtual
* port and increment semaphore to indicate that an update was
* already done.
*/
if (MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1) !=
SK_PNMI_ERR_OK) {
SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
return (0);
}
pAC->Pnmi.MacUpdatedFlag ++;
/*
* Calculate new counter offset for virtual port to grant continous
* counting on port switches. A new port is added to the virtual port.
* Therefore substract the counter value of the new port from the
* CounterOffset for the virtual port to grant the same value.
*/
for (CounterIndex = 0; CounterIndex < SK_PNMI_MAX_IDX;
CounterIndex ++) {
if (!StatAddr[CounterIndex][MacType].GetOffset) {
continue;
}
Value = GetPhysStatVal(pAC, IoC, PhysPortIndex, CounterIndex);
pAC->Pnmi.VirtualCounterOffset[CounterIndex] -= Value;
}
/*
* 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.
*/
/*
* Store a trap message in the trap buffer and generate an event for
* user space applications with the SK_DRIVER_SENDEVENT macro.
*/
QueueSimpleTrap(pAC, OID_SKGE_TRAP_RLMT_SEGMENTATION);
(void)SK_DRIVER_SENDEVENT(pAC, IoC);
break;
case SK_PNMI_EVT_RLMT_SET_NETS:
/*
* Param.Para32[0] contains the number of Nets.
* Param.Para32[1] is reserved, contains -1.
*/
/*
* Check number of nets
*/
MaxNetNumber = pAC->GIni.GIMacsFound;
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 */
pAC->Pnmi.DualNetActiveFlag = SK_FALSE;
}
else { /* dual net 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));
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);
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->PMdiPairLen[i] > 35) {
CableLength = 1000 * (((175 * pPrt->PMdiPairLen[i]) / 210) - 28);
}
else {
CableLength = 0;
}
pVctBackupData->PMdiPairLen[i] = CableLength;
pVctBackupData->PMdiPairSts[i] = pPrt->PMdiPairSts[i];
}
Param.Para32[0] = PhysPortIndex;
Param.Para32[1] = -1;
SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Param);
SkEventDispatcher(pAC, IoC);
}
break;
default:
break;
}
SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
return (0);
}
/******************************************************************************
*
* 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
*/
PNMI_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 int *pLen, /* Total length of mgmt data */
SK_U32 Instance, /* Instance (1..n) that is to be set or -1 */
SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */
{
unsigned int TableIndex;
int Ret;
if ((TableIndex = LookupId(Id)) == (unsigned int)(-1)) {
*pLen = 0;
return (SK_PNMI_ERR_UNKNOWN_OID);
}
/*
* Check NetIndex
*/
if (NetIndex >= pAC->Rlmt.NumNets) {
return (SK_PNMI_ERR_UNKNOWN_NET);
}
SK_PNMI_CHECKFLAGS("PnmiVar: On call");
Ret = IdTable[TableIndex].Func(pAC, IoC, Action, Id, pBuf, pLen,
Instance, TableIndex, NetIndex);
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
*/
PNMI_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 int *pLen, /* Length of buffer */
SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */
{
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) {
/* 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));
}
*pLen = SK_PNMI_STRUCT_SIZE;
return (SK_PNMI_ERR_TOO_SHORT);
}
/*
* Check NetIndex
*/
if (NetIndex >= pAC->Rlmt.NumNets) {
return (SK_PNMI_ERR_UNKNOWN_NET);
}
SK_PNMI_CHECKFLAGS("PnmiStruct: On call");
/*
* Update the values of RLMT and SIRQ and increment semaphores to
* indicate that an update was already done.
*/
if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) {
SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
*pLen = SK_PNMI_MIN_STRUCT_SIZE;
return (Ret);
}
if ((Ret = SirqUpdate(pAC, IoC)) != SK_PNMI_ERR_OK) {
SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
*pLen = SK_PNMI_MIN_STRUCT_SIZE;
return (Ret);
}
pAC->Pnmi.RlmtUpdatedFlag ++;
pAC->Pnmi.SirqUpdatedFlag ++;
/* 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;
}
InstanceNo = IdTable[TableIndex].InstanceNo;
Id = IdTable[TableIndex].Id;
for (InstanceCnt = 1; InstanceCnt <= InstanceNo;
InstanceCnt ++) {
DstOffset = IdTable[TableIndex].Offset +
(InstanceCnt - 1) *
IdTable[TableIndex].StructSize;
/*
* Because VPD multiple instance variables are
* not setable we do not need to evaluate VPD
* instances. Have a look to VPD instance
* calculation in SkPnmiGetStruct().
*/
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, NetIndex);
if (Ret == SK_PNMI_ERR_UNKNOWN_INST) {
break;
}
if (Ret != SK_PNMI_ERR_TOO_SHORT) {
pAC->Pnmi.RlmtUpdatedFlag --;
pAC->Pnmi.SirqUpdatedFlag --;
SK_PNMI_CHECKFLAGS("PnmiStruct: On return");
SK_PNMI_SET_STAT(pBuf,
SK_PNMI_ERR_GENERAL, DstOffset);
*pLen = SK_PNMI_MIN_STRUCT_SIZE;
return (SK_PNMI_ERR_GENERAL);
}
if (Id == OID_SKGE_VPD_ACTION) {
switch (*(pBuf + DstOffset)) {
case SK_PNMI_VPD_CREATE:
Len = 3 + *(pBuf + DstOffset + 3);
break;
case SK_PNMI_VPD_DELETE:
Len = 3;
break;
default:
Len = 1;
break;
}
}
/* Call the OID handler function */
Ret = IdTable[TableIndex].Func(pAC, IoC, Action,
IdTable[TableIndex].Id, pBuf + DstOffset,
&Len, Instance, TableIndex, NetIndex);
if (Ret != SK_PNMI_ERR_OK) {
pAC->Pnmi.RlmtUpdatedFlag --;
pAC->Pnmi.SirqUpdatedFlag --;
SK_PNMI_CHECKFLAGS("PnmiStruct: On return");
SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_BAD_VALUE,
DstOffset);
*pLen = SK_PNMI_MIN_STRUCT_SIZE;
return (SK_PNMI_ERR_BAD_VALUE);
}
}
}
pAC->Pnmi.RlmtUpdatedFlag --;
pAC->Pnmi.SirqUpdatedFlag --;
SK_PNMI_CHECKFLAGS("PnmiStruct: On return");
SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_OK, (SK_U32)(-1));
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.
*/
PNMI_STATIC int LookupId(
SK_U32 Id) /* Object identifier to be searched */
{
int i;
for (i = 0; i < ID_TABLE_SIZE; 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.
*/
PNMI_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 int *pLen, /* On call: 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 allways zero */
{
if (Id != OID_SKGE_ALL_DATA) {
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
*/
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, NetIndex));
case SK_PNMI_PRESET:
return (SkPnmiPreSetStruct(pAC, IoC, pBuf, pLen, NetIndex));
case SK_PNMI_SET:
return (SkPnmiSetStruct(pAC, IoC, pBuf, pLen, NetIndex));
}
SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR004, SK_PNMI_ERR004MSG);
*pLen = 0;
return (SK_PNMI_ERR_GENERAL);
}
/*****************************************************************************
*
* Perform - OID handler of OID_SKGE_ACTION
*
* Description:
* None.
*
* 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.
*/
PNMI_STATIC int Perform(
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 int *pLen, /* On call: 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 allways zero */
{
int Ret;
SK_U32 ActionOp;
/*
* Check instance. We only handle single instance variables
*/
if (Instance != (SK_U32)(-1) && Instance != 1) {
*pLen = 0;
return (SK_PNMI_ERR_UNKNOWN_INST);
}
if (*pLen < sizeof(SK_U32)) {
*pLen = sizeof(SK_U32);
return (SK_PNMI_ERR_TOO_SHORT);
}
/* Check if a get should be performed */
if (Action == SK_PNMI_GET) {
/* 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);
return (SK_PNMI_ERR_OK);
}
/* Continue with PRESET/SET action */
if (*pLen > sizeof(SK_U32)) {
return (SK_PNMI_ERR_BAD_VALUE);
}
/* Check if the command is a known one */
SK_PNMI_READ_U32(pBuf, ActionOp);
if (*pLen > sizeof(SK_U32) ||
(ActionOp != SK_PNMI_ACT_IDLE &&
ActionOp != SK_PNMI_ACT_RESET &&
ActionOp != SK_PNMI_ACT_SELFTEST &&
ActionOp != SK_PNMI_ACT_RESETCNT)) {
*pLen = 0;
return (SK_PNMI_ERR_BAD_VALUE);
}
/* A preset ends here */
if (Action == SK_PNMI_PRESET) {
return (SK_PNMI_ERR_OK);
}
switch (ActionOp) {
case SK_PNMI_ACT_IDLE:
/* Nothing to do */
break;
case SK_PNMI_ACT_RESET:
/*
* 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);
return (SK_PNMI_ERR_GENERAL);
}
break;
case SK_PNMI_ACT_SELFTEST:
/*
* Perform a driver selftest or something similar to this.
* Currently this feature is not used and will probably
* implemented in another way.
*/
Ret = SK_DRIVER_SELFTEST(pAC, IoC);
pAC->Pnmi.TestResult = Ret;
break;
case SK_PNMI_ACT_RESETCNT:
/* 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);
return (SK_PNMI_ERR_GENERAL);
}
return (SK_PNMI_ERR_OK);
}
/*****************************************************************************
*
* Mac8023Stat - 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.
*/
PNMI_STATIC int Mac8023Stat(
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 int *pLen, /* On call: 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 allways zero */
{
int Ret;
SK_U64 StatVal;
SK_U32 StatVal32;
SK_BOOL Is64BitReq = SK_FALSE;
/*
* Only the active Mac is returned
*/
if (Instance != (SK_U32)(-1) && Instance != 1) {
*pLen = 0;
return (SK_PNMI_ERR_UNKNOWN_INST);
}
/*
* Check action type
*/
if (Action != SK_PNMI_GET) {
*pLen = 0;
return (SK_PNMI_ERR_READ_ONLY);
}
/*
* Check length
*/
switch (Id) {
case OID_802_3_PERMANENT_ADDRESS:
case OID_802_3_CURRENT_ADDRESS:
if (*pLen < sizeof(SK_MAC_ADDR)) {
*pLen = sizeof(SK_MAC_ADDR);
return (SK_PNMI_ERR_TOO_SHORT);
}
break;
default:
#ifndef SK_NDIS_64BIT_CTR
if (*pLen < sizeof(SK_U32)) {
*pLen = sizeof(SK_U32);
return (SK_PNMI_ERR_TOO_SHORT);
}
#else /* SK_NDIS_64BIT_CTR */
/*
* 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
*/
*pLen = sizeof(SK_U64);
return (SK_PNMI_ERR_TOO_SHORT);
}
Is64BitReq = (*pLen < sizeof(SK_U64)) ? SK_FALSE : SK_TRUE;
#endif /* SK_NDIS_64BIT_CTR */
break;
}
/*
* Update all statistics, because we retrieve virtual MAC, which
* consists of multiple physical statistics and increment semaphore
* to indicate that an update was already done.
*/
Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1);
if ( Ret != SK_PNMI_ERR_OK) {
*pLen = 0;
return (Ret);
}
pAC->Pnmi.MacUpdatedFlag ++;
/*
* Get value (MAC Index 0 identifies the virtual MAC)
*/
switch (Id) {
case OID_802_3_PERMANENT_ADDRESS:
CopyMac(pBuf, &pAC->Addr.Net[NetIndex].PermanentMacAddress);
*pLen = sizeof(SK_MAC_ADDR);
break;
case OID_802_3_CURRENT_ADDRESS:
CopyMac(pBuf, &pAC->Addr.Net[NetIndex].CurrentMacAddress);
*pLen = sizeof(SK_MAC_ADDR);
break;
default:
StatVal = GetStatVal(pAC, IoC, 0, IdTable[TableIndex].Param, NetIndex);
/*
* by default 32bit values are evaluated
*/
if (!Is64BitReq) {
StatVal32 = (SK_U32)StatVal;
SK_PNMI_STORE_U32(pBuf, StatVal32);
*pLen = sizeof(SK_U32);
}
else {
SK_PNMI_STORE_U64(pBuf, StatVal);
*pLen = sizeof(SK_U64);
}
break;
}
pAC->Pnmi.MacUpdatedFlag --;
return (SK_PNMI_ERR_OK);
}
/*****************************************************************************
*
* MacPrivateStat - 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.
*/
PNMI_STATIC int MacPrivateStat(
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 int *pLen, /* On call: 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 allways zero */
{
unsigned int LogPortMax;
unsigned int LogPortIndex;
unsigned int PhysPortMax;
unsigned int Limit;
unsigned int Offset;
int Ret;
SK_U64 StatVal;
/*
* 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 */
LogPortMax--;
}
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 = SK_PNMI_PORT_INST2LOG(Instance);
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);
}
/*
* Update XMAC statistic and increment semaphore to indicate that
* an update was already done.
*/
Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1);
if (Ret != SK_PNMI_ERR_OK) {
*pLen = 0;
return (Ret);
}
pAC->Pnmi.MacUpdatedFlag ++;
/*
* Get value
*/
Offset = 0;
for (; LogPortIndex < Limit; LogPortIndex ++) {
switch (Id) {
/* XXX not yet implemented due to XMAC problems
case OID_SKGE_STAT_TX_UTIL:
return (SK_PNMI_ERR_GENERAL);
*/
/* XXX not yet implemented due to XMAC problems
case OID_SKGE_STAT_RX_UTIL:
return (SK_PNMI_ERR_GENERAL);
*/
case OID_SKGE_STAT_RX:
case OID_SKGE_STAT_TX:
switch (pAC->GIni.GIMacType) {
case SK_MAC_XMAC:
StatVal = GetStatVal(pAC, IoC, LogPortIndex,
IdTable[TableIndex].Param, NetIndex);
break;
case SK_MAC_GMAC:
if (Id == OID_SKGE_STAT_TX) {
StatVal =
GetStatVal(pAC, IoC, LogPortIndex,
SK_PNMI_HTX_BROADCAST, NetIndex) +
GetStatVal(pAC, IoC, LogPortIndex,
SK_PNMI_HTX_MULTICAST, NetIndex) +
GetStatVal(pAC, IoC, LogPortIndex,
SK_PNMI_HTX_UNICAST, NetIndex);
}
else {
StatVal =
GetStatVal(pAC, IoC, LogPortIndex,
SK_PNMI_HRX_BROADCAST, NetIndex) +
GetStatVal(pAC, IoC, LogPortIndex,
SK_PNMI_HRX_MULTICAST, NetIndex) +
GetStatVal(pAC, IoC, LogPortIndex,
SK_PNMI_HRX_UNICAST, NetIndex) +
GetStatVal(pAC, IoC, LogPortIndex,
SK_PNMI_HRX_UNDERSIZE, NetIndex);
}
break;
default:
StatVal = 0;
break;
}
SK_PNMI_STORE_U64(pBuf + Offset, StatVal);
break;
default:
StatVal = GetStatVal(pAC, IoC, LogPortIndex,
IdTable[TableIndex].Param, NetIndex);
SK_PNMI_STORE_U64(pBuf + Offset, StatVal);
break;
}
Offset += sizeof(SK_U64);
}
*pLen = Offset;
pAC->Pnmi.MacUpdatedFlag --;
return (SK_PNMI_ERR_OK);
}
/*****************************************************************************
*
* Addr - OID handler function of OID_SKGE_PHYS_CUR_ADDR and _FAC_ADDR
*
* Description:
* Get/Presets/Sets the current and factory MAC address. The MAC
* address of the virtual port, which is reported to the OS, may
* not be changed, but the physical ones. A set to the virtual port
* will be ignored. No error should be reported because otherwise
* a multiple instance set (-1) would always fail.
*
* 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.
*/
PNMI_STATIC int Addr(
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 int *pLen, /* On call: 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 allways zero */
{
int Ret;
unsigned int LogPortMax;
unsigned int PhysPortMax;
unsigned int LogPortIndex;
unsigned int PhysPortIndex;
unsigned int Limit;
unsigned int Offset = 0;
/*
* 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 */
LogPortMax--;
}
if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried */
/* Check instance range */
if ((Instance < 1) || (Instance > LogPortMax)) {