|  | /***************************************************************************** | 
|  | * | 
|  | * 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> | 
|  |  | 
|  | 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)) { | 
|  |  | 
|  | *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; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Perform Action | 
|  | */ | 
|  | if (Action == SK_PNMI_GET) { | 
|  |  | 
|  | /* | 
|  | * Check length | 
|  | */ | 
|  | if (*pLen < (Limit - LogPortIndex) * 6) { | 
|  |  | 
|  | *pLen = (Limit - LogPortIndex) * 6; | 
|  | return (SK_PNMI_ERR_TOO_SHORT); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Get value | 
|  | */ | 
|  | for (; LogPortIndex < Limit; LogPortIndex ++) { | 
|  |  | 
|  | switch (Id) { | 
|  |  | 
|  | case OID_SKGE_PHYS_CUR_ADDR: | 
|  | if (LogPortIndex == 0) { | 
|  | CopyMac(pBuf + Offset, &pAC->Addr.Net[NetIndex].CurrentMacAddress); | 
|  | } | 
|  | else { | 
|  | PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex); | 
|  |  | 
|  | CopyMac(pBuf + Offset, | 
|  | &pAC->Addr.Port[PhysPortIndex].CurrentMacAddress); | 
|  | } | 
|  | Offset += 6; | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_PHYS_FAC_ADDR: | 
|  | if (LogPortIndex == 0) { | 
|  | CopyMac(pBuf + Offset, | 
|  | &pAC->Addr.Net[NetIndex].PermanentMacAddress); | 
|  | } | 
|  | else { | 
|  | PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( | 
|  | pAC, LogPortIndex); | 
|  |  | 
|  | CopyMac(pBuf + Offset, | 
|  | &pAC->Addr.Port[PhysPortIndex].PermanentMacAddress); | 
|  | } | 
|  | Offset += 6; | 
|  | break; | 
|  |  | 
|  | default: | 
|  | SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR008, | 
|  | SK_PNMI_ERR008MSG); | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  | } | 
|  | } | 
|  |  | 
|  | *pLen = Offset; | 
|  | } | 
|  | else { | 
|  | /* | 
|  | * The logical MAC address may not be changed only | 
|  | * the physical ones | 
|  | */ | 
|  | if (Id == OID_SKGE_PHYS_FAC_ADDR) { | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_READ_ONLY); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Only the current address may be changed | 
|  | */ | 
|  | if (Id != OID_SKGE_PHYS_CUR_ADDR) { | 
|  |  | 
|  | SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR009, | 
|  | SK_PNMI_ERR009MSG); | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Check length | 
|  | */ | 
|  | if (*pLen < (Limit - LogPortIndex) * 6) { | 
|  |  | 
|  | *pLen = (Limit - LogPortIndex) * 6; | 
|  | return (SK_PNMI_ERR_TOO_SHORT); | 
|  | } | 
|  | if (*pLen > (Limit - LogPortIndex) * 6) { | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_BAD_VALUE); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Check Action | 
|  | */ | 
|  | if (Action == SK_PNMI_PRESET) { | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_OK); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Set OID_SKGE_MAC_CUR_ADDR | 
|  | */ | 
|  | for (; LogPortIndex < Limit; LogPortIndex ++, Offset += 6) { | 
|  |  | 
|  | /* | 
|  | * A set to virtual port and set of broadcast | 
|  | * address will be ignored | 
|  | */ | 
|  | if (LogPortIndex == 0 || SK_MEMCMP(pBuf + Offset, | 
|  | "\xff\xff\xff\xff\xff\xff", 6) == 0) { | 
|  |  | 
|  | continue; | 
|  | } | 
|  |  | 
|  | PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, | 
|  | LogPortIndex); | 
|  |  | 
|  | Ret = SkAddrOverride(pAC, IoC, PhysPortIndex, | 
|  | (SK_MAC_ADDR *)(pBuf + Offset), | 
|  | (LogPortIndex == 0 ? SK_ADDR_VIRTUAL_ADDRESS : | 
|  | SK_ADDR_PHYSICAL_ADDRESS)); | 
|  | if (Ret != SK_ADDR_OVERRIDE_SUCCESS) { | 
|  |  | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  | } | 
|  | } | 
|  | *pLen = Offset; | 
|  | } | 
|  |  | 
|  | return (SK_PNMI_ERR_OK); | 
|  | } | 
|  |  | 
|  | /***************************************************************************** | 
|  | * | 
|  | * CsumStat - OID handler function of OID_SKGE_CHKSM_XXX | 
|  | * | 
|  | * Description: | 
|  | *	Retrieves the statistic values of the CSUM module. The CSUM data | 
|  | *	structure must be available in the SK_AC even if the CSUM module | 
|  | *	is not included, because PNMI reads the statistic data from the | 
|  | *	CSUM part of SK_AC directly. | 
|  | * | 
|  | * 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 CsumStat( | 
|  | 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	Index; | 
|  | unsigned int	Limit; | 
|  | unsigned int	Offset = 0; | 
|  | SK_U64		StatVal; | 
|  |  | 
|  |  | 
|  | /* | 
|  | * Calculate instance if wished | 
|  | */ | 
|  | if (Instance != (SK_U32)(-1)) { | 
|  |  | 
|  | if ((Instance < 1) || (Instance > SKCS_NUM_PROTOCOLS)) { | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_UNKNOWN_INST); | 
|  | } | 
|  | Index = (unsigned int)Instance - 1; | 
|  | Limit = Index + 1; | 
|  | } | 
|  | else { | 
|  | Index = 0; | 
|  | Limit = SKCS_NUM_PROTOCOLS; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Check action | 
|  | */ | 
|  | if (Action != SK_PNMI_GET) { | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_READ_ONLY); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Check length | 
|  | */ | 
|  | if (*pLen < (Limit - Index) * sizeof(SK_U64)) { | 
|  |  | 
|  | *pLen = (Limit - Index) * sizeof(SK_U64); | 
|  | return (SK_PNMI_ERR_TOO_SHORT); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Get value | 
|  | */ | 
|  | for (; Index < Limit; Index ++) { | 
|  |  | 
|  | switch (Id) { | 
|  |  | 
|  | case OID_SKGE_CHKSM_RX_OK_CTS: | 
|  | StatVal = pAC->Csum.ProtoStats[NetIndex][Index].RxOkCts; | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_CHKSM_RX_UNABLE_CTS: | 
|  | StatVal = pAC->Csum.ProtoStats[NetIndex][Index].RxUnableCts; | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_CHKSM_RX_ERR_CTS: | 
|  | StatVal = pAC->Csum.ProtoStats[NetIndex][Index].RxErrCts; | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_CHKSM_TX_OK_CTS: | 
|  | StatVal = pAC->Csum.ProtoStats[NetIndex][Index].TxOkCts; | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_CHKSM_TX_UNABLE_CTS: | 
|  | StatVal = pAC->Csum.ProtoStats[NetIndex][Index].TxUnableCts; | 
|  | break; | 
|  |  | 
|  | default: | 
|  | SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR010, | 
|  | SK_PNMI_ERR010MSG); | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  | } | 
|  |  | 
|  | SK_PNMI_STORE_U64(pBuf + Offset, StatVal); | 
|  | Offset += sizeof(SK_U64); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Store used buffer space | 
|  | */ | 
|  | *pLen = Offset; | 
|  |  | 
|  | return (SK_PNMI_ERR_OK); | 
|  | } | 
|  |  | 
|  | /***************************************************************************** | 
|  | * | 
|  | * SensorStat - OID handler function of OID_SKGE_SENSOR_XXX | 
|  | * | 
|  | * Description: | 
|  | *	Retrieves the statistic values of the I2C module, which handles | 
|  | *	the temperature and voltage sensors. | 
|  | * | 
|  | * 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 SensorStat( | 
|  | 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	i; | 
|  | unsigned int	Index; | 
|  | unsigned int	Limit; | 
|  | unsigned int	Offset; | 
|  | unsigned int	Len; | 
|  | SK_U32		Val32; | 
|  | SK_U64		Val64; | 
|  |  | 
|  |  | 
|  | /* | 
|  | * Calculate instance if wished | 
|  | */ | 
|  | if ((Instance != (SK_U32)(-1))) { | 
|  |  | 
|  | if ((Instance < 1) || (Instance > (SK_U32)pAC->I2c.MaxSens)) { | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_UNKNOWN_INST); | 
|  | } | 
|  |  | 
|  | Index = (unsigned int)Instance -1; | 
|  | Limit = (unsigned int)Instance; | 
|  | } | 
|  | else { | 
|  | Index = 0; | 
|  | Limit = (unsigned int) pAC->I2c.MaxSens; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Check action | 
|  | */ | 
|  | if (Action != SK_PNMI_GET) { | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_READ_ONLY); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Check length | 
|  | */ | 
|  | switch (Id) { | 
|  |  | 
|  | case OID_SKGE_SENSOR_VALUE: | 
|  | case OID_SKGE_SENSOR_WAR_THRES_LOW: | 
|  | case OID_SKGE_SENSOR_WAR_THRES_UPP: | 
|  | case OID_SKGE_SENSOR_ERR_THRES_LOW: | 
|  | case OID_SKGE_SENSOR_ERR_THRES_UPP: | 
|  | if (*pLen < (Limit - Index) * sizeof(SK_U32)) { | 
|  |  | 
|  | *pLen = (Limit - Index) * sizeof(SK_U32); | 
|  | return (SK_PNMI_ERR_TOO_SHORT); | 
|  | } | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_SENSOR_DESCR: | 
|  | for (Offset = 0, i = Index; i < Limit; i ++) { | 
|  |  | 
|  | Len = (unsigned int) | 
|  | SK_STRLEN(pAC->I2c.SenTable[i].SenDesc) + 1; | 
|  | if (Len >= SK_PNMI_STRINGLEN2) { | 
|  |  | 
|  | SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR011, | 
|  | SK_PNMI_ERR011MSG); | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  | } | 
|  | Offset += Len; | 
|  | } | 
|  | if (*pLen < Offset) { | 
|  |  | 
|  | *pLen = Offset; | 
|  | return (SK_PNMI_ERR_TOO_SHORT); | 
|  | } | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_SENSOR_INDEX: | 
|  | case OID_SKGE_SENSOR_TYPE: | 
|  | case OID_SKGE_SENSOR_STATUS: | 
|  | if (*pLen < Limit - Index) { | 
|  |  | 
|  | *pLen = Limit - Index; | 
|  | return (SK_PNMI_ERR_TOO_SHORT); | 
|  | } | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_SENSOR_WAR_CTS: | 
|  | case OID_SKGE_SENSOR_WAR_TIME: | 
|  | case OID_SKGE_SENSOR_ERR_CTS: | 
|  | case OID_SKGE_SENSOR_ERR_TIME: | 
|  | if (*pLen < (Limit - Index) * sizeof(SK_U64)) { | 
|  |  | 
|  | *pLen = (Limit - Index) * sizeof(SK_U64); | 
|  | return (SK_PNMI_ERR_TOO_SHORT); | 
|  | } | 
|  | break; | 
|  |  | 
|  | default: | 
|  | SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR012, | 
|  | SK_PNMI_ERR012MSG); | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  |  | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Get value | 
|  | */ | 
|  | for (Offset = 0; Index < Limit; Index ++) { | 
|  |  | 
|  | switch (Id) { | 
|  |  | 
|  | case OID_SKGE_SENSOR_INDEX: | 
|  | *(pBuf + Offset) = (char)Index; | 
|  | Offset += sizeof(char); | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_SENSOR_DESCR: | 
|  | Len = SK_STRLEN(pAC->I2c.SenTable[Index].SenDesc); | 
|  | SK_MEMCPY(pBuf + Offset + 1, | 
|  | pAC->I2c.SenTable[Index].SenDesc, Len); | 
|  | *(pBuf + Offset) = (char)Len; | 
|  | Offset += Len + 1; | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_SENSOR_TYPE: | 
|  | *(pBuf + Offset) = | 
|  | (char)pAC->I2c.SenTable[Index].SenType; | 
|  | Offset += sizeof(char); | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_SENSOR_VALUE: | 
|  | Val32 = (SK_U32)pAC->I2c.SenTable[Index].SenValue; | 
|  | SK_PNMI_STORE_U32(pBuf + Offset, Val32); | 
|  | Offset += sizeof(SK_U32); | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_SENSOR_WAR_THRES_LOW: | 
|  | Val32 = (SK_U32)pAC->I2c.SenTable[Index]. | 
|  | SenThreWarnLow; | 
|  | SK_PNMI_STORE_U32(pBuf + Offset, Val32); | 
|  | Offset += sizeof(SK_U32); | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_SENSOR_WAR_THRES_UPP: | 
|  | Val32 = (SK_U32)pAC->I2c.SenTable[Index]. | 
|  | SenThreWarnHigh; | 
|  | SK_PNMI_STORE_U32(pBuf + Offset, Val32); | 
|  | Offset += sizeof(SK_U32); | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_SENSOR_ERR_THRES_LOW: | 
|  | Val32 = (SK_U32)pAC->I2c.SenTable[Index]. | 
|  | SenThreErrLow; | 
|  | SK_PNMI_STORE_U32(pBuf + Offset, Val32); | 
|  | Offset += sizeof(SK_U32); | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_SENSOR_ERR_THRES_UPP: | 
|  | Val32 = pAC->I2c.SenTable[Index].SenThreErrHigh; | 
|  | SK_PNMI_STORE_U32(pBuf + Offset, Val32); | 
|  | Offset += sizeof(SK_U32); | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_SENSOR_STATUS: | 
|  | *(pBuf + Offset) = | 
|  | (char)pAC->I2c.SenTable[Index].SenErrFlag; | 
|  | Offset += sizeof(char); | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_SENSOR_WAR_CTS: | 
|  | Val64 = pAC->I2c.SenTable[Index].SenWarnCts; | 
|  | SK_PNMI_STORE_U64(pBuf + Offset, Val64); | 
|  | Offset += sizeof(SK_U64); | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_SENSOR_ERR_CTS: | 
|  | Val64 = pAC->I2c.SenTable[Index].SenErrCts; | 
|  | SK_PNMI_STORE_U64(pBuf + Offset, Val64); | 
|  | Offset += sizeof(SK_U64); | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_SENSOR_WAR_TIME: | 
|  | Val64 = SK_PNMI_HUNDREDS_SEC(pAC->I2c.SenTable[Index]. | 
|  | SenBegWarnTS); | 
|  | SK_PNMI_STORE_U64(pBuf + Offset, Val64); | 
|  | Offset += sizeof(SK_U64); | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_SENSOR_ERR_TIME: | 
|  | Val64 = SK_PNMI_HUNDREDS_SEC(pAC->I2c.SenTable[Index]. | 
|  | SenBegErrTS); | 
|  | SK_PNMI_STORE_U64(pBuf + Offset, Val64); | 
|  | Offset += sizeof(SK_U64); | 
|  | break; | 
|  |  | 
|  | default: | 
|  | SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR, | 
|  | ("SensorStat: Unknown OID should be handled before")); | 
|  |  | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Store used buffer space | 
|  | */ | 
|  | *pLen = Offset; | 
|  |  | 
|  | return (SK_PNMI_ERR_OK); | 
|  | } | 
|  |  | 
|  | /***************************************************************************** | 
|  | * | 
|  | * Vpd - OID handler function of OID_SKGE_VPD_XXX | 
|  | * | 
|  | * Description: | 
|  | *	Get/preset/set of VPD data. As instance the name of a VPD key | 
|  | *	can be passed. The Instance parameter is a SK_U32 and can be | 
|  | *	used as a string buffer for the VPD key, because their maximum | 
|  | *	length is 4 byte. | 
|  | * | 
|  | * 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 Vpd( | 
|  | 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 */ | 
|  | { | 
|  | SK_VPD_STATUS	*pVpdStatus; | 
|  | unsigned int	BufLen; | 
|  | char		Buf[256]; | 
|  | char		KeyArr[SK_PNMI_VPD_ENTRIES][SK_PNMI_VPD_KEY_SIZE]; | 
|  | char		KeyStr[SK_PNMI_VPD_KEY_SIZE]; | 
|  | unsigned int	KeyNo; | 
|  | unsigned int	Offset; | 
|  | unsigned int	Index; | 
|  | unsigned int	FirstIndex; | 
|  | unsigned int	LastIndex; | 
|  | unsigned int	Len; | 
|  | int		Ret; | 
|  | SK_U32		Val32; | 
|  |  | 
|  | /* | 
|  | * Get array of all currently stored VPD keys | 
|  | */ | 
|  | Ret = GetVpdKeyArr(pAC, IoC, &KeyArr[0][0], sizeof(KeyArr), | 
|  | &KeyNo); | 
|  | if (Ret != SK_PNMI_ERR_OK) { | 
|  | *pLen = 0; | 
|  | return (Ret); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * If instance is not -1, try to find the requested VPD key for | 
|  | * the multiple instance variables. The other OIDs as for example | 
|  | * OID VPD_ACTION are single instance variables and must be | 
|  | * handled separatly. | 
|  | */ | 
|  | FirstIndex = 0; | 
|  | LastIndex = KeyNo; | 
|  |  | 
|  | if ((Instance != (SK_U32)(-1))) { | 
|  |  | 
|  | if (Id == OID_SKGE_VPD_KEY || Id == OID_SKGE_VPD_VALUE || | 
|  | Id == OID_SKGE_VPD_ACCESS) { | 
|  |  | 
|  | SK_STRNCPY(KeyStr, (char *)&Instance, 4); | 
|  | KeyStr[4] = 0; | 
|  |  | 
|  | for (Index = 0; Index < KeyNo; Index ++) { | 
|  |  | 
|  | if (SK_STRCMP(KeyStr, KeyArr[Index]) == 0) { | 
|  | FirstIndex = Index; | 
|  | LastIndex = Index+1; | 
|  | break; | 
|  | } | 
|  | } | 
|  | if (Index == KeyNo) { | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_UNKNOWN_INST); | 
|  | } | 
|  | } | 
|  | else if (Instance != 1) { | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_UNKNOWN_INST); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Get value, if a query should be performed | 
|  | */ | 
|  | if (Action == SK_PNMI_GET) { | 
|  |  | 
|  | switch (Id) { | 
|  |  | 
|  | case OID_SKGE_VPD_FREE_BYTES: | 
|  | /* Check length of buffer */ | 
|  | if (*pLen < sizeof(SK_U32)) { | 
|  |  | 
|  | *pLen = sizeof(SK_U32); | 
|  | return (SK_PNMI_ERR_TOO_SHORT); | 
|  | } | 
|  | /* Get number of free bytes */ | 
|  | pVpdStatus = VpdStat(pAC, IoC); | 
|  | if (pVpdStatus == NULL) { | 
|  |  | 
|  | SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR017, | 
|  | SK_PNMI_ERR017MSG); | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  | } | 
|  | if ((pVpdStatus->vpd_status & VPD_VALID) == 0) { | 
|  |  | 
|  | SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR018, | 
|  | SK_PNMI_ERR018MSG); | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  | } | 
|  |  | 
|  | Val32 = (SK_U32)pVpdStatus->vpd_free_rw; | 
|  | SK_PNMI_STORE_U32(pBuf, Val32); | 
|  | *pLen = sizeof(SK_U32); | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_VPD_ENTRIES_LIST: | 
|  | /* Check length */ | 
|  | for (Len = 0, Index = 0; Index < KeyNo; Index ++) { | 
|  |  | 
|  | Len += SK_STRLEN(KeyArr[Index]) + 1; | 
|  | } | 
|  | if (*pLen < Len) { | 
|  |  | 
|  | *pLen = Len; | 
|  | return (SK_PNMI_ERR_TOO_SHORT); | 
|  | } | 
|  |  | 
|  | /* Get value */ | 
|  | *(pBuf) = (char)Len - 1; | 
|  | for (Offset = 1, Index = 0; Index < KeyNo; Index ++) { | 
|  |  | 
|  | Len = SK_STRLEN(KeyArr[Index]); | 
|  | SK_MEMCPY(pBuf + Offset, KeyArr[Index], Len); | 
|  |  | 
|  | Offset += Len; | 
|  |  | 
|  | if (Index < KeyNo - 1) { | 
|  |  | 
|  | *(pBuf + Offset) = ' '; | 
|  | Offset ++; | 
|  | } | 
|  | } | 
|  | *pLen = Offset; | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_VPD_ENTRIES_NUMBER: | 
|  | /* Check length */ | 
|  | if (*pLen < sizeof(SK_U32)) { | 
|  |  | 
|  | *pLen = sizeof(SK_U32); | 
|  | return (SK_PNMI_ERR_TOO_SHORT); | 
|  | } | 
|  |  | 
|  | Val32 = (SK_U32)KeyNo; | 
|  | SK_PNMI_STORE_U32(pBuf, Val32); | 
|  | *pLen = sizeof(SK_U32); | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_VPD_KEY: | 
|  | /* Check buffer length, if it is large enough */ | 
|  | for (Len = 0, Index = FirstIndex; | 
|  | Index < LastIndex; Index ++) { | 
|  |  | 
|  | Len += SK_STRLEN(KeyArr[Index]) + 1; | 
|  | } | 
|  | if (*pLen < Len) { | 
|  |  | 
|  | *pLen = Len; | 
|  | return (SK_PNMI_ERR_TOO_SHORT); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Get the key to an intermediate buffer, because | 
|  | * we have to prepend a length byte. | 
|  | */ | 
|  | for (Offset = 0, Index = FirstIndex; | 
|  | Index < LastIndex; Index ++) { | 
|  |  | 
|  | Len = SK_STRLEN(KeyArr[Index]); | 
|  |  | 
|  | *(pBuf + Offset) = (char)Len; | 
|  | SK_MEMCPY(pBuf + Offset + 1, KeyArr[Index], | 
|  | Len); | 
|  | Offset += Len + 1; | 
|  | } | 
|  | *pLen = Offset; | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_VPD_VALUE: | 
|  | /* Check the buffer length if it is large enough */ | 
|  | for (Offset = 0, Index = FirstIndex; | 
|  | Index < LastIndex; Index ++) { | 
|  |  | 
|  | BufLen = 256; | 
|  | if (VpdRead(pAC, IoC, KeyArr[Index], Buf, | 
|  | (int *)&BufLen) > 0 || | 
|  | BufLen >= SK_PNMI_VPD_DATALEN) { | 
|  |  | 
|  | SK_ERR_LOG(pAC, SK_ERRCL_SW, | 
|  | SK_PNMI_ERR021, | 
|  | SK_PNMI_ERR021MSG); | 
|  |  | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  | } | 
|  | Offset += BufLen + 1; | 
|  | } | 
|  | if (*pLen < Offset) { | 
|  |  | 
|  | *pLen = Offset; | 
|  | return (SK_PNMI_ERR_TOO_SHORT); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Get the value to an intermediate buffer, because | 
|  | * we have to prepend a length byte. | 
|  | */ | 
|  | for (Offset = 0, Index = FirstIndex; | 
|  | Index < LastIndex; Index ++) { | 
|  |  | 
|  | BufLen = 256; | 
|  | if (VpdRead(pAC, IoC, KeyArr[Index], Buf, | 
|  | (int *)&BufLen) > 0 || | 
|  | BufLen >= SK_PNMI_VPD_DATALEN) { | 
|  |  | 
|  | SK_ERR_LOG(pAC, SK_ERRCL_SW, | 
|  | SK_PNMI_ERR022, | 
|  | SK_PNMI_ERR022MSG); | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  | } | 
|  |  | 
|  | *(pBuf + Offset) = (char)BufLen; | 
|  | SK_MEMCPY(pBuf + Offset + 1, Buf, BufLen); | 
|  | Offset += BufLen + 1; | 
|  | } | 
|  | *pLen = Offset; | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_VPD_ACCESS: | 
|  | if (*pLen < LastIndex - FirstIndex) { | 
|  |  | 
|  | *pLen = LastIndex - FirstIndex; | 
|  | return (SK_PNMI_ERR_TOO_SHORT); | 
|  | } | 
|  |  | 
|  | for (Offset = 0, Index = FirstIndex; | 
|  | Index < LastIndex; Index ++) { | 
|  |  | 
|  | if (VpdMayWrite(KeyArr[Index])) { | 
|  |  | 
|  | *(pBuf + Offset) = SK_PNMI_VPD_RW; | 
|  | } | 
|  | else { | 
|  | *(pBuf + Offset) = SK_PNMI_VPD_RO; | 
|  | } | 
|  | Offset ++; | 
|  | } | 
|  | *pLen = Offset; | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_VPD_ACTION: | 
|  | Offset = LastIndex - FirstIndex; | 
|  | if (*pLen < Offset) { | 
|  |  | 
|  | *pLen = Offset; | 
|  | return (SK_PNMI_ERR_TOO_SHORT); | 
|  | } | 
|  | SK_MEMSET(pBuf, 0, Offset); | 
|  | *pLen = Offset; | 
|  | break; | 
|  |  | 
|  | default: | 
|  | SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR023, | 
|  | SK_PNMI_ERR023MSG); | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  | } | 
|  | } | 
|  | else { | 
|  | /* The only OID which can be set is VPD_ACTION */ | 
|  | if (Id != OID_SKGE_VPD_ACTION) { | 
|  |  | 
|  | if (Id == OID_SKGE_VPD_FREE_BYTES || | 
|  | Id == OID_SKGE_VPD_ENTRIES_LIST || | 
|  | Id == OID_SKGE_VPD_ENTRIES_NUMBER || | 
|  | Id == OID_SKGE_VPD_KEY || | 
|  | Id == OID_SKGE_VPD_VALUE || | 
|  | Id == OID_SKGE_VPD_ACCESS) { | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_READ_ONLY); | 
|  | } | 
|  |  | 
|  | SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR024, | 
|  | SK_PNMI_ERR024MSG); | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * From this point we handle VPD_ACTION. Check the buffer | 
|  | * length. It should at least have the size of one byte. | 
|  | */ | 
|  | if (*pLen < 1) { | 
|  |  | 
|  | *pLen = 1; | 
|  | return (SK_PNMI_ERR_TOO_SHORT); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * The first byte contains the VPD action type we should | 
|  | * perform. | 
|  | */ | 
|  | switch (*pBuf) { | 
|  |  | 
|  | case SK_PNMI_VPD_IGNORE: | 
|  | /* Nothing to do */ | 
|  | break; | 
|  |  | 
|  | case SK_PNMI_VPD_CREATE: | 
|  | /* | 
|  | * We have to create a new VPD entry or we modify | 
|  | * an existing one. Check first the buffer length. | 
|  | */ | 
|  | if (*pLen < 4) { | 
|  |  | 
|  | *pLen = 4; | 
|  | return (SK_PNMI_ERR_TOO_SHORT); | 
|  | } | 
|  | KeyStr[0] = pBuf[1]; | 
|  | KeyStr[1] = pBuf[2]; | 
|  | KeyStr[2] = 0; | 
|  |  | 
|  | /* | 
|  | * Is the entry writable or does it belong to the | 
|  | * read-only area? | 
|  | */ | 
|  | if (!VpdMayWrite(KeyStr)) { | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_BAD_VALUE); | 
|  | } | 
|  |  | 
|  | Offset = (int)pBuf[3] & 0xFF; | 
|  |  | 
|  | SK_MEMCPY(Buf, pBuf + 4, Offset); | 
|  | Buf[Offset] = 0; | 
|  |  | 
|  | /* A preset ends here */ | 
|  | if (Action == SK_PNMI_PRESET) { | 
|  |  | 
|  | return (SK_PNMI_ERR_OK); | 
|  | } | 
|  |  | 
|  | /* Write the new entry or modify an existing one */ | 
|  | Ret = VpdWrite(pAC, IoC, KeyStr, Buf); | 
|  | if (Ret == SK_PNMI_VPD_NOWRITE ) { | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_BAD_VALUE); | 
|  | } | 
|  | else if (Ret != SK_PNMI_VPD_OK) { | 
|  |  | 
|  | SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR025, | 
|  | SK_PNMI_ERR025MSG); | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Perform an update of the VPD data. This is | 
|  | * not mandantory, but just to be sure. | 
|  | */ | 
|  | Ret = VpdUpdate(pAC, IoC); | 
|  | if (Ret != SK_PNMI_VPD_OK) { | 
|  |  | 
|  | SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR026, | 
|  | SK_PNMI_ERR026MSG); | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  | } | 
|  | break; | 
|  |  | 
|  | case SK_PNMI_VPD_DELETE: | 
|  | /* Check if the buffer size is plausible */ | 
|  | if (*pLen < 3) { | 
|  |  | 
|  | *pLen = 3; | 
|  | return (SK_PNMI_ERR_TOO_SHORT); | 
|  | } | 
|  | if (*pLen > 3) { | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_BAD_VALUE); | 
|  | } | 
|  | KeyStr[0] = pBuf[1]; | 
|  | KeyStr[1] = pBuf[2]; | 
|  | KeyStr[2] = 0; | 
|  |  | 
|  | /* Find the passed key in the array */ | 
|  | for (Index = 0; Index < KeyNo; Index ++) { | 
|  |  | 
|  | if (SK_STRCMP(KeyStr, KeyArr[Index]) == 0) { | 
|  |  | 
|  | break; | 
|  | } | 
|  | } | 
|  | /* | 
|  | * If we cannot find the key it is wrong, so we | 
|  | * return an appropriate error value. | 
|  | */ | 
|  | if (Index == KeyNo) { | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_BAD_VALUE); | 
|  | } | 
|  |  | 
|  | if (Action == SK_PNMI_PRESET) { | 
|  |  | 
|  | return (SK_PNMI_ERR_OK); | 
|  | } | 
|  |  | 
|  | /* Ok, you wanted it and you will get it */ | 
|  | Ret = VpdDelete(pAC, IoC, KeyStr); | 
|  | if (Ret != SK_PNMI_VPD_OK) { | 
|  |  | 
|  | SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR027, | 
|  | SK_PNMI_ERR027MSG); | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Perform an update of the VPD data. This is | 
|  | * not mandantory, but just to be sure. | 
|  | */ | 
|  | Ret = VpdUpdate(pAC, IoC); | 
|  | if (Ret != SK_PNMI_VPD_OK) { | 
|  |  | 
|  | SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR028, | 
|  | SK_PNMI_ERR028MSG); | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  | } | 
|  | break; | 
|  |  | 
|  | default: | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_BAD_VALUE); | 
|  | } | 
|  | } | 
|  |  | 
|  | 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. | 
|  | */ | 
|  | PNMI_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 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	Index; | 
|  | unsigned int	Len; | 
|  | unsigned int	Offset; | 
|  | unsigned int	Val; | 
|  | SK_U8		Val8; | 
|  | SK_U16		Val16; | 
|  | SK_U32		Val32; | 
|  | SK_U64		Val64; | 
|  | SK_U64		Val64RxHwErrs = 0; | 
|  | SK_U64		Val64TxHwErrs = 0; | 
|  | SK_BOOL		Is64BitReq = SK_FALSE; | 
|  | char		Buf[256]; | 
|  | int			MacType; | 
|  |  | 
|  | /* | 
|  | * 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); | 
|  | } | 
|  |  | 
|  | MacType = pAC->GIni.GIMacType; | 
|  |  | 
|  | /* | 
|  | * Check length for the various supported OIDs | 
|  | */ | 
|  | switch (Id) { | 
|  |  | 
|  | case OID_GEN_XMIT_ERROR: | 
|  | case OID_GEN_RCV_ERROR: | 
|  | case OID_GEN_RCV_NO_BUFFER: | 
|  | #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; | 
|  |  | 
|  | case OID_SKGE_PORT_NUMBER: | 
|  | 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: | 
|  | case OID_SKGE_MDB_VERSION: | 
|  | if (*pLen < sizeof(SK_U32)) { | 
|  |  | 
|  | *pLen = sizeof(SK_U32); | 
|  | return (SK_PNMI_ERR_TOO_SHORT); | 
|  | } | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_CHIPSET: | 
|  | if (*pLen < sizeof(SK_U16)) { | 
|  |  | 
|  | *pLen = sizeof(SK_U16); | 
|  | return (SK_PNMI_ERR_TOO_SHORT); | 
|  | } | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_BUS_TYPE: | 
|  | case OID_SKGE_BUS_SPEED: | 
|  | case OID_SKGE_BUS_WIDTH: | 
|  | case OID_SKGE_SENSOR_NUMBER: | 
|  | case OID_SKGE_CHKSM_NUMBER: | 
|  | if (*pLen < sizeof(SK_U8)) { | 
|  |  | 
|  | *pLen = sizeof(SK_U8); | 
|  | return (SK_PNMI_ERR_TOO_SHORT); | 
|  | } | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_TX_SW_QUEUE_LEN: | 
|  | case OID_SKGE_TX_SW_QUEUE_MAX: | 
|  | 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); | 
|  | } | 
|  | break; | 
|  |  | 
|  | default: | 
|  | /* Checked later */ | 
|  | break; | 
|  | } | 
|  |  | 
|  | /* Update statistic */ | 
|  | if (Id == OID_SKGE_RX_HW_ERROR_CTS || | 
|  | Id == OID_SKGE_TX_HW_ERROR_CTS || | 
|  | Id == OID_SKGE_IN_ERRORS_CTS || | 
|  | Id == OID_SKGE_OUT_ERROR_CTS || | 
|  | Id == OID_GEN_XMIT_ERROR || | 
|  | Id == OID_GEN_RCV_ERROR) { | 
|  |  | 
|  | /* Force the XMAC to update its statistic counters 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 ++; | 
|  |  | 
|  | /* | 
|  | * Some OIDs consist of multiple hardware counters. Those | 
|  | * values which are contained in all of them will be added | 
|  | * now. | 
|  | */ | 
|  | switch (Id) { | 
|  |  | 
|  | case OID_SKGE_RX_HW_ERROR_CTS: | 
|  | case OID_SKGE_IN_ERRORS_CTS: | 
|  | case OID_GEN_RCV_ERROR: | 
|  | Val64RxHwErrs = | 
|  | GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_MISSED, NetIndex) + | 
|  | GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_FRAMING, NetIndex) + | 
|  | GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_OVERFLOW, NetIndex)+ | 
|  | GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_JABBER, NetIndex) + | 
|  | GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_CARRIER, NetIndex) + | 
|  | GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_IRLENGTH, NetIndex)+ | 
|  | GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_SYMBOL, NetIndex) + | 
|  | GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_SHORTS, NetIndex) + | 
|  | GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_RUNT, NetIndex) + | 
|  | GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_TOO_LONG, NetIndex) + | 
|  | GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_FCS, NetIndex) + | 
|  | GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_CEXT, NetIndex); | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_TX_HW_ERROR_CTS: | 
|  | case OID_SKGE_OUT_ERROR_CTS: | 
|  | case OID_GEN_XMIT_ERROR: | 
|  | Val64TxHwErrs = | 
|  | GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_EXCESS_COL, NetIndex) + | 
|  | GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_LATE_COL, NetIndex)+ | 
|  | GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_UNDERRUN, NetIndex)+ | 
|  | GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_CARRIER, NetIndex); | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Retrieve value | 
|  | */ | 
|  | switch (Id) { | 
|  |  | 
|  | case OID_SKGE_SUPPORTED_LIST: | 
|  | Len = ID_TABLE_SIZE * 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 = (SK_U32)pAC->GIni.GIMacsFound; | 
|  | 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) { | 
|  |  | 
|  | SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR007, | 
|  | SK_PNMI_ERR007MSG); | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  | } | 
|  |  | 
|  | Len = SK_STRLEN(pAC->Pnmi.pDriverDescription) + 1; | 
|  | if (Len > SK_PNMI_STRINGLEN1) { | 
|  |  | 
|  | SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR029, | 
|  | SK_PNMI_ERR029MSG); | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  | } | 
|  |  | 
|  | if (*pLen < Len) { | 
|  |  | 
|  | *pLen = Len; | 
|  | return (SK_PNMI_ERR_TOO_SHORT); | 
|  | } | 
|  | *pBuf = (char)(Len - 1); | 
|  | SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverDescription, Len - 1); | 
|  | *pLen = Len; | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_DRIVER_VERSION: | 
|  | if (pAC->Pnmi.pDriverVersion == NULL) { | 
|  |  | 
|  | SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR030, | 
|  | SK_PNMI_ERR030MSG); | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  | } | 
|  |  | 
|  | Len = SK_STRLEN(pAC->Pnmi.pDriverVersion) + 1; | 
|  | if (Len > SK_PNMI_STRINGLEN1) { | 
|  |  | 
|  | SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR031, | 
|  | SK_PNMI_ERR031MSG); | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  | } | 
|  |  | 
|  | if (*pLen < Len) { | 
|  |  | 
|  | *pLen = Len; | 
|  | return (SK_PNMI_ERR_TOO_SHORT); | 
|  | } | 
|  | *pBuf = (char)(Len - 1); | 
|  | SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverVersion, Len - 1); | 
|  | *pLen = Len; | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_HW_DESCR: | 
|  | /* | 
|  | * The hardware description is located in the VPD. This | 
|  | * query may move to the initialisation routine. But | 
|  | * the VPD data is cached and therefore a call here | 
|  | * will not make much difference. | 
|  | */ | 
|  | Len = 256; | 
|  | if (VpdRead(pAC, IoC, VPD_NAME, Buf, (int *)&Len) > 0) { | 
|  |  | 
|  | SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR032, | 
|  | SK_PNMI_ERR032MSG); | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  | } | 
|  | Len ++; | 
|  | if (Len > SK_PNMI_STRINGLEN1) { | 
|  |  | 
|  | SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR033, | 
|  | SK_PNMI_ERR033MSG); | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  | } | 
|  | if (*pLen < Len) { | 
|  |  | 
|  | *pLen = Len; | 
|  | return (SK_PNMI_ERR_TOO_SHORT); | 
|  | } | 
|  | *pBuf = (char)(Len - 1); | 
|  | SK_MEMCPY(pBuf + 1, Buf, Len - 1); | 
|  | *pLen = Len; | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_HW_VERSION: | 
|  | /* Oh, I love to do some string manipulation */ | 
|  | if (*pLen < 5) { | 
|  |  | 
|  | *pLen = 5; | 
|  | return (SK_PNMI_ERR_TOO_SHORT); | 
|  | } | 
|  | Val8 = (SK_U8)pAC->GIni.GIPciHwRev; | 
|  | pBuf[0] = 4; | 
|  | pBuf[1] = 'v'; | 
|  | pBuf[2] = (char)(0x30 | ((Val8 >> 4) & 0x0F)); | 
|  | pBuf[3] = '.'; | 
|  | pBuf[4] = (char)(0x30 | (Val8 & 0x0F)); | 
|  | *pLen = 5; | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_CHIPSET: | 
|  | Val16 = pAC->Pnmi.Chipset; | 
|  | SK_PNMI_STORE_U16(pBuf, Val16); | 
|  | *pLen = sizeof(SK_U16); | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_BUS_TYPE: | 
|  | *pBuf = (char)SK_PNMI_BUS_PCI; | 
|  | *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_RESULT: | 
|  | Val32 = pAC->Pnmi.TestResult; | 
|  | SK_PNMI_STORE_U32(pBuf, Val32); | 
|  | *pLen = sizeof(SK_U32); | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_SENSOR_NUMBER: | 
|  | *pBuf = (char)pAC->I2c.MaxSens; | 
|  | *pLen = sizeof(char); | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_CHKSM_NUMBER: | 
|  | *pBuf = SKCS_NUM_PROTOCOLS; | 
|  | *pLen = sizeof(char); | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_TRAP_NUMBER: | 
|  | GetTrapQueueLen(pAC, &Len, &Val); | 
|  | Val32 = (SK_U32)Val; | 
|  | SK_PNMI_STORE_U32(pBuf, Val32); | 
|  | *pLen = sizeof(SK_U32); | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_TRAP: | 
|  | GetTrapQueueLen(pAC, &Len, &Val); | 
|  | if (*pLen < Len) { | 
|  |  | 
|  | *pLen = Len; | 
|  | return (SK_PNMI_ERR_TOO_SHORT); | 
|  | } | 
|  | CopyTrapQueue(pAC, pBuf); | 
|  | *pLen = Len; | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_RLMT_MONITOR_NUMBER: | 
|  | /* XXX Not yet implemented by RLMT therefore we return zero elements */ | 
|  | Val32 = 0; | 
|  | SK_PNMI_STORE_U32(pBuf, Val32); | 
|  | *pLen = sizeof(SK_U32); | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_TX_SW_QUEUE_LEN: | 
|  | /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ | 
|  | if (MacType == SK_MAC_XMAC) { | 
|  | /* Dual net mode */ | 
|  | if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { | 
|  | Val64 = pAC->Pnmi.BufPort[NetIndex].TxSwQueueLen; | 
|  | } | 
|  | /* Single net mode */ | 
|  | else { | 
|  | Val64 = pAC->Pnmi.BufPort[0].TxSwQueueLen + | 
|  | pAC->Pnmi.BufPort[1].TxSwQueueLen; | 
|  | } | 
|  | } | 
|  | else { | 
|  | /* Dual net mode */ | 
|  | if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { | 
|  | Val64 = pAC->Pnmi.Port[NetIndex].TxSwQueueLen; | 
|  | } | 
|  | /* Single net mode */ | 
|  | else { | 
|  | Val64 = pAC->Pnmi.Port[0].TxSwQueueLen + | 
|  | pAC->Pnmi.Port[1].TxSwQueueLen; | 
|  | } | 
|  | } | 
|  | SK_PNMI_STORE_U64(pBuf, Val64); | 
|  | *pLen = sizeof(SK_U64); | 
|  | break; | 
|  |  | 
|  |  | 
|  | case OID_SKGE_TX_SW_QUEUE_MAX: | 
|  | /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ | 
|  | if (MacType == SK_MAC_XMAC) { | 
|  | /* Dual net mode */ | 
|  | if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { | 
|  | Val64 = pAC->Pnmi.BufPort[NetIndex].TxSwQueueMax; | 
|  | } | 
|  | /* Single net mode */ | 
|  | else { | 
|  | Val64 = pAC->Pnmi.BufPort[0].TxSwQueueMax + | 
|  | pAC->Pnmi.BufPort[1].TxSwQueueMax; | 
|  | } | 
|  | } | 
|  | else { | 
|  | /* Dual net mode */ | 
|  | if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { | 
|  | Val64 = pAC->Pnmi.Port[NetIndex].TxSwQueueMax; | 
|  | } | 
|  | /* Single net mode */ | 
|  | else { | 
|  | Val64 = pAC->Pnmi.Port[0].TxSwQueueMax + | 
|  | pAC->Pnmi.Port[1].TxSwQueueMax; | 
|  | } | 
|  | } | 
|  | SK_PNMI_STORE_U64(pBuf, Val64); | 
|  | *pLen = sizeof(SK_U64); | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_TX_RETRY: | 
|  | /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ | 
|  | if (MacType == SK_MAC_XMAC) { | 
|  | /* Dual net mode */ | 
|  | if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { | 
|  | Val64 = pAC->Pnmi.BufPort[NetIndex].TxRetryCts; | 
|  | } | 
|  | /* Single net mode */ | 
|  | else { | 
|  | Val64 = pAC->Pnmi.BufPort[0].TxRetryCts + | 
|  | pAC->Pnmi.BufPort[1].TxRetryCts; | 
|  | } | 
|  | } | 
|  | else { | 
|  | /* Dual net mode */ | 
|  | if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { | 
|  | Val64 = pAC->Pnmi.Port[NetIndex].TxRetryCts; | 
|  | } | 
|  | /* Single net mode */ | 
|  | else { | 
|  | Val64 = pAC->Pnmi.Port[0].TxRetryCts + | 
|  | pAC->Pnmi.Port[1].TxRetryCts; | 
|  | } | 
|  | } | 
|  | SK_PNMI_STORE_U64(pBuf, Val64); | 
|  | *pLen = sizeof(SK_U64); | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_RX_INTR_CTS: | 
|  | /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ | 
|  | if (MacType == SK_MAC_XMAC) { | 
|  | /* Dual net mode */ | 
|  | if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { | 
|  | Val64 = pAC->Pnmi.BufPort[NetIndex].RxIntrCts; | 
|  | } | 
|  | /* Single net mode */ | 
|  | else { | 
|  | Val64 = pAC->Pnmi.BufPort[0].RxIntrCts + | 
|  | pAC->Pnmi.BufPort[1].RxIntrCts; | 
|  | } | 
|  | } | 
|  | else { | 
|  | /* Dual net mode */ | 
|  | if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { | 
|  | Val64 = pAC->Pnmi.Port[NetIndex].RxIntrCts; | 
|  | } | 
|  | /* Single net mode */ | 
|  | else { | 
|  | Val64 = pAC->Pnmi.Port[0].RxIntrCts + | 
|  | pAC->Pnmi.Port[1].RxIntrCts; | 
|  | } | 
|  | } | 
|  | SK_PNMI_STORE_U64(pBuf, Val64); | 
|  | *pLen = sizeof(SK_U64); | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_TX_INTR_CTS: | 
|  | /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ | 
|  | if (MacType == SK_MAC_XMAC) { | 
|  | /* Dual net mode */ | 
|  | if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { | 
|  | Val64 = pAC->Pnmi.BufPort[NetIndex].TxIntrCts; | 
|  | } | 
|  | /* Single net mode */ | 
|  | else { | 
|  | Val64 = pAC->Pnmi.BufPort[0].TxIntrCts + | 
|  | pAC->Pnmi.BufPort[1].TxIntrCts; | 
|  | } | 
|  | } | 
|  | else { | 
|  | /* Dual net mode */ | 
|  | if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { | 
|  | Val64 = pAC->Pnmi.Port[NetIndex].TxIntrCts; | 
|  | } | 
|  | /* Single net mode */ | 
|  | else { | 
|  | Val64 = pAC->Pnmi.Port[0].TxIntrCts + | 
|  | pAC->Pnmi.Port[1].TxIntrCts; | 
|  | } | 
|  | } | 
|  | SK_PNMI_STORE_U64(pBuf, Val64); | 
|  | *pLen = sizeof(SK_U64); | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_RX_NO_BUF_CTS: | 
|  | /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ | 
|  | if (MacType == SK_MAC_XMAC) { | 
|  | /* Dual net mode */ | 
|  | if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { | 
|  | Val64 = pAC->Pnmi.BufPort[NetIndex].RxNoBufCts; | 
|  | } | 
|  | /* Single net mode */ | 
|  | else { | 
|  | Val64 = pAC->Pnmi.BufPort[0].RxNoBufCts + | 
|  | pAC->Pnmi.BufPort[1].RxNoBufCts; | 
|  | } | 
|  | } | 
|  | else { | 
|  | /* Dual net mode */ | 
|  | if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { | 
|  | Val64 = pAC->Pnmi.Port[NetIndex].RxNoBufCts; | 
|  | } | 
|  | /* Single net mode */ | 
|  | else { | 
|  | Val64 = pAC->Pnmi.Port[0].RxNoBufCts + | 
|  | pAC->Pnmi.Port[1].RxNoBufCts; | 
|  | } | 
|  | } | 
|  | SK_PNMI_STORE_U64(pBuf, Val64); | 
|  | *pLen = sizeof(SK_U64); | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_TX_NO_BUF_CTS: | 
|  | /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ | 
|  | if (MacType == SK_MAC_XMAC) { | 
|  | /* Dual net mode */ | 
|  | if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { | 
|  | Val64 = pAC->Pnmi.BufPort[NetIndex].TxNoBufCts; | 
|  | } | 
|  | /* Single net mode */ | 
|  | else { | 
|  | Val64 = pAC->Pnmi.BufPort[0].TxNoBufCts + | 
|  | pAC->Pnmi.BufPort[1].TxNoBufCts; | 
|  | } | 
|  | } | 
|  | else { | 
|  | /* Dual net mode */ | 
|  | if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { | 
|  | Val64 = pAC->Pnmi.Port[NetIndex].TxNoBufCts; | 
|  | } | 
|  | /* Single net mode */ | 
|  | else { | 
|  | Val64 = pAC->Pnmi.Port[0].TxNoBufCts + | 
|  | pAC->Pnmi.Port[1].TxNoBufCts; | 
|  | } | 
|  | } | 
|  | SK_PNMI_STORE_U64(pBuf, Val64); | 
|  | *pLen = sizeof(SK_U64); | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_TX_USED_DESCR_NO: | 
|  | /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ | 
|  | if (MacType == SK_MAC_XMAC) { | 
|  | /* Dual net mode */ | 
|  | if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { | 
|  | Val64 = pAC->Pnmi.BufPort[NetIndex].TxUsedDescrNo; | 
|  | } | 
|  | /* Single net mode */ | 
|  | else { | 
|  | Val64 = pAC->Pnmi.BufPort[0].TxUsedDescrNo + | 
|  | pAC->Pnmi.BufPort[1].TxUsedDescrNo; | 
|  | } | 
|  | } | 
|  | else { | 
|  | /* Dual net mode */ | 
|  | if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { | 
|  | Val64 = pAC->Pnmi.Port[NetIndex].TxUsedDescrNo; | 
|  | } | 
|  | /* Single net mode */ | 
|  | else { | 
|  | Val64 = pAC->Pnmi.Port[0].TxUsedDescrNo + | 
|  | pAC->Pnmi.Port[1].TxUsedDescrNo; | 
|  | } | 
|  | } | 
|  | SK_PNMI_STORE_U64(pBuf, Val64); | 
|  | *pLen = sizeof(SK_U64); | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_RX_DELIVERED_CTS: | 
|  | /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ | 
|  | if (MacType == SK_MAC_XMAC) { | 
|  | /* Dual net mode */ | 
|  | if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { | 
|  | Val64 = pAC->Pnmi.BufPort[NetIndex].RxDeliveredCts; | 
|  | } | 
|  | /* Single net mode */ | 
|  | else { | 
|  | Val64 = pAC->Pnmi.BufPort[0].RxDeliveredCts + | 
|  | pAC->Pnmi.BufPort[1].RxDeliveredCts; | 
|  | } | 
|  | } | 
|  | else { | 
|  | /* Dual net mode */ | 
|  | if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { | 
|  | Val64 = pAC->Pnmi.Port[NetIndex].RxDeliveredCts; | 
|  | } | 
|  | /* Single net mode */ | 
|  | else { | 
|  | Val64 = pAC->Pnmi.Port[0].RxDeliveredCts + | 
|  | pAC->Pnmi.Port[1].RxDeliveredCts; | 
|  | } | 
|  | } | 
|  | SK_PNMI_STORE_U64(pBuf, Val64); | 
|  | *pLen = sizeof(SK_U64); | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_RX_OCTETS_DELIV_CTS: | 
|  | /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ | 
|  | if (MacType == SK_MAC_XMAC) { | 
|  | /* Dual net mode */ | 
|  | if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { | 
|  | Val64 = pAC->Pnmi.BufPort[NetIndex].RxOctetsDeliveredCts; | 
|  | } | 
|  | /* Single net mode */ | 
|  | else { | 
|  | Val64 = pAC->Pnmi.BufPort[0].RxOctetsDeliveredCts + | 
|  | pAC->Pnmi.BufPort[1].RxOctetsDeliveredCts; | 
|  | } | 
|  | } | 
|  | else { | 
|  | /* Dual net mode */ | 
|  | if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { | 
|  | Val64 = pAC->Pnmi.Port[NetIndex].RxOctetsDeliveredCts; | 
|  | } | 
|  | /* Single net mode */ | 
|  | else { | 
|  | Val64 = pAC->Pnmi.Port[0].RxOctetsDeliveredCts + | 
|  | pAC->Pnmi.Port[1].RxOctetsDeliveredCts; | 
|  | } | 
|  | } | 
|  | SK_PNMI_STORE_U64(pBuf, Val64); | 
|  | *pLen = sizeof(SK_U64); | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_RX_HW_ERROR_CTS: | 
|  | SK_PNMI_STORE_U64(pBuf, Val64RxHwErrs); | 
|  | *pLen = sizeof(SK_U64); | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_TX_HW_ERROR_CTS: | 
|  | SK_PNMI_STORE_U64(pBuf, Val64TxHwErrs); | 
|  | *pLen = sizeof(SK_U64); | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_IN_ERRORS_CTS: | 
|  | /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ | 
|  | if (MacType == SK_MAC_XMAC) { | 
|  | /* Dual net mode */ | 
|  | if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { | 
|  | Val64 = Val64RxHwErrs + pAC->Pnmi.BufPort[NetIndex].RxNoBufCts; | 
|  | } | 
|  | /* Single net mode */ | 
|  | else { | 
|  | Val64 = Val64RxHwErrs + | 
|  | pAC->Pnmi.BufPort[0].RxNoBufCts + | 
|  | pAC->Pnmi.BufPort[1].RxNoBufCts; | 
|  | } | 
|  | } | 
|  | else { | 
|  | /* Dual net mode */ | 
|  | if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { | 
|  | Val64 = Val64RxHwErrs + pAC->Pnmi.Port[NetIndex].RxNoBufCts; | 
|  | } | 
|  | /* Single net mode */ | 
|  | else { | 
|  | Val64 = Val64RxHwErrs + | 
|  | pAC->Pnmi.Port[0].RxNoBufCts + | 
|  | pAC->Pnmi.Port[1].RxNoBufCts; | 
|  | } | 
|  | } | 
|  | SK_PNMI_STORE_U64(pBuf, Val64); | 
|  | *pLen = sizeof(SK_U64); | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_OUT_ERROR_CTS: | 
|  | /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ | 
|  | if (MacType == SK_MAC_XMAC) { | 
|  | /* Dual net mode */ | 
|  | if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { | 
|  | Val64 = Val64TxHwErrs + pAC->Pnmi.BufPort[NetIndex].TxNoBufCts; | 
|  | } | 
|  | /* Single net mode */ | 
|  | else { | 
|  | Val64 = Val64TxHwErrs + | 
|  | pAC->Pnmi.BufPort[0].TxNoBufCts + | 
|  | pAC->Pnmi.BufPort[1].TxNoBufCts; | 
|  | } | 
|  | } | 
|  | else { | 
|  | /* Dual net mode */ | 
|  | if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { | 
|  | Val64 = Val64TxHwErrs + pAC->Pnmi.Port[NetIndex].TxNoBufCts; | 
|  | } | 
|  | /* Single net mode */ | 
|  | else { | 
|  | Val64 = Val64TxHwErrs + | 
|  | pAC->Pnmi.Port[0].TxNoBufCts + | 
|  | pAC->Pnmi.Port[1].TxNoBufCts; | 
|  | } | 
|  | } | 
|  | SK_PNMI_STORE_U64(pBuf, Val64); | 
|  | *pLen = sizeof(SK_U64); | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_ERR_RECOVERY_CTS: | 
|  | /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ | 
|  | if (MacType == SK_MAC_XMAC) { | 
|  | /* Dual net mode */ | 
|  | if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { | 
|  | Val64 = pAC->Pnmi.BufPort[NetIndex].ErrRecoveryCts; | 
|  | } | 
|  | /* Single net mode */ | 
|  | else { | 
|  | Val64 = pAC->Pnmi.BufPort[0].ErrRecoveryCts + | 
|  | pAC->Pnmi.BufPort[1].ErrRecoveryCts; | 
|  | } | 
|  | } | 
|  | else { | 
|  | /* Dual net mode */ | 
|  | if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { | 
|  | Val64 = pAC->Pnmi.Port[NetIndex].ErrRecoveryCts; | 
|  | } | 
|  | /* Single net mode */ | 
|  | else { | 
|  | Val64 = pAC->Pnmi.Port[0].ErrRecoveryCts + | 
|  | pAC->Pnmi.Port[1].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; | 
|  |  | 
|  | case OID_GEN_RCV_ERROR: | 
|  | /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ | 
|  | if (MacType == SK_MAC_XMAC) { | 
|  | Val64 = Val64RxHwErrs + pAC->Pnmi.BufPort[NetIndex].RxNoBufCts; | 
|  | } | 
|  | else { | 
|  | Val64 = Val64RxHwErrs + pAC->Pnmi.Port[NetIndex].RxNoBufCts; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * by default 32bit values are evaluated | 
|  | */ | 
|  | if (!Is64BitReq) { | 
|  | Val32 = (SK_U32)Val64; | 
|  | SK_PNMI_STORE_U32(pBuf, Val32); | 
|  | *pLen = sizeof(SK_U32); | 
|  | } | 
|  | else { | 
|  | SK_PNMI_STORE_U64(pBuf, Val64); | 
|  | *pLen = sizeof(SK_U64); | 
|  | } | 
|  | break; | 
|  |  | 
|  | case OID_GEN_XMIT_ERROR: | 
|  | /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ | 
|  | if (MacType == SK_MAC_XMAC) { | 
|  | Val64 = Val64TxHwErrs + pAC->Pnmi.BufPort[NetIndex].TxNoBufCts; | 
|  | } | 
|  | else { | 
|  | Val64 = Val64TxHwErrs + pAC->Pnmi.Port[NetIndex].TxNoBufCts; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * by default 32bit values are evaluated | 
|  | */ | 
|  | if (!Is64BitReq) { | 
|  | Val32 = (SK_U32)Val64; | 
|  | SK_PNMI_STORE_U32(pBuf, Val32); | 
|  | *pLen = sizeof(SK_U32); | 
|  | } | 
|  | else { | 
|  | SK_PNMI_STORE_U64(pBuf, Val64); | 
|  | *pLen = sizeof(SK_U64); | 
|  | } | 
|  | break; | 
|  |  | 
|  | case OID_GEN_RCV_NO_BUFFER: | 
|  | /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ | 
|  | if (MacType == SK_MAC_XMAC) { | 
|  | Val64 = pAC->Pnmi.BufPort[NetIndex].RxNoBufCts; | 
|  | } | 
|  | else { | 
|  | Val64 = pAC->Pnmi.Port[NetIndex].RxNoBufCts; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * by default 32bit values are evaluated | 
|  | */ | 
|  | if (!Is64BitReq) { | 
|  | Val32 = (SK_U32)Val64; | 
|  | SK_PNMI_STORE_U32(pBuf, Val32); | 
|  | *pLen = sizeof(SK_U32); | 
|  | } | 
|  | else { | 
|  | SK_PNMI_STORE_U64(pBuf, Val64); | 
|  | *pLen = sizeof(SK_U64); | 
|  | } | 
|  | break; | 
|  |  | 
|  | case OID_GEN_TRANSMIT_QUEUE_LENGTH: | 
|  | Val32 = (SK_U32)pAC->Pnmi.Port[NetIndex].TxSwQueueLen; | 
|  | SK_PNMI_STORE_U32(pBuf, Val32); | 
|  | *pLen = sizeof(SK_U32); | 
|  | break; | 
|  |  | 
|  | default: | 
|  | SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR034, | 
|  | SK_PNMI_ERR034MSG); | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  | } | 
|  |  | 
|  | if (Id == OID_SKGE_RX_HW_ERROR_CTS || | 
|  | Id == OID_SKGE_TX_HW_ERROR_CTS || | 
|  | Id == OID_SKGE_IN_ERRORS_CTS || | 
|  | Id == OID_SKGE_OUT_ERROR_CTS || | 
|  | Id == OID_GEN_XMIT_ERROR || | 
|  | Id == OID_GEN_RCV_ERROR) { | 
|  |  | 
|  | pAC->Pnmi.MacUpdatedFlag --; | 
|  | } | 
|  |  | 
|  | return (SK_PNMI_ERR_OK); | 
|  | } | 
|  |  | 
|  | /***************************************************************************** | 
|  | * | 
|  | * Rlmt - OID handler function of OID_SKGE_RLMT_XXX single instance. | 
|  | * | 
|  | * Description: | 
|  | *	Get/Presets/Sets the RLMT OIDs. | 
|  | * | 
|  | * 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 Rlmt( | 
|  | 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	PhysPortIndex; | 
|  | unsigned int	PhysPortMax; | 
|  | SK_EVPARA	EventParam; | 
|  | SK_U32		Val32; | 
|  | SK_U64		Val64; | 
|  |  | 
|  |  | 
|  | /* | 
|  | * Check instance. Only single instance OIDs are allowed here. | 
|  | */ | 
|  | if (Instance != (SK_U32)(-1) && Instance != 1) { | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_UNKNOWN_INST); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Perform the requested action | 
|  | */ | 
|  | if (Action == SK_PNMI_GET) { | 
|  |  | 
|  | /* | 
|  | * Check if the buffer length is large enough. | 
|  | */ | 
|  |  | 
|  | switch (Id) { | 
|  |  | 
|  | case OID_SKGE_RLMT_MODE: | 
|  | case OID_SKGE_RLMT_PORT_ACTIVE: | 
|  | case OID_SKGE_RLMT_PORT_PREFERRED: | 
|  | if (*pLen < sizeof(SK_U8)) { | 
|  |  | 
|  | *pLen = sizeof(SK_U8); | 
|  | return (SK_PNMI_ERR_TOO_SHORT); | 
|  | } | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_RLMT_PORT_NUMBER: | 
|  | if (*pLen < sizeof(SK_U32)) { | 
|  |  | 
|  | *pLen = sizeof(SK_U32); | 
|  | return (SK_PNMI_ERR_TOO_SHORT); | 
|  | } | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_RLMT_CHANGE_CTS: | 
|  | case OID_SKGE_RLMT_CHANGE_TIME: | 
|  | case OID_SKGE_RLMT_CHANGE_ESTIM: | 
|  | case OID_SKGE_RLMT_CHANGE_THRES: | 
|  | if (*pLen < sizeof(SK_U64)) { | 
|  |  | 
|  | *pLen = sizeof(SK_U64); | 
|  | return (SK_PNMI_ERR_TOO_SHORT); | 
|  | } | 
|  | break; | 
|  |  | 
|  | default: | 
|  | SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR035, | 
|  | SK_PNMI_ERR035MSG); | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Update RLMT statistic and increment semaphores to indicate | 
|  | * that an update was already done. Maybe RLMT will hold its | 
|  | * statistic always up to date some time. Then we can | 
|  | * remove this type of call. | 
|  | */ | 
|  | if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) { | 
|  |  | 
|  | *pLen = 0; | 
|  | return (Ret); | 
|  | } | 
|  | pAC->Pnmi.RlmtUpdatedFlag ++; | 
|  |  | 
|  | /* | 
|  | * Retrieve Value | 
|  | */ | 
|  | switch (Id) { | 
|  |  | 
|  | case OID_SKGE_RLMT_MODE: | 
|  | *pBuf = (char)pAC->Rlmt.Net[0].RlmtMode; | 
|  | *pLen = sizeof(char); | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_RLMT_PORT_NUMBER: | 
|  | Val32 = (SK_U32)pAC->GIni.GIMacsFound; | 
|  | SK_PNMI_STORE_U32(pBuf, Val32); | 
|  | *pLen = sizeof(SK_U32); | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_RLMT_PORT_ACTIVE: | 
|  | *pBuf = 0; | 
|  | /* | 
|  | * If multiple ports may become active this OID | 
|  | * doesn't make sense any more. A new variable in | 
|  | * the port structure should be created. However, | 
|  | * for this variable the first active port is | 
|  | * returned. | 
|  | */ | 
|  | PhysPortMax = pAC->GIni.GIMacsFound; | 
|  |  | 
|  | for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax; | 
|  | PhysPortIndex ++) { | 
|  |  | 
|  | if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) { | 
|  |  | 
|  | *pBuf = (char)SK_PNMI_PORT_PHYS2LOG(PhysPortIndex); | 
|  | break; | 
|  | } | 
|  | } | 
|  | *pLen = sizeof(char); | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_RLMT_PORT_PREFERRED: | 
|  | *pBuf = (char)SK_PNMI_PORT_PHYS2LOG(pAC->Rlmt.Net[NetIndex].Preference); | 
|  | *pLen = sizeof(char); | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_RLMT_CHANGE_CTS: | 
|  | Val64 = pAC->Pnmi.RlmtChangeCts; | 
|  | SK_PNMI_STORE_U64(pBuf, Val64); | 
|  | *pLen = sizeof(SK_U64); | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_RLMT_CHANGE_TIME: | 
|  | Val64 = pAC->Pnmi.RlmtChangeTime; | 
|  | SK_PNMI_STORE_U64(pBuf, Val64); | 
|  | *pLen = sizeof(SK_U64); | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_RLMT_CHANGE_ESTIM: | 
|  | Val64 = pAC->Pnmi.RlmtChangeEstimate.Estimate; | 
|  | SK_PNMI_STORE_U64(pBuf, Val64); | 
|  | *pLen = sizeof(SK_U64); | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_RLMT_CHANGE_THRES: | 
|  | Val64 = pAC->Pnmi.RlmtChangeThreshold; | 
|  | SK_PNMI_STORE_U64(pBuf, Val64); | 
|  | *pLen = sizeof(SK_U64); | 
|  | break; | 
|  |  | 
|  | default: | 
|  | SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR, | 
|  | ("Rlmt: Unknown OID should be handled before")); | 
|  |  | 
|  | pAC->Pnmi.RlmtUpdatedFlag --; | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  | } | 
|  |  | 
|  | pAC->Pnmi.RlmtUpdatedFlag --; | 
|  | } | 
|  | else { | 
|  | /* Perform a preset or set */ | 
|  | switch (Id) { | 
|  |  | 
|  | case OID_SKGE_RLMT_MODE: | 
|  | /* Check if the buffer length is plausible */ | 
|  | if (*pLen < sizeof(char)) { | 
|  |  | 
|  | *pLen = sizeof(char); | 
|  | return (SK_PNMI_ERR_TOO_SHORT); | 
|  | } | 
|  | /* Check if the value range is correct */ | 
|  | if (*pLen != sizeof(char) || | 
|  | (*pBuf & SK_PNMI_RLMT_MODE_CHK_LINK) == 0 || | 
|  | *(SK_U8 *)pBuf > 15) { | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_BAD_VALUE); | 
|  | } | 
|  | /* The preset ends here */ | 
|  | if (Action == SK_PNMI_PRESET) { | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_OK); | 
|  | } | 
|  | /* Send an event to RLMT to change the mode */ | 
|  | SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam)); | 
|  | EventParam.Para32[0] |= (SK_U32)(*pBuf); | 
|  | EventParam.Para32[1] = 0; | 
|  | if (SkRlmtEvent(pAC, IoC, SK_RLMT_MODE_CHANGE, | 
|  | EventParam) > 0) { | 
|  |  | 
|  | SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR037, | 
|  | SK_PNMI_ERR037MSG); | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  | } | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_RLMT_PORT_PREFERRED: | 
|  | /* Check if the buffer length is plausible */ | 
|  | if (*pLen < sizeof(char)) { | 
|  |  | 
|  | *pLen = sizeof(char); | 
|  | return (SK_PNMI_ERR_TOO_SHORT); | 
|  | } | 
|  | /* Check if the value range is correct */ | 
|  | if (*pLen != sizeof(char) || *(SK_U8 *)pBuf > | 
|  | (SK_U8)pAC->GIni.GIMacsFound) { | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_BAD_VALUE); | 
|  | } | 
|  | /* The preset ends here */ | 
|  | if (Action == SK_PNMI_PRESET) { | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_OK); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Send an event to RLMT change the preferred port. | 
|  | * A param of -1 means automatic mode. RLMT will | 
|  | * make the decision which is the preferred port. | 
|  | */ | 
|  | SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam)); | 
|  | EventParam.Para32[0] = (SK_U32)(*pBuf) - 1; | 
|  | EventParam.Para32[1] = NetIndex; | 
|  | if (SkRlmtEvent(pAC, IoC, SK_RLMT_PREFPORT_CHANGE, | 
|  | EventParam) > 0) { | 
|  |  | 
|  | SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR038, | 
|  | SK_PNMI_ERR038MSG); | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  | } | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_RLMT_CHANGE_THRES: | 
|  | /* Check if the buffer length is plausible */ | 
|  | if (*pLen < sizeof(SK_U64)) { | 
|  |  | 
|  | *pLen = sizeof(SK_U64); | 
|  | return (SK_PNMI_ERR_TOO_SHORT); | 
|  | } | 
|  | /* | 
|  | * There are not many restrictions to the | 
|  | * value range. | 
|  | */ | 
|  | if (*pLen != sizeof(SK_U64)) { | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_BAD_VALUE); | 
|  | } | 
|  | /* A preset ends here */ | 
|  | if (Action == SK_PNMI_PRESET) { | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_OK); | 
|  | } | 
|  | /* | 
|  | * Store the new threshold, which will be taken | 
|  | * on the next timer event. | 
|  | */ | 
|  | SK_PNMI_READ_U64(pBuf, Val64); | 
|  | pAC->Pnmi.RlmtChangeThreshold = Val64; | 
|  | break; | 
|  |  | 
|  | default: | 
|  | /* The other OIDs are not be able for set */ | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_READ_ONLY); | 
|  | } | 
|  | } | 
|  |  | 
|  | return (SK_PNMI_ERR_OK); | 
|  | } | 
|  |  | 
|  | /***************************************************************************** | 
|  | * | 
|  | * RlmtStat - OID handler function of OID_SKGE_RLMT_XXX multiple instance. | 
|  | * | 
|  | * Description: | 
|  | *	Performs get requests on multiple instance variables. | 
|  | * | 
|  | * 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 RlmtStat( | 
|  | 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	PhysPortMax; | 
|  | unsigned int	PhysPortIndex; | 
|  | unsigned int	Limit; | 
|  | unsigned int	Offset; | 
|  | int		Ret; | 
|  | SK_U32		Val32; | 
|  | SK_U64		Val64; | 
|  |  | 
|  | /* | 
|  | * Calculate the port indexes from the instance | 
|  | */ | 
|  | PhysPortMax = pAC->GIni.GIMacsFound; | 
|  |  | 
|  | if ((Instance != (SK_U32)(-1))) { | 
|  | /* Check instance range */ | 
|  | if ((Instance < 1) || (Instance > PhysPortMax)) { | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_UNKNOWN_INST); | 
|  | } | 
|  |  | 
|  | /* Single net mode */ | 
|  | PhysPortIndex = Instance - 1; | 
|  |  | 
|  | /* Dual net mode */ | 
|  | if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { | 
|  | PhysPortIndex = NetIndex; | 
|  | } | 
|  |  | 
|  | /* Both net modes */ | 
|  | Limit = PhysPortIndex + 1; | 
|  | } | 
|  | else { | 
|  | /* Single net mode */ | 
|  | PhysPortIndex = 0; | 
|  | Limit = PhysPortMax; | 
|  |  | 
|  | /* Dual net mode */ | 
|  | if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { | 
|  | PhysPortIndex = NetIndex; | 
|  | Limit = PhysPortIndex + 1; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Currently only get requests are allowed. | 
|  | */ | 
|  | if (Action != SK_PNMI_GET) { | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_READ_ONLY); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Check if the buffer length is large enough. | 
|  | */ | 
|  | switch (Id) { | 
|  |  | 
|  | case OID_SKGE_RLMT_PORT_INDEX: | 
|  | case OID_SKGE_RLMT_STATUS: | 
|  | if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U32)) { | 
|  |  | 
|  | *pLen = (Limit - PhysPortIndex) * sizeof(SK_U32); | 
|  | return (SK_PNMI_ERR_TOO_SHORT); | 
|  | } | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_RLMT_TX_HELLO_CTS: | 
|  | case OID_SKGE_RLMT_RX_HELLO_CTS: | 
|  | case OID_SKGE_RLMT_TX_SP_REQ_CTS: | 
|  | case OID_SKGE_RLMT_RX_SP_CTS: | 
|  | if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U64)) { | 
|  |  | 
|  | *pLen = (Limit - PhysPortIndex) * sizeof(SK_U64); | 
|  | return (SK_PNMI_ERR_TOO_SHORT); | 
|  | } | 
|  | break; | 
|  |  | 
|  | default: | 
|  | SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR039, | 
|  | SK_PNMI_ERR039MSG); | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  |  | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Update statistic and increment semaphores to indicate that | 
|  | * an update was already done. | 
|  | */ | 
|  | if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) { | 
|  |  | 
|  | *pLen = 0; | 
|  | return (Ret); | 
|  | } | 
|  | pAC->Pnmi.RlmtUpdatedFlag ++; | 
|  |  | 
|  | /* | 
|  | * Get value | 
|  | */ | 
|  | Offset = 0; | 
|  | for (; PhysPortIndex < Limit; PhysPortIndex ++) { | 
|  |  | 
|  | switch (Id) { | 
|  |  | 
|  | case OID_SKGE_RLMT_PORT_INDEX: | 
|  | Val32 = PhysPortIndex; | 
|  | SK_PNMI_STORE_U32(pBuf + Offset, Val32); | 
|  | Offset += sizeof(SK_U32); | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_RLMT_STATUS: | 
|  | if (pAC->Rlmt.Port[PhysPortIndex].PortState == | 
|  | SK_RLMT_PS_INIT || | 
|  | pAC->Rlmt.Port[PhysPortIndex].PortState == | 
|  | SK_RLMT_PS_DOWN) { | 
|  |  | 
|  | Val32 = SK_PNMI_RLMT_STATUS_ERROR; | 
|  | } | 
|  | else if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) { | 
|  |  | 
|  | Val32 = SK_PNMI_RLMT_STATUS_ACTIVE; | 
|  | } | 
|  | else { | 
|  | Val32 = SK_PNMI_RLMT_STATUS_STANDBY; | 
|  | } | 
|  | SK_PNMI_STORE_U32(pBuf + Offset, Val32); | 
|  | Offset += sizeof(SK_U32); | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_RLMT_TX_HELLO_CTS: | 
|  | Val64 = pAC->Rlmt.Port[PhysPortIndex].TxHelloCts; | 
|  | SK_PNMI_STORE_U64(pBuf + Offset, Val64); | 
|  | Offset += sizeof(SK_U64); | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_RLMT_RX_HELLO_CTS: | 
|  | Val64 = pAC->Rlmt.Port[PhysPortIndex].RxHelloCts; | 
|  | SK_PNMI_STORE_U64(pBuf + Offset, Val64); | 
|  | Offset += sizeof(SK_U64); | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_RLMT_TX_SP_REQ_CTS: | 
|  | Val64 = pAC->Rlmt.Port[PhysPortIndex].TxSpHelloReqCts; | 
|  | SK_PNMI_STORE_U64(pBuf + Offset, Val64); | 
|  | Offset += sizeof(SK_U64); | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_RLMT_RX_SP_CTS: | 
|  | Val64 = pAC->Rlmt.Port[PhysPortIndex].RxSpHelloCts; | 
|  | SK_PNMI_STORE_U64(pBuf + Offset, Val64); | 
|  | Offset += sizeof(SK_U64); | 
|  | break; | 
|  |  | 
|  | default: | 
|  | SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR, | 
|  | ("RlmtStat: Unknown OID should be errored before")); | 
|  |  | 
|  | pAC->Pnmi.RlmtUpdatedFlag --; | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  | } | 
|  | } | 
|  | *pLen = Offset; | 
|  |  | 
|  | pAC->Pnmi.RlmtUpdatedFlag --; | 
|  |  | 
|  | return (SK_PNMI_ERR_OK); | 
|  | } | 
|  |  | 
|  | /***************************************************************************** | 
|  | * | 
|  | * MacPrivateConf - OID handler function of OIDs concerning the configuration | 
|  | * | 
|  | * Description: | 
|  | *	Get/Presets/Sets the OIDs concerning the configuration. | 
|  | * | 
|  | * 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 MacPrivateConf( | 
|  | 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	PhysPortMax; | 
|  | unsigned int	PhysPortIndex; | 
|  | unsigned int	LogPortMax; | 
|  | unsigned int	LogPortIndex; | 
|  | unsigned int	Limit; | 
|  | unsigned int	Offset; | 
|  | char		Val8; | 
|  | int		Ret; | 
|  | SK_EVPARA	EventParam; | 
|  | SK_U32		Val32; | 
|  |  | 
|  |  | 
|  | /* | 
|  | * 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; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Perform action | 
|  | */ | 
|  | if (Action == SK_PNMI_GET) { | 
|  |  | 
|  | /* | 
|  | * Check length | 
|  | */ | 
|  | switch (Id) { | 
|  |  | 
|  | case OID_SKGE_PMD: | 
|  | case OID_SKGE_CONNECTOR: | 
|  | case OID_SKGE_LINK_CAP: | 
|  | case OID_SKGE_LINK_MODE: | 
|  | case OID_SKGE_LINK_MODE_STATUS: | 
|  | case OID_SKGE_LINK_STATUS: | 
|  | case OID_SKGE_FLOWCTRL_CAP: | 
|  | case OID_SKGE_FLOWCTRL_MODE: | 
|  | case OID_SKGE_FLOWCTRL_STATUS: | 
|  | case OID_SKGE_PHY_OPERATION_CAP: | 
|  | case OID_SKGE_PHY_OPERATION_MODE: | 
|  | case OID_SKGE_PHY_OPERATION_STATUS: | 
|  | case OID_SKGE_SPEED_CAP: | 
|  | case OID_SKGE_SPEED_MODE: | 
|  | case OID_SKGE_SPEED_STATUS: | 
|  | if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U8)) { | 
|  |  | 
|  | *pLen = (Limit - LogPortIndex) * | 
|  | sizeof(SK_U8); | 
|  | return (SK_PNMI_ERR_TOO_SHORT); | 
|  | } | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_MTU: | 
|  | if (*pLen < sizeof(SK_U32)) { | 
|  |  | 
|  | *pLen = sizeof(SK_U32); | 
|  | return (SK_PNMI_ERR_TOO_SHORT); | 
|  | } | 
|  | break; | 
|  |  | 
|  | default: | 
|  | SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR041, | 
|  | SK_PNMI_ERR041MSG); | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Update statistic and increment semaphore to indicate | 
|  | * that an update was already done. | 
|  | */ | 
|  | if ((Ret = SirqUpdate(pAC, IoC)) != SK_PNMI_ERR_OK) { | 
|  |  | 
|  | *pLen = 0; | 
|  | return (Ret); | 
|  | } | 
|  | pAC->Pnmi.SirqUpdatedFlag ++; | 
|  |  | 
|  | /* | 
|  | * Get value | 
|  | */ | 
|  | Offset = 0; | 
|  | for (; LogPortIndex < Limit; LogPortIndex ++) { | 
|  |  | 
|  | switch (Id) { | 
|  |  | 
|  | case OID_SKGE_PMD: | 
|  | *(pBuf + Offset) = pAC->Pnmi.PMD; | 
|  | Offset += sizeof(char); | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_CONNECTOR: | 
|  | *(pBuf + Offset) = pAC->Pnmi.Connector; | 
|  | Offset += sizeof(char); | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_LINK_CAP: | 
|  | if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ | 
|  | if (LogPortIndex == 0) { | 
|  |  | 
|  | /* Get value for virtual port */ | 
|  | VirtualConf(pAC, IoC, Id, pBuf + | 
|  | Offset); | 
|  | } | 
|  | else { | 
|  | /* Get value for physical ports */ | 
|  | PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( | 
|  | pAC, LogPortIndex); | 
|  |  | 
|  | *(pBuf + Offset) = pAC->GIni.GP[ | 
|  | PhysPortIndex].PLinkCap; | 
|  | } | 
|  | Offset += sizeof(char); | 
|  | } | 
|  | else { /* DualNetMode */ | 
|  |  | 
|  | *(pBuf + Offset) = pAC->GIni.GP[NetIndex].PLinkCap; | 
|  | Offset += sizeof(char); | 
|  | } | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_LINK_MODE: | 
|  | if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ | 
|  | if (LogPortIndex == 0) { | 
|  |  | 
|  | /* Get value for virtual port */ | 
|  | VirtualConf(pAC, IoC, Id, pBuf + | 
|  | Offset); | 
|  | } | 
|  | else { | 
|  | /* Get value for physical ports */ | 
|  | PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( | 
|  | pAC, LogPortIndex); | 
|  |  | 
|  | *(pBuf + Offset) = pAC->GIni.GP[ | 
|  | PhysPortIndex].PLinkModeConf; | 
|  | } | 
|  | Offset += sizeof(char); | 
|  | } | 
|  | else { /* DualNetMode */ | 
|  |  | 
|  | *(pBuf + Offset) = pAC->GIni.GP[NetIndex].PLinkModeConf; | 
|  | Offset += sizeof(char); | 
|  | } | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_LINK_MODE_STATUS: | 
|  | if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ | 
|  | if (LogPortIndex == 0) { | 
|  |  | 
|  | /* Get value for virtual port */ | 
|  | VirtualConf(pAC, IoC, Id, pBuf + | 
|  | Offset); | 
|  | } | 
|  | else { | 
|  | /* Get value for physical port */ | 
|  | PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( | 
|  | pAC, LogPortIndex); | 
|  |  | 
|  | *(pBuf + Offset) = | 
|  | CalculateLinkModeStatus(pAC, | 
|  | IoC, PhysPortIndex); | 
|  | } | 
|  | Offset += sizeof(char); | 
|  | } | 
|  | else { /* DualNetMode */ | 
|  | *(pBuf + Offset) = CalculateLinkModeStatus(pAC, IoC, NetIndex); | 
|  | Offset += sizeof(char); | 
|  | } | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_LINK_STATUS: | 
|  | if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ | 
|  | if (LogPortIndex == 0) { | 
|  |  | 
|  | /* Get value for virtual port */ | 
|  | VirtualConf(pAC, IoC, Id, pBuf + | 
|  | Offset); | 
|  | } | 
|  | else { | 
|  | /* Get value for physical ports */ | 
|  | PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( | 
|  | pAC, LogPortIndex); | 
|  |  | 
|  | *(pBuf + Offset) = | 
|  | CalculateLinkStatus(pAC, | 
|  | IoC, PhysPortIndex); | 
|  | } | 
|  | Offset += sizeof(char); | 
|  | } | 
|  | else { /* DualNetMode */ | 
|  |  | 
|  | *(pBuf + Offset) = CalculateLinkStatus(pAC, IoC, NetIndex); | 
|  | Offset += sizeof(char); | 
|  | } | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_FLOWCTRL_CAP: | 
|  | if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ | 
|  | if (LogPortIndex == 0) { | 
|  |  | 
|  | /* Get value for virtual port */ | 
|  | VirtualConf(pAC, IoC, Id, pBuf + | 
|  | Offset); | 
|  | } | 
|  | else { | 
|  | /* Get value for physical ports */ | 
|  | PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( | 
|  | pAC, LogPortIndex); | 
|  |  | 
|  | *(pBuf + Offset) = pAC->GIni.GP[ | 
|  | PhysPortIndex].PFlowCtrlCap; | 
|  | } | 
|  | Offset += sizeof(char); | 
|  | } | 
|  | else { /* DualNetMode */ | 
|  |  | 
|  | *(pBuf + Offset) = pAC->GIni.GP[NetIndex].PFlowCtrlCap; | 
|  | Offset += sizeof(char); | 
|  | } | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_FLOWCTRL_MODE: | 
|  | if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ | 
|  | if (LogPortIndex == 0) { | 
|  |  | 
|  | /* Get value for virtual port */ | 
|  | VirtualConf(pAC, IoC, Id, pBuf + | 
|  | Offset); | 
|  | } | 
|  | else { | 
|  | /* Get value for physical port */ | 
|  | PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( | 
|  | pAC, LogPortIndex); | 
|  |  | 
|  | *(pBuf + Offset) = pAC->GIni.GP[ | 
|  | PhysPortIndex].PFlowCtrlMode; | 
|  | } | 
|  | Offset += sizeof(char); | 
|  | } | 
|  | else { /* DualNetMode */ | 
|  |  | 
|  | *(pBuf + Offset) = pAC->GIni.GP[NetIndex].PFlowCtrlMode; | 
|  | Offset += sizeof(char); | 
|  | } | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_FLOWCTRL_STATUS: | 
|  | if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ | 
|  | if (LogPortIndex == 0) { | 
|  |  | 
|  | /* Get value for virtual port */ | 
|  | VirtualConf(pAC, IoC, Id, pBuf + | 
|  | Offset); | 
|  | } | 
|  | else { | 
|  | /* Get value for physical port */ | 
|  | PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( | 
|  | pAC, LogPortIndex); | 
|  |  | 
|  | *(pBuf + Offset) = pAC->GIni.GP[ | 
|  | PhysPortIndex].PFlowCtrlStatus; | 
|  | } | 
|  | Offset += sizeof(char); | 
|  | } | 
|  | else { /* DualNetMode */ | 
|  |  | 
|  | *(pBuf + Offset) = pAC->GIni.GP[NetIndex].PFlowCtrlStatus; | 
|  | Offset += sizeof(char); | 
|  | } | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_PHY_OPERATION_CAP: | 
|  | if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ | 
|  | if (LogPortIndex == 0) { | 
|  |  | 
|  | /* Get value for virtual port */ | 
|  | VirtualConf(pAC, IoC, Id, pBuf + | 
|  | Offset); | 
|  | } | 
|  | else { | 
|  | /* Get value for physical ports */ | 
|  | PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( | 
|  | pAC, LogPortIndex); | 
|  |  | 
|  | *(pBuf + Offset) = pAC->GIni.GP[ | 
|  | PhysPortIndex].PMSCap; | 
|  | } | 
|  | Offset += sizeof(char); | 
|  | } | 
|  | else { /* DualNetMode */ | 
|  |  | 
|  | *(pBuf + Offset) = pAC->GIni.GP[NetIndex].PMSCap; | 
|  | Offset += sizeof(char); | 
|  | } | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_PHY_OPERATION_MODE: | 
|  | if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ | 
|  | if (LogPortIndex == 0) { | 
|  |  | 
|  | /* Get value for virtual port */ | 
|  | VirtualConf(pAC, IoC, Id, pBuf + Offset); | 
|  | } | 
|  | else { | 
|  | /* Get value for physical port */ | 
|  | PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( | 
|  | pAC, LogPortIndex); | 
|  |  | 
|  | *(pBuf + Offset) = pAC->GIni.GP[ | 
|  | PhysPortIndex].PMSMode; | 
|  | } | 
|  | Offset += sizeof(char); | 
|  | } | 
|  | else { /* DualNetMode */ | 
|  |  | 
|  | *(pBuf + Offset) = pAC->GIni.GP[NetIndex].PMSMode; | 
|  | Offset += sizeof(char); | 
|  | } | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_PHY_OPERATION_STATUS: | 
|  | if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ | 
|  | if (LogPortIndex == 0) { | 
|  |  | 
|  | /* Get value for virtual port */ | 
|  | VirtualConf(pAC, IoC, Id, pBuf + Offset); | 
|  | } | 
|  | else { | 
|  | /* Get value for physical port */ | 
|  | PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( | 
|  | pAC, LogPortIndex); | 
|  |  | 
|  | *(pBuf + Offset) = pAC->GIni.GP[ | 
|  | PhysPortIndex].PMSStatus; | 
|  | } | 
|  | Offset += sizeof(char); | 
|  | } | 
|  | else { | 
|  |  | 
|  | *(pBuf + Offset) = pAC->GIni.GP[NetIndex].PMSStatus; | 
|  | Offset += sizeof(char); | 
|  | } | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_SPEED_CAP: | 
|  | if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ | 
|  | if (LogPortIndex == 0) { | 
|  |  | 
|  | /* Get value for virtual port */ | 
|  | VirtualConf(pAC, IoC, Id, pBuf + | 
|  | Offset); | 
|  | } | 
|  | else { | 
|  | /* Get value for physical ports */ | 
|  | PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( | 
|  | pAC, LogPortIndex); | 
|  |  | 
|  | *(pBuf + Offset) = pAC->GIni.GP[ | 
|  | PhysPortIndex].PLinkSpeedCap; | 
|  | } | 
|  | Offset += sizeof(char); | 
|  | } | 
|  | else { /* DualNetMode */ | 
|  |  | 
|  | *(pBuf + Offset) = pAC->GIni.GP[NetIndex].PLinkSpeedCap; | 
|  | Offset += sizeof(char); | 
|  | } | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_SPEED_MODE: | 
|  | if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ | 
|  | if (LogPortIndex == 0) { | 
|  |  | 
|  | /* Get value for virtual port */ | 
|  | VirtualConf(pAC, IoC, Id, pBuf + Offset); | 
|  | } | 
|  | else { | 
|  | /* Get value for physical port */ | 
|  | PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( | 
|  | pAC, LogPortIndex); | 
|  |  | 
|  | *(pBuf + Offset) = pAC->GIni.GP[ | 
|  | PhysPortIndex].PLinkSpeed; | 
|  | } | 
|  | Offset += sizeof(char); | 
|  | } | 
|  | else { /* DualNetMode */ | 
|  |  | 
|  | *(pBuf + Offset) = pAC->GIni.GP[NetIndex].PLinkSpeed; | 
|  | Offset += sizeof(char); | 
|  | } | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_SPEED_STATUS: | 
|  | if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ | 
|  | if (LogPortIndex == 0) { | 
|  |  | 
|  | /* Get value for virtual port */ | 
|  | VirtualConf(pAC, IoC, Id, pBuf + Offset); | 
|  | } | 
|  | else { | 
|  | /* Get value for physical port */ | 
|  | PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( | 
|  | pAC, LogPortIndex); | 
|  |  | 
|  | *(pBuf + Offset) = pAC->GIni.GP[ | 
|  | PhysPortIndex].PLinkSpeedUsed; | 
|  | } | 
|  | Offset += sizeof(char); | 
|  | } | 
|  | else { /* DualNetMode */ | 
|  |  | 
|  | *(pBuf + Offset) = pAC->GIni.GP[NetIndex].PLinkSpeedUsed; | 
|  | Offset += sizeof(char); | 
|  | } | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_MTU: | 
|  | Val32 = SK_DRIVER_GET_MTU(pAC, IoC, NetIndex); | 
|  | SK_PNMI_STORE_U32(pBuf + Offset, Val32); | 
|  | Offset += sizeof(SK_U32); | 
|  | break; | 
|  |  | 
|  | default: | 
|  | SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR, | 
|  | ("MacPrivateConf: Unknown OID should be handled before")); | 
|  |  | 
|  | pAC->Pnmi.SirqUpdatedFlag --; | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  | } | 
|  | } | 
|  | *pLen = Offset; | 
|  | pAC->Pnmi.SirqUpdatedFlag --; | 
|  |  | 
|  | return (SK_PNMI_ERR_OK); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * From here SET or PRESET action. Check if the passed | 
|  | * buffer length is plausible. | 
|  | */ | 
|  | switch (Id) { | 
|  |  | 
|  | case OID_SKGE_LINK_MODE: | 
|  | case OID_SKGE_FLOWCTRL_MODE: | 
|  | case OID_SKGE_PHY_OPERATION_MODE: | 
|  | case OID_SKGE_SPEED_MODE: | 
|  | if (*pLen < Limit - LogPortIndex) { | 
|  |  | 
|  | *pLen = Limit - LogPortIndex; | 
|  | return (SK_PNMI_ERR_TOO_SHORT); | 
|  | } | 
|  | if (*pLen != Limit - LogPortIndex) { | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_BAD_VALUE); | 
|  | } | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_MTU: | 
|  | if (*pLen < sizeof(SK_U32)) { | 
|  |  | 
|  | *pLen = sizeof(SK_U32); | 
|  | return (SK_PNMI_ERR_TOO_SHORT); | 
|  | } | 
|  | if (*pLen != sizeof(SK_U32)) { | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_BAD_VALUE); | 
|  | } | 
|  | break; | 
|  |  | 
|  | default: | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_READ_ONLY); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Perform preset or set | 
|  | */ | 
|  | Offset = 0; | 
|  | for (; LogPortIndex < Limit; LogPortIndex ++) { | 
|  |  | 
|  | switch (Id) { | 
|  |  | 
|  | case OID_SKGE_LINK_MODE: | 
|  | /* Check the value range */ | 
|  | Val8 = *(pBuf + Offset); | 
|  | if (Val8 == 0) { | 
|  |  | 
|  | Offset += sizeof(char); | 
|  | break; | 
|  | } | 
|  | if (Val8 < SK_LMODE_HALF || | 
|  | (LogPortIndex != 0 && Val8 > SK_LMODE_AUTOSENSE) || | 
|  | (LogPortIndex == 0 && Val8 > SK_LMODE_INDETERMINATED)) { | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_BAD_VALUE); | 
|  | } | 
|  |  | 
|  | /* The preset ends here */ | 
|  | if (Action == SK_PNMI_PRESET) { | 
|  |  | 
|  | return (SK_PNMI_ERR_OK); | 
|  | } | 
|  |  | 
|  | if (LogPortIndex == 0) { | 
|  |  | 
|  | /* | 
|  | * The virtual port consists of all currently | 
|  | * active ports. Find them and send an event | 
|  | * with the new link mode to SIRQ. | 
|  | */ | 
|  | for (PhysPortIndex = 0; | 
|  | PhysPortIndex < PhysPortMax; | 
|  | PhysPortIndex ++) { | 
|  |  | 
|  | if (!pAC->Pnmi.Port[PhysPortIndex]. | 
|  | ActiveFlag) { | 
|  |  | 
|  | continue; | 
|  | } | 
|  |  | 
|  | EventParam.Para32[0] = PhysPortIndex; | 
|  | EventParam.Para32[1] = (SK_U32)Val8; | 
|  | if (SkGeSirqEvent(pAC, IoC, | 
|  | SK_HWEV_SET_LMODE, | 
|  | EventParam) > 0) { | 
|  |  | 
|  | SK_ERR_LOG(pAC, SK_ERRCL_SW, | 
|  | SK_PNMI_ERR043, | 
|  | SK_PNMI_ERR043MSG); | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  | } | 
|  | } | 
|  | } | 
|  | else { | 
|  | /* | 
|  | * Send an event with the new link mode to | 
|  | * the SIRQ module. | 
|  | */ | 
|  | EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS( | 
|  | pAC, LogPortIndex); | 
|  | EventParam.Para32[1] = (SK_U32)Val8; | 
|  | if (SkGeSirqEvent(pAC, IoC, SK_HWEV_SET_LMODE, | 
|  | EventParam) > 0) { | 
|  |  | 
|  | SK_ERR_LOG(pAC, SK_ERRCL_SW, | 
|  | SK_PNMI_ERR043, | 
|  | SK_PNMI_ERR043MSG); | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  | } | 
|  | } | 
|  | Offset += sizeof(char); | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_FLOWCTRL_MODE: | 
|  | /* Check the value range */ | 
|  | Val8 = *(pBuf + Offset); | 
|  | if (Val8 == 0) { | 
|  |  | 
|  | Offset += sizeof(char); | 
|  | break; | 
|  | } | 
|  | if (Val8 < SK_FLOW_MODE_NONE || | 
|  | (LogPortIndex != 0 && Val8 > SK_FLOW_MODE_SYM_OR_REM) || | 
|  | (LogPortIndex == 0 && Val8 > SK_FLOW_MODE_INDETERMINATED)) { | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_BAD_VALUE); | 
|  | } | 
|  |  | 
|  | /* The preset ends here */ | 
|  | if (Action == SK_PNMI_PRESET) { | 
|  |  | 
|  | return (SK_PNMI_ERR_OK); | 
|  | } | 
|  |  | 
|  | if (LogPortIndex == 0) { | 
|  |  | 
|  | /* | 
|  | * The virtual port consists of all currently | 
|  | * active ports. Find them and send an event | 
|  | * with the new flow control mode to SIRQ. | 
|  | */ | 
|  | for (PhysPortIndex = 0; | 
|  | PhysPortIndex < PhysPortMax; | 
|  | PhysPortIndex ++) { | 
|  |  | 
|  | if (!pAC->Pnmi.Port[PhysPortIndex]. | 
|  | ActiveFlag) { | 
|  |  | 
|  | continue; | 
|  | } | 
|  |  | 
|  | EventParam.Para32[0] = PhysPortIndex; | 
|  | EventParam.Para32[1] = (SK_U32)Val8; | 
|  | if (SkGeSirqEvent(pAC, IoC, | 
|  | SK_HWEV_SET_FLOWMODE, | 
|  | EventParam) > 0) { | 
|  |  | 
|  | SK_ERR_LOG(pAC, SK_ERRCL_SW, | 
|  | SK_PNMI_ERR044, | 
|  | SK_PNMI_ERR044MSG); | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  | } | 
|  | } | 
|  | } | 
|  | else { | 
|  | /* | 
|  | * Send an event with the new flow control | 
|  | * mode to the SIRQ module. | 
|  | */ | 
|  | EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS( | 
|  | pAC, LogPortIndex); | 
|  | EventParam.Para32[1] = (SK_U32)Val8; | 
|  | if (SkGeSirqEvent(pAC, IoC, | 
|  | SK_HWEV_SET_FLOWMODE, EventParam) | 
|  | > 0) { | 
|  |  | 
|  | SK_ERR_LOG(pAC, SK_ERRCL_SW, | 
|  | SK_PNMI_ERR044, | 
|  | SK_PNMI_ERR044MSG); | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  | } | 
|  | } | 
|  | Offset += sizeof(char); | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_PHY_OPERATION_MODE : | 
|  | /* Check the value range */ | 
|  | Val8 = *(pBuf + Offset); | 
|  | if (Val8 == 0) { | 
|  | /* mode of this port remains unchanged */ | 
|  | Offset += sizeof(char); | 
|  | break; | 
|  | } | 
|  | if (Val8 < SK_MS_MODE_AUTO || | 
|  | (LogPortIndex != 0 && Val8 > SK_MS_MODE_SLAVE) || | 
|  | (LogPortIndex == 0 && Val8 > SK_MS_MODE_INDETERMINATED)) { | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_BAD_VALUE); | 
|  | } | 
|  |  | 
|  | /* The preset ends here */ | 
|  | if (Action == SK_PNMI_PRESET) { | 
|  |  | 
|  | return (SK_PNMI_ERR_OK); | 
|  | } | 
|  |  | 
|  | if (LogPortIndex == 0) { | 
|  |  | 
|  | /* | 
|  | * The virtual port consists of all currently | 
|  | * active ports. Find them and send an event | 
|  | * with new master/slave (role) mode to SIRQ. | 
|  | */ | 
|  | for (PhysPortIndex = 0; | 
|  | PhysPortIndex < PhysPortMax; | 
|  | PhysPortIndex ++) { | 
|  |  | 
|  | if (!pAC->Pnmi.Port[PhysPortIndex]. | 
|  | ActiveFlag) { | 
|  |  | 
|  | continue; | 
|  | } | 
|  |  | 
|  | EventParam.Para32[0] = PhysPortIndex; | 
|  | EventParam.Para32[1] = (SK_U32)Val8; | 
|  | if (SkGeSirqEvent(pAC, IoC, | 
|  | SK_HWEV_SET_ROLE, | 
|  | EventParam) > 0) { | 
|  |  | 
|  | SK_ERR_LOG(pAC, SK_ERRCL_SW, | 
|  | SK_PNMI_ERR042, | 
|  | SK_PNMI_ERR042MSG); | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  | } | 
|  | } | 
|  | } | 
|  | else { | 
|  | /* | 
|  | * Send an event with the new master/slave | 
|  | * (role) mode to the SIRQ module. | 
|  | */ | 
|  | EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS( | 
|  | pAC, LogPortIndex); | 
|  | EventParam.Para32[1] = (SK_U32)Val8; | 
|  | if (SkGeSirqEvent(pAC, IoC, | 
|  | SK_HWEV_SET_ROLE, EventParam) > 0) { | 
|  |  | 
|  | SK_ERR_LOG(pAC, SK_ERRCL_SW, | 
|  | SK_PNMI_ERR042, | 
|  | SK_PNMI_ERR042MSG); | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  | } | 
|  | } | 
|  |  | 
|  | Offset += sizeof(char); | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_SPEED_MODE: | 
|  | /* Check the value range */ | 
|  | Val8 = *(pBuf + Offset); | 
|  | if (Val8 == 0) { | 
|  |  | 
|  | Offset += sizeof(char); | 
|  | break; | 
|  | } | 
|  | if (Val8 < (SK_LSPEED_AUTO) || | 
|  | (LogPortIndex != 0 && Val8 > (SK_LSPEED_1000MBPS)) || | 
|  | (LogPortIndex == 0 && Val8 > (SK_LSPEED_INDETERMINATED))) { | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_BAD_VALUE); | 
|  | } | 
|  |  | 
|  | /* The preset ends here */ | 
|  | if (Action == SK_PNMI_PRESET) { | 
|  |  | 
|  | return (SK_PNMI_ERR_OK); | 
|  | } | 
|  |  | 
|  | if (LogPortIndex == 0) { | 
|  |  | 
|  | /* | 
|  | * The virtual port consists of all currently | 
|  | * active ports. Find them and send an event | 
|  | * with the new flow control mode to SIRQ. | 
|  | */ | 
|  | for (PhysPortIndex = 0; | 
|  | PhysPortIndex < PhysPortMax; | 
|  | PhysPortIndex ++) { | 
|  |  | 
|  | if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) { | 
|  |  | 
|  | continue; | 
|  | } | 
|  |  | 
|  | EventParam.Para32[0] = PhysPortIndex; | 
|  | EventParam.Para32[1] = (SK_U32)Val8; | 
|  | if (SkGeSirqEvent(pAC, IoC, | 
|  | SK_HWEV_SET_SPEED, | 
|  | EventParam) > 0) { | 
|  |  | 
|  | SK_ERR_LOG(pAC, SK_ERRCL_SW, | 
|  | SK_PNMI_ERR045, | 
|  | SK_PNMI_ERR045MSG); | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  | } | 
|  | } | 
|  | } | 
|  | else { | 
|  | /* | 
|  | * Send an event with the new flow control | 
|  | * mode to the SIRQ module. | 
|  | */ | 
|  | EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS( | 
|  | pAC, LogPortIndex); | 
|  | EventParam.Para32[1] = (SK_U32)Val8; | 
|  | if (SkGeSirqEvent(pAC, IoC, | 
|  | SK_HWEV_SET_SPEED, | 
|  | EventParam) > 0) { | 
|  |  | 
|  | SK_ERR_LOG(pAC, SK_ERRCL_SW, | 
|  | SK_PNMI_ERR045, | 
|  | SK_PNMI_ERR045MSG); | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  | } | 
|  | } | 
|  | Offset += sizeof(char); | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_MTU : | 
|  | /* Check the value range */ | 
|  | Val32 = *(SK_U32*)(pBuf + Offset); | 
|  | if (Val32 == 0) { | 
|  | /* mtu of this port remains unchanged */ | 
|  | Offset += sizeof(SK_U32); | 
|  | break; | 
|  | } | 
|  | if (SK_DRIVER_PRESET_MTU(pAC, IoC, NetIndex, Val32) != 0) { | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_BAD_VALUE); | 
|  | } | 
|  |  | 
|  | /* The preset ends here */ | 
|  | if (Action == SK_PNMI_PRESET) { | 
|  | return (SK_PNMI_ERR_OK); | 
|  | } | 
|  |  | 
|  | if (SK_DRIVER_SET_MTU(pAC, IoC, NetIndex, Val32) != 0) { | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  | } | 
|  |  | 
|  | Offset += sizeof(SK_U32); | 
|  | break; | 
|  |  | 
|  | default: | 
|  | SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR, | 
|  | ("MacPrivateConf: Unknown OID should be handled before set")); | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  | } | 
|  | } | 
|  |  | 
|  | return (SK_PNMI_ERR_OK); | 
|  | } | 
|  |  | 
|  | /***************************************************************************** | 
|  | * | 
|  | * Monitor - OID handler function for RLMT_MONITOR_XXX | 
|  | * | 
|  | * Description: | 
|  | *	Because RLMT currently does not support the monitoring of | 
|  | *	remote adapter cards, we return always an empty table. | 
|  | * | 
|  | * 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 Monitor( | 
|  | 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	Index; | 
|  | unsigned int	Limit; | 
|  | unsigned int	Offset; | 
|  | unsigned int	Entries; | 
|  |  | 
|  |  | 
|  | /* | 
|  | * Calculate instance if wished. | 
|  | */ | 
|  | /* XXX Not yet implemented. Return always an empty table. */ | 
|  | Entries = 0; | 
|  |  | 
|  | if ((Instance != (SK_U32)(-1))) { | 
|  |  | 
|  | if ((Instance < 1) || (Instance > Entries)) { | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_UNKNOWN_INST); | 
|  | } | 
|  |  | 
|  | Index = (unsigned int)Instance - 1; | 
|  | Limit = (unsigned int)Instance; | 
|  | } | 
|  | else { | 
|  | Index = 0; | 
|  | Limit = Entries; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Get/Set value | 
|  | */ | 
|  | if (Action == SK_PNMI_GET) { | 
|  |  | 
|  | for (Offset=0; Index < Limit; Index ++) { | 
|  |  | 
|  | switch (Id) { | 
|  |  | 
|  | case OID_SKGE_RLMT_MONITOR_INDEX: | 
|  | case OID_SKGE_RLMT_MONITOR_ADDR: | 
|  | case OID_SKGE_RLMT_MONITOR_ERRS: | 
|  | case OID_SKGE_RLMT_MONITOR_TIMESTAMP: | 
|  | case OID_SKGE_RLMT_MONITOR_ADMIN: | 
|  | break; | 
|  |  | 
|  | default: | 
|  | SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR046, | 
|  | SK_PNMI_ERR046MSG); | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  | } | 
|  | } | 
|  | *pLen = Offset; | 
|  | } | 
|  | else { | 
|  | /* Only MONITOR_ADMIN can be set */ | 
|  | if (Id != OID_SKGE_RLMT_MONITOR_ADMIN) { | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_READ_ONLY); | 
|  | } | 
|  |  | 
|  | /* Check if the length is plausible */ | 
|  | if (*pLen < (Limit - Index)) { | 
|  |  | 
|  | return (SK_PNMI_ERR_TOO_SHORT); | 
|  | } | 
|  | /* Okay, we have a wide value range */ | 
|  | if (*pLen != (Limit - Index)) { | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_BAD_VALUE); | 
|  | } | 
|  | /* | 
|  | for (Offset=0; Index < Limit; Index ++) { | 
|  | } | 
|  | */ | 
|  | /* | 
|  | * XXX Not yet implemented. Return always BAD_VALUE, because the table | 
|  | * is empty. | 
|  | */ | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_BAD_VALUE); | 
|  | } | 
|  |  | 
|  | return (SK_PNMI_ERR_OK); | 
|  | } | 
|  |  | 
|  | /***************************************************************************** | 
|  | * | 
|  | * VirtualConf - Calculates the values of configuration OIDs for virtual port | 
|  | * | 
|  | * Description: | 
|  | *	We handle here the get of the configuration group OIDs, which are | 
|  | *	a little bit complicated. The virtual port consists of all currently | 
|  | *	active physical ports. If multiple ports are active and configured | 
|  | *	differently we get in some trouble to return a single value. So we | 
|  | *	get the value of the first active port and compare it with that of | 
|  | *	the other active ports. If they are not the same, we return a value | 
|  | *	that indicates that the state is indeterminated. | 
|  | * | 
|  | * Returns: | 
|  | *	Nothing | 
|  | */ | 
|  | PNMI_STATIC void VirtualConf( | 
|  | SK_AC *pAC,		/* Pointer to adapter context */ | 
|  | SK_IOC IoC,		/* IO context handle */ | 
|  | SK_U32 Id,		/* Object ID that is to be processed */ | 
|  | char *pBuf)		/* Buffer to which to mgmt data will be retrieved */ | 
|  | { | 
|  | unsigned int	PhysPortMax; | 
|  | unsigned int	PhysPortIndex; | 
|  | SK_U8		Val8; | 
|  | SK_BOOL		PortActiveFlag; | 
|  |  | 
|  |  | 
|  | *pBuf = 0; | 
|  | PortActiveFlag = SK_FALSE; | 
|  | PhysPortMax = pAC->GIni.GIMacsFound; | 
|  |  | 
|  | for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax; | 
|  | PhysPortIndex ++) { | 
|  |  | 
|  | /* Check if the physical port is active */ | 
|  | if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) { | 
|  |  | 
|  | continue; | 
|  | } | 
|  |  | 
|  | PortActiveFlag = SK_TRUE; | 
|  |  | 
|  | switch (Id) { | 
|  |  | 
|  | case OID_SKGE_LINK_CAP: | 
|  |  | 
|  | /* | 
|  | * Different capabilities should not happen, but | 
|  | * in the case of the cases OR them all together. | 
|  | * From a curious point of view the virtual port | 
|  | * is capable of all found capabilities. | 
|  | */ | 
|  | *pBuf |= pAC->GIni.GP[PhysPortIndex].PLinkCap; | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_LINK_MODE: | 
|  | /* Check if it is the first active port */ | 
|  | if (*pBuf == 0) { | 
|  |  | 
|  | *pBuf = pAC->GIni.GP[PhysPortIndex].PLinkModeConf; | 
|  | continue; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * If we find an active port with a different link | 
|  | * mode than the first one we return a value that | 
|  | * indicates that the link mode is indeterminated. | 
|  | */ | 
|  | if (*pBuf != pAC->GIni.GP[PhysPortIndex].PLinkModeConf | 
|  | ) { | 
|  |  | 
|  | *pBuf = SK_LMODE_INDETERMINATED; | 
|  | } | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_LINK_MODE_STATUS: | 
|  | /* Get the link mode of the physical port */ | 
|  | Val8 = CalculateLinkModeStatus(pAC, IoC, PhysPortIndex); | 
|  |  | 
|  | /* Check if it is the first active port */ | 
|  | if (*pBuf == 0) { | 
|  |  | 
|  | *pBuf = Val8; | 
|  | continue; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * If we find an active port with a different link | 
|  | * mode status than the first one we return a value | 
|  | * that indicates that the link mode status is | 
|  | * indeterminated. | 
|  | */ | 
|  | if (*pBuf != Val8) { | 
|  |  | 
|  | *pBuf = SK_LMODE_STAT_INDETERMINATED; | 
|  | } | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_LINK_STATUS: | 
|  | /* Get the link status of the physical port */ | 
|  | Val8 = CalculateLinkStatus(pAC, IoC, PhysPortIndex); | 
|  |  | 
|  | /* Check if it is the first active port */ | 
|  | if (*pBuf == 0) { | 
|  |  | 
|  | *pBuf = Val8; | 
|  | continue; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * If we find an active port with a different link | 
|  | * status than the first one, we return a value | 
|  | * that indicates that the link status is | 
|  | * indeterminated. | 
|  | */ | 
|  | if (*pBuf != Val8) { | 
|  |  | 
|  | *pBuf = SK_PNMI_RLMT_LSTAT_INDETERMINATED; | 
|  | } | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_FLOWCTRL_CAP: | 
|  | /* Check if it is the first active port */ | 
|  | if (*pBuf == 0) { | 
|  |  | 
|  | *pBuf = pAC->GIni.GP[PhysPortIndex].PFlowCtrlCap; | 
|  | continue; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * From a curious point of view the virtual port | 
|  | * is capable of all found capabilities. | 
|  | */ | 
|  | *pBuf |= pAC->GIni.GP[PhysPortIndex].PFlowCtrlCap; | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_FLOWCTRL_MODE: | 
|  | /* Check if it is the first active port */ | 
|  | if (*pBuf == 0) { | 
|  |  | 
|  | *pBuf = pAC->GIni.GP[PhysPortIndex].PFlowCtrlMode; | 
|  | continue; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * If we find an active port with a different flow | 
|  | * control mode than the first one, we return a value | 
|  | * that indicates that the mode is indeterminated. | 
|  | */ | 
|  | if (*pBuf != pAC->GIni.GP[PhysPortIndex].PFlowCtrlMode) { | 
|  |  | 
|  | *pBuf = SK_FLOW_MODE_INDETERMINATED; | 
|  | } | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_FLOWCTRL_STATUS: | 
|  | /* Check if it is the first active port */ | 
|  | if (*pBuf == 0) { | 
|  |  | 
|  | *pBuf = pAC->GIni.GP[PhysPortIndex].PFlowCtrlStatus; | 
|  | continue; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * If we find an active port with a different flow | 
|  | * control status than the first one, we return a | 
|  | * value that indicates that the status is | 
|  | * indeterminated. | 
|  | */ | 
|  | if (*pBuf != pAC->GIni.GP[PhysPortIndex].PFlowCtrlStatus) { | 
|  |  | 
|  | *pBuf = SK_FLOW_STAT_INDETERMINATED; | 
|  | } | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_PHY_OPERATION_CAP: | 
|  | /* Check if it is the first active port */ | 
|  | if (*pBuf == 0) { | 
|  |  | 
|  | *pBuf = pAC->GIni.GP[PhysPortIndex].PMSCap; | 
|  | continue; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * From a curious point of view the virtual port | 
|  | * is capable of all found capabilities. | 
|  | */ | 
|  | *pBuf |= pAC->GIni.GP[PhysPortIndex].PMSCap; | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_PHY_OPERATION_MODE: | 
|  | /* Check if it is the first active port */ | 
|  | if (*pBuf == 0) { | 
|  |  | 
|  | *pBuf = pAC->GIni.GP[PhysPortIndex].PMSMode; | 
|  | continue; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * If we find an active port with a different master/ | 
|  | * slave mode than the first one, we return a value | 
|  | * that indicates that the mode is indeterminated. | 
|  | */ | 
|  | if (*pBuf != pAC->GIni.GP[PhysPortIndex].PMSMode) { | 
|  |  | 
|  | *pBuf = SK_MS_MODE_INDETERMINATED; | 
|  | } | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_PHY_OPERATION_STATUS: | 
|  | /* Check if it is the first active port */ | 
|  | if (*pBuf == 0) { | 
|  |  | 
|  | *pBuf = pAC->GIni.GP[PhysPortIndex].PMSStatus; | 
|  | continue; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * If we find an active port with a different master/ | 
|  | * slave status than the first one, we return a | 
|  | * value that indicates that the status is | 
|  | * indeterminated. | 
|  | */ | 
|  | if (*pBuf != pAC->GIni.GP[PhysPortIndex].PMSStatus) { | 
|  |  | 
|  | *pBuf = SK_MS_STAT_INDETERMINATED; | 
|  | } | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_SPEED_MODE: | 
|  | /* Check if it is the first active port */ | 
|  | if (*pBuf == 0) { | 
|  |  | 
|  | *pBuf = pAC->GIni.GP[PhysPortIndex].PLinkSpeed; | 
|  | continue; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * If we find an active port with a different flow | 
|  | * control mode than the first one, we return a value | 
|  | * that indicates that the mode is indeterminated. | 
|  | */ | 
|  | if (*pBuf != pAC->GIni.GP[PhysPortIndex].PLinkSpeed) { | 
|  |  | 
|  | *pBuf = SK_LSPEED_INDETERMINATED; | 
|  | } | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_SPEED_STATUS: | 
|  | /* Check if it is the first active port */ | 
|  | if (*pBuf == 0) { | 
|  |  | 
|  | *pBuf = pAC->GIni.GP[PhysPortIndex].PLinkSpeedUsed; | 
|  | continue; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * If we find an active port with a different flow | 
|  | * control status than the first one, we return a | 
|  | * value that indicates that the status is | 
|  | * indeterminated. | 
|  | */ | 
|  | if (*pBuf != pAC->GIni.GP[PhysPortIndex].PLinkSpeedUsed) { | 
|  |  | 
|  | *pBuf = SK_LSPEED_STAT_INDETERMINATED; | 
|  | } | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* | 
|  | * If no port is active return an indeterminated answer | 
|  | */ | 
|  | if (!PortActiveFlag) { | 
|  |  | 
|  | switch (Id) { | 
|  |  | 
|  | case OID_SKGE_LINK_CAP: | 
|  | *pBuf = SK_LMODE_CAP_INDETERMINATED; | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_LINK_MODE: | 
|  | *pBuf = SK_LMODE_INDETERMINATED; | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_LINK_MODE_STATUS: | 
|  | *pBuf = SK_LMODE_STAT_INDETERMINATED; | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_LINK_STATUS: | 
|  | *pBuf = SK_PNMI_RLMT_LSTAT_INDETERMINATED; | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_FLOWCTRL_CAP: | 
|  | case OID_SKGE_FLOWCTRL_MODE: | 
|  | *pBuf = SK_FLOW_MODE_INDETERMINATED; | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_FLOWCTRL_STATUS: | 
|  | *pBuf = SK_FLOW_STAT_INDETERMINATED; | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_PHY_OPERATION_CAP: | 
|  | *pBuf = SK_MS_CAP_INDETERMINATED; | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_PHY_OPERATION_MODE: | 
|  | *pBuf = SK_MS_MODE_INDETERMINATED; | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_PHY_OPERATION_STATUS: | 
|  | *pBuf = SK_MS_STAT_INDETERMINATED; | 
|  | break; | 
|  | case OID_SKGE_SPEED_CAP: | 
|  | *pBuf = SK_LSPEED_CAP_INDETERMINATED; | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_SPEED_MODE: | 
|  | *pBuf = SK_LSPEED_INDETERMINATED; | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_SPEED_STATUS: | 
|  | *pBuf = SK_LSPEED_STAT_INDETERMINATED; | 
|  | break; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /***************************************************************************** | 
|  | * | 
|  | * CalculateLinkStatus - Determins the link status of a physical port | 
|  | * | 
|  | * Description: | 
|  | *	Determins the link status the following way: | 
|  | *	  LSTAT_PHY_DOWN:  Link is down | 
|  | *	  LSTAT_AUTONEG:   Auto-negotiation failed | 
|  | *	  LSTAT_LOG_DOWN:  Link is up but RLMT did not yet put the port | 
|  | *	                   logically up. | 
|  | *	  LSTAT_LOG_UP:    RLMT marked the port as up | 
|  | * | 
|  | * Returns: | 
|  | *	Link status of physical port | 
|  | */ | 
|  | PNMI_STATIC SK_U8 CalculateLinkStatus( | 
|  | SK_AC *pAC,			/* Pointer to adapter context */ | 
|  | SK_IOC IoC,			/* IO context handle */ | 
|  | unsigned int PhysPortIndex)	/* Physical port index */ | 
|  | { | 
|  | SK_U8	Result; | 
|  |  | 
|  |  | 
|  | if (!pAC->GIni.GP[PhysPortIndex].PHWLinkUp) { | 
|  |  | 
|  | Result = SK_PNMI_RLMT_LSTAT_PHY_DOWN; | 
|  | } | 
|  | else if (pAC->GIni.GP[PhysPortIndex].PAutoNegFail > 0) { | 
|  |  | 
|  | Result = SK_PNMI_RLMT_LSTAT_AUTONEG; | 
|  | } | 
|  | else if (!pAC->Rlmt.Port[PhysPortIndex].PortDown) { | 
|  |  | 
|  | Result = SK_PNMI_RLMT_LSTAT_LOG_UP; | 
|  | } | 
|  | else { | 
|  | Result = SK_PNMI_RLMT_LSTAT_LOG_DOWN; | 
|  | } | 
|  |  | 
|  | return (Result); | 
|  | } | 
|  |  | 
|  | /***************************************************************************** | 
|  | * | 
|  | * CalculateLinkModeStatus - Determins the link mode status of a phys. port | 
|  | * | 
|  | * Description: | 
|  | *	The COMMON module only tells us if the mode is half or full duplex. | 
|  | *	But in the decade of auto sensing it is usefull for the user to | 
|  | *	know if the mode was negotiated or forced. Therefore we have a | 
|  | *	look to the mode, which was last used by the negotiation process. | 
|  | * | 
|  | * Returns: | 
|  | *	The link mode status | 
|  | */ | 
|  | PNMI_STATIC SK_U8 CalculateLinkModeStatus( | 
|  | SK_AC *pAC,			/* Pointer to adapter context */ | 
|  | SK_IOC IoC,			/* IO context handle */ | 
|  | unsigned int PhysPortIndex)	/* Physical port index */ | 
|  | { | 
|  | SK_U8	Result; | 
|  |  | 
|  |  | 
|  | /* Get the current mode, which can be full or half duplex */ | 
|  | Result = pAC->GIni.GP[PhysPortIndex].PLinkModeStatus; | 
|  |  | 
|  | /* Check if no valid mode could be found (link is down) */ | 
|  | if (Result < SK_LMODE_STAT_HALF) { | 
|  |  | 
|  | Result = SK_LMODE_STAT_UNKNOWN; | 
|  | } | 
|  | else if (pAC->GIni.GP[PhysPortIndex].PLinkMode >= SK_LMODE_AUTOHALF) { | 
|  |  | 
|  | /* | 
|  | * Auto-negotiation was used to bring up the link. Change | 
|  | * the already found duplex status that it indicates | 
|  | * auto-negotiation was involved. | 
|  | */ | 
|  | if (Result == SK_LMODE_STAT_HALF) { | 
|  |  | 
|  | Result = SK_LMODE_STAT_AUTOHALF; | 
|  | } | 
|  | else if (Result == SK_LMODE_STAT_FULL) { | 
|  |  | 
|  | Result = SK_LMODE_STAT_AUTOFULL; | 
|  | } | 
|  | } | 
|  |  | 
|  | return (Result); | 
|  | } | 
|  |  | 
|  | /***************************************************************************** | 
|  | * | 
|  | * GetVpdKeyArr - Obtain an array of VPD keys | 
|  | * | 
|  | * Description: | 
|  | *	Read the VPD keys and build an array of VPD keys, which are | 
|  | *	easy to access. | 
|  | * | 
|  | * Returns: | 
|  | *	SK_PNMI_ERR_OK	     Task successfully performed. | 
|  | *	SK_PNMI_ERR_GENERAL  Something went wrong. | 
|  | */ | 
|  | PNMI_STATIC int GetVpdKeyArr( | 
|  | SK_AC *pAC,		/* Pointer to adapter context */ | 
|  | SK_IOC IoC,		/* IO context handle */ | 
|  | char *pKeyArr,		/* Ptr KeyArray */ | 
|  | unsigned int KeyArrLen,	/* Length of array in bytes */ | 
|  | unsigned int *pKeyNo)	/* Number of keys */ | 
|  | { | 
|  | unsigned int		BufKeysLen = SK_PNMI_VPD_BUFSIZE; | 
|  | char			BufKeys[SK_PNMI_VPD_BUFSIZE]; | 
|  | unsigned int		StartOffset; | 
|  | unsigned int		Offset; | 
|  | int			Index; | 
|  | int			Ret; | 
|  |  | 
|  |  | 
|  | SK_MEMSET(pKeyArr, 0, KeyArrLen); | 
|  |  | 
|  | /* | 
|  | * Get VPD key list | 
|  | */ | 
|  | Ret = VpdKeys(pAC, IoC, (char *)&BufKeys, (int *)&BufKeysLen, | 
|  | (int *)pKeyNo); | 
|  | if (Ret > 0) { | 
|  |  | 
|  | SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR014, | 
|  | SK_PNMI_ERR014MSG); | 
|  |  | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  | } | 
|  | /* If no keys are available return now */ | 
|  | if (*pKeyNo == 0 || BufKeysLen == 0) { | 
|  |  | 
|  | return (SK_PNMI_ERR_OK); | 
|  | } | 
|  | /* | 
|  | * If the key list is too long for us trunc it and give a | 
|  | * errorlog notification. This case should not happen because | 
|  | * the maximum number of keys is limited due to RAM limitations | 
|  | */ | 
|  | if (*pKeyNo > SK_PNMI_VPD_ENTRIES) { | 
|  |  | 
|  | SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR015, | 
|  | SK_PNMI_ERR015MSG); | 
|  |  | 
|  | *pKeyNo = SK_PNMI_VPD_ENTRIES; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Now build an array of fixed string length size and copy | 
|  | * the keys together. | 
|  | */ | 
|  | for (Index = 0, StartOffset = 0, Offset = 0; Offset < BufKeysLen; | 
|  | Offset ++) { | 
|  |  | 
|  | if (BufKeys[Offset] != 0) { | 
|  |  | 
|  | continue; | 
|  | } | 
|  |  | 
|  | if (Offset - StartOffset > SK_PNMI_VPD_KEY_SIZE) { | 
|  |  | 
|  | SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR016, | 
|  | SK_PNMI_ERR016MSG); | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  | } | 
|  |  | 
|  | SK_STRNCPY(pKeyArr + Index * SK_PNMI_VPD_KEY_SIZE, | 
|  | &BufKeys[StartOffset], SK_PNMI_VPD_KEY_SIZE); | 
|  |  | 
|  | Index ++; | 
|  | StartOffset = Offset + 1; | 
|  | } | 
|  |  | 
|  | /* Last key not zero terminated? Get it anyway */ | 
|  | if (StartOffset < Offset) { | 
|  |  | 
|  | SK_STRNCPY(pKeyArr + Index * SK_PNMI_VPD_KEY_SIZE, | 
|  | &BufKeys[StartOffset], SK_PNMI_VPD_KEY_SIZE); | 
|  | } | 
|  |  | 
|  | return (SK_PNMI_ERR_OK); | 
|  | } | 
|  |  | 
|  | /***************************************************************************** | 
|  | * | 
|  | * SirqUpdate - Let the SIRQ update its internal values | 
|  | * | 
|  | * Description: | 
|  | *	Just to be sure that the SIRQ module holds its internal data | 
|  | *	structures up to date, we send an update event before we make | 
|  | *	any access. | 
|  | * | 
|  | * Returns: | 
|  | *	SK_PNMI_ERR_OK	     Task successfully performed. | 
|  | *	SK_PNMI_ERR_GENERAL  Something went wrong. | 
|  | */ | 
|  | PNMI_STATIC int SirqUpdate( | 
|  | SK_AC *pAC,	/* Pointer to adapter context */ | 
|  | SK_IOC IoC)	/* IO context handle */ | 
|  | { | 
|  | SK_EVPARA	EventParam; | 
|  |  | 
|  |  | 
|  | /* Was the module already updated during the current PNMI call? */ | 
|  | if (pAC->Pnmi.SirqUpdatedFlag > 0) { | 
|  |  | 
|  | return (SK_PNMI_ERR_OK); | 
|  | } | 
|  |  | 
|  | /* Send an synchronuous update event to the module */ | 
|  | SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam)); | 
|  | if (SkGeSirqEvent(pAC, IoC, SK_HWEV_UPDATE_STAT, EventParam) > 0) { | 
|  |  | 
|  | SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR047, | 
|  | SK_PNMI_ERR047MSG); | 
|  |  | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  | } | 
|  |  | 
|  | return (SK_PNMI_ERR_OK); | 
|  | } | 
|  |  | 
|  | /***************************************************************************** | 
|  | * | 
|  | * RlmtUpdate - Let the RLMT update its internal values | 
|  | * | 
|  | * Description: | 
|  | *	Just to be sure that the RLMT module holds its internal data | 
|  | *	structures up to date, we send an update event before we make | 
|  | *	any access. | 
|  | * | 
|  | * Returns: | 
|  | *	SK_PNMI_ERR_OK	     Task successfully performed. | 
|  | *	SK_PNMI_ERR_GENERAL  Something went wrong. | 
|  | */ | 
|  | PNMI_STATIC int RlmtUpdate( | 
|  | SK_AC *pAC,	/* Pointer to adapter context */ | 
|  | SK_IOC IoC,	/* IO context handle */ | 
|  | SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode allways zero */ | 
|  | { | 
|  | SK_EVPARA	EventParam; | 
|  |  | 
|  |  | 
|  | /* Was the module already updated during the current PNMI call? */ | 
|  | if (pAC->Pnmi.RlmtUpdatedFlag > 0) { | 
|  |  | 
|  | return (SK_PNMI_ERR_OK); | 
|  | } | 
|  |  | 
|  | /* Send an synchronuous update event to the module */ | 
|  | SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam)); | 
|  | EventParam.Para32[0] = NetIndex; | 
|  | EventParam.Para32[1] = (SK_U32)-1; | 
|  | if (SkRlmtEvent(pAC, IoC, SK_RLMT_STATS_UPDATE, EventParam) > 0) { | 
|  |  | 
|  | SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR048, | 
|  | SK_PNMI_ERR048MSG); | 
|  |  | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  | } | 
|  |  | 
|  | return (SK_PNMI_ERR_OK); | 
|  | } | 
|  |  | 
|  | /***************************************************************************** | 
|  | * | 
|  | * MacUpdate - Force the XMAC to output the current statistic | 
|  | * | 
|  | * Description: | 
|  | *	The XMAC holds its statistic internally. To obtain the current | 
|  | *	values we send a command so that the statistic data will | 
|  | *	be written to apredefined memory area on the adapter. | 
|  | * | 
|  | * Returns: | 
|  | *	SK_PNMI_ERR_OK	     Task successfully performed. | 
|  | *	SK_PNMI_ERR_GENERAL  Something went wrong. | 
|  | */ | 
|  | PNMI_STATIC int MacUpdate( | 
|  | SK_AC *pAC,		/* Pointer to adapter context */ | 
|  | SK_IOC IoC,		/* IO context handle */ | 
|  | unsigned int FirstMac,	/* Index of the first Mac to be updated */ | 
|  | unsigned int LastMac)	/* Index of the last Mac to be updated */ | 
|  | { | 
|  | unsigned int	MacIndex; | 
|  |  | 
|  | /* | 
|  | * Were the statistics already updated during the | 
|  | * current PNMI call? | 
|  | */ | 
|  | if (pAC->Pnmi.MacUpdatedFlag > 0) { | 
|  |  | 
|  | return (SK_PNMI_ERR_OK); | 
|  | } | 
|  |  | 
|  | /* Send an update command to all MACs specified */ | 
|  | for (MacIndex = FirstMac; MacIndex <= LastMac; MacIndex ++) { | 
|  |  | 
|  | /* | 
|  | * 2002-09-13 pweber:	Freeze the current sw counters. | 
|  | *                      (That should be done as close as | 
|  | *                      possible to the update of the | 
|  | *                      hw counters) | 
|  | */ | 
|  | if (pAC->GIni.GIMacType == SK_MAC_XMAC) { | 
|  | pAC->Pnmi.BufPort[MacIndex] = pAC->Pnmi.Port[MacIndex]; | 
|  | } | 
|  |  | 
|  | /* 2002-09-13 pweber:  Update the hw counter  */ | 
|  | if (pAC->GIni.GIFunc.pFnMacUpdateStats(pAC, IoC, MacIndex) != 0) { | 
|  |  | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  | } | 
|  | } | 
|  |  | 
|  | return (SK_PNMI_ERR_OK); | 
|  | } | 
|  |  | 
|  | /***************************************************************************** | 
|  | * | 
|  | * GetStatVal - Retrieve an XMAC statistic counter | 
|  | * | 
|  | * Description: | 
|  | *	Retrieves the statistic counter of a virtual or physical port. The | 
|  | *	virtual port is identified by the index 0. It consists of all | 
|  | *	currently active ports. To obtain the counter value for this port | 
|  | *	we must add the statistic counter of all active ports. To grant | 
|  | *	continuous counter values for the virtual port even when port | 
|  | *	switches occur we must additionally add a delta value, which was | 
|  | *	calculated during a SK_PNMI_EVT_RLMT_ACTIVE_UP event. | 
|  | * | 
|  | * Returns: | 
|  | *	Requested statistic value | 
|  | */ | 
|  | PNMI_STATIC SK_U64 GetStatVal( | 
|  | SK_AC *pAC,					/* Pointer to adapter context */ | 
|  | SK_IOC IoC,					/* IO context handle */ | 
|  | unsigned int LogPortIndex,	/* Index of the logical Port to be processed */ | 
|  | unsigned int StatIndex,		/* Index to statistic value */ | 
|  | SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode allways zero */ | 
|  | { | 
|  | unsigned int	PhysPortIndex; | 
|  | unsigned int	PhysPortMax; | 
|  | SK_U64			Val = 0; | 
|  |  | 
|  |  | 
|  | if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {	/* Dual net mode */ | 
|  |  | 
|  | PhysPortIndex = NetIndex; | 
|  | Val = GetPhysStatVal(pAC, IoC, PhysPortIndex, StatIndex); | 
|  | } | 
|  | else {	/* Single Net mode */ | 
|  |  | 
|  | if (LogPortIndex == 0) { | 
|  |  | 
|  | PhysPortMax = pAC->GIni.GIMacsFound; | 
|  |  | 
|  | /* Add counter of all active ports */ | 
|  | for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax; | 
|  | PhysPortIndex ++) { | 
|  |  | 
|  | if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) { | 
|  |  | 
|  | Val += GetPhysStatVal(pAC, IoC, PhysPortIndex, | 
|  | StatIndex); | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Correct value because of port switches */ | 
|  | Val += pAC->Pnmi.VirtualCounterOffset[StatIndex]; | 
|  | } | 
|  | else { | 
|  | /* Get counter value of physical port */ | 
|  | PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex); | 
|  | Val = GetPhysStatVal(pAC, IoC, PhysPortIndex, StatIndex); | 
|  | } | 
|  | } | 
|  | return (Val); | 
|  | } | 
|  |  | 
|  | /***************************************************************************** | 
|  | * | 
|  | * GetPhysStatVal - Get counter value for physical port | 
|  | * | 
|  | * Description: | 
|  | *	Builds a 64bit counter value. Except for the octet counters | 
|  | *	the lower 32bit are counted in hardware and the upper 32bit | 
|  | *	in software by monitoring counter overflow interrupts in the | 
|  | *	event handler. To grant continous counter values during XMAC | 
|  | *	resets (caused by a workaround) we must add a delta value. | 
|  | *	The delta was calculated in the event handler when a | 
|  | *	SK_PNMI_EVT_XMAC_RESET was received. | 
|  | * | 
|  | * Returns: | 
|  | *	Counter value | 
|  | */ | 
|  | PNMI_STATIC SK_U64 GetPhysStatVal( | 
|  | SK_AC *pAC,					/* Pointer to adapter context */ | 
|  | SK_IOC IoC,					/* IO context handle */ | 
|  | unsigned int PhysPortIndex,	/* Index of the logical Port to be processed */ | 
|  | unsigned int StatIndex)		/* Index to statistic value */ | 
|  | { | 
|  | SK_U64	Val = 0; | 
|  | SK_U32	LowVal = 0; | 
|  | SK_U32	HighVal = 0; | 
|  | SK_U16	Word; | 
|  | int		MacType; | 
|  |  | 
|  | SK_PNMI_PORT	*pPnmiPrt; | 
|  | SK_GEMACFUNC	*pFnMac; | 
|  |  | 
|  | MacType = pAC->GIni.GIMacType; | 
|  |  | 
|  | /* 2002-09-17 pweber: For XMAC, use the frozen sw counters (BufPort) */ | 
|  | if (pAC->GIni.GIMacType == SK_MAC_XMAC) { | 
|  | pPnmiPrt = &pAC->Pnmi.BufPort[PhysPortIndex]; | 
|  | } | 
|  | else { | 
|  | pPnmiPrt = &pAC->Pnmi.Port[PhysPortIndex]; | 
|  | } | 
|  |  | 
|  | pFnMac   = &pAC->GIni.GIFunc; | 
|  |  | 
|  | switch (StatIndex) { | 
|  | case SK_PNMI_HTX: | 
|  | case SK_PNMI_HRX: | 
|  | /* Not supported by GMAC */ | 
|  | if (MacType == SK_MAC_GMAC) { | 
|  | return (Val); | 
|  | } | 
|  |  | 
|  | (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, | 
|  | StatAddr[StatIndex][MacType].Reg, | 
|  | &LowVal); | 
|  | HighVal = pPnmiPrt->CounterHigh[StatIndex]; | 
|  | break; | 
|  |  | 
|  | case SK_PNMI_HTX_OCTET: | 
|  | case SK_PNMI_HRX_OCTET: | 
|  | (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, | 
|  | StatAddr[StatIndex][MacType].Reg, | 
|  | &HighVal); | 
|  | (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, | 
|  | StatAddr[StatIndex + 1][MacType].Reg, | 
|  | &LowVal); | 
|  | break; | 
|  |  | 
|  | case SK_PNMI_HTX_BURST: | 
|  | case SK_PNMI_HTX_EXCESS_DEF: | 
|  | case SK_PNMI_HTX_CARRIER: | 
|  | /* Not supported by GMAC */ | 
|  | if (MacType == SK_MAC_GMAC) { | 
|  | return (Val); | 
|  | } | 
|  |  | 
|  | (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, | 
|  | StatAddr[StatIndex][MacType].Reg, | 
|  | &LowVal); | 
|  | HighVal = pPnmiPrt->CounterHigh[StatIndex]; | 
|  | break; | 
|  |  | 
|  | case SK_PNMI_HTX_MACC: | 
|  | /* GMAC only supports PAUSE MAC control frames */ | 
|  | if (MacType == SK_MAC_GMAC) { | 
|  | Val = GetPhysStatVal(pAC, IoC, PhysPortIndex, SK_PNMI_HTX_PMACC); | 
|  |  | 
|  | return (Val); | 
|  | } | 
|  |  | 
|  | (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, | 
|  | StatAddr[StatIndex][MacType].Reg, | 
|  | &LowVal); | 
|  | HighVal = pPnmiPrt->CounterHigh[StatIndex]; | 
|  | break; | 
|  |  | 
|  | case SK_PNMI_HTX_COL: | 
|  | case SK_PNMI_HRX_UNDERSIZE: | 
|  | /* Not supported by XMAC */ | 
|  | if (MacType == SK_MAC_XMAC) { | 
|  | return (Val); | 
|  | } | 
|  |  | 
|  | (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, | 
|  | StatAddr[StatIndex][MacType].Reg, | 
|  | &LowVal); | 
|  | HighVal = pPnmiPrt->CounterHigh[StatIndex]; | 
|  | break; | 
|  |  | 
|  |  | 
|  | case SK_PNMI_HTX_DEFFERAL: | 
|  | /* Not supported by GMAC */ | 
|  | if (MacType == SK_MAC_GMAC) { | 
|  | return (Val); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * XMAC counts frames with deferred transmission | 
|  | * even in full-duplex mode. | 
|  | * | 
|  | * In full-duplex mode the counter remains constant! | 
|  | */ | 
|  | if ((pAC->GIni.GP[PhysPortIndex].PLinkModeStatus == SK_LMODE_STAT_AUTOFULL) || | 
|  | (pAC->GIni.GP[PhysPortIndex].PLinkModeStatus == SK_LMODE_STAT_FULL)) { | 
|  |  | 
|  | LowVal = 0; | 
|  | HighVal = 0; | 
|  | } | 
|  | else { | 
|  | /* Otherwise get contents of hardware register. */ | 
|  | (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, | 
|  | StatAddr[SK_PNMI_HTX_DEFFERAL][MacType].Reg, | 
|  | &LowVal); | 
|  | HighVal = pPnmiPrt->CounterHigh[StatIndex]; | 
|  | } | 
|  | break; | 
|  |  | 
|  | case SK_PNMI_HRX_BADOCTET: | 
|  | /* Not supported by XMAC */ | 
|  | if (MacType == SK_MAC_XMAC) { | 
|  | return (Val); | 
|  | } | 
|  |  | 
|  | (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, | 
|  | StatAddr[StatIndex][MacType].Reg, | 
|  | &HighVal); | 
|  | (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, | 
|  | StatAddr[StatIndex + 1][MacType].Reg, | 
|  | &LowVal); | 
|  | break; | 
|  |  | 
|  | case SK_PNMI_HTX_OCTETLOW: | 
|  | case SK_PNMI_HRX_OCTETLOW: | 
|  | case SK_PNMI_HRX_BADOCTETLOW: | 
|  | return (Val); | 
|  |  | 
|  | case SK_PNMI_HRX_LONGFRAMES: | 
|  | /* For XMAC the SW counter is managed by PNMI */ | 
|  | if (MacType == SK_MAC_XMAC) { | 
|  | return (pPnmiPrt->StatRxLongFrameCts); | 
|  | } | 
|  |  | 
|  | (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, | 
|  | StatAddr[StatIndex][MacType].Reg, | 
|  | &LowVal); | 
|  | HighVal = pPnmiPrt->CounterHigh[StatIndex]; | 
|  | break; | 
|  |  | 
|  | case SK_PNMI_HRX_TOO_LONG: | 
|  | (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, | 
|  | StatAddr[StatIndex][MacType].Reg, | 
|  | &LowVal); | 
|  | HighVal = pPnmiPrt->CounterHigh[StatIndex]; | 
|  |  | 
|  | Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal); | 
|  |  | 
|  | switch (MacType) { | 
|  | case SK_MAC_GMAC: | 
|  | /* For GMAC the SW counter is additionally managed by PNMI */ | 
|  | Val += pPnmiPrt->StatRxFrameTooLongCts; | 
|  | break; | 
|  |  | 
|  | case SK_MAC_XMAC: | 
|  | /* | 
|  | * Frames longer than IEEE 802.3 frame max size are counted | 
|  | * by XMAC in frame_too_long counter even reception of long | 
|  | * frames was enabled and the frame was correct. | 
|  | * So correct the value by subtracting RxLongFrame counter. | 
|  | */ | 
|  | Val -= pPnmiPrt->StatRxLongFrameCts; | 
|  | break; | 
|  |  | 
|  | default: | 
|  | break; | 
|  | } | 
|  |  | 
|  | LowVal = (SK_U32)Val; | 
|  | HighVal = (SK_U32)(Val >> 32); | 
|  | break; | 
|  |  | 
|  | case SK_PNMI_HRX_SHORTS: | 
|  | /* Not supported by GMAC */ | 
|  | if (MacType == SK_MAC_GMAC) { | 
|  | /* GM_RXE_FRAG?? */ | 
|  | return (Val); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * XMAC counts short frame errors even if link down (#10620) | 
|  | * | 
|  | * If link-down the counter remains constant | 
|  | */ | 
|  | if (pAC->GIni.GP[PhysPortIndex].PLinkModeStatus != SK_LMODE_STAT_UNKNOWN) { | 
|  |  | 
|  | /* Otherwise get incremental difference */ | 
|  | (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, | 
|  | StatAddr[StatIndex][MacType].Reg, | 
|  | &LowVal); | 
|  | HighVal = pPnmiPrt->CounterHigh[StatIndex]; | 
|  |  | 
|  | Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal); | 
|  | Val -= pPnmiPrt->RxShortZeroMark; | 
|  |  | 
|  | LowVal = (SK_U32)Val; | 
|  | HighVal = (SK_U32)(Val >> 32); | 
|  | } | 
|  | break; | 
|  |  | 
|  | case SK_PNMI_HRX_MACC: | 
|  | case SK_PNMI_HRX_MACC_UNKWN: | 
|  | case SK_PNMI_HRX_BURST: | 
|  | case SK_PNMI_HRX_MISSED: | 
|  | case SK_PNMI_HRX_FRAMING: | 
|  | case SK_PNMI_HRX_CARRIER: | 
|  | case SK_PNMI_HRX_IRLENGTH: | 
|  | case SK_PNMI_HRX_SYMBOL: | 
|  | case SK_PNMI_HRX_CEXT: | 
|  | /* Not supported by GMAC */ | 
|  | if (MacType == SK_MAC_GMAC) { | 
|  | /* GM_RXE_FRAG?? */ | 
|  | return (Val); | 
|  | } | 
|  |  | 
|  | (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, | 
|  | StatAddr[StatIndex][MacType].Reg, | 
|  | &LowVal); | 
|  | HighVal = pPnmiPrt->CounterHigh[StatIndex]; | 
|  | break; | 
|  |  | 
|  | case SK_PNMI_HRX_PMACC_ERR: | 
|  | /* For GMAC the SW counter is managed by PNMI */ | 
|  | if (MacType == SK_MAC_GMAC) { | 
|  | return (pPnmiPrt->StatRxPMaccErr); | 
|  | } | 
|  |  | 
|  | (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, | 
|  | StatAddr[StatIndex][MacType].Reg, | 
|  | &LowVal); | 
|  | HighVal = pPnmiPrt->CounterHigh[StatIndex]; | 
|  | break; | 
|  |  | 
|  | /* SW counter managed by PNMI */ | 
|  | case SK_PNMI_HTX_SYNC: | 
|  | LowVal = (SK_U32)pPnmiPrt->StatSyncCts; | 
|  | HighVal = (SK_U32)(pPnmiPrt->StatSyncCts >> 32); | 
|  | break; | 
|  |  | 
|  | /* SW counter managed by PNMI */ | 
|  | case SK_PNMI_HTX_SYNC_OCTET: | 
|  | LowVal = (SK_U32)pPnmiPrt->StatSyncOctetsCts; | 
|  | HighVal = (SK_U32)(pPnmiPrt->StatSyncOctetsCts >> 32); | 
|  | break; | 
|  |  | 
|  | case SK_PNMI_HRX_FCS: | 
|  | /* | 
|  | * Broadcom filters fcs errors and counts it in | 
|  | * Receive Error Counter register | 
|  | */ | 
|  | if (pAC->GIni.GP[PhysPortIndex].PhyType == SK_PHY_BCOM) { | 
|  | /* do not read while not initialized (PHY_READ hangs!)*/ | 
|  | if (pAC->GIni.GP[PhysPortIndex].PState) { | 
|  | PHY_READ(IoC, &pAC->GIni.GP[PhysPortIndex], | 
|  | PhysPortIndex, PHY_BCOM_RE_CTR, | 
|  | &Word); | 
|  |  | 
|  | LowVal = Word; | 
|  | } | 
|  | HighVal = pPnmiPrt->CounterHigh[StatIndex]; | 
|  | } | 
|  | else { | 
|  | (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, | 
|  | StatAddr[StatIndex][MacType].Reg, | 
|  | &LowVal); | 
|  | HighVal = pPnmiPrt->CounterHigh[StatIndex]; | 
|  | } | 
|  | break; | 
|  |  | 
|  | default: | 
|  | (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, | 
|  | StatAddr[StatIndex][MacType].Reg, | 
|  | &LowVal); | 
|  | HighVal = pPnmiPrt->CounterHigh[StatIndex]; | 
|  | break; | 
|  | } | 
|  |  | 
|  | Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal); | 
|  |  | 
|  | /* Correct value because of possible XMAC reset. XMAC Errata #2 */ | 
|  | Val += pPnmiPrt->CounterOffset[StatIndex]; | 
|  |  | 
|  | return (Val); | 
|  | } | 
|  |  | 
|  | /***************************************************************************** | 
|  | * | 
|  | * ResetCounter - Set all counters and timestamps to zero | 
|  | * | 
|  | * Description: | 
|  | *	Notifies other common modules which store statistic data to | 
|  | *	reset their counters and finally reset our own counters. | 
|  | * | 
|  | * Returns: | 
|  | *	Nothing | 
|  | */ | 
|  | PNMI_STATIC void ResetCounter( | 
|  | SK_AC *pAC,		/* Pointer to adapter context */ | 
|  | SK_IOC IoC,		/* IO context handle */ | 
|  | SK_U32 NetIndex) | 
|  | { | 
|  | unsigned int	PhysPortIndex; | 
|  | SK_EVPARA	EventParam; | 
|  |  | 
|  |  | 
|  | SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam)); | 
|  |  | 
|  | /* Notify sensor module */ | 
|  | SkEventQueue(pAC, SKGE_I2C, SK_I2CEV_CLEAR, EventParam); | 
|  |  | 
|  | /* Notify RLMT module */ | 
|  | EventParam.Para32[0] = NetIndex; | 
|  | EventParam.Para32[1] = (SK_U32)-1; | 
|  | SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STATS_CLEAR, EventParam); | 
|  | EventParam.Para32[1] = 0; | 
|  |  | 
|  | /* Notify SIRQ module */ | 
|  | SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_CLEAR_STAT, EventParam); | 
|  |  | 
|  | /* Notify CSUM module */ | 
|  | #ifdef SK_USE_CSUM | 
|  | EventParam.Para32[0] = NetIndex; | 
|  | EventParam.Para32[1] = (SK_U32)-1; | 
|  | SkEventQueue(pAC, SKGE_CSUM, SK_CSUM_EVENT_CLEAR_PROTO_STATS, | 
|  | EventParam); | 
|  | #endif | 
|  |  | 
|  | /* Clear XMAC statistic */ | 
|  | for (PhysPortIndex = 0; PhysPortIndex < | 
|  | (unsigned int)pAC->GIni.GIMacsFound; PhysPortIndex ++) { | 
|  |  | 
|  | (void)pAC->GIni.GIFunc.pFnMacResetCounter(pAC, IoC, PhysPortIndex); | 
|  |  | 
|  | SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].CounterHigh, | 
|  | 0, sizeof(pAC->Pnmi.Port[PhysPortIndex].CounterHigh)); | 
|  | SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex]. | 
|  | CounterOffset, 0, sizeof(pAC->Pnmi.Port[ | 
|  | PhysPortIndex].CounterOffset)); | 
|  | SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].StatSyncCts, | 
|  | 0, sizeof(pAC->Pnmi.Port[PhysPortIndex].StatSyncCts)); | 
|  | SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex]. | 
|  | StatSyncOctetsCts, 0, sizeof(pAC->Pnmi.Port[ | 
|  | PhysPortIndex].StatSyncOctetsCts)); | 
|  | SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex]. | 
|  | StatRxLongFrameCts, 0, sizeof(pAC->Pnmi.Port[ | 
|  | PhysPortIndex].StatRxLongFrameCts)); | 
|  | SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex]. | 
|  | StatRxFrameTooLongCts, 0, sizeof(pAC->Pnmi.Port[ | 
|  | PhysPortIndex].StatRxFrameTooLongCts)); | 
|  | SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex]. | 
|  | StatRxPMaccErr, 0, sizeof(pAC->Pnmi.Port[ | 
|  | PhysPortIndex].StatRxPMaccErr)); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Clear local statistics | 
|  | */ | 
|  | SK_MEMSET((char *)&pAC->Pnmi.VirtualCounterOffset, 0, | 
|  | sizeof(pAC->Pnmi.VirtualCounterOffset)); | 
|  | pAC->Pnmi.RlmtChangeCts = 0; | 
|  | pAC->Pnmi.RlmtChangeTime = 0; | 
|  | SK_MEMSET((char *)&pAC->Pnmi.RlmtChangeEstimate.EstValue[0], 0, | 
|  | sizeof(pAC->Pnmi.RlmtChangeEstimate.EstValue)); | 
|  | pAC->Pnmi.RlmtChangeEstimate.EstValueIndex = 0; | 
|  | pAC->Pnmi.RlmtChangeEstimate.Estimate = 0; | 
|  | pAC->Pnmi.Port[NetIndex].TxSwQueueMax = 0; | 
|  | pAC->Pnmi.Port[NetIndex].TxRetryCts = 0; | 
|  | pAC->Pnmi.Port[NetIndex].RxIntrCts = 0; | 
|  | pAC->Pnmi.Port[NetIndex].TxIntrCts = 0; | 
|  | pAC->Pnmi.Port[NetIndex].RxNoBufCts = 0; | 
|  | pAC->Pnmi.Port[NetIndex].TxNoBufCts = 0; | 
|  | pAC->Pnmi.Port[NetIndex].TxUsedDescrNo = 0; | 
|  | pAC->Pnmi.Port[NetIndex].RxDeliveredCts = 0; | 
|  | pAC->Pnmi.Port[NetIndex].RxOctetsDeliveredCts = 0; | 
|  | pAC->Pnmi.Port[NetIndex].ErrRecoveryCts = 0; | 
|  | } | 
|  |  | 
|  | /***************************************************************************** | 
|  | * | 
|  | * GetTrapEntry - Get an entry in the trap buffer | 
|  | * | 
|  | * Description: | 
|  | *	The trap buffer stores various events. A user application somehow | 
|  | *	gets notified that an event occured and retrieves the trap buffer | 
|  | *	contens (or simply polls the buffer). The buffer is organized as | 
|  | *	a ring which stores the newest traps at the beginning. The oldest | 
|  | *	traps are overwritten by the newest ones. Each trap entry has a | 
|  | *	unique number, so that applications may detect new trap entries. | 
|  | * | 
|  | * Returns: | 
|  | *	A pointer to the trap entry | 
|  | */ | 
|  | PNMI_STATIC char* GetTrapEntry( | 
|  | SK_AC *pAC,		/* Pointer to adapter context */ | 
|  | SK_U32 TrapId,		/* SNMP ID of the trap */ | 
|  | unsigned int Size)	/* Space needed for trap entry */ | 
|  | { | 
|  | unsigned int		BufPad = pAC->Pnmi.TrapBufPad; | 
|  | unsigned int		BufFree = pAC->Pnmi.TrapBufFree; | 
|  | unsigned int		Beg = pAC->Pnmi.TrapQueueBeg; | 
|  | unsigned int		End = pAC->Pnmi.TrapQueueEnd; | 
|  | char			*pBuf = &pAC->Pnmi.TrapBuf[0]; | 
|  | int			Wrap; | 
|  | unsigned int		NeededSpace; | 
|  | unsigned int		EntrySize; | 
|  | SK_U32			Val32; | 
|  | SK_U64			Val64; | 
|  |  | 
|  |  | 
|  | /* Last byte of entry will get a copy of the entry length */ | 
|  | Size ++; | 
|  |  | 
|  | /* | 
|  | * Calculate needed buffer space */ | 
|  | if (Beg >= Size) { | 
|  |  | 
|  | NeededSpace = Size; | 
|  | Wrap = SK_FALSE; | 
|  | } | 
|  | else { | 
|  | NeededSpace = Beg + Size; | 
|  | Wrap = SK_TRUE; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Check if enough buffer space is provided. Otherwise | 
|  | * free some entries. Leave one byte space between begin | 
|  | * and end of buffer to make it possible to detect whether | 
|  | * the buffer is full or empty | 
|  | */ | 
|  | while (BufFree < NeededSpace + 1) { | 
|  |  | 
|  | if (End == 0) { | 
|  |  | 
|  | End = SK_PNMI_TRAP_QUEUE_LEN; | 
|  | } | 
|  |  | 
|  | EntrySize = (unsigned int)*((unsigned char *)pBuf + End - 1); | 
|  | BufFree += EntrySize; | 
|  | End -= EntrySize; | 
|  | #ifdef DEBUG | 
|  | SK_MEMSET(pBuf + End, (char)(-1), EntrySize); | 
|  | #endif | 
|  | if (End == BufPad) { | 
|  | #ifdef DEBUG | 
|  | SK_MEMSET(pBuf, (char)(-1), End); | 
|  | #endif | 
|  | BufFree += End; | 
|  | End = 0; | 
|  | BufPad = 0; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Insert new entry as first entry. Newest entries are | 
|  | * stored at the beginning of the queue. | 
|  | */ | 
|  | if (Wrap) { | 
|  |  | 
|  | BufPad = Beg; | 
|  | Beg = SK_PNMI_TRAP_QUEUE_LEN - Size; | 
|  | } | 
|  | else { | 
|  | Beg = Beg - Size; | 
|  | } | 
|  | BufFree -= NeededSpace; | 
|  |  | 
|  | /* Save the current offsets */ | 
|  | pAC->Pnmi.TrapQueueBeg = Beg; | 
|  | pAC->Pnmi.TrapQueueEnd = End; | 
|  | pAC->Pnmi.TrapBufPad = BufPad; | 
|  | pAC->Pnmi.TrapBufFree = BufFree; | 
|  |  | 
|  | /* Initialize the trap entry */ | 
|  | *(pBuf + Beg + Size - 1) = (char)Size; | 
|  | *(pBuf + Beg) = (char)Size; | 
|  | Val32 = (pAC->Pnmi.TrapUnique) ++; | 
|  | SK_PNMI_STORE_U32(pBuf + Beg + 1, Val32); | 
|  | SK_PNMI_STORE_U32(pBuf + Beg + 1 + sizeof(SK_U32), TrapId); | 
|  | Val64 = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC)); | 
|  | SK_PNMI_STORE_U64(pBuf + Beg + 1 + 2 * sizeof(SK_U32), Val64); | 
|  |  | 
|  | return (pBuf + Beg); | 
|  | } | 
|  |  | 
|  | /***************************************************************************** | 
|  | * | 
|  | * CopyTrapQueue - Copies the trap buffer for the TRAP OID | 
|  | * | 
|  | * Description: | 
|  | *	On a query of the TRAP OID the trap buffer contents will be | 
|  | *	copied continuously to the request buffer, which must be large | 
|  | *	enough. No length check is performed. | 
|  | * | 
|  | * Returns: | 
|  | *	Nothing | 
|  | */ | 
|  | PNMI_STATIC void CopyTrapQueue( | 
|  | SK_AC *pAC,		/* Pointer to adapter context */ | 
|  | char *pDstBuf)		/* Buffer to which the queued traps will be copied */ | 
|  | { | 
|  | unsigned int	BufPad = pAC->Pnmi.TrapBufPad; | 
|  | unsigned int	Trap = pAC->Pnmi.TrapQueueBeg; | 
|  | unsigned int	End = pAC->Pnmi.TrapQueueEnd; | 
|  | char		*pBuf = &pAC->Pnmi.TrapBuf[0]; | 
|  | unsigned int	Len; | 
|  | unsigned int	DstOff = 0; | 
|  |  | 
|  |  | 
|  | while (Trap != End) { | 
|  |  | 
|  | Len = (unsigned int)*(pBuf + Trap); | 
|  |  | 
|  | /* | 
|  | * Last byte containing a copy of the length will | 
|  | * not be copied. | 
|  | */ | 
|  | *(pDstBuf + DstOff) = (char)(Len - 1); | 
|  | SK_MEMCPY(pDstBuf + DstOff + 1, pBuf + Trap + 1, Len - 2); | 
|  | DstOff += Len - 1; | 
|  |  | 
|  | Trap += Len; | 
|  | if (Trap == SK_PNMI_TRAP_QUEUE_LEN) { | 
|  |  | 
|  | Trap = BufPad; | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | /***************************************************************************** | 
|  | * | 
|  | * GetTrapQueueLen - Get the length of the trap buffer | 
|  | * | 
|  | * Description: | 
|  | *	Evaluates the number of currently stored traps and the needed | 
|  | *	buffer size to retrieve them. | 
|  | * | 
|  | * Returns: | 
|  | *	Nothing | 
|  | */ | 
|  | PNMI_STATIC void GetTrapQueueLen( | 
|  | SK_AC *pAC,		/* Pointer to adapter context */ | 
|  | unsigned int *pLen,	/* Length in Bytes of all queued traps */ | 
|  | unsigned int *pEntries)	/* Returns number of trapes stored in queue */ | 
|  | { | 
|  | unsigned int	BufPad = pAC->Pnmi.TrapBufPad; | 
|  | unsigned int	Trap = pAC->Pnmi.TrapQueueBeg; | 
|  | unsigned int	End = pAC->Pnmi.TrapQueueEnd; | 
|  | char		*pBuf = &pAC->Pnmi.TrapBuf[0]; | 
|  | unsigned int	Len; | 
|  | unsigned int	Entries = 0; | 
|  | unsigned int	TotalLen = 0; | 
|  |  | 
|  |  | 
|  | while (Trap != End) { | 
|  |  | 
|  | Len = (unsigned int)*(pBuf + Trap); | 
|  | TotalLen += Len - 1; | 
|  | Entries ++; | 
|  |  | 
|  | Trap += Len; | 
|  | if (Trap == SK_PNMI_TRAP_QUEUE_LEN) { | 
|  |  | 
|  | Trap = BufPad; | 
|  | } | 
|  | } | 
|  |  | 
|  | *pEntries = Entries; | 
|  | *pLen = TotalLen; | 
|  | } | 
|  |  | 
|  | /***************************************************************************** | 
|  | * | 
|  | * QueueSimpleTrap - Store a simple trap to the trap buffer | 
|  | * | 
|  | * Description: | 
|  | *	A simple trap is a trap with now additional data. It consists | 
|  | *	simply of a trap code. | 
|  | * | 
|  | * Returns: | 
|  | *	Nothing | 
|  | */ | 
|  | PNMI_STATIC void QueueSimpleTrap( | 
|  | SK_AC *pAC,		/* Pointer to adapter context */ | 
|  | SK_U32 TrapId)		/* Type of sensor trap */ | 
|  | { | 
|  | GetTrapEntry(pAC, TrapId, SK_PNMI_TRAP_SIMPLE_LEN); | 
|  | } | 
|  |  | 
|  | /***************************************************************************** | 
|  | * | 
|  | * QueueSensorTrap - Stores a sensor trap in the trap buffer | 
|  | * | 
|  | * Description: | 
|  | *	Gets an entry in the trap buffer and fills it with sensor related | 
|  | *	data. | 
|  | * | 
|  | * Returns: | 
|  | *	Nothing | 
|  | */ | 
|  | PNMI_STATIC void QueueSensorTrap( | 
|  | SK_AC *pAC,			/* Pointer to adapter context */ | 
|  | SK_U32 TrapId,			/* Type of sensor trap */ | 
|  | unsigned int SensorIndex)	/* Index of sensor which caused the trap */ | 
|  | { | 
|  | char		*pBuf; | 
|  | unsigned int	Offset; | 
|  | unsigned int	DescrLen; | 
|  | SK_U32		Val32; | 
|  |  | 
|  |  | 
|  | /* Get trap buffer entry */ | 
|  | DescrLen = SK_STRLEN(pAC->I2c.SenTable[SensorIndex].SenDesc); | 
|  | pBuf = GetTrapEntry(pAC, TrapId, | 
|  | SK_PNMI_TRAP_SENSOR_LEN_BASE + DescrLen); | 
|  | Offset = SK_PNMI_TRAP_SIMPLE_LEN; | 
|  |  | 
|  | /* Store additionally sensor trap related data */ | 
|  | Val32 = OID_SKGE_SENSOR_INDEX; | 
|  | SK_PNMI_STORE_U32(pBuf + Offset, Val32); | 
|  | *(pBuf + Offset + 4) = 4; | 
|  | Val32 = (SK_U32)SensorIndex; | 
|  | SK_PNMI_STORE_U32(pBuf + Offset + 5, Val32); | 
|  | Offset += 9; | 
|  |  | 
|  | Val32 = (SK_U32)OID_SKGE_SENSOR_DESCR; | 
|  | SK_PNMI_STORE_U32(pBuf + Offset, Val32); | 
|  | *(pBuf + Offset + 4) = (char)DescrLen; | 
|  | SK_MEMCPY(pBuf + Offset + 5, pAC->I2c.SenTable[SensorIndex].SenDesc, | 
|  | DescrLen); | 
|  | Offset += DescrLen + 5; | 
|  |  | 
|  | Val32 = OID_SKGE_SENSOR_TYPE; | 
|  | SK_PNMI_STORE_U32(pBuf + Offset, Val32); | 
|  | *(pBuf + Offset + 4) = 1; | 
|  | *(pBuf + Offset + 5) = (char)pAC->I2c.SenTable[SensorIndex].SenType; | 
|  | Offset += 6; | 
|  |  | 
|  | Val32 = OID_SKGE_SENSOR_VALUE; | 
|  | SK_PNMI_STORE_U32(pBuf + Offset, Val32); | 
|  | *(pBuf + Offset + 4) = 4; | 
|  | Val32 = (SK_U32)pAC->I2c.SenTable[SensorIndex].SenValue; | 
|  | SK_PNMI_STORE_U32(pBuf + Offset + 5, Val32); | 
|  | } | 
|  |  | 
|  | /***************************************************************************** | 
|  | * | 
|  | * QueueRlmtNewMacTrap - Store a port switch trap in the trap buffer | 
|  | * | 
|  | * Description: | 
|  | *	Nothing further to explain. | 
|  | * | 
|  | * Returns: | 
|  | *	Nothing | 
|  | */ | 
|  | PNMI_STATIC void QueueRlmtNewMacTrap( | 
|  | SK_AC *pAC,		/* Pointer to adapter context */ | 
|  | unsigned int ActiveMac)	/* Index (0..n) of the currently active port */ | 
|  | { | 
|  | char	*pBuf; | 
|  | SK_U32	Val32; | 
|  |  | 
|  |  | 
|  | pBuf = GetTrapEntry(pAC, OID_SKGE_TRAP_RLMT_CHANGE_PORT, | 
|  | SK_PNMI_TRAP_RLMT_CHANGE_LEN); | 
|  |  | 
|  | Val32 = OID_SKGE_RLMT_PORT_ACTIVE; | 
|  | SK_PNMI_STORE_U32(pBuf + SK_PNMI_TRAP_SIMPLE_LEN, Val32); | 
|  | *(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 4) = 1; | 
|  | *(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 5) = (char)ActiveMac; | 
|  | } | 
|  |  | 
|  | /***************************************************************************** | 
|  | * | 
|  | * QueueRlmtPortTrap - Store port related RLMT trap to trap buffer | 
|  | * | 
|  | * Description: | 
|  | *	Nothing further to explain. | 
|  | * | 
|  | * Returns: | 
|  | *	Nothing | 
|  | */ | 
|  | PNMI_STATIC void QueueRlmtPortTrap( | 
|  | SK_AC *pAC,		/* Pointer to adapter context */ | 
|  | SK_U32 TrapId,		/* Type of RLMT port trap */ | 
|  | unsigned int PortIndex)	/* Index of the port, which changed its state */ | 
|  | { | 
|  | char	*pBuf; | 
|  | SK_U32	Val32; | 
|  |  | 
|  |  | 
|  | pBuf = GetTrapEntry(pAC, TrapId, SK_PNMI_TRAP_RLMT_PORT_LEN); | 
|  |  | 
|  | Val32 = OID_SKGE_RLMT_PORT_INDEX; | 
|  | SK_PNMI_STORE_U32(pBuf + SK_PNMI_TRAP_SIMPLE_LEN, Val32); | 
|  | *(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 4) = 1; | 
|  | *(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 5) = (char)PortIndex; | 
|  | } | 
|  |  | 
|  | /***************************************************************************** | 
|  | * | 
|  | * CopyMac - Copies a MAC address | 
|  | * | 
|  | * Description: | 
|  | *	Nothing further to explain. | 
|  | * | 
|  | * Returns: | 
|  | *	Nothing | 
|  | */ | 
|  | PNMI_STATIC void CopyMac( | 
|  | char *pDst,		/* Pointer to destination buffer */ | 
|  | SK_MAC_ADDR *pMac)	/* Pointer of Source */ | 
|  | { | 
|  | int	i; | 
|  |  | 
|  |  | 
|  | for (i = 0; i < sizeof(SK_MAC_ADDR); i ++) { | 
|  |  | 
|  | *(pDst + i) = pMac->a[i]; | 
|  | } | 
|  | } | 
|  |  | 
|  |  | 
|  | #ifdef SK_POWER_MGMT | 
|  | /***************************************************************************** | 
|  | * | 
|  | * PowerManagement - OID handler function of PowerManagement 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. | 
|  | */ | 
|  |  | 
|  | PNMI_STATIC int PowerManagement( | 
|  | 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 */ | 
|  | { | 
|  |  | 
|  | SK_U32	RetCode = SK_PNMI_ERR_GENERAL; | 
|  |  | 
|  | /* | 
|  | * Check instance. We only handle single instance variables | 
|  | */ | 
|  | if (Instance != (SK_U32)(-1) && Instance != 1) { | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_UNKNOWN_INST); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Perform action | 
|  | */ | 
|  | if (Action == SK_PNMI_GET) { | 
|  |  | 
|  | /* | 
|  | * Check length | 
|  | */ | 
|  | switch (Id) { | 
|  |  | 
|  | case OID_PNP_CAPABILITIES: | 
|  | if (*pLen < sizeof(SK_PNP_CAPABILITIES)) { | 
|  |  | 
|  | *pLen = sizeof(SK_PNP_CAPABILITIES); | 
|  | return (SK_PNMI_ERR_TOO_SHORT); | 
|  | } | 
|  | break; | 
|  |  | 
|  | case OID_PNP_QUERY_POWER: | 
|  | case OID_PNP_ENABLE_WAKE_UP: | 
|  | if (*pLen < sizeof(SK_U32)) { | 
|  |  | 
|  | *pLen = sizeof(SK_U32); | 
|  | return (SK_PNMI_ERR_TOO_SHORT); | 
|  | } | 
|  | break; | 
|  |  | 
|  | case OID_PNP_SET_POWER: | 
|  | case OID_PNP_ADD_WAKE_UP_PATTERN: | 
|  | case OID_PNP_REMOVE_WAKE_UP_PATTERN: | 
|  | break; | 
|  |  | 
|  | default: | 
|  | SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR040, | 
|  | SK_PNMI_ERR040MSG); | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Get value | 
|  | */ | 
|  | switch (Id) { | 
|  |  | 
|  | case OID_PNP_CAPABILITIES: | 
|  | RetCode = SkPowerQueryPnPCapabilities(pAC, IoC, pBuf, pLen); | 
|  | break; | 
|  |  | 
|  | case OID_PNP_QUERY_POWER: | 
|  | /* The Windows DDK describes: An OID_PNP_QUERY_POWER requests | 
|  | the miniport to indicate whether it can transition its NIC | 
|  | to the low-power state. | 
|  | A miniport driver must always return NDIS_STATUS_SUCCESS | 
|  | to a query of OID_PNP_QUERY_POWER. */ | 
|  | RetCode = SK_PNMI_ERR_OK; | 
|  | break; | 
|  |  | 
|  | /* NDIS handles these OIDs as write-only. | 
|  | * So in case of get action the buffer with written length = 0 | 
|  | * is returned | 
|  | */ | 
|  | case OID_PNP_SET_POWER: | 
|  | case OID_PNP_ADD_WAKE_UP_PATTERN: | 
|  | case OID_PNP_REMOVE_WAKE_UP_PATTERN: | 
|  | *pLen = 0; | 
|  | RetCode = SK_PNMI_ERR_OK; | 
|  | break; | 
|  |  | 
|  | case OID_PNP_ENABLE_WAKE_UP: | 
|  | RetCode = SkPowerGetEnableWakeUp(pAC, IoC, pBuf, pLen); | 
|  | break; | 
|  |  | 
|  | default: | 
|  | RetCode = SK_PNMI_ERR_GENERAL; | 
|  | break; | 
|  | } | 
|  |  | 
|  | return (RetCode); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * From here SET or PRESET action. Check if the passed | 
|  | * buffer length is plausible. | 
|  | */ | 
|  | switch (Id) { | 
|  | case OID_PNP_SET_POWER: | 
|  | case OID_PNP_ENABLE_WAKE_UP: | 
|  | if (*pLen < sizeof(SK_U32)) { | 
|  |  | 
|  | *pLen = sizeof(SK_U32); | 
|  | return (SK_PNMI_ERR_TOO_SHORT); | 
|  | } | 
|  | if (*pLen != sizeof(SK_U32)) { | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_BAD_VALUE); | 
|  | } | 
|  | break; | 
|  |  | 
|  | case OID_PNP_ADD_WAKE_UP_PATTERN: | 
|  | case OID_PNP_REMOVE_WAKE_UP_PATTERN: | 
|  | if (*pLen < sizeof(SK_PM_PACKET_PATTERN)) { | 
|  |  | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_BAD_VALUE); | 
|  | } | 
|  | break; | 
|  |  | 
|  | default: | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_READ_ONLY); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Perform preset or set | 
|  | */ | 
|  |  | 
|  | /* POWER module does not support PRESET action */ | 
|  | if (Action == SK_PNMI_PRESET) { | 
|  | return (SK_PNMI_ERR_OK); | 
|  | } | 
|  |  | 
|  | switch (Id) { | 
|  | case OID_PNP_SET_POWER: | 
|  | RetCode = SkPowerSetPower(pAC, IoC, pBuf, pLen); | 
|  | break; | 
|  |  | 
|  | case OID_PNP_ADD_WAKE_UP_PATTERN: | 
|  | RetCode = SkPowerAddWakeUpPattern(pAC, IoC, pBuf, pLen); | 
|  | break; | 
|  |  | 
|  | case OID_PNP_REMOVE_WAKE_UP_PATTERN: | 
|  | RetCode = SkPowerRemoveWakeUpPattern(pAC, IoC, pBuf, pLen); | 
|  | break; | 
|  |  | 
|  | case OID_PNP_ENABLE_WAKE_UP: | 
|  | RetCode = SkPowerSetEnableWakeUp(pAC, IoC, pBuf, pLen); | 
|  | break; | 
|  |  | 
|  | default: | 
|  | RetCode = SK_PNMI_ERR_GENERAL; | 
|  | } | 
|  |  | 
|  | return (RetCode); | 
|  | } | 
|  | #endif /* SK_POWER_MGMT */ | 
|  |  | 
|  |  | 
|  | /***************************************************************************** | 
|  | * | 
|  | * Vct - OID handler function of  OIDs | 
|  | * | 
|  | * Description: | 
|  | *	The code is simple. No description necessary. | 
|  | * | 
|  | * Returns: | 
|  | *	SK_PNMI_ERR_OK           The request was performed successfully. | 
|  | *	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). | 
|  | *	SK_PNMI_ERR_READ_ONLY	 Only the Get action is allowed. | 
|  | * | 
|  | */ | 
|  |  | 
|  | PNMI_STATIC int Vct( | 
|  | 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 the mgmt data will be copied */ | 
|  | unsigned int *pLen,	/* On call: buffer length. On return: used buffer */ | 
|  | SK_U32 Instance,	/* Instance (-1,2..n) that is to be queried */ | 
|  | unsigned int TableIndex, /* Index to the Id table */ | 
|  | SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode always zero */ | 
|  | { | 
|  | SK_GEPORT	*pPrt; | 
|  | SK_PNMI_VCT	*pVctBackupData; | 
|  | SK_U32		LogPortMax; | 
|  | SK_U32		PhysPortMax; | 
|  | SK_U32		PhysPortIndex; | 
|  | SK_U32		Limit; | 
|  | SK_U32		Offset; | 
|  | SK_BOOL		Link; | 
|  | SK_U32		RetCode = SK_PNMI_ERR_GENERAL; | 
|  | int		i; | 
|  | SK_EVPARA	Para; | 
|  | SK_U32		CableLength; | 
|  |  | 
|  | /* | 
|  | * Calculate the port indexes from the instance. | 
|  | */ | 
|  | PhysPortMax = pAC->GIni.GIMacsFound; | 
|  | LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax); | 
|  |  | 
|  | /* Dual net mode? */ | 
|  | if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { | 
|  | LogPortMax--; | 
|  | } | 
|  |  | 
|  | if ((Instance != (SK_U32) (-1))) { | 
|  | /* Check instance range. */ | 
|  | if ((Instance < 2) || (Instance > LogPortMax)) { | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_UNKNOWN_INST); | 
|  | } | 
|  |  | 
|  | if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { | 
|  | PhysPortIndex = NetIndex; | 
|  | } | 
|  | else { | 
|  | PhysPortIndex = Instance - 2; | 
|  | } | 
|  | Limit = PhysPortIndex + 1; | 
|  | } | 
|  | else {	/* | 
|  | * Instance == (SK_U32) (-1), get all Instances of that OID. | 
|  | * | 
|  | * Not implemented yet. May be used in future releases. | 
|  | */ | 
|  | PhysPortIndex = 0; | 
|  | Limit = PhysPortMax; | 
|  | } | 
|  |  | 
|  | pPrt = &pAC->GIni.GP[PhysPortIndex]; | 
|  | if (pPrt->PHWLinkUp) { | 
|  | Link = SK_TRUE; | 
|  | } | 
|  | else { | 
|  | Link = SK_FALSE; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Check MAC type. | 
|  | */ | 
|  | if (pPrt->PhyType != SK_PHY_MARV_COPPER) { | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  | } | 
|  |  | 
|  | /* Initialize backup data pointer. */ | 
|  | pVctBackupData = &pAC->Pnmi.VctBackup[PhysPortIndex]; | 
|  |  | 
|  | /* | 
|  | * Check action type. | 
|  | */ | 
|  | if (Action == SK_PNMI_GET) { | 
|  | /* | 
|  | * Check length. | 
|  | */ | 
|  | switch (Id) { | 
|  |  | 
|  | case OID_SKGE_VCT_GET: | 
|  | if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_PNMI_VCT)) { | 
|  | *pLen = (Limit - PhysPortIndex) * sizeof(SK_PNMI_VCT); | 
|  | return (SK_PNMI_ERR_TOO_SHORT); | 
|  | } | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_VCT_STATUS: | 
|  | if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U8)) { | 
|  | *pLen = (Limit - PhysPortIndex) * sizeof(SK_U8); | 
|  | return (SK_PNMI_ERR_TOO_SHORT); | 
|  | } | 
|  | break; | 
|  |  | 
|  | default: | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Get value. | 
|  | */ | 
|  | Offset = 0; | 
|  | for (; PhysPortIndex < Limit; PhysPortIndex++) { | 
|  | switch (Id) { | 
|  |  | 
|  | case OID_SKGE_VCT_GET: | 
|  | if ((Link == SK_FALSE) && | 
|  | (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING)) { | 
|  | RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_FALSE); | 
|  | if (RetCode == 0) { | 
|  | pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_PENDING; | 
|  | pAC->Pnmi.VctStatus[PhysPortIndex] |= | 
|  | (SK_PNMI_VCT_NEW_VCT_DATA | SK_PNMI_VCT_TEST_DONE); | 
|  |  | 
|  | /* Copy results for later use to PNMI struct. */ | 
|  | for (i = 0; i < 4; i++)  { | 
|  | if (pPrt->PMdiPairSts[i] == SK_PNMI_VCT_NORMAL_CABLE) { | 
|  | if ((pPrt->PMdiPairLen[i] > 35) && (pPrt->PMdiPairLen[i] < 0xff)) { | 
|  | pPrt->PMdiPairSts[i] = SK_PNMI_VCT_IMPEDANCE_MISMATCH; | 
|  | } | 
|  | } | 
|  | if ((pPrt->PMdiPairLen[i] > 35) && (pPrt->PMdiPairLen[i] != 0xff)) { | 
|  | CableLength = 1000 * (((175 * pPrt->PMdiPairLen[i]) / 210) - 28); | 
|  | } | 
|  | else { | 
|  | CableLength = 0; | 
|  | } | 
|  | pVctBackupData->PMdiPairLen[i] = CableLength; | 
|  | pVctBackupData->PMdiPairSts[i] = pPrt->PMdiPairSts[i]; | 
|  | } | 
|  |  | 
|  | Para.Para32[0] = PhysPortIndex; | 
|  | Para.Para32[1] = -1; | 
|  | SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para); | 
|  | SkEventDispatcher(pAC, IoC); | 
|  | } | 
|  | else { | 
|  | ; /* VCT test is running. */ | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Get all results. */ | 
|  | CheckVctStatus(pAC, IoC, pBuf, Offset, PhysPortIndex); | 
|  | Offset += sizeof(SK_U8); | 
|  | *(pBuf + Offset) = pPrt->PCableLen; | 
|  | Offset += sizeof(SK_U8); | 
|  | for (i = 0; i < 4; i++)  { | 
|  | SK_PNMI_STORE_U32((pBuf + Offset), pVctBackupData->PMdiPairLen[i]); | 
|  | Offset += sizeof(SK_U32); | 
|  | } | 
|  | for (i = 0; i < 4; i++)  { | 
|  | *(pBuf + Offset) = pVctBackupData->PMdiPairSts[i]; | 
|  | Offset += sizeof(SK_U8); | 
|  | } | 
|  |  | 
|  | RetCode = SK_PNMI_ERR_OK; | 
|  | break; | 
|  |  | 
|  | case OID_SKGE_VCT_STATUS: | 
|  | CheckVctStatus(pAC, IoC, pBuf, Offset, PhysPortIndex); | 
|  | Offset += sizeof(SK_U8); | 
|  | RetCode = SK_PNMI_ERR_OK; | 
|  | break; | 
|  |  | 
|  | default: | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  | } | 
|  | } /* for */ | 
|  | *pLen = Offset; | 
|  | return (RetCode); | 
|  |  | 
|  | } /* if SK_PNMI_GET */ | 
|  |  | 
|  | /* | 
|  | * From here SET or PRESET action. Check if the passed | 
|  | * buffer length is plausible. | 
|  | */ | 
|  |  | 
|  | /* | 
|  | * Check length. | 
|  | */ | 
|  | switch (Id) { | 
|  | case OID_SKGE_VCT_SET: | 
|  | if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U32)) { | 
|  | *pLen = (Limit - PhysPortIndex) * sizeof(SK_U32); | 
|  | return (SK_PNMI_ERR_TOO_SHORT); | 
|  | } | 
|  | break; | 
|  |  | 
|  | default: | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Perform preset or set. | 
|  | */ | 
|  |  | 
|  | /* VCT does not support PRESET action. */ | 
|  | if (Action == SK_PNMI_PRESET) { | 
|  | return (SK_PNMI_ERR_OK); | 
|  | } | 
|  |  | 
|  | Offset = 0; | 
|  | for (; PhysPortIndex < Limit; PhysPortIndex++) { | 
|  | switch (Id) { | 
|  | case OID_SKGE_VCT_SET: /* Start VCT test. */ | 
|  | if (Link == SK_FALSE) { | 
|  | SkGeStopPort(pAC, IoC, PhysPortIndex, SK_STOP_ALL, SK_SOFT_RST); | 
|  |  | 
|  | RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_TRUE); | 
|  | if (RetCode == 0) { /* RetCode: 0 => Start! */ | 
|  | pAC->Pnmi.VctStatus[PhysPortIndex] |= SK_PNMI_VCT_PENDING; | 
|  | pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_NEW_VCT_DATA; | 
|  | pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_LINK; | 
|  |  | 
|  | /* | 
|  | * Start VCT timer counter. | 
|  | */ | 
|  | SK_MEMSET((char *) &Para, 0, sizeof(Para)); | 
|  | Para.Para32[0] = PhysPortIndex; | 
|  | Para.Para32[1] = -1; | 
|  | SkTimerStart(pAC, IoC, &pAC->Pnmi.VctTimeout[PhysPortIndex].VctTimer, | 
|  | 4000000, SKGE_PNMI, SK_PNMI_EVT_VCT_RESET, Para); | 
|  | SK_PNMI_STORE_U32((pBuf + Offset), RetCode); | 
|  | RetCode = SK_PNMI_ERR_OK; | 
|  | } | 
|  | else { /* RetCode: 2 => Running! */ | 
|  | SK_PNMI_STORE_U32((pBuf + Offset), RetCode); | 
|  | RetCode = SK_PNMI_ERR_OK; | 
|  | } | 
|  | } | 
|  | else { /* RetCode: 4 => Link! */ | 
|  | RetCode = 4; | 
|  | SK_PNMI_STORE_U32((pBuf + Offset), RetCode); | 
|  | RetCode = SK_PNMI_ERR_OK; | 
|  | } | 
|  | Offset += sizeof(SK_U32); | 
|  | break; | 
|  |  | 
|  | default: | 
|  | *pLen = 0; | 
|  | return (SK_PNMI_ERR_GENERAL); | 
|  | } | 
|  | } /* for */ | 
|  | *pLen = Offset; | 
|  | return (RetCode); | 
|  |  | 
|  | } /* Vct */ | 
|  |  | 
|  |  | 
|  | PNMI_STATIC void CheckVctStatus( | 
|  | SK_AC		*pAC, | 
|  | SK_IOC		IoC, | 
|  | char		*pBuf, | 
|  | SK_U32		Offset, | 
|  | SK_U32		PhysPortIndex) | 
|  | { | 
|  | SK_GEPORT	*pPrt; | 
|  | SK_PNMI_VCT	*pVctData; | 
|  | SK_U32		RetCode; | 
|  | SK_U8		LinkSpeedUsed; | 
|  |  | 
|  | pPrt = &pAC->GIni.GP[PhysPortIndex]; | 
|  |  | 
|  | pVctData = (SK_PNMI_VCT *) (pBuf + Offset); | 
|  | pVctData->VctStatus = SK_PNMI_VCT_NONE; | 
|  |  | 
|  | if (!pPrt->PHWLinkUp) { | 
|  |  | 
|  | /* Was a VCT test ever made before? */ | 
|  | if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_TEST_DONE) { | 
|  | if ((pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_LINK)) { | 
|  | pVctData->VctStatus |= SK_PNMI_VCT_OLD_VCT_DATA; | 
|  | } | 
|  | else { | 
|  | pVctData->VctStatus |= SK_PNMI_VCT_NEW_VCT_DATA; | 
|  | } | 
|  | } | 
|  |  | 
|  | /* Check VCT test status. */ | 
|  | RetCode = SkGmCableDiagStatus(pAC,IoC, PhysPortIndex, SK_FALSE); | 
|  | if (RetCode == 2) { /* VCT test is running. */ | 
|  | pVctData->VctStatus |= SK_PNMI_VCT_RUNNING; | 
|  | } | 
|  | else { /* VCT data was copied to pAC here. Check PENDING state. */ | 
|  | if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING) { | 
|  | pVctData->VctStatus |= SK_PNMI_VCT_NEW_VCT_DATA; | 
|  | } | 
|  | } | 
|  |  | 
|  | if (pPrt->PCableLen != 0xff) { /* Old DSP value. */ | 
|  | pVctData->VctStatus |= SK_PNMI_VCT_OLD_DSP_DATA; | 
|  | } | 
|  | } | 
|  | else { | 
|  |  | 
|  | /* Was a VCT test ever made before? */ | 
|  | if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_TEST_DONE) { | 
|  | pVctData->VctStatus &= ~SK_PNMI_VCT_NEW_VCT_DATA; | 
|  | pVctData->VctStatus |= SK_PNMI_VCT_OLD_VCT_DATA; | 
|  | } | 
|  |  | 
|  | /* DSP only valid in 100/1000 modes. */ | 
|  | LinkSpeedUsed = pAC->GIni.GP[PhysPortIndex].PLinkSpeedUsed; | 
|  | if (LinkSpeedUsed != SK_LSPEED_STAT_10MBPS) { | 
|  | pVctData->VctStatus |= SK_PNMI_VCT_NEW_DSP_DATA; | 
|  | } | 
|  | } | 
|  |  | 
|  | } /* CheckVctStatus */ |