1/*****************************************************************************
2 *
3 * Name:	skgepnmi.c
4 * Project:	GEnesis, PCI Gigabit Ethernet Adapter
5 * Version:	$Revision: 1.1.1.1 $
6 * Date:	$Date: 2008/10/15 03:26:44 $
7 * Purpose:	Private Network Management Interface
8 *
9 ****************************************************************************/
10
11/******************************************************************************
12 *
13 *	(C)Copyright 1998-2001 SysKonnect GmbH.
14 *
15 *	This program is free software; you can redistribute it and/or modify
16 *	it under the terms of the GNU General Public License as published by
17 *	the Free Software Foundation; either version 2 of the License, or
18 *	(at your option) any later version.
19 *
20 *	The information in this file is provided "AS IS" without warranty.
21 *
22 ******************************************************************************/
23
24/*****************************************************************************
25 *
26 * History:
27 *
28 *	$Log: skgepnmi.c,v $
29 *	Revision 1.1.1.1  2008/10/15 03:26:44  james26_jang
30 *	Initial.
31 *
32 *	Revision 1.1.1.1  2008/07/21 09:15:07  james26_jang
33 *	New UI, New QoS, New wireless driver(4.151.10.29), ipmonitor.
34 *
35 *	Revision 1.1  2008/07/17 12:42:44  james26_jang
36 *	*** empty log message ***
37 *
38 *	Revision 1.1.1.1  2007/02/15 12:11:35  jiahao
39 *	initial update
40 *
41 *	Revision 1.1.1.1  2007/01/25 12:51:56  jiahao_jhou
42 *
43 *
44 *	Revision 1.1.1.1  2003/02/03 22:37:48  mhuang
45 *	LINUX_2_4 branch snapshot from linux-mips.org CVS
46 *
47 *	Revision 1.87  2001/04/06 13:35:09  mkunz
48 *	-Bugs fixed in handling of OID_SKGE_MTU and the VPD OID's
49 *
50 *	Revision 1.86  2001/03/09 09:18:03  mkunz
51 *	Changes in SK_DBG_MSG
52 *
53 *	Revision 1.85  2001/03/08 09:37:31  mkunz
54 *	Bugfix in ResetCounter for Pnmi.Port structure
55 *
56 *	Revision 1.84  2001/03/06 09:04:55  mkunz
57 *	Made some changes in instance calculation
58 *	C	^VS:
59 *
60 *	Revision 1.83  2001/02/15 09:15:32  mkunz
61 *	Necessary changes for dual net mode added
62 *
63 *	Revision 1.82  2001/02/07 08:24:19  mkunz
64 *	-Made changes in handling of OID_SKGE_MTU
65 *
66 *	Revision 1.81  2001/02/06 09:58:00  mkunz
67 *	-Vpd bug fixed
68 *	-OID_SKGE_MTU added
69 *	-pnmi support for dual net mode. Interface function and macros extended
70 *
71 *	Revision 1.80  2001/01/22 13:41:35  rassmann
72 *	Supporting two nets on dual-port adapters.
73 *
74 *	Revision 1.79  2000/12/05 14:57:40  cgoos
75 *	SetStruct failed before first Link Up (link mode of virtual
76 *	port "INDETERMINATED").
77 *
78 *	Revision 1.78  2000/09/12 10:44:58  cgoos
79 *	Fixed SK_PNMI_STORE_U32 calls with typecasted argument.
80 *
81 *	Revision 1.77  2000/09/07 08:10:19  rwahl
82 *	- Modified algorithm for 64bit NDIS statistic counters;
83 *	  returns 64bit or 32bit value depending on passed buffer
84 *	  size. Indicate capability for 64bit NDIS counter, if passed
85 *	  buffer size is zero. OID_GEN_XMIT_ERROR, OID_GEN_RCV_ERROR,
86 *	  and OID_GEN_RCV_NO_BUFFER handled as 64bit counter, too.
87 *	- corrected OID_SKGE_RLMT_PORT_PREFERRED.
88 *
89 *	Revision 1.76  2000/08/03 15:23:39  rwahl
90 *	- Correction for FrameTooLong counter has to be moved to OID handling
91 *	  routines (instead of statistic counter routine).
92 *	- Fix in XMAC Reset Event handling: Only offset counter for hardware
93 *	  statistic registers are updated.
94 *
95 *	Revision 1.75  2000/08/01 16:46:05  rwahl
96 *	- Added StatRxLongFrames counter and correction of FrameTooLong counter.
97 *	- Added directive to control width (default = 32bit) of NDIS statistic
98 *	  counters (SK_NDIS_64BIT_CTR).
99 *
100 *	Revision 1.74  2000/07/04 11:41:53  rwahl
101 *	- Added volition connector type.
102 *
103 *	Revision 1.73  2000/03/15 16:33:10  rwahl
104 *	Fixed bug 10510; wrong reset of virtual port statistic counters.
105 *
106 *	Revision 1.72  1999/12/06 16:15:53  rwahl
107 *	Fixed problem of instance range for current and factory MAC address.
108 *
109 *	Revision 1.71  1999/12/06 10:14:20  rwahl
110 *	Fixed bug 10476; set operation for PHY_OPERATION_MODE.
111 *
112 *	Revision 1.70  1999/11/22 13:33:34  cgoos
113 *	Changed license header to GPL.
114 *
115 *	Revision 1.69  1999/10/18 11:42:15  rwahl
116 *	Added typecasts for checking event dependent param (debug only).
117 *
118 *	Revision 1.68  1999/10/06 09:35:59  cgoos
119 *	Added state check to PHY_READ call (hanged if called during startup).
120 *
121 *	Revision 1.67  1999/09/22 09:53:20  rwahl
122 *	- Read Broadcom register for updating fcs error counter (1000Base-T).
123 *
124 *	Revision 1.66  1999/08/26 13:47:56  rwahl
125 *	Added SK_DRIVER_SENDEVENT when queueing RLMT_CHANGE_THRES trap.
126 *
127 *	Revision 1.65  1999/07/26 07:49:35  cgoos
128 *	Added two typecasts to avoid compiler warnings.
129 *
130 *	Revision 1.64  1999/05/20 09:24:12  cgoos
131 *	Changes for 1000Base-T (sensors, Master/Slave).
132 *
133 *	Revision 1.63  1999/04/13 15:11:58  mhaveman
134 *	Moved include of rlmt.h to header skgepnmi.h because some macros
135 *	are needed there.
136 *
137 *	Revision 1.62  1999/04/13 15:08:07  mhaveman
138 *	Replaced again SK_RLMT_CHECK_LINK with SK_PNMI_RLMT_MODE_CHK_LINK
139 *	to grant unified interface by only using the PNMI header file.
140 *	SK_PNMI_RLMT_MODE_CHK_LINK is defined the same as SK_RLMT_CHECK_LINK.
141 *
142 *	Revision 1.61  1999/04/13 15:02:48  mhaveman
143 *	Changes caused by review:
144 *	-Changed some comments
145 *	-Removed redundant check for OID_SKGE_PHYS_FAC_ADDR
146 *	-Optimized PRESET check.
147 *	-Meaning of error SK_ADDR_DUPLICATE_ADDRESS changed. Set of same
148 *	 address will now not cause this error. Removed corresponding check.
149 *
150 *	Revision 1.60  1999/03/23 10:41:23  mhaveman
151 *	Added comments.
152 *
153 *	Revision 1.59  1999/02/19 08:01:28  mhaveman
154 *	Fixed bug 10372 that after counter reset all ports were displayed
155 *	as inactive.
156 *
157 *	Revision 1.58  1999/02/16 18:04:47  mhaveman
158 *	Fixed problem of twisted OIDs SENSOR_WAR_TIME and SENSOR_ERR_TIME.
159 *
160 *	Revision 1.56  1999/01/27 12:29:11  mhaveman
161 *	SkTimerStart was called with time value in milli seconds but needs
162 *	micro seconds.
163 *
164 *	Revision 1.55  1999/01/25 15:00:38  mhaveman
165 *	Added support to allow multiple ports to be active. If this feature in
166 *	future will be used, the Management Data Base variables PORT_ACTIVE
167 *	and PORT_PREFERED should be moved to the port specific part of RLMT.
168 *	Currently they return the values of the first active physical port
169 *	found. A set to the virtual port will actually change all active
170 *	physical ports. A get returns the melted values of all active physical
171 *	ports. If the port values differ a return value INDETERMINATED will
172 *	be returned. This effects especially the CONF group.
173 *
174 *	Revision 1.54  1999/01/19 10:10:22  mhaveman
175 *	-Fixed bug 10354: Counter values of virtual port were wrong after port
176 *	 switches
177 *	-Added check if a switch to the same port is notified.
178 *
179 *	Revision 1.53  1999/01/07 09:25:21  mhaveman
180 *	Forgot to initialize a variable.
181 *
182 *	Revision 1.52  1999/01/05 10:34:33  mhaveman
183 *	Fixed little error in RlmtChangeEstimate calculation.
184 *
185 *	Revision 1.51  1999/01/05 09:59:07  mhaveman
186 *	-Moved timer start to init level 2
187 *	-Redesigned port switch average calculation to avoid 64bit
188 *	 arithmetic.
189 *
190 *	Revision 1.50  1998/12/10 15:13:59  mhaveman
191 *	-Fixed: PHYS_CUR_ADDR returned wrong addresses
192 *	-Fixed: RLMT_PORT_PREFERED and RLMT_CHANGE_THRES preset returned
193 *	        always BAD_VALUE.
194 *	-Fixed: TRAP buffer seemed to sometimes suddenly empty
195 *
196 *	Revision 1.49  1998/12/09 16:17:07  mhaveman
197 *	Fixed: Couldnot delete VPD keys on UNIX.
198 *
199 *	Revision 1.48  1998/12/09 14:11:10  mhaveman
200 *	-Add: Debugmessage for XMAC_RESET supressed to minimize output.
201 *	-Fixed: RlmtChangeThreshold will now be initialized.
202 *	-Fixed: VPD_ENTRIES_LIST extended value with unnecessary space char.
203 *	-Fixed: On VPD key creation an invalid key name could be created
204 *	        (e.g. A5)
205 *	-Some minor changes in comments and code.
206 *
207 *	Revision 1.47  1998/12/08 16:00:31  mhaveman
208 *	-Fixed: For RLMT_PORT_ACTIVE will now be returned a 0 if no port
209 *		is active.
210 *	-Fixed: For the RLMT statistics group only the last value was
211 *		returned and the rest of the buffer was filled with 0xff
212 *	-Fixed: Mysteriously the preset on RLMT_MODE still returned
213 *		BAD_VALUE.
214 *	Revision 1.46  1998/12/08 10:04:56  mhaveman
215 *	-Fixed: Preset on RLMT_MODE returned always BAD_VALUE error.
216 *	-Fixed: Alignment error in GetStruct
217 *	-Fixed: If for Get/Preset/SetStruct the buffer size is equal or
218 *	        larger than SK_PNMI_MIN_STRUCT_SIZE the return value is stored
219 *		to the buffer. In this case the caller should always return
220 *	        ok to its upper routines. Only if the buffer size is less
221 *	        than SK_PNMI_MIN_STRUCT_SIZE and the return value is unequal
222 *	        to 0, an error should be returned by the caller.
223 *	-Fixed: Wrong number of instances with RLMT statistic.
224 *	-Fixed: Return now SK_LMODE_STAT_UNKNOWN if the LinkModeStatus is 0.
225 *
226 *	Revision 1.45  1998/12/03 17:17:24  mhaveman
227 *	-Removed for VPD create action the buffer size limitation to 4 bytes.
228 *	-Pass now physical/active physical port to ADDR for CUR_ADDR set
229 *
230 *	Revision 1.44  1998/12/03 15:14:35  mhaveman
231 *	Another change to Vpd instance evaluation.
232 *
233 *	Revision 1.43  1998/12/03 14:18:10  mhaveman
234 *	-Fixed problem in PnmiSetStruct. It was impossible to set any value.
235 *	-Removed VPD key evaluation for VPD_FREE_BYTES and VPD_ACTION.
236 *
237 *	Revision 1.42  1998/12/03 11:31:47  mhaveman
238 *	Inserted cast to satisfy lint.
239 *
240 *	Revision 1.41  1998/12/03 11:28:16  mhaveman
241 *	Removed SK_PNMI_CHECKPTR
242 *
243 *	Revision 1.40  1998/12/03 11:19:07  mhaveman
244 *	Fixed problems
245 *	-A set to virtual port will now be ignored. A set with broadcast
246 *	 address to any port will be ignored.
247 *	-GetStruct function made VPD instance calculation wrong.
248 *	-Prefered port returned -1 instead of 0.
249 *
250 *	Revision 1.39  1998/11/26 15:30:29  mhaveman
251 *	Added sense mode to link mode.
252 *
253 *	Revision 1.38  1998/11/23 15:34:00  mhaveman
254 *	-Fixed bug for RX counters. On an RX overflow interrupt the high
255 *	 words of all RX counters were incremented.
256 *	-SET operations on FLOWCTRL_MODE and LINK_MODE accept now the
257 *	 value 0, which has no effect. It is usefull for multiple instance
258 *	 SETs.
259 *
260 *	Revision 1.37  1998/11/20 08:02:04  mhaveman
261 *	-Fixed: Ports were compared with MAX_SENSORS
262 *	-Fixed: Crash in GetTrapEntry with MEMSET macro
263 *	-Fixed: Conversions between physical, logical port index and instance
264 *
265 *	Revision 1.36  1998/11/16 07:48:53  mhaveman
266 *	Casted SK_DRIVER_SENDEVENT with (void) to eleminate compiler warnings
267 *	on Solaris.
268 *
269 *	Revision 1.35  1998/11/16 07:45:34  mhaveman
270 *	SkAddrOverride now returns value and will be checked.
271 *
272 *	Revision 1.34  1998/11/10 13:40:37  mhaveman
273 *	Needed to change interface, because NT driver needs a return value
274 *	of needed buffer space on TOO_SHORT errors. Therefore all
275 *	SkPnmiGet/Preset/Set functions now have a pointer to the length
276 *	parameter, where the needed space on error is returned.
277 *
278 *	Revision 1.33  1998/11/03 13:52:46  mhaveman
279 *	Made file lint conform.
280 *
281 *	Revision 1.32  1998/11/03 13:19:07  mhaveman
282 *	The events SK_HWEV_SET_LMODE and SK_HWEV_SET_FLOWMODE pass now in
283 *	Para32[0] the physical MAC index and in Para32[1] the new mode.
284 *
285 *	Revision 1.31  1998/11/03 12:30:40  gklug
286 *	fix: compiler warning memset
287 *
288 *	Revision 1.30  1998/11/03 12:04:46  mhaveman
289 *	Fixed problem in SENSOR_VALUE, which wrote beyond the buffer end
290 *	Fixed alignment problem with CHIPSET.
291 *
292 *	Revision 1.29  1998/11/02 11:23:54  mhaveman
293 *	Corrected SK_ERROR_LOG to SK_ERR_LOG. Sorry.
294 *
295 *	Revision 1.28  1998/11/02 10:47:16  mhaveman
296 *	Added syslog messages for internal errors.
297 *
298 *	Revision 1.27  1998/10/30 15:48:06  mhaveman
299 *	Fixed problems after simulation of SK_PNMI_EVT_CHG_EST_TIMER and
300 *	RlmtChangeThreshold calculation.
301 *
302 *	Revision 1.26  1998/10/29 15:36:55  mhaveman
303 *	-Fixed bug in trap buffer handling.
304 *	-OID_SKGE_DRIVER_DESCR, OID_SKGE_DRIVER_VERSION, OID_SKGE_HW_DESCR,
305 *	 OID_SKGE_HW_VERSION, OID_SKGE_VPD_ENTRIES_LIST, OID_SKGE_VPD_KEY,
306 *	 OID_SKGE_VPD_VALUE, and OID_SKGE_SENSOR_DESCR return values with
307 *	 a leading octet before each string storing the string length.
308 *	-Perform a RlmtUpdate during SK_PNMI_EVT_XMAC_RESET to minimize
309 *	 RlmtUpdate calls in GetStatVal.
310 *	-Inserted SK_PNMI_CHECKFLAGS macro increase readability.
311 *
312 *	Revision 1.25  1998/10/29 08:50:36  mhaveman
313 *	Fixed problems after second event simulation.
314 *
315 *	Revision 1.24  1998/10/28 08:44:37  mhaveman
316 *	-Fixed alignment problem
317 *	-Fixed problems during event simulation
318 *	-Fixed sequence of error return code (INSTANCE -> ACCESS -> SHORT)
319 *	-Changed type of parameter Instance back to SK_U32 because of VPD
320 *	-Updated new VPD function calls
321 *
322 *	Revision 1.23  1998/10/23 10:16:37  mhaveman
323 *	Fixed bugs after buffer test simulation.
324 *
325 *	Revision 1.22  1998/10/21 13:23:52  mhaveman
326 *	-Call syntax of SkOsGetTime() changed to SkOsGetTime(pAc).
327 *	-Changed calculation of hundrets of seconds.
328 *
329 *	Revision 1.20  1998/10/20 07:30:45  mhaveman
330 *	Made type changes to unsigned integer where possible.
331 *
332 *	Revision 1.19  1998/10/19 10:51:30  mhaveman
333 *	-Made Bug fixes after simulation run
334 *	-Renamed RlmtMAC... to RlmtPort...
335 *	-Marked workarounds with Errata comments
336 *
337 *	Revision 1.18  1998/10/14 07:50:08  mhaveman
338 *	-For OID_SKGE_LINK_STATUS the link down detection has moved from RLMT
339 *	 to HWACCESS.
340 *	-Provided all MEMCPY/MEMSET macros with (char *) pointers, because
341 *	 Solaris throwed warnings when mapping to bcopy/bset.
342 *
343 *	Revision 1.17  1998/10/13 07:42:01  mhaveman
344 *	-Added OIDs OID_SKGE_TRAP_NUMBER and OID_SKGE_ALL_DATA
345 *	-Removed old cvs history entries
346 *	-Renamed MacNumber to PortNumber
347 *
348 *	Revision 1.16  1998/10/07 10:52:49  mhaveman
349 *	-Inserted handling of some OID_GEN_ Ids for windows
350 *	-Fixed problem with 803.2 statistic.
351 *
352 *	Revision 1.15  1998/10/01 09:16:29  mhaveman
353 *	Added Debug messages for function call and UpdateFlag tracing.
354 *
355 *	Revision 1.14  1998/09/30 13:39:09  mhaveman
356 *	-Reduced namings of 'MAC' by replacing them with 'PORT'.
357 *	-Completed counting of OID_SKGE_RX_HW_ERROR_CTS,
358 *       OID_SKGE_TX_HW_ERROR_CTS,
359 *	 OID_SKGE_IN_ERRORS_CTS, and OID_SKGE_OUT_ERROR_CTS.
360 *	-SET check for RlmtMode
361 *
362 *	Revision 1.13  1998/09/28 13:13:08  mhaveman
363 *	Hide strcmp, strlen, and strncpy behind macros SK_STRCMP, SK_STRLEN,
364 *	and SK_STRNCPY. (Same reasons as for mem.. and MEM..)
365 *
366 *	Revision 1.12  1998/09/16 08:18:36  cgoos
367 *	Fix: XM_INxx and XM_OUTxx called with different parameter order:
368 *      sometimes IoC,Mac,...  sometimes Mac,IoC,... Now always first variant.
369 *	Fix: inserted "Pnmi." into some pAC->pDriverDescription / Version.
370 *	Change: memset, memcpy to makros SK_MEMSET, SK_MEMCPY
371 *
372 *	Revision 1.11  1998/09/04 17:01:45  mhaveman
373 *	Added SyncCounter as macro and OID_SKGE_.._NO_DESCR_CTS to
374 *	OID_SKGE_RX_NO_BUF_CTS.
375 *
376 *	Revision 1.10  1998/09/04 14:35:35  mhaveman
377 *	Added macro counters, that are counted by driver.
378 *
379 ****************************************************************************/
380
381
382static const char SysKonnectFileId[] =
383	"@(#) $Id: skgepnmi.c,v 1.1.1.1 2008/10/15 03:26:44 james26_jang Exp $"
384	" (C) SysKonnect.";
385
386#include "h/skdrv1st.h"
387#include "h/sktypes.h"
388#include "h/xmac_ii.h"
389
390#include "h/skdebug.h"
391#include "h/skqueue.h"
392#include "h/skgepnmi.h"
393#include "h/skgesirq.h"
394#include "h/skcsum.h"
395#include "h/skvpd.h"
396#include "h/skgehw.h"
397#include "h/skgeinit.h"
398#include "h/skdrv2nd.h"
399#include "h/skgepnm2.h"
400
401
402/*
403 * Public Function prototypes
404 */
405int SkPnmiInit(SK_AC *pAC, SK_IOC IoC, int level);
406int SkPnmiGetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, void *pBuf,
407	unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex);
408int SkPnmiPreSetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, void *pBuf,
409	unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex);
410int SkPnmiSetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, void *pBuf,
411	unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex);
412int SkPnmiGetStruct(SK_AC *pAC, SK_IOC IoC, void *pBuf,
413	unsigned int *pLen, SK_U32 NetIndex);
414int SkPnmiPreSetStruct(SK_AC *pAC, SK_IOC IoC, void *pBuf,
415	unsigned int *pLen, SK_U32 NetIndex);
416int SkPnmiSetStruct(SK_AC *pAC, SK_IOC IoC, void *pBuf,
417	unsigned int *pLen, SK_U32 NetIndex);
418int SkPnmiEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event, SK_EVPARA Param);
419
420
421/*
422 * Private Function prototypes
423 */
424static int Addr(SK_AC *pAC, SK_IOC IoC, int action,
425	SK_U32 Id, char *pBuf, unsigned int *pLen, SK_U32 Instance,
426	unsigned int TableIndex, SK_U32 NetIndex);
427static SK_U8 CalculateLinkModeStatus(SK_AC *pAC, SK_IOC IoC, unsigned int
428	PhysPortIndex);
429static SK_U8 CalculateLinkStatus(SK_AC *pAC, SK_IOC IoC, unsigned int
430	PhysPortIndex);
431static void CopyMac(char *pDst, SK_MAC_ADDR *pMac);
432static void CopyTrapQueue(SK_AC *pAC, char *pDstBuf);
433static int CsumStat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
434	char *pBuf, unsigned int *pLen, SK_U32 Instance,
435	unsigned int TableIndex, SK_U32 NetIndex);
436static int General(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
437	char *pBuf, unsigned int *pLen, SK_U32 Instance,
438	unsigned int TableIndex, SK_U32 NetIndex);
439static SK_U64 GetPhysStatVal(SK_AC *pAC, SK_IOC IoC,
440	unsigned int PhysPortIndex, unsigned int StatIndex);
441static SK_U64 GetStatVal(SK_AC *pAC, SK_IOC IoC, unsigned int LogPortIndex,
442	unsigned int StatIndex, SK_U32 NetIndex);
443static char* GetTrapEntry(SK_AC *pAC, SK_U32 TrapId, unsigned int Size);
444static void GetTrapQueueLen(SK_AC *pAC, unsigned int *pLen,
445	unsigned int *pEntries);
446static int GetVpdKeyArr(SK_AC *pAC, SK_IOC IoC, char *pKeyArr,
447	unsigned int KeyArrLen, unsigned int *pKeyNo);
448static int LookupId(SK_U32 Id);
449static int Mac8023Stat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
450	char *pBuf, unsigned int *pLen, SK_U32 Instance,
451	unsigned int TableIndex, SK_U32 NetIndex);
452static int MacPrivateConf(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
453	char *pBuf, unsigned int *pLen, SK_U32 Instance,
454	unsigned int TableIndex, SK_U32 NetIndex);
455static int MacPrivateStat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
456	char *pBuf, unsigned int *pLen, SK_U32 Instance,
457	unsigned int TableIndex, SK_U32 NetIndex);
458static int MacUpdate(SK_AC *pAC, SK_IOC IoC, unsigned int FirstMac,
459	unsigned int LastMac);
460static int Monitor(SK_AC *pAC, SK_IOC IoC, int action,
461	SK_U32 Id, char *pBuf, unsigned int *pLen, SK_U32 Instance,
462	unsigned int TableIndex, SK_U32 NetIndex);
463static int OidStruct(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
464	char *pBuf, unsigned int *pLen, SK_U32 Instance,
465	unsigned int TableIndex, SK_U32 NetIndex);
466static int Perform(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
467	char *pBuf, unsigned int* pLen, SK_U32 Instance,
468	unsigned int TableIndex, SK_U32 NetIndex);
469static int PnmiStruct(SK_AC *pAC, SK_IOC IoC, int Action, char *pBuf,
470	unsigned int *pLen, SK_U32 NetIndex);
471static int PnmiVar(SK_AC *pAC, SK_IOC IoC, int Action, SK_U32 Id,
472	char *pBuf, unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex);
473static void QueueRlmtNewMacTrap(SK_AC *pAC, unsigned int ActiveMac);
474static void QueueRlmtPortTrap(SK_AC *pAC, SK_U32 TrapId,
475	unsigned int PortIndex);
476static void QueueSensorTrap(SK_AC *pAC, SK_U32 TrapId,
477	unsigned int SensorIndex);
478static void QueueSimpleTrap(SK_AC *pAC, SK_U32 TrapId);
479static void ResetCounter(SK_AC *pAC, SK_IOC IoC, SK_U32 NetIndex);
480static int Rlmt(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
481	char *pBuf, unsigned int *pLen, SK_U32 Instance,
482	unsigned int TableIndex, SK_U32 NetIndex);
483static int RlmtStat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
484	char *pBuf, unsigned int *pLen, SK_U32 Instance,
485	unsigned int TableIndex, SK_U32 NetIndex);
486static int RlmtUpdate(SK_AC *pAC, SK_IOC IoC, SK_U32 NetIndex);
487static int SensorStat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
488	char *pBuf, unsigned int *pLen, SK_U32 Instance,
489	unsigned int TableIndex, SK_U32 NetIndex);
490static int SirqUpdate(SK_AC *pAC, SK_IOC IoC);
491static void VirtualConf(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, char *pBuf);
492static int Vpd(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id,
493	char *pBuf, unsigned int *pLen, SK_U32 Instance,
494	unsigned int TableIndex, SK_U32 NetIndex);
495
496
497/******************************************************************************
498 *
499 * Global variables
500 */
501
502/*
503 * Table to correlate OID with handler function and index to
504 * hardware register stored in StatAddress if applicable.
505 */
506static const SK_PNMI_TAB_ENTRY IdTable[] = {
507	{OID_GEN_XMIT_OK,
508		0,
509		0,
510		0,
511		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX},
512	{OID_GEN_RCV_OK,
513		0,
514		0,
515		0,
516		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX},
517	{OID_GEN_XMIT_ERROR,
518		0,
519		0,
520		0,
521		SK_PNMI_RO, General, 0},
522	{OID_GEN_RCV_ERROR,
523		0,
524		0,
525		0,
526		SK_PNMI_RO, General, 0},
527	{OID_GEN_RCV_NO_BUFFER,
528		0,
529		0,
530		0,
531		SK_PNMI_RO, General, 0},
532	{OID_GEN_DIRECTED_FRAMES_XMIT,
533		0,
534		0,
535		0,
536		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_UNICAST},
537	{OID_GEN_MULTICAST_FRAMES_XMIT,
538		0,
539		0,
540		0,
541		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_MULTICAST},
542	{OID_GEN_BROADCAST_FRAMES_XMIT,
543		0,
544		0,
545		0,
546		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_BROADCAST},
547	{OID_GEN_DIRECTED_FRAMES_RCV,
548		0,
549		0,
550		0,
551		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_UNICAST},
552	{OID_GEN_MULTICAST_FRAMES_RCV,
553		0,
554		0,
555		0,
556		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_MULTICAST},
557	{OID_GEN_BROADCAST_FRAMES_RCV,
558		0,
559		0,
560		0,
561		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_BROADCAST},
562	{OID_GEN_RCV_CRC_ERROR,
563		0,
564		0,
565		0,
566		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_FCS},
567	{OID_GEN_TRANSMIT_QUEUE_LENGTH,
568		0,
569		0,
570		0,
571		SK_PNMI_RO, General, 0},
572	{OID_802_3_PERMANENT_ADDRESS,
573		0,
574		0,
575		0,
576		SK_PNMI_RO, Mac8023Stat, 0},
577	{OID_802_3_CURRENT_ADDRESS,
578		0,
579		0,
580		0,
581		SK_PNMI_RO, Mac8023Stat, 0},
582	{OID_802_3_RCV_ERROR_ALIGNMENT,
583		0,
584		0,
585		0,
586		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_FRAMING},
587	{OID_802_3_XMIT_ONE_COLLISION,
588		0,
589		0,
590		0,
591		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_SINGLE_COL},
592	{OID_802_3_XMIT_MORE_COLLISIONS,
593		0,
594		0,
595		0,
596		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_MULTI_COL},
597	{OID_802_3_XMIT_DEFERRED,
598		0,
599		0,
600		0,
601		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_DEFFERAL},
602	{OID_802_3_XMIT_MAX_COLLISIONS,
603		0,
604		0,
605		0,
606		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_EXCESS_COL},
607	{OID_802_3_RCV_OVERRUN,
608		0,
609		0,
610		0,
611		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_OVERFLOW},
612	{OID_802_3_XMIT_UNDERRUN,
613		0,
614		0,
615		0,
616		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_UNDERRUN},
617	{OID_802_3_XMIT_TIMES_CRS_LOST,
618		0,
619		0,
620		0,
621		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_CARRIER},
622	{OID_802_3_XMIT_LATE_COLLISIONS,
623		0,
624		0,
625		0,
626		SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_LATE_COL},
627	{OID_SKGE_MDB_VERSION,
628		1,
629		0,
630		SK_PNMI_MAI_OFF(MgmtDBVersion),
631		SK_PNMI_RO, General, 0},
632	{OID_SKGE_SUPPORTED_LIST,
633		0,
634		0,
635		0,
636		SK_PNMI_RO, General, 0},
637	{OID_SKGE_ALL_DATA,
638		0,
639		0,
640		0,
641		SK_PNMI_RW, OidStruct, 0},
642	{OID_SKGE_VPD_FREE_BYTES,
643		1,
644		0,
645		SK_PNMI_MAI_OFF(VpdFreeBytes),
646		SK_PNMI_RO, Vpd, 0},
647	{OID_SKGE_VPD_ENTRIES_LIST,
648		1,
649		0,
650		SK_PNMI_MAI_OFF(VpdEntriesList),
651		SK_PNMI_RO, Vpd, 0},
652	{OID_SKGE_VPD_ENTRIES_NUMBER,
653		1,
654		0,
655		SK_PNMI_MAI_OFF(VpdEntriesNumber),
656		SK_PNMI_RO, Vpd, 0},
657	{OID_SKGE_VPD_KEY,
658		SK_PNMI_VPD_ENTRIES,
659		sizeof(SK_PNMI_VPD),
660		SK_PNMI_OFF(Vpd) + SK_PNMI_VPD_OFF(VpdKey),
661		SK_PNMI_RO, Vpd, 0},
662	{OID_SKGE_VPD_VALUE,
663		SK_PNMI_VPD_ENTRIES,
664		sizeof(SK_PNMI_VPD),
665		SK_PNMI_OFF(Vpd) + SK_PNMI_VPD_OFF(VpdValue),
666		SK_PNMI_RO, Vpd, 0},
667	{OID_SKGE_VPD_ACCESS,
668		SK_PNMI_VPD_ENTRIES,
669		sizeof(SK_PNMI_VPD),
670		SK_PNMI_OFF(Vpd) + SK_PNMI_VPD_OFF(VpdAccess),
671		SK_PNMI_RO, Vpd, 0},
672	{OID_SKGE_VPD_ACTION,
673		SK_PNMI_VPD_ENTRIES,
674		sizeof(SK_PNMI_VPD),
675		SK_PNMI_OFF(Vpd) + SK_PNMI_VPD_OFF(VpdAction),
676		SK_PNMI_RW, Vpd, 0},
677	{OID_SKGE_PORT_NUMBER,
678		1,
679		0,
680		SK_PNMI_MAI_OFF(PortNumber),
681		SK_PNMI_RO, General, 0},
682	{OID_SKGE_DEVICE_TYPE,
683		1,
684		0,
685		SK_PNMI_MAI_OFF(DeviceType),
686		SK_PNMI_RO, General, 0},
687	{OID_SKGE_DRIVER_DESCR,
688		1,
689		0,
690		SK_PNMI_MAI_OFF(DriverDescr),
691		SK_PNMI_RO, General, 0},
692	{OID_SKGE_DRIVER_VERSION,
693		1,
694		0,
695		SK_PNMI_MAI_OFF(DriverVersion),
696		SK_PNMI_RO, General, 0},
697	{OID_SKGE_HW_DESCR,
698		1,
699		0,
700		SK_PNMI_MAI_OFF(HwDescr),
701		SK_PNMI_RO, General, 0},
702	{OID_SKGE_HW_VERSION,
703		1,
704		0,
705		SK_PNMI_MAI_OFF(HwVersion),
706		SK_PNMI_RO, General, 0},
707	{OID_SKGE_CHIPSET,
708		1,
709		0,
710		SK_PNMI_MAI_OFF(Chipset),
711		SK_PNMI_RO, General, 0},
712	{OID_SKGE_ACTION,
713		1,
714		0,
715		SK_PNMI_MAI_OFF(Action),
716		SK_PNMI_RW, Perform, 0},
717	{OID_SKGE_RESULT,
718		1,
719		0,
720		SK_PNMI_MAI_OFF(TestResult),
721		SK_PNMI_RO, General, 0},
722	{OID_SKGE_BUS_TYPE,
723		1,
724		0,
725		SK_PNMI_MAI_OFF(BusType),
726		SK_PNMI_RO, General, 0},
727	{OID_SKGE_BUS_SPEED,
728		1,
729		0,
730		SK_PNMI_MAI_OFF(BusSpeed),
731		SK_PNMI_RO, General, 0},
732	{OID_SKGE_BUS_WIDTH,
733		1,
734		0,
735		SK_PNMI_MAI_OFF(BusWidth),
736		SK_PNMI_RO, General, 0},
737	{OID_SKGE_TX_SW_QUEUE_LEN,
738		1,
739		0,
740		SK_PNMI_MAI_OFF(TxSwQueueLen),
741		SK_PNMI_RO, General, 0},
742	{OID_SKGE_TX_SW_QUEUE_MAX,
743		1,
744		0,
745		SK_PNMI_MAI_OFF(TxSwQueueMax),
746		SK_PNMI_RO, General, 0},
747	{OID_SKGE_TX_RETRY,
748		1,
749		0,
750		SK_PNMI_MAI_OFF(TxRetryCts),
751		SK_PNMI_RO, General, 0},
752	{OID_SKGE_RX_INTR_CTS,
753		1,
754		0,
755		SK_PNMI_MAI_OFF(RxIntrCts),
756		SK_PNMI_RO, General, 0},
757	{OID_SKGE_TX_INTR_CTS,
758		1,
759		0,
760		SK_PNMI_MAI_OFF(TxIntrCts),
761		SK_PNMI_RO, General, 0},
762	{OID_SKGE_RX_NO_BUF_CTS,
763		1,
764		0,
765		SK_PNMI_MAI_OFF(RxNoBufCts),
766		SK_PNMI_RO, General, 0},
767	{OID_SKGE_TX_NO_BUF_CTS,
768		1,
769		0,
770		SK_PNMI_MAI_OFF(TxNoBufCts),
771		SK_PNMI_RO, General, 0},
772	{OID_SKGE_TX_USED_DESCR_NO,
773		1,
774		0,
775		SK_PNMI_MAI_OFF(TxUsedDescrNo),
776		SK_PNMI_RO, General, 0},
777	{OID_SKGE_RX_DELIVERED_CTS,
778		1,
779		0,
780		SK_PNMI_MAI_OFF(RxDeliveredCts),
781		SK_PNMI_RO, General, 0},
782	{OID_SKGE_RX_OCTETS_DELIV_CTS,
783		1,
784		0,
785		SK_PNMI_MAI_OFF(RxOctetsDeliveredCts),
786		SK_PNMI_RO, General, 0},
787	{OID_SKGE_RX_HW_ERROR_CTS,
788		1,
789		0,
790		SK_PNMI_MAI_OFF(RxHwErrorsCts),
791		SK_PNMI_RO, General, 0},
792	{OID_SKGE_TX_HW_ERROR_CTS,
793		1,
794		0,
795		SK_PNMI_MAI_OFF(TxHwErrorsCts),
796		SK_PNMI_RO, General, 0},
797	{OID_SKGE_IN_ERRORS_CTS,
798		1,
799		0,
800		SK_PNMI_MAI_OFF(InErrorsCts),
801		SK_PNMI_RO, General, 0},
802	{OID_SKGE_OUT_ERROR_CTS,
803		1,
804		0,
805		SK_PNMI_MAI_OFF(OutErrorsCts),
806		SK_PNMI_RO, General, 0},
807	{OID_SKGE_ERR_RECOVERY_CTS,
808		1,
809		0,
810		SK_PNMI_MAI_OFF(ErrRecoveryCts),
811		SK_PNMI_RO, General, 0},
812	{OID_SKGE_SYSUPTIME,
813		1,
814		0,
815		SK_PNMI_MAI_OFF(SysUpTime),
816		SK_PNMI_RO, General, 0},
817	{OID_SKGE_SENSOR_NUMBER,
818		1,
819		0,
820		SK_PNMI_MAI_OFF(SensorNumber),
821		SK_PNMI_RO, General, 0},
822	{OID_SKGE_SENSOR_INDEX,
823		SK_PNMI_SENSOR_ENTRIES,
824		sizeof(SK_PNMI_SENSOR),
825		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorIndex),
826		SK_PNMI_RO, SensorStat, 0},
827	{OID_SKGE_SENSOR_DESCR,
828		SK_PNMI_SENSOR_ENTRIES,
829		sizeof(SK_PNMI_SENSOR),
830		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorDescr),
831		SK_PNMI_RO, SensorStat, 0},
832	{OID_SKGE_SENSOR_TYPE,
833		SK_PNMI_SENSOR_ENTRIES,
834		sizeof(SK_PNMI_SENSOR),
835		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorType),
836		SK_PNMI_RO, SensorStat, 0},
837	{OID_SKGE_SENSOR_VALUE,
838		SK_PNMI_SENSOR_ENTRIES,
839		sizeof(SK_PNMI_SENSOR),
840		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorValue),
841		SK_PNMI_RO, SensorStat, 0},
842	{OID_SKGE_SENSOR_WAR_THRES_LOW,
843		SK_PNMI_SENSOR_ENTRIES,
844		sizeof(SK_PNMI_SENSOR),
845		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorWarningThresholdLow),
846		SK_PNMI_RO, SensorStat, 0},
847	{OID_SKGE_SENSOR_WAR_THRES_UPP,
848		SK_PNMI_SENSOR_ENTRIES,
849		sizeof(SK_PNMI_SENSOR),
850		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorWarningThresholdHigh),
851		SK_PNMI_RO, SensorStat, 0},
852	{OID_SKGE_SENSOR_ERR_THRES_LOW,
853		SK_PNMI_SENSOR_ENTRIES,
854		sizeof(SK_PNMI_SENSOR),
855		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorErrorThresholdLow),
856		SK_PNMI_RO, SensorStat, 0},
857	{OID_SKGE_SENSOR_ERR_THRES_UPP,
858		SK_PNMI_SENSOR_ENTRIES,
859		sizeof(SK_PNMI_SENSOR),
860		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorErrorThresholdHigh),
861		SK_PNMI_RO, SensorStat, 0},
862	{OID_SKGE_SENSOR_STATUS,
863		SK_PNMI_SENSOR_ENTRIES,
864		sizeof(SK_PNMI_SENSOR),
865		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorStatus),
866		SK_PNMI_RO, SensorStat, 0},
867	{OID_SKGE_SENSOR_WAR_CTS,
868		SK_PNMI_SENSOR_ENTRIES,
869		sizeof(SK_PNMI_SENSOR),
870		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorWarningCts),
871		SK_PNMI_RO, SensorStat, 0},
872	{OID_SKGE_SENSOR_ERR_CTS,
873		SK_PNMI_SENSOR_ENTRIES,
874		sizeof(SK_PNMI_SENSOR),
875		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorErrorCts),
876		SK_PNMI_RO, SensorStat, 0},
877	{OID_SKGE_SENSOR_WAR_TIME,
878		SK_PNMI_SENSOR_ENTRIES,
879		sizeof(SK_PNMI_SENSOR),
880		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorWarningTimestamp),
881		SK_PNMI_RO, SensorStat, 0},
882	{OID_SKGE_SENSOR_ERR_TIME,
883		SK_PNMI_SENSOR_ENTRIES,
884		sizeof(SK_PNMI_SENSOR),
885		SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorErrorTimestamp),
886		SK_PNMI_RO, SensorStat, 0},
887	{OID_SKGE_CHKSM_NUMBER,
888		1,
889		0,
890		SK_PNMI_MAI_OFF(ChecksumNumber),
891		SK_PNMI_RO, General, 0},
892	{OID_SKGE_CHKSM_RX_OK_CTS,
893		SKCS_NUM_PROTOCOLS,
894		sizeof(SK_PNMI_CHECKSUM),
895		SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumRxOkCts),
896		SK_PNMI_RO, CsumStat, 0},
897	{OID_SKGE_CHKSM_RX_UNABLE_CTS,
898		SKCS_NUM_PROTOCOLS,
899		sizeof(SK_PNMI_CHECKSUM),
900		SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumRxUnableCts),
901		SK_PNMI_RO, CsumStat, 0},
902	{OID_SKGE_CHKSM_RX_ERR_CTS,
903		SKCS_NUM_PROTOCOLS,
904		sizeof(SK_PNMI_CHECKSUM),
905		SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumRxErrCts),
906		SK_PNMI_RO, CsumStat, 0},
907	{OID_SKGE_CHKSM_TX_OK_CTS,
908		SKCS_NUM_PROTOCOLS,
909		sizeof(SK_PNMI_CHECKSUM),
910		SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumTxOkCts),
911		SK_PNMI_RO, CsumStat, 0},
912	{OID_SKGE_CHKSM_TX_UNABLE_CTS,
913		SKCS_NUM_PROTOCOLS,
914		sizeof(SK_PNMI_CHECKSUM),
915		SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumTxUnableCts),
916		SK_PNMI_RO, CsumStat, 0},
917	{OID_SKGE_STAT_TX,
918		SK_PNMI_MAC_ENTRIES,
919		sizeof(SK_PNMI_STAT),
920		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxOkCts),
921		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX},
922	{OID_SKGE_STAT_TX_OCTETS,
923		SK_PNMI_MAC_ENTRIES,
924		sizeof(SK_PNMI_STAT),
925		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxOctetsOkCts),
926		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_OCTET},
927	{OID_SKGE_STAT_TX_BROADCAST,
928		SK_PNMI_MAC_ENTRIES,
929		sizeof(SK_PNMI_STAT),
930		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxBroadcastOkCts),
931		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_BROADCAST},
932	{OID_SKGE_STAT_TX_MULTICAST,
933		SK_PNMI_MAC_ENTRIES,
934		sizeof(SK_PNMI_STAT),
935		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxMulticastOkCts),
936		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_MULTICAST},
937	{OID_SKGE_STAT_TX_UNICAST,
938		SK_PNMI_MAC_ENTRIES,
939		sizeof(SK_PNMI_STAT),
940		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxUnicastOkCts),
941		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_UNICAST},
942	{OID_SKGE_STAT_TX_LONGFRAMES,
943		SK_PNMI_MAC_ENTRIES,
944		sizeof(SK_PNMI_STAT),
945		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxLongFramesCts),
946		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_LONGFRAMES},
947	{OID_SKGE_STAT_TX_BURST,
948		SK_PNMI_MAC_ENTRIES,
949		sizeof(SK_PNMI_STAT),
950		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxBurstCts),
951		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_BURST},
952	{OID_SKGE_STAT_TX_PFLOWC,
953		SK_PNMI_MAC_ENTRIES,
954		sizeof(SK_PNMI_STAT),
955		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxPauseMacCtrlCts),
956		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_PMACC},
957	{OID_SKGE_STAT_TX_FLOWC,
958		SK_PNMI_MAC_ENTRIES,
959		sizeof(SK_PNMI_STAT),
960		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxMacCtrlCts),
961		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_MACC},
962	{OID_SKGE_STAT_TX_SINGLE_COL,
963		SK_PNMI_MAC_ENTRIES,
964		sizeof(SK_PNMI_STAT),
965		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxSingleCollisionCts),
966		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_SINGLE_COL},
967	{OID_SKGE_STAT_TX_MULTI_COL,
968		SK_PNMI_MAC_ENTRIES,
969		sizeof(SK_PNMI_STAT),
970		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxMultipleCollisionCts),
971		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_MULTI_COL},
972	{OID_SKGE_STAT_TX_EXCESS_COL,
973		SK_PNMI_MAC_ENTRIES,
974		sizeof(SK_PNMI_STAT),
975		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxExcessiveCollisionCts),
976		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_EXCESS_COL},
977	{OID_SKGE_STAT_TX_LATE_COL,
978		SK_PNMI_MAC_ENTRIES,
979		sizeof(SK_PNMI_STAT),
980		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxLateCollisionCts),
981		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_LATE_COL},
982	{OID_SKGE_STAT_TX_DEFFERAL,
983		SK_PNMI_MAC_ENTRIES,
984		sizeof(SK_PNMI_STAT),
985		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxDeferralCts),
986		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_DEFFERAL},
987	{OID_SKGE_STAT_TX_EXCESS_DEF,
988		SK_PNMI_MAC_ENTRIES,
989		sizeof(SK_PNMI_STAT),
990		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxExcessiveDeferralCts),
991		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_EXCESS_DEF},
992	{OID_SKGE_STAT_TX_UNDERRUN,
993		SK_PNMI_MAC_ENTRIES,
994		sizeof(SK_PNMI_STAT),
995		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxFifoUnderrunCts),
996		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_UNDERRUN},
997	{OID_SKGE_STAT_TX_CARRIER,
998		SK_PNMI_MAC_ENTRIES,
999		sizeof(SK_PNMI_STAT),
1000		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxCarrierCts),
1001		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_CARRIER},
1002/*	{OID_SKGE_STAT_TX_UTIL,
1003		SK_PNMI_MAC_ENTRIES,
1004		sizeof(SK_PNMI_STAT),
1005		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxUtilization),
1006		SK_PNMI_RO, MacPrivateStat, (SK_U16)(-1)}, */
1007	{OID_SKGE_STAT_TX_64,
1008		SK_PNMI_MAC_ENTRIES,
1009		sizeof(SK_PNMI_STAT),
1010		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx64Cts),
1011		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_64},
1012	{OID_SKGE_STAT_TX_127,
1013		SK_PNMI_MAC_ENTRIES,
1014		sizeof(SK_PNMI_STAT),
1015		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx127Cts),
1016		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_127},
1017	{OID_SKGE_STAT_TX_255,
1018		SK_PNMI_MAC_ENTRIES,
1019		sizeof(SK_PNMI_STAT),
1020		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx255Cts),
1021		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_255},
1022	{OID_SKGE_STAT_TX_511,
1023		SK_PNMI_MAC_ENTRIES,
1024		sizeof(SK_PNMI_STAT),
1025		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx511Cts),
1026		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_511},
1027	{OID_SKGE_STAT_TX_1023,
1028		SK_PNMI_MAC_ENTRIES,
1029		sizeof(SK_PNMI_STAT),
1030		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx1023Cts),
1031		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_1023},
1032	{OID_SKGE_STAT_TX_MAX,
1033		SK_PNMI_MAC_ENTRIES,
1034		sizeof(SK_PNMI_STAT),
1035		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxMaxCts),
1036		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_MAX},
1037	{OID_SKGE_STAT_TX_SYNC,
1038		SK_PNMI_MAC_ENTRIES,
1039		sizeof(SK_PNMI_STAT),
1040		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxSyncCts),
1041		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_SYNC},
1042	{OID_SKGE_STAT_TX_SYNC_OCTETS,
1043		SK_PNMI_MAC_ENTRIES,
1044		sizeof(SK_PNMI_STAT),
1045		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxSyncOctetsCts),
1046		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_SYNC_OCTET},
1047	{OID_SKGE_STAT_RX,
1048		SK_PNMI_MAC_ENTRIES,
1049		sizeof(SK_PNMI_STAT),
1050		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxOkCts),
1051		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX},
1052	{OID_SKGE_STAT_RX_OCTETS,
1053		SK_PNMI_MAC_ENTRIES,
1054		sizeof(SK_PNMI_STAT),
1055		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxOctetsOkCts),
1056		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_OCTET},
1057	{OID_SKGE_STAT_RX_BROADCAST,
1058		SK_PNMI_MAC_ENTRIES,
1059		sizeof(SK_PNMI_STAT),
1060		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxBroadcastOkCts),
1061		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_BROADCAST},
1062	{OID_SKGE_STAT_RX_MULTICAST,
1063		SK_PNMI_MAC_ENTRIES,
1064		sizeof(SK_PNMI_STAT),
1065		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMulticastOkCts),
1066		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MULTICAST},
1067	{OID_SKGE_STAT_RX_UNICAST,
1068		SK_PNMI_MAC_ENTRIES,
1069		sizeof(SK_PNMI_STAT),
1070		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxUnicastOkCts),
1071		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_UNICAST},
1072	{OID_SKGE_STAT_RX_LONGFRAMES,
1073		SK_PNMI_MAC_ENTRIES,
1074		sizeof(SK_PNMI_STAT),
1075		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxLongFramesCts),
1076		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_LONGFRAMES},
1077	{OID_SKGE_STAT_RX_PFLOWC,
1078		SK_PNMI_MAC_ENTRIES,
1079		sizeof(SK_PNMI_STAT),
1080		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxPauseMacCtrlCts),
1081		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_PMACC},
1082	{OID_SKGE_STAT_RX_FLOWC,
1083		SK_PNMI_MAC_ENTRIES,
1084		sizeof(SK_PNMI_STAT),
1085		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMacCtrlCts),
1086		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MACC},
1087	{OID_SKGE_STAT_RX_PFLOWC_ERR,
1088		SK_PNMI_MAC_ENTRIES,
1089		sizeof(SK_PNMI_STAT),
1090		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxPauseMacCtrlErrorCts),
1091		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_PMACC_ERR},
1092	{OID_SKGE_STAT_RX_FLOWC_UNKWN,
1093		SK_PNMI_MAC_ENTRIES,
1094		sizeof(SK_PNMI_STAT),
1095		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMacCtrlUnknownCts),
1096		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MACC_UNKWN},
1097	{OID_SKGE_STAT_RX_BURST,
1098		SK_PNMI_MAC_ENTRIES,
1099		sizeof(SK_PNMI_STAT),
1100		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxBurstCts),
1101		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_BURST},
1102	{OID_SKGE_STAT_RX_MISSED,
1103		SK_PNMI_MAC_ENTRIES,
1104		sizeof(SK_PNMI_STAT),
1105		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMissedCts),
1106		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MISSED},
1107	{OID_SKGE_STAT_RX_FRAMING,
1108		SK_PNMI_MAC_ENTRIES,
1109		sizeof(SK_PNMI_STAT),
1110		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxFramingCts),
1111		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_FRAMING},
1112	{OID_SKGE_STAT_RX_OVERFLOW,
1113		SK_PNMI_MAC_ENTRIES,
1114		sizeof(SK_PNMI_STAT),
1115		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxFifoOverflowCts),
1116		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_OVERFLOW},
1117	{OID_SKGE_STAT_RX_JABBER,
1118		SK_PNMI_MAC_ENTRIES,
1119		sizeof(SK_PNMI_STAT),
1120		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxJabberCts),
1121		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_JABBER},
1122	{OID_SKGE_STAT_RX_CARRIER,
1123		SK_PNMI_MAC_ENTRIES,
1124		sizeof(SK_PNMI_STAT),
1125		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxCarrierCts),
1126		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_CARRIER},
1127	{OID_SKGE_STAT_RX_IR_LENGTH,
1128		SK_PNMI_MAC_ENTRIES,
1129		sizeof(SK_PNMI_STAT),
1130		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxIRLengthCts),
1131		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_IRLENGTH},
1132	{OID_SKGE_STAT_RX_SYMBOL,
1133		SK_PNMI_MAC_ENTRIES,
1134		sizeof(SK_PNMI_STAT),
1135		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxSymbolCts),
1136		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_SYMBOL},
1137	{OID_SKGE_STAT_RX_SHORTS,
1138		SK_PNMI_MAC_ENTRIES,
1139		sizeof(SK_PNMI_STAT),
1140		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxShortsCts),
1141		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_SHORTS},
1142	{OID_SKGE_STAT_RX_RUNT,
1143		SK_PNMI_MAC_ENTRIES,
1144		sizeof(SK_PNMI_STAT),
1145		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxRuntCts),
1146		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_RUNT},
1147	{OID_SKGE_STAT_RX_CEXT,
1148		SK_PNMI_MAC_ENTRIES,
1149		sizeof(SK_PNMI_STAT),
1150		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxCextCts),
1151		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_CEXT},
1152	{OID_SKGE_STAT_RX_TOO_LONG,
1153		SK_PNMI_MAC_ENTRIES,
1154		sizeof(SK_PNMI_STAT),
1155		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxTooLongCts),
1156		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_TOO_LONG},
1157	{OID_SKGE_STAT_RX_FCS,
1158		SK_PNMI_MAC_ENTRIES,
1159		sizeof(SK_PNMI_STAT),
1160		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxFcsCts),
1161		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_FCS},
1162/*	{OID_SKGE_STAT_RX_UTIL,
1163		SK_PNMI_MAC_ENTRIES,
1164		sizeof(SK_PNMI_STAT),
1165		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxUtilization),
1166		SK_PNMI_RO, MacPrivateStat, (SK_U16)(-1)}, */
1167	{OID_SKGE_STAT_RX_64,
1168		SK_PNMI_MAC_ENTRIES,
1169		sizeof(SK_PNMI_STAT),
1170		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx64Cts),
1171		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_64},
1172	{OID_SKGE_STAT_RX_127,
1173		SK_PNMI_MAC_ENTRIES,
1174		sizeof(SK_PNMI_STAT),
1175		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx127Cts),
1176		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_127},
1177	{OID_SKGE_STAT_RX_255,
1178		SK_PNMI_MAC_ENTRIES,
1179		sizeof(SK_PNMI_STAT),
1180		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx255Cts),
1181		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_255},
1182	{OID_SKGE_STAT_RX_511,
1183		SK_PNMI_MAC_ENTRIES,
1184		sizeof(SK_PNMI_STAT),
1185		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx511Cts),
1186		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_511},
1187	{OID_SKGE_STAT_RX_1023,
1188		SK_PNMI_MAC_ENTRIES,
1189		sizeof(SK_PNMI_STAT),
1190		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx1023Cts),
1191		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_1023},
1192	{OID_SKGE_STAT_RX_MAX,
1193		SK_PNMI_MAC_ENTRIES,
1194		sizeof(SK_PNMI_STAT),
1195		SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMaxCts),
1196		SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MAX},
1197	{OID_SKGE_PHYS_CUR_ADDR,
1198		SK_PNMI_MAC_ENTRIES,
1199		sizeof(SK_PNMI_CONF),
1200		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfMacCurrentAddr),
1201		SK_PNMI_RW, Addr, 0},
1202	{OID_SKGE_PHYS_FAC_ADDR,
1203		SK_PNMI_MAC_ENTRIES,
1204		sizeof(SK_PNMI_CONF),
1205		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfMacFactoryAddr),
1206		SK_PNMI_RO, Addr, 0},
1207	{OID_SKGE_PMD,
1208		SK_PNMI_MAC_ENTRIES,
1209		sizeof(SK_PNMI_CONF),
1210		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPMD),
1211		SK_PNMI_RO, MacPrivateConf, 0},
1212	{OID_SKGE_CONNECTOR,
1213		SK_PNMI_MAC_ENTRIES,
1214		sizeof(SK_PNMI_CONF),
1215		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfConnector),
1216		SK_PNMI_RO, MacPrivateConf, 0},
1217	{OID_SKGE_LINK_CAP,
1218		SK_PNMI_MAC_ENTRIES,
1219		sizeof(SK_PNMI_CONF),
1220		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfLinkCapability),
1221		SK_PNMI_RO, MacPrivateConf, 0},
1222	{OID_SKGE_LINK_MODE,
1223		SK_PNMI_MAC_ENTRIES,
1224		sizeof(SK_PNMI_CONF),
1225		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfLinkMode),
1226		SK_PNMI_RW, MacPrivateConf, 0},
1227	{OID_SKGE_LINK_MODE_STATUS,
1228		SK_PNMI_MAC_ENTRIES,
1229		sizeof(SK_PNMI_CONF),
1230		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfLinkModeStatus),
1231		SK_PNMI_RO, MacPrivateConf, 0},
1232	{OID_SKGE_LINK_STATUS,
1233		SK_PNMI_MAC_ENTRIES,
1234		sizeof(SK_PNMI_CONF),
1235		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfLinkStatus),
1236		SK_PNMI_RO, MacPrivateConf, 0},
1237	{OID_SKGE_FLOWCTRL_CAP,
1238		SK_PNMI_MAC_ENTRIES,
1239		sizeof(SK_PNMI_CONF),
1240		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfFlowCtrlCapability),
1241		SK_PNMI_RO, MacPrivateConf, 0},
1242	{OID_SKGE_FLOWCTRL_MODE,
1243		SK_PNMI_MAC_ENTRIES,
1244		sizeof(SK_PNMI_CONF),
1245		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfFlowCtrlMode),
1246		SK_PNMI_RW, MacPrivateConf, 0},
1247	{OID_SKGE_FLOWCTRL_STATUS,
1248		SK_PNMI_MAC_ENTRIES,
1249		sizeof(SK_PNMI_CONF),
1250		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfFlowCtrlStatus),
1251		SK_PNMI_RO, MacPrivateConf, 0},
1252	{OID_SKGE_PHY_OPERATION_CAP,
1253		SK_PNMI_MAC_ENTRIES,
1254		sizeof(SK_PNMI_CONF),
1255		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyOperationCapability),
1256		SK_PNMI_RO, MacPrivateConf, 0},
1257	{OID_SKGE_PHY_OPERATION_MODE,
1258		SK_PNMI_MAC_ENTRIES,
1259		sizeof(SK_PNMI_CONF),
1260		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyOperationMode),
1261		SK_PNMI_RW, MacPrivateConf, 0},
1262	{OID_SKGE_PHY_OPERATION_STATUS,
1263		SK_PNMI_MAC_ENTRIES,
1264		sizeof(SK_PNMI_CONF),
1265		SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyOperationStatus),
1266		SK_PNMI_RO, MacPrivateConf, 0},
1267	{OID_SKGE_TRAP,
1268		1,
1269		0,
1270		SK_PNMI_MAI_OFF(Trap),
1271		SK_PNMI_RO, General, 0},
1272	{OID_SKGE_TRAP_NUMBER,
1273		1,
1274		0,
1275		SK_PNMI_MAI_OFF(TrapNumber),
1276		SK_PNMI_RO, General, 0},
1277	{OID_SKGE_RLMT_MODE,
1278		1,
1279		0,
1280		SK_PNMI_MAI_OFF(RlmtMode),
1281		SK_PNMI_RW, Rlmt, 0},
1282	{OID_SKGE_RLMT_PORT_NUMBER,
1283		1,
1284		0,
1285		SK_PNMI_MAI_OFF(RlmtPortNumber),
1286		SK_PNMI_RO, Rlmt, 0},
1287	{OID_SKGE_RLMT_PORT_ACTIVE,
1288		1,
1289		0,
1290		SK_PNMI_MAI_OFF(RlmtPortActive),
1291		SK_PNMI_RO, Rlmt, 0},
1292	{OID_SKGE_RLMT_PORT_PREFERRED,
1293		1,
1294		0,
1295		SK_PNMI_MAI_OFF(RlmtPortPreferred),
1296		SK_PNMI_RW, Rlmt, 0},
1297	{OID_SKGE_RLMT_CHANGE_CTS,
1298		1,
1299		0,
1300		SK_PNMI_MAI_OFF(RlmtChangeCts),
1301		SK_PNMI_RO, Rlmt, 0},
1302	{OID_SKGE_RLMT_CHANGE_TIME,
1303		1,
1304		0,
1305		SK_PNMI_MAI_OFF(RlmtChangeTime),
1306		SK_PNMI_RO, Rlmt, 0},
1307	{OID_SKGE_RLMT_CHANGE_ESTIM,
1308		1,
1309		0,
1310		SK_PNMI_MAI_OFF(RlmtChangeEstimate),
1311		SK_PNMI_RO, Rlmt, 0},
1312	{OID_SKGE_RLMT_CHANGE_THRES,
1313		1,
1314		0,
1315		SK_PNMI_MAI_OFF(RlmtChangeThreshold),
1316		SK_PNMI_RW, Rlmt, 0},
1317	{OID_SKGE_RLMT_PORT_INDEX,
1318		SK_PNMI_MAC_ENTRIES,
1319		sizeof(SK_PNMI_RLMT),
1320		SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtIndex),
1321		SK_PNMI_RO, RlmtStat, 0},
1322	{OID_SKGE_RLMT_STATUS,
1323		SK_PNMI_MAC_ENTRIES,
1324		sizeof(SK_PNMI_RLMT),
1325		SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtStatus),
1326		SK_PNMI_RO, RlmtStat, 0},
1327	{OID_SKGE_RLMT_TX_HELLO_CTS,
1328		SK_PNMI_MAC_ENTRIES,
1329		sizeof(SK_PNMI_RLMT),
1330		SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtTxHelloCts),
1331		SK_PNMI_RO, RlmtStat, 0},
1332	{OID_SKGE_RLMT_RX_HELLO_CTS,
1333		SK_PNMI_MAC_ENTRIES,
1334		sizeof(SK_PNMI_RLMT),
1335		SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtRxHelloCts),
1336		SK_PNMI_RO, RlmtStat, 0},
1337	{OID_SKGE_RLMT_TX_SP_REQ_CTS,
1338		SK_PNMI_MAC_ENTRIES,
1339		sizeof(SK_PNMI_RLMT),
1340		SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtTxSpHelloReqCts),
1341		SK_PNMI_RO, RlmtStat, 0},
1342	{OID_SKGE_RLMT_RX_SP_CTS,
1343		SK_PNMI_MAC_ENTRIES,
1344		sizeof(SK_PNMI_RLMT),
1345		SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtRxSpHelloCts),
1346		SK_PNMI_RO, RlmtStat, 0},
1347	{OID_SKGE_RLMT_MONITOR_NUMBER,
1348		1,
1349		0,
1350		SK_PNMI_MAI_OFF(RlmtMonitorNumber),
1351		SK_PNMI_RO, General, 0},
1352	{OID_SKGE_RLMT_MONITOR_INDEX,
1353		SK_PNMI_MONITOR_ENTRIES,
1354		sizeof(SK_PNMI_RLMT_MONITOR),
1355		SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorIndex),
1356		SK_PNMI_RO, Monitor, 0},
1357	{OID_SKGE_RLMT_MONITOR_ADDR,
1358		SK_PNMI_MONITOR_ENTRIES,
1359		sizeof(SK_PNMI_RLMT_MONITOR),
1360		SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorAddr),
1361		SK_PNMI_RO, Monitor, 0},
1362	{OID_SKGE_RLMT_MONITOR_ERRS,
1363		SK_PNMI_MONITOR_ENTRIES,
1364		sizeof(SK_PNMI_RLMT_MONITOR),
1365		SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorErrorCts),
1366		SK_PNMI_RO, Monitor, 0},
1367	{OID_SKGE_RLMT_MONITOR_TIMESTAMP,
1368		SK_PNMI_MONITOR_ENTRIES,
1369		sizeof(SK_PNMI_RLMT_MONITOR),
1370		SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorTimestamp),
1371		SK_PNMI_RO, Monitor, 0},
1372	{OID_SKGE_RLMT_MONITOR_ADMIN,
1373		SK_PNMI_MONITOR_ENTRIES,
1374		sizeof(SK_PNMI_RLMT_MONITOR),
1375		SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorAdmin),
1376		SK_PNMI_RW, Monitor, 0},
1377	{OID_SKGE_MTU,
1378		1,
1379		0,
1380		SK_PNMI_MAI_OFF(MtuSize),
1381		SK_PNMI_RW, MacPrivateConf, 0},
1382};
1383
1384/*
1385 * Table for hardware register saving on resets and port switches
1386 */
1387static const SK_PNMI_STATADDR StatAddress[SK_PNMI_MAX_IDX] = {
1388	/*  0 */	{TRUE, XM_TXF_OK},
1389	/*  1 */	{TRUE, 0},
1390	/*  2 */	{FALSE, 0},
1391	/*  3 */	{TRUE, XM_TXF_BC_OK},
1392	/*  4 */	{TRUE, XM_TXF_MC_OK},
1393	/*  5 */	{TRUE, XM_TXF_UC_OK},
1394	/*  6 */	{TRUE, XM_TXF_LONG},
1395	/*  7 */	{TRUE, XM_TXE_BURST},
1396	/*  8 */	{TRUE, XM_TXF_MPAUSE},
1397	/*  9 */	{TRUE, XM_TXF_MCTRL},
1398	/* 10 */	{TRUE, XM_TXF_SNG_COL},
1399	/* 11 */	{TRUE, XM_TXF_MUL_COL},
1400	/* 12 */	{TRUE, XM_TXF_ABO_COL},
1401	/* 13 */	{TRUE, XM_TXF_LAT_COL},
1402	/* 14 */	{TRUE, XM_TXF_DEF},
1403	/* 15 */	{TRUE, XM_TXF_EX_DEF},
1404	/* 16 */	{TRUE, XM_TXE_FIFO_UR},
1405	/* 17 */	{TRUE, XM_TXE_CS_ERR},
1406	/* 18 */	{FALSE, 0},
1407	/* 19 */	{FALSE, 0},
1408	/* 20 */	{TRUE, XM_TXF_64B},
1409	/* 21 */	{TRUE, XM_TXF_127B},
1410	/* 22 */	{TRUE, XM_TXF_255B},
1411	/* 23 */	{TRUE, XM_TXF_511B},
1412	/* 24 */	{TRUE, XM_TXF_1023B},
1413	/* 25 */	{TRUE, XM_TXF_MAX_SZ},
1414	/* 26 */	{FALSE, 0},
1415	/* 27 */	{FALSE, 0},
1416	/* 28 */	{FALSE, 0},
1417	/* 29 */	{FALSE, 0},
1418	/* 30 */	{FALSE, 0},
1419	/* 31 */	{FALSE, 0},
1420	/* 32 */	{TRUE, XM_RXF_OK},
1421	/* 33 */	{TRUE, 0},
1422	/* 34 */	{FALSE, 0},
1423	/* 35 */	{TRUE, XM_RXF_BC_OK},
1424	/* 36 */	{TRUE, XM_RXF_MC_OK},
1425	/* 37 */	{TRUE, XM_RXF_UC_OK},
1426	/* 38 */	{TRUE, XM_RXF_MPAUSE},
1427	/* 39 */	{TRUE, XM_RXF_MCTRL},
1428	/* 40 */	{TRUE, XM_RXF_INV_MP},
1429	/* 41 */	{TRUE, XM_RXF_INV_MOC},
1430	/* 42 */	{TRUE, XM_RXE_BURST},
1431	/* 43 */	{TRUE, XM_RXE_FMISS},
1432	/* 44 */	{TRUE, XM_RXF_FRA_ERR},
1433	/* 45 */	{TRUE, XM_RXE_FIFO_OV},
1434	/* 46 */	{TRUE, XM_RXF_JAB_PKT},
1435	/* 47 */	{TRUE, XM_RXE_CAR_ERR},
1436	/* 48 */	{TRUE, XM_RXF_LEN_ERR},
1437	/* 49 */	{TRUE, XM_RXE_SYM_ERR},
1438	/* 50 */	{TRUE, XM_RXE_SHT_ERR},
1439	/* 51 */	{TRUE, XM_RXE_RUNT},
1440	/* 52 */	{TRUE, XM_RXF_LNG_ERR},
1441	/* 53 */	{TRUE, XM_RXF_FCS_ERR},
1442	/* 54 */	{FALSE, 0},
1443	/* 55 */	{TRUE, XM_RXF_CEX_ERR},
1444	/* 56 */	{FALSE, 0},
1445	/* 57 */	{FALSE, 0},
1446	/* 58 */	{TRUE, XM_RXF_64B},
1447	/* 59 */	{TRUE, XM_RXF_127B},
1448	/* 60 */	{TRUE, XM_RXF_255B},
1449	/* 61 */	{TRUE, XM_RXF_511B},
1450	/* 62 */	{TRUE, XM_RXF_1023B},
1451	/* 63 */	{TRUE, XM_RXF_MAX_SZ},
1452	/* 64 */	{FALSE, 0},
1453	/* 65 */	{FALSE, 0},
1454	/* 66 */	{TRUE, 0}
1455};
1456
1457
1458/*****************************************************************************
1459 *
1460 * Public functions
1461 *
1462 */
1463
1464/*****************************************************************************
1465 *
1466 * SkPnmiInit - Init function of PNMI
1467 *
1468 * Description:
1469 *	SK_INIT_DATA: Initialises the data structures
1470 *	SK_INIT_IO:   Resets the XMAC statistics, determines the device and
1471 *	              connector type.
1472 *	SK_INIT_RUN:  Starts a timer event for port switch per hour
1473 *	              calculation.
1474 *
1475 * Returns:
1476 *	Always 0
1477 */
1478
1479int SkPnmiInit(
1480SK_AC *pAC,		/* Pointer to adapter context */
1481SK_IOC IoC,		/* IO context handle */
1482int Level)		/* Initialization level */
1483{
1484	unsigned int	PortMax;	/* Number of ports */
1485	unsigned int	PortIndex;	/* Current port index in loop */
1486	SK_U16		Val16;		/* Multiple purpose 16 bit variable */
1487	SK_U8		Val8;		/* Mulitple purpose 8 bit variable */
1488	SK_EVPARA	EventParam;	/* Event struct for timer event */
1489
1490
1491	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
1492		("PNMI: SkPnmiInit: Called, level=%d\n", Level));
1493
1494	switch (Level) {
1495
1496	case SK_INIT_DATA:
1497		SK_MEMSET((char *)&pAC->Pnmi, 0, sizeof(pAC->Pnmi));
1498		pAC->Pnmi.TrapBufFree = SK_PNMI_TRAP_QUEUE_LEN;
1499		pAC->Pnmi.StartUpTime = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC));
1500		pAC->Pnmi.RlmtChangeThreshold = SK_PNMI_DEF_RLMT_CHG_THRES;
1501		for (PortIndex = 0; PortIndex < SK_MAX_MACS; PortIndex ++) {
1502
1503			pAC->Pnmi.Port[PortIndex].ActiveFlag = SK_FALSE;
1504			pAC->Pnmi.DualNetActiveFlag = SK_FALSE;
1505		}
1506		break;
1507
1508	case SK_INIT_IO:
1509		/*
1510		 * Reset MAC counters
1511		 */
1512		PortMax = pAC->GIni.GIMacsFound;
1513
1514		for (PortIndex = 0; PortIndex < PortMax; PortIndex ++) {
1515
1516			Val16 = XM_SC_CLR_RXC | XM_SC_CLR_TXC;
1517			XM_OUT16(IoC, PortIndex, XM_STAT_CMD, Val16);
1518			/* Clear two times according to Errata #3 */
1519			XM_OUT16(IoC, PortIndex, XM_STAT_CMD, Val16);
1520		}
1521
1522		/*
1523		 * Get pci bus speed
1524		 */
1525		SK_IN16(IoC, B0_CTST, &Val16);
1526		if ((Val16 & CS_BUS_CLOCK) == 0) {
1527
1528			pAC->Pnmi.PciBusSpeed = 33;
1529		}
1530		else {
1531			pAC->Pnmi.PciBusSpeed = 66;
1532		}
1533
1534		/*
1535		 * Get pci bus width
1536		 */
1537		SK_IN16(IoC, B0_CTST, &Val16);
1538		if ((Val16 & CS_BUS_SLOT_SZ) == 0) {
1539
1540			pAC->Pnmi.PciBusWidth = 32;
1541		}
1542		else {
1543			pAC->Pnmi.PciBusWidth = 64;
1544		}
1545
1546		/*
1547		 * Get PMD and DeviceType
1548		 */
1549		SK_IN8(IoC, B2_PMD_TYP, &Val8);
1550		switch (Val8) {
1551		case 'S':
1552			pAC->Pnmi.PMD = 3;
1553			if (pAC->GIni.GIMacsFound > 1) {
1554
1555				pAC->Pnmi.DeviceType = 0x00020002;
1556			}
1557			else {
1558				pAC->Pnmi.DeviceType = 0x00020001;
1559			}
1560			break;
1561
1562		case 'L':
1563			pAC->Pnmi.PMD = 2;
1564			if (pAC->GIni.GIMacsFound > 1) {
1565
1566				pAC->Pnmi.DeviceType = 0x00020004;
1567			}
1568			else {
1569				pAC->Pnmi.DeviceType = 0x00020003;
1570			}
1571			break;
1572
1573		case 'C':
1574			pAC->Pnmi.PMD = 4;
1575			if (pAC->GIni.GIMacsFound > 1) {
1576
1577				pAC->Pnmi.DeviceType = 0x00020006;
1578			}
1579			else {
1580				pAC->Pnmi.DeviceType = 0x00020005;
1581			}
1582			break;
1583
1584		case 'T':
1585			pAC->Pnmi.PMD = 5;
1586			if (pAC->GIni.GIMacsFound > 1) {
1587
1588				pAC->Pnmi.DeviceType = 0x00020008;
1589			}
1590			else {
1591				pAC->Pnmi.DeviceType = 0x00020007;
1592			}
1593			break;
1594
1595		default :
1596			pAC->Pnmi.PMD = 1;
1597			pAC->Pnmi.DeviceType = 0;
1598			break;
1599		}
1600
1601		/*
1602		 * Get connector
1603		 */
1604		SK_IN8(IoC, B2_CONN_TYP, &Val8);
1605		switch (Val8) {
1606		case 'C':
1607			pAC->Pnmi.Connector = 2;
1608			break;
1609
1610		case 'D':
1611			pAC->Pnmi.Connector = 3;
1612			break;
1613
1614		case 'F':
1615			pAC->Pnmi.Connector = 4;
1616			break;
1617
1618		case 'J':
1619			pAC->Pnmi.Connector = 5;
1620			break;
1621
1622		case 'V':
1623			pAC->Pnmi.Connector = 6;
1624			break;
1625
1626		default:
1627			pAC->Pnmi.Connector = 1;
1628			break;
1629		}
1630		break;
1631
1632	case SK_INIT_RUN:
1633		/*
1634		 * Start timer for RLMT change counter
1635		 */
1636		SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
1637		SkTimerStart(pAC, IoC, &pAC->Pnmi.RlmtChangeEstimate.EstTimer,
1638			28125000, SKGE_PNMI, SK_PNMI_EVT_CHG_EST_TIMER,
1639			EventParam);
1640		break;
1641
1642	default:
1643		break; /* Nothing todo */
1644	}
1645
1646	return (0);
1647}
1648
1649/*****************************************************************************
1650 *
1651 * SkPnmiGetVar - Retrieves the value of a single OID
1652 *
1653 * Description:
1654 *	Calls a general sub-function for all this stuff. If the instance
1655 *	-1 is passed, the values of all instances are returned in an
1656 *	array of values.
1657 *
1658 * Returns:
1659 *	SK_PNMI_ERR_OK           The request was successfully performed
1660 *	SK_PNMI_ERR_GENERAL      A general severe internal error occured
1661 *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to take
1662 *	                         the data.
1663 *	SK_PNMI_ERR_UNKNOWN_OID  The requested OID is unknown
1664 *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
1665 *                               exist (e.g. port instance 3 on a two port
1666 *	                         adapter.
1667 */
1668
1669int SkPnmiGetVar(
1670SK_AC *pAC,		/* Pointer to adapter context */
1671SK_IOC IoC,		/* IO context handle */
1672SK_U32 Id,		/* Object ID that is to be processed */
1673void *pBuf,		/* Buffer to which to mgmt data will be retrieved */
1674unsigned int *pLen,	/* On call: buffer length. On return: used buffer */
1675SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
1676SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode allways zero */
1677{
1678	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
1679		("PNMI: SkPnmiGetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n",
1680			Id, *pLen, Instance, NetIndex));
1681
1682	return (PnmiVar(pAC, IoC, SK_PNMI_GET, Id, (char *)pBuf, pLen,
1683		Instance, NetIndex));
1684}
1685
1686/*****************************************************************************
1687 *
1688 * SkPnmiPreSetVar - Presets the value of a single OID
1689 *
1690 * Description:
1691 *	Calls a general sub-function for all this stuff. The preset does
1692 *	the same as a set, but returns just before finally setting the
1693 *	new value. This is usefull to check if a set might be successfull.
1694 *	If as instance a -1 is passed, an array of values is supposed and
1695 *	all instance of the OID will be set.
1696 *
1697 * Returns:
1698 *	SK_PNMI_ERR_OK           The request was successfully performed.
1699 *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
1700 *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
1701 *	                         the correct data (e.g. a 32bit value is
1702 *	                         needed, but a 16 bit value was passed).
1703 *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
1704 *	                         value range.
1705 *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
1706 *	SK_PNMI_ERR_UNKNOWN_OID  The requested OID is unknown.
1707 *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
1708 *                               exist (e.g. port instance 3 on a two port
1709 *	                         adapter.
1710 */
1711
1712int SkPnmiPreSetVar(
1713SK_AC *pAC,		/* Pointer to adapter context */
1714SK_IOC IoC,		/* IO context handle */
1715SK_U32 Id,		/* Object ID that is to be processed */
1716void *pBuf,		/* Buffer which stores the mgmt data to be set */
1717unsigned int *pLen,	/* Total length of mgmt data */
1718SK_U32 Instance,	/* Instance (1..n) that is to be set or -1 */
1719SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode allways zero */
1720{
1721	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
1722		("PNMI: SkPnmiPreSetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n",
1723			Id, *pLen, Instance, NetIndex));
1724
1725
1726	return (PnmiVar(pAC, IoC, SK_PNMI_PRESET, Id, (char *)pBuf, pLen,
1727		Instance, NetIndex));
1728}
1729
1730/*****************************************************************************
1731 *
1732 * SkPnmiSetVar - Sets the value of a single OID
1733 *
1734 * Description:
1735 *	Calls a general sub-function for all this stuff. The preset does
1736 *	the same as a set, but returns just before finally setting the
1737 *	new value. This is usefull to check if a set might be successfull.
1738 *	If as instance a -1 is passed, an array of values is supposed and
1739 *	all instance of the OID will be set.
1740 *
1741 * Returns:
1742 *	SK_PNMI_ERR_OK           The request was successfully performed.
1743 *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
1744 *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
1745 *	                         the correct data (e.g. a 32bit value is
1746 *	                         needed, but a 16 bit value was passed).
1747 *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
1748 *	                         value range.
1749 *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
1750 *	SK_PNMI_ERR_UNKNOWN_OID  The requested OID is unknown.
1751 *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
1752 *                               exist (e.g. port instance 3 on a two port
1753 *	                         adapter.
1754 */
1755
1756int SkPnmiSetVar(
1757SK_AC *pAC,		/* Pointer to adapter context */
1758SK_IOC IoC,		/* IO context handle */
1759SK_U32 Id,		/* Object ID that is to be processed */
1760void *pBuf,		/* Buffer which stores the mgmt data to be set */
1761unsigned int *pLen,	/* Total length of mgmt data */
1762SK_U32 Instance,	/* Instance (1..n) that is to be set or -1 */
1763SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode allways zero */
1764{
1765	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
1766		("PNMI: SkPnmiSetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n",
1767			Id, *pLen, Instance, NetIndex));
1768
1769	return (PnmiVar(pAC, IoC, SK_PNMI_SET, Id, (char *)pBuf, pLen,
1770		Instance, NetIndex));
1771}
1772
1773/*****************************************************************************
1774 *
1775 * SkPnmiGetStruct - Retrieves the management database in SK_PNMI_STRUCT_DATA
1776 *
1777 * Description:
1778 *	Runs through the IdTable, queries the single OIDs and stores the
1779 *	returned data into the management database structure
1780 *	SK_PNMI_STRUCT_DATA. The offset of the OID in the structure
1781 *	is stored in the IdTable. The return value of the function will also
1782 *	be stored in SK_PNMI_STRUCT_DATA if the passed buffer has the
1783 *	minimum size of SK_PNMI_MIN_STRUCT_SIZE.
1784 *
1785 * Returns:
1786 *	SK_PNMI_ERR_OK           The request was successfully performed
1787 *	SK_PNMI_ERR_GENERAL      A general severe internal error occured
1788 *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to take
1789 *	                         the data.
1790 *	SK_PNMI_ERR_UNKNOWN_NET  The requested NetIndex doesn't exist
1791 */
1792
1793int SkPnmiGetStruct(
1794SK_AC *pAC,		/* Pointer to adapter context */
1795SK_IOC IoC,		/* IO context handle */
1796void *pBuf,		/* Buffer which will store the retrieved data */
1797unsigned int *pLen,	/* Length of buffer */
1798SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode allways zero */
1799{
1800	int		Ret;
1801	unsigned int	TableIndex;
1802	unsigned int	DstOffset;
1803	unsigned int	InstanceNo;
1804	unsigned int	InstanceCnt;
1805	SK_U32		Instance;
1806	unsigned int	TmpLen;
1807	char		KeyArr[SK_PNMI_VPD_ENTRIES][SK_PNMI_VPD_KEY_SIZE];
1808
1809
1810	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
1811		("PNMI: SkPnmiGetStruct: Called, BufLen=%d, NetIndex=%d\n",
1812			*pLen, NetIndex));
1813
1814	if (*pLen < SK_PNMI_STRUCT_SIZE) {
1815
1816		if (*pLen >= SK_PNMI_MIN_STRUCT_SIZE) {
1817
1818			SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_TOO_SHORT,
1819				(SK_U32)(-1));
1820		}
1821
1822		*pLen = SK_PNMI_STRUCT_SIZE;
1823		return (SK_PNMI_ERR_TOO_SHORT);
1824	}
1825
1826    /*
1827     * Check NetIndex
1828     */
1829	if (NetIndex >= pAC->Rlmt.NumNets) {
1830		return (SK_PNMI_ERR_UNKNOWN_NET);
1831	}
1832
1833	/* Update statistic */
1834	SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On call");
1835
1836	if ((Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1)) !=
1837		SK_PNMI_ERR_OK) {
1838
1839		SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
1840		*pLen = SK_PNMI_MIN_STRUCT_SIZE;
1841		return (Ret);
1842	}
1843
1844	if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) {
1845
1846		SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
1847		*pLen = SK_PNMI_MIN_STRUCT_SIZE;
1848		return (Ret);
1849	}
1850
1851	if ((Ret = SirqUpdate(pAC, IoC)) != SK_PNMI_ERR_OK) {
1852
1853		SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
1854		*pLen = SK_PNMI_MIN_STRUCT_SIZE;
1855		return (Ret);
1856	}
1857
1858	/*
1859	 * Increment semaphores to indicate that an update was
1860	 * already done
1861	 */
1862	pAC->Pnmi.MacUpdatedFlag ++;
1863	pAC->Pnmi.RlmtUpdatedFlag ++;
1864	pAC->Pnmi.SirqUpdatedFlag ++;
1865
1866	/* Get vpd keys for instance calculation */
1867	Ret = GetVpdKeyArr(pAC, IoC, &KeyArr[0][0], sizeof(KeyArr), &TmpLen);
1868	if (Ret != SK_PNMI_ERR_OK) {
1869
1870		pAC->Pnmi.MacUpdatedFlag --;
1871		pAC->Pnmi.RlmtUpdatedFlag --;
1872		pAC->Pnmi.SirqUpdatedFlag --;
1873
1874		SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return");
1875		SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
1876		*pLen = SK_PNMI_MIN_STRUCT_SIZE;
1877		return (SK_PNMI_ERR_GENERAL);
1878	}
1879
1880	/* Retrieve values */
1881	SK_MEMSET((char *)pBuf, 0, SK_PNMI_STRUCT_SIZE);
1882	for (TableIndex = 0; TableIndex < sizeof(IdTable)/sizeof(IdTable[0]);
1883		TableIndex ++) {
1884
1885		InstanceNo = IdTable[TableIndex].InstanceNo;
1886		for (InstanceCnt = 1; InstanceCnt <= InstanceNo;
1887			InstanceCnt ++) {
1888
1889			DstOffset = IdTable[TableIndex].Offset +
1890				(InstanceCnt - 1) *
1891				IdTable[TableIndex].StructSize;
1892
1893			/*
1894			 * For the VPD the instance is not an index number
1895			 * but the key itself. Determin with the instance
1896			 * counter the VPD key to be used.
1897			 */
1898			if (IdTable[TableIndex].Id == OID_SKGE_VPD_KEY ||
1899				IdTable[TableIndex].Id == OID_SKGE_VPD_VALUE ||
1900				IdTable[TableIndex].Id == OID_SKGE_VPD_ACCESS ||
1901				IdTable[TableIndex].Id == OID_SKGE_VPD_ACTION) {
1902
1903				SK_STRNCPY((char *)&Instance, KeyArr[InstanceCnt - 1], 4);
1904			}
1905			else {
1906				Instance = (SK_U32)InstanceCnt;
1907			}
1908
1909			TmpLen = *pLen - DstOffset;
1910			Ret = IdTable[TableIndex].Func(pAC, IoC, SK_PNMI_GET,
1911				IdTable[TableIndex].Id, (char *)pBuf +
1912				DstOffset, &TmpLen, Instance, TableIndex, NetIndex);
1913
1914			/*
1915			 * An unknown instance error means that we reached
1916			 * the last instance of that variable. Proceed with
1917			 * the next OID in the table and ignore the return
1918			 * code.
1919			 */
1920			if (Ret == SK_PNMI_ERR_UNKNOWN_INST) {
1921
1922                break;
1923			}
1924
1925			if (Ret != SK_PNMI_ERR_OK) {
1926
1927				pAC->Pnmi.MacUpdatedFlag --;
1928				pAC->Pnmi.RlmtUpdatedFlag --;
1929				pAC->Pnmi.SirqUpdatedFlag --;
1930
1931				SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return");
1932				SK_PNMI_SET_STAT(pBuf, Ret, DstOffset);
1933				*pLen = SK_PNMI_MIN_STRUCT_SIZE;
1934				return (Ret);
1935			}
1936		}
1937	}
1938
1939	pAC->Pnmi.MacUpdatedFlag --;
1940	pAC->Pnmi.RlmtUpdatedFlag --;
1941	pAC->Pnmi.SirqUpdatedFlag --;
1942
1943	*pLen = SK_PNMI_STRUCT_SIZE;
1944	SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return");
1945	SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_OK, (SK_U32)(-1));
1946	return (SK_PNMI_ERR_OK);
1947}
1948
1949/*****************************************************************************
1950 *
1951 * SkPnmiPreSetStruct - Presets the management database in SK_PNMI_STRUCT_DATA
1952 *
1953 * Description:
1954 *	Calls a general sub-function for all this set stuff. The preset does
1955 *	the same as a set, but returns just before finally setting the
1956 *	new value. This is usefull to check if a set might be successfull.
1957 *	The sub-function runs through the IdTable, checks which OIDs are able
1958 *	to set, and calls the handler function of the OID to perform the
1959 *	preset. The return value of the function will also be stored in
1960 *	SK_PNMI_STRUCT_DATA if the passed buffer has the minimum size of
1961 *	SK_PNMI_MIN_STRUCT_SIZE.
1962 *
1963 * Returns:
1964 *	SK_PNMI_ERR_OK           The request was successfully performed.
1965 *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
1966 *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
1967 *	                         the correct data (e.g. a 32bit value is
1968 *	                         needed, but a 16 bit value was passed).
1969 *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
1970 *	                         value range.
1971 */
1972
1973int SkPnmiPreSetStruct(
1974SK_AC *pAC,		/* Pointer to adapter context */
1975SK_IOC IoC,		/* IO context handle */
1976void *pBuf,		/* Buffer which contains the data to be set */
1977unsigned int *pLen,	/* Length of buffer */
1978SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode allways zero */
1979{
1980	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
1981		("PNMI: SkPnmiPreSetStruct: Called, BufLen=%d, NetIndex=%d\n",
1982			*pLen, NetIndex));
1983
1984	return (PnmiStruct(pAC, IoC, SK_PNMI_PRESET, (char *)pBuf,
1985    					pLen, NetIndex));
1986}
1987
1988/*****************************************************************************
1989 *
1990 * SkPnmiSetStruct - Sets the management database in SK_PNMI_STRUCT_DATA
1991 *
1992 * Description:
1993 *	Calls a general sub-function for all this set stuff. The return value
1994 *	of the function will also be stored in SK_PNMI_STRUCT_DATA if the
1995 *	passed buffer has the minimum size of SK_PNMI_MIN_STRUCT_SIZE.
1996 *	The sub-function runs through the IdTable, checks which OIDs are able
1997 *	to set, and calls the handler function of the OID to perform the
1998 *	set. The return value of the function will also be stored in
1999 *	SK_PNMI_STRUCT_DATA if the passed buffer has the minimum size of
2000 *	SK_PNMI_MIN_STRUCT_SIZE.
2001 *
2002 * Returns:
2003 *	SK_PNMI_ERR_OK           The request was successfully performed.
2004 *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
2005 *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
2006 *	                         the correct data (e.g. a 32bit value is
2007 *	                         needed, but a 16 bit value was passed).
2008 *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
2009 *	                         value range.
2010 */
2011
2012int SkPnmiSetStruct(
2013SK_AC *pAC,		/* Pointer to adapter context */
2014SK_IOC IoC,		/* IO context handle */
2015void *pBuf,		/* Buffer which contains the data to be set */
2016unsigned int *pLen,	/* Length of buffer */
2017SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode allways zero */
2018{
2019	SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
2020		("PNMI: SkPnmiSetStruct: Called, BufLen=%d, NetIndex=%d\n",
2021			*pLen, NetIndex));
2022
2023	return (PnmiStruct(pAC, IoC, SK_PNMI_SET, (char *)pBuf,
2024    					pLen, NetIndex));
2025}
2026
2027/*****************************************************************************
2028 *
2029 * SkPnmiEvent - Event handler
2030 *
2031 * Description:
2032 *	Handles the following events:
2033 *	SK_PNMI_EVT_SIRQ_OVERFLOW     When a hardware counter overflows an
2034 *	                              interrupt will be generated which is
2035 *	                              first handled by SIRQ which generates a
2036 *	                              this event. The event increments the
2037 *	                              upper 32 bit of the 64 bit counter.
2038 *	SK_PNMI_EVT_SEN_XXX           The event is generated by the I2C module
2039 *	                              when a sensor reports a warning or
2040 *	                              error. The event will store a trap
2041 *	                              message in the trap buffer.
2042 *	SK_PNMI_EVT_CHG_EST_TIMER     The timer event was initiated by this
2043 *	                              module and is used to calculate the
2044 *	                              port switches per hour.
2045 *	SK_PNMI_EVT_CLEAR_COUNTER     The event clears all counters and
2046 *	                              timestamps.
2047 *	SK_PNMI_EVT_XMAC_RESET        The event is generated by the driver
2048 *	                              before a hard reset of the XMAC is
2049 *	                              performed. All counters will be saved
2050 *	                              and added to the hardware counter
2051 *	                              values after reset to grant continuous
2052 *	                              counter values.
2053 *	SK_PNMI_EVT_RLMT_PORT_UP      Generated by RLMT to notify that a port
2054 *	                              went logically up. A trap message will
2055 *	                              be stored to the trap buffer.
2056 *	SK_PNMI_EVT_RLMT_PORT_DOWN    Generated by RLMT to notify that a port
2057 *	                              went logically down. A trap message will
2058 *	                              be stored to the trap buffer.
2059 *	SK_PNMI_EVT_RLMT_SEGMENTATION Generated by RLMT to notify that two
2060 *	                              spanning tree root bridges were
2061 *	                              detected. A trap message will be stored
2062 *	                              to the trap buffer.
2063 *	SK_PNMI_EVT_RLMT_ACTIVE_DOWN  Notifies PNMI that an active port went
2064 *	                              down. PNMI will not further add the
2065 *	                              statistic values to the virtual port.
2066 *	SK_PNMI_EVT_RLMT_ACTIVE_UP    Notifies PNMI that a port went up and
2067 *	                              is now an active port. PNMI will now
2068 *	                              add the statistic data of this port to
2069 *	                              the virtual port.
2070 *	SK_PNMI_EVT_RLMT_SET_NETS     Notifies PNMI about the net mode. The first Parameter
2071 *	                              contains the number of nets. 1 means single net, 2 means
2072 *	                              dual net. The second Parameter is -1
2073 *
2074 * Returns:
2075 *	Always 0
2076 */
2077
2078int SkPnmiEvent(
2079SK_AC *pAC,		/* Pointer to adapter context */
2080SK_IOC IoC,		/* IO context handle */
2081SK_U32 Event,		/* Event-Id */
2082SK_EVPARA Param)	/* Event dependent parameter */
2083{
2084	unsigned int	PhysPortIndex;
2085    unsigned int	MaxNetNumber;
2086	int		CounterIndex;
2087	int		Ret;
2088	SK_U16		MacStatus;
2089	SK_U64		OverflowStatus;
2090	SK_U64		Mask;
2091	SK_U32		MacCntEvent;
2092	SK_U64		Value;
2093	SK_U16		Register;
2094	SK_EVPARA	EventParam;
2095	SK_U64		NewestValue;
2096	SK_U64		OldestValue;
2097	SK_U64		Delta;
2098	SK_PNMI_ESTIMATE *pEst;
2099	SK_U32		NetIndex;
2100
2101
2102#ifdef DEBUG
2103	if (Event != SK_PNMI_EVT_XMAC_RESET) {
2104
2105		SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
2106			("PNMI: SkPnmiEvent: Called, Event=0x%x, Param=0x%x\n",
2107			(unsigned long)Event, (unsigned long)Param.Para64));
2108	}
2109#endif
2110	SK_PNMI_CHECKFLAGS("SkPnmiEvent: On call");
2111
2112	switch (Event) {
2113
2114	case SK_PNMI_EVT_SIRQ_OVERFLOW:
2115		PhysPortIndex = (int)Param.Para32[0];
2116		MacStatus = (SK_U16)Param.Para32[1];
2117#ifdef DEBUG
2118		if (PhysPortIndex >= SK_MAX_MACS) {
2119
2120			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
2121				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SIRQ_OVERFLOW parameter wrong, PhysPortIndex=0x%x\n",
2122				PhysPortIndex));
2123			return (0);
2124		}
2125#endif
2126		OverflowStatus = 0;
2127
2128		/*
2129		 * Check which source caused an overflow interrupt. The
2130		 * interrupt source is a self-clearing register. We only
2131		 * need to check the interrupt source once. Another check
2132		 * will be done by the SIRQ module to be sure that no
2133		 * interrupt get lost during process time.
2134		 */
2135		if ((MacStatus & XM_IS_RXC_OV) == XM_IS_RXC_OV) {
2136
2137			XM_IN32(IoC, PhysPortIndex, XM_RX_CNT_EV,
2138				&MacCntEvent);
2139			OverflowStatus |= (SK_U64)MacCntEvent << 32;
2140		}
2141		if ((MacStatus & XM_IS_TXC_OV) == XM_IS_TXC_OV) {
2142
2143			XM_IN32(IoC, PhysPortIndex, XM_TX_CNT_EV,
2144				&MacCntEvent);
2145			OverflowStatus |= (SK_U64)MacCntEvent;
2146		}
2147		if (OverflowStatus == 0) {
2148
2149			SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
2150			return (0);
2151		}
2152
2153		/*
2154		 * Check the overflow status register and increment
2155		 * the upper dword of corresponding counter.
2156		 */
2157		for (CounterIndex = 0; CounterIndex < sizeof(Mask) * 8;
2158			CounterIndex ++) {
2159
2160			Mask = (SK_U64)1 << CounterIndex;
2161			if ((OverflowStatus & Mask) == 0) {
2162
2163				continue;
2164			}
2165
2166			switch (CounterIndex) {
2167
2168			case SK_PNMI_HTX_UTILUNDER:
2169			case SK_PNMI_HTX_UTILOVER:
2170				XM_IN16(IoC, PhysPortIndex, XM_TX_CMD,
2171					&Register);
2172				Register |= XM_TX_SAM_LINE;
2173				XM_OUT16(IoC, PhysPortIndex, XM_TX_CMD,
2174					Register);
2175				break;
2176
2177			case SK_PNMI_HRX_UTILUNDER:
2178			case SK_PNMI_HRX_UTILOVER:
2179				XM_IN16(IoC, PhysPortIndex, XM_RX_CMD,
2180					&Register);
2181				Register |= XM_RX_SAM_LINE;
2182				XM_OUT16(IoC, PhysPortIndex, XM_RX_CMD,
2183					Register);
2184				break;
2185
2186			case SK_PNMI_HTX_OCTETHIGH:
2187			case SK_PNMI_HTX_OCTETLOW:
2188			case SK_PNMI_HTX_RESERVED26:
2189			case SK_PNMI_HTX_RESERVED27:
2190			case SK_PNMI_HTX_RESERVED28:
2191			case SK_PNMI_HTX_RESERVED29:
2192			case SK_PNMI_HTX_RESERVED30:
2193			case SK_PNMI_HTX_RESERVED31:
2194			case SK_PNMI_HRX_OCTETHIGH:
2195			case SK_PNMI_HRX_OCTETLOW:
2196			case SK_PNMI_HRX_IRLENGTH:
2197			case SK_PNMI_HRX_RESERVED22:
2198
2199			/*
2200			 * the following counters aren't be handled (id > 63)
2201			 */
2202			case SK_PNMI_HTX_SYNC:
2203			case SK_PNMI_HTX_SYNC_OCTET:
2204			case SK_PNMI_HRX_LONGFRAMES:
2205				break;
2206
2207			default:
2208				pAC->Pnmi.Port[PhysPortIndex].
2209					CounterHigh[CounterIndex] ++;
2210			}
2211		}
2212		break;
2213
2214	case SK_PNMI_EVT_SEN_WAR_LOW:
2215#ifdef DEBUG
2216		if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) {
2217
2218			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
2219				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_WAR_LOW parameter wrong, SensorIndex=%d\n",
2220				(unsigned int)Param.Para64));
2221			return (0);
2222		}
2223#endif
2224		/*
2225		 * Store a trap message in the trap buffer and generate
2226		 * an event for user space applications with the
2227		 * SK_DRIVER_SENDEVENT macro.
2228		 */
2229		QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_WAR_LOW,
2230			(unsigned int)Param.Para64);
2231		(void)SK_DRIVER_SENDEVENT(pAC, IoC);
2232		break;
2233
2234	case SK_PNMI_EVT_SEN_WAR_UPP:
2235#ifdef DEBUG
2236		if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) {
2237
2238			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
2239				("PNMI: ERR:SkPnmiEvent: SK_PNMI_EVT_SEN_WAR_UPP parameter wrong, SensorIndex=%d\n",
2240				(unsigned int)Param.Para64));
2241			return (0);
2242		}
2243#endif
2244		/*
2245		 * Store a trap message in the trap buffer and generate
2246		 * an event for user space applications with the
2247		 * SK_DRIVER_SENDEVENT macro.
2248		 */
2249		QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_WAR_UPP,
2250			(unsigned int)Param.Para64);
2251		(void)SK_DRIVER_SENDEVENT(pAC, IoC);
2252		break;
2253
2254	case SK_PNMI_EVT_SEN_ERR_LOW:
2255#ifdef DEBUG
2256		if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) {
2257
2258			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
2259				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_ERR_LOW parameter wrong, SensorIndex=%d\n",
2260				(unsigned int)Param.Para64));
2261			return (0);
2262		}
2263#endif
2264		/*
2265		 * Store a trap message in the trap buffer and generate
2266		 * an event for user space applications with the
2267		 * SK_DRIVER_SENDEVENT macro.
2268		 */
2269		QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_ERR_LOW,
2270			(unsigned int)Param.Para64);
2271		(void)SK_DRIVER_SENDEVENT(pAC, IoC);
2272		break;
2273
2274	case SK_PNMI_EVT_SEN_ERR_UPP:
2275#ifdef DEBUG
2276		if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) {
2277
2278			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
2279				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_ERR_UPP parameter wrong, SensorIndex=%d\n",
2280				(unsigned int)Param.Para64));
2281			return (0);
2282		}
2283#endif
2284		/*
2285		 * Store a trap message in the trap buffer and generate
2286		 * an event for user space applications with the
2287		 * SK_DRIVER_SENDEVENT macro.
2288		 */
2289		QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_ERR_UPP,
2290			(unsigned int)Param.Para64);
2291		(void)SK_DRIVER_SENDEVENT(pAC, IoC);
2292		break;
2293
2294	case SK_PNMI_EVT_CHG_EST_TIMER:
2295		/*
2296		 * Calculate port switch average on a per hour basis
2297		 *   Time interval for check       : 28125 ms
2298		 *   Number of values for average  : 8
2299		 *
2300		 * Be careful in changing these values, on change check
2301		 *   - typedef of SK_PNMI_ESTIMATE (Size of EstValue
2302		 *     array one less than value number)
2303		 *   - Timer initilization SkTimerStart() in SkPnmiInit
2304		 *   - Delta value below must be multiplicated with
2305		 *     power of 2
2306		 *
2307		 */
2308		pEst = &pAC->Pnmi.RlmtChangeEstimate;
2309		CounterIndex = pEst->EstValueIndex + 1;
2310		if (CounterIndex == 7) {
2311
2312			CounterIndex = 0;
2313		}
2314		pEst->EstValueIndex = CounterIndex;
2315
2316		NewestValue = pAC->Pnmi.RlmtChangeCts;
2317		OldestValue = pEst->EstValue[CounterIndex];
2318		pEst->EstValue[CounterIndex] = NewestValue;
2319
2320		/*
2321		 * Calculate average. Delta stores the number of
2322		 * port switches per 28125 * 8 = 225000 ms
2323		 */
2324		if (NewestValue >= OldestValue) {
2325
2326			Delta = NewestValue - OldestValue;
2327		}
2328		else {
2329			/* Overflow situation */
2330			Delta = (SK_U64)(0 - OldestValue) + NewestValue;
2331		}
2332
2333		/*
2334		 * Extrapolate delta to port switches per hour.
2335		 *     Estimate = Delta * (3600000 / 225000)
2336		 *              = Delta * 16
2337		 *              = Delta << 4
2338		 */
2339		pAC->Pnmi.RlmtChangeEstimate.Estimate = Delta << 4;
2340
2341		/*
2342		 * Check if threshold is exceeded. If the threshold is
2343		 * permanently exceeded every 28125 ms an event will be
2344		 * generated to remind the user of this condition.
2345		 */
2346		if ((pAC->Pnmi.RlmtChangeThreshold != 0) &&
2347			(pAC->Pnmi.RlmtChangeEstimate.Estimate >=
2348			pAC->Pnmi.RlmtChangeThreshold)) {
2349
2350			QueueSimpleTrap(pAC, OID_SKGE_TRAP_RLMT_CHANGE_THRES);
2351			(void)SK_DRIVER_SENDEVENT(pAC, IoC);
2352		}
2353
2354		SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
2355		SkTimerStart(pAC, IoC, &pAC->Pnmi.RlmtChangeEstimate.EstTimer,
2356			28125000, SKGE_PNMI, SK_PNMI_EVT_CHG_EST_TIMER,
2357			EventParam);
2358		break;
2359
2360	case SK_PNMI_EVT_CLEAR_COUNTER:
2361		/*
2362		 *  Param.Para32[0] contains the NetIndex (0 ..1).
2363		 *  Param.Para32[1] is reserved, contains -1.
2364		 */
2365		NetIndex = (SK_U32)Param.Para32[0];
2366
2367#ifdef DEBUG
2368		if (NetIndex >= pAC->Rlmt.NumNets) {
2369
2370			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
2371				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_CLEAR_COUNTER parameter wrong, NetIndex=%d\n",
2372				NetIndex));
2373
2374			return (0);
2375		}
2376#endif
2377
2378		/*
2379		 * Set all counters and timestamps to zero
2380		 */
2381		ResetCounter(pAC, IoC, NetIndex); /* the according NetIndex is required
2382												as a Parameter of the Event */
2383		break;
2384
2385	case SK_PNMI_EVT_XMAC_RESET:
2386		/*
2387		 * To grant continuous counter values store the current
2388		 * XMAC statistic values to the entries 1..n of the
2389		 * CounterOffset array. XMAC Errata #2
2390		 */
2391#ifdef DEBUG
2392		if ((unsigned int)Param.Para64 >= SK_MAX_MACS) {
2393
2394			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
2395				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_XMAC_RESET parameter wrong, PhysPortIndex=%d\n",
2396				(unsigned int)Param.Para64));
2397			return (0);
2398		}
2399#endif
2400		PhysPortIndex = (unsigned int)Param.Para64;
2401
2402		/*
2403		 * Update XMAC statistic to get fresh values
2404		 */
2405		Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1);
2406		if (Ret != SK_PNMI_ERR_OK) {
2407
2408			SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
2409			return (0);
2410		}
2411		/*
2412		 * Increment semaphore to indicate that an update was
2413		 * already done
2414		 */
2415		pAC->Pnmi.MacUpdatedFlag ++;
2416
2417		for (CounterIndex = 0; CounterIndex < SK_PNMI_SCNT_NOT;
2418			CounterIndex ++) {
2419
2420			if (!StatAddress[CounterIndex].GetOffset) {
2421
2422				continue;
2423			}
2424
2425			pAC->Pnmi.Port[PhysPortIndex].
2426				CounterOffset[CounterIndex] = GetPhysStatVal(
2427				pAC, IoC, PhysPortIndex, CounterIndex);
2428			pAC->Pnmi.Port[PhysPortIndex].
2429				CounterHigh[CounterIndex] = 0;
2430		}
2431
2432		pAC->Pnmi.MacUpdatedFlag --;
2433		break;
2434
2435	case SK_PNMI_EVT_RLMT_PORT_UP:
2436#ifdef DEBUG
2437		if ((unsigned int)Param.Para32[0] >= SK_MAX_MACS) {
2438
2439			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
2440				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_PORT_UP parameter wrong, PhysPortIndex=%d\n",
2441				(unsigned int)Param.Para32[0]));
2442
2443			return (0);
2444		}
2445#endif
2446		/*
2447		 * Store a trap message in the trap buffer and generate an event for
2448		 * user space applications with the SK_DRIVER_SENDEVENT macro.
2449		 */
2450		QueueRlmtPortTrap(pAC, OID_SKGE_TRAP_RLMT_PORT_UP,
2451			(unsigned int)Param.Para32[0]);
2452		(void)SK_DRIVER_SENDEVENT(pAC, IoC);
2453		break;
2454
2455	case SK_PNMI_EVT_RLMT_PORT_DOWN:
2456#ifdef DEBUG
2457		if ((unsigned int)Param.Para32[0] >= SK_MAX_MACS) {
2458
2459			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
2460				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_PORT_DOWN parameter wrong, PhysPortIndex=%d\n",
2461				(unsigned int)Param.Para32[0]));
2462
2463			return (0);
2464		}
2465#endif
2466		/*
2467		 * Store a trap message in the trap buffer and generate an event for
2468		 * user space applications with the SK_DRIVER_SENDEVENT macro.
2469		 */
2470		QueueRlmtPortTrap(pAC, OID_SKGE_TRAP_RLMT_PORT_DOWN,
2471			(unsigned int)Param.Para32[0]);
2472		(void)SK_DRIVER_SENDEVENT(pAC, IoC);
2473		break;
2474
2475	case SK_PNMI_EVT_RLMT_ACTIVE_DOWN:
2476		PhysPortIndex = (unsigned int)Param.Para32[0];
2477		NetIndex = (SK_U32)Param.Para32[1];
2478#ifdef DEBUG
2479		if (PhysPortIndex >= SK_MAX_MACS) {
2480
2481			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
2482				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_DOWN parameter too high, PhysPort=%d\n",
2483				PhysPortIndex));
2484		}
2485
2486		if (NetIndex >= pAC->Rlmt.NumNets) {
2487
2488			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
2489				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_DOWN parameter too high, NetIndex=%d\n",
2490				NetIndex));
2491		}
2492#endif
2493		/*
2494		 * For now, ignore event if NetIndex != 0.
2495		 */
2496		if (Param.Para32[1] != 0) {
2497
2498			return (0);
2499		}
2500
2501		/*
2502		 * Nothing to do if port is already inactive
2503		 */
2504		if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
2505
2506			return (0);
2507		}
2508
2509		/*
2510		 * Update statistic counters to calculate new offset for the virtual
2511		 * port and increment semaphore to indicate that an update was already
2512		 * done.
2513		 */
2514		if (MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1) !=
2515			SK_PNMI_ERR_OK) {
2516
2517			SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
2518			return (0);
2519		}
2520		pAC->Pnmi.MacUpdatedFlag ++;
2521
2522		/*
2523		 * Calculate new counter offset for virtual port to grant continous
2524		 * counting on port switches. The virtual port consists of all currently
2525		 * active ports. The port down event indicates that a port is removed
2526		 * from the virtual port. Therefore add the counter value of the removed
2527		 * port to the CounterOffset for the virtual port to grant the same
2528		 * counter value.
2529		 */
2530		for (CounterIndex = 0; CounterIndex < SK_PNMI_MAX_IDX;
2531			CounterIndex ++) {
2532
2533			if (!StatAddress[CounterIndex].GetOffset) {
2534
2535				continue;
2536			}
2537
2538			Value = GetPhysStatVal(pAC, IoC, PhysPortIndex, CounterIndex);
2539
2540			pAC->Pnmi.VirtualCounterOffset[CounterIndex] += Value;
2541		}
2542
2543		/*
2544		 * Set port to inactive
2545		 */
2546		pAC->Pnmi.Port[PhysPortIndex].ActiveFlag = SK_FALSE;
2547
2548		pAC->Pnmi.MacUpdatedFlag --;
2549		break;
2550
2551	case SK_PNMI_EVT_RLMT_ACTIVE_UP:
2552		PhysPortIndex = (unsigned int)Param.Para32[0];
2553		NetIndex = (SK_U32)Param.Para32[1];
2554#ifdef DEBUG
2555		if (PhysPortIndex >= SK_MAX_MACS) {
2556
2557			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
2558				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_UP parameter too high, PhysPort=%d\n",
2559				PhysPortIndex));
2560		}
2561
2562		if (NetIndex >= pAC->Rlmt.NumNets) {
2563
2564			SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
2565				("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_UP parameter too high, NetIndex=%d\n",
2566				NetIndex));
2567		}
2568#endif
2569		/*
2570		 * For now, ignore event if NetIndex != 0.
2571		 */
2572		if (Param.Para32[1] != 0) {
2573
2574			return (0);
2575		}
2576
2577		/*
2578		 * Nothing to do if port is already active
2579		 */
2580		if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
2581
2582			return (0);
2583		}
2584
2585		/*
2586		 * Statistic maintenance
2587		 */
2588		pAC->Pnmi.RlmtChangeCts ++;
2589		pAC->Pnmi.RlmtChangeTime = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC));
2590
2591		/*
2592		 * Store a trap message in the trap buffer and generate an event for
2593		 * user space applications with the SK_DRIVER_SENDEVENT macro.
2594		 */
2595		QueueRlmtNewMacTrap(pAC, PhysPortIndex);
2596		(void)SK_DRIVER_SENDEVENT(pAC, IoC);
2597
2598		/*
2599		 * Update statistic counters to calculate new offset for the virtual
2600		 * port and increment semaphore to indicate that an update was
2601		 * already done.
2602		 */
2603		if (MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1) !=
2604			SK_PNMI_ERR_OK) {
2605
2606			SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
2607			return (0);
2608		}
2609		pAC->Pnmi.MacUpdatedFlag ++;
2610
2611		/*
2612		 * Calculate new counter offset for virtual port to grant continous
2613		 * counting on port switches. A new port is added to the virtual port.
2614		 * Therefore substract the counter value of the new port from the
2615		 * CounterOffset for the virtual port to grant the same value.
2616		 */
2617		for (CounterIndex = 0; CounterIndex < SK_PNMI_MAX_IDX;
2618			CounterIndex ++) {
2619
2620			if (!StatAddress[CounterIndex].GetOffset) {
2621
2622				continue;
2623			}
2624
2625			Value = GetPhysStatVal(pAC, IoC, PhysPortIndex, CounterIndex);
2626
2627			pAC->Pnmi.VirtualCounterOffset[CounterIndex] -= Value;
2628		}
2629
2630		/*
2631		 * Set port to active
2632		 */
2633		pAC->Pnmi.Port[PhysPortIndex].ActiveFlag = SK_TRUE;
2634
2635		pAC->Pnmi.MacUpdatedFlag --;
2636		break;
2637
2638	case SK_PNMI_EVT_RLMT_SEGMENTATION:
2639		/*
2640		 * Para.Para32[0] contains the NetIndex.
2641		 */
2642
2643		/*
2644		 * Store a trap message in the trap buffer and generate an event for
2645		 * user space applications with the SK_DRIVER_SENDEVENT macro.
2646		 */
2647		QueueSimpleTrap(pAC, OID_SKGE_TRAP_RLMT_SEGMENTATION);
2648		(void)SK_DRIVER_SENDEVENT(pAC, IoC);
2649		break;
2650
2651    case SK_PNMI_EVT_RLMT_SET_NETS:
2652		/*
2653		 *  Param.Para32[0] contains the number of Nets.
2654		 *  Param.Para32[1] is reserved, contains -1.
2655		 */
2656	    /*
2657    	 * Check number of nets
2658		 */
2659		MaxNetNumber = pAC->GIni.GIMacsFound;
2660		if (((unsigned int)Param.Para32[0] < 1)
2661			|| ((unsigned int)Param.Para32[0] > MaxNetNumber)) {
2662			return (SK_PNMI_ERR_UNKNOWN_NET);
2663		}
2664
2665        if((unsigned int)Param.Para32[0] == 1){ /* single net mode */
2666        	pAC->Pnmi.DualNetActiveFlag = SK_FALSE;
2667        }
2668        else { /* dual net mode */
2669        	pAC->Pnmi.DualNetActiveFlag = SK_TRUE;
2670        }
2671        break;
2672
2673	default:
2674		break;
2675	}
2676
2677	SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
2678	return (0);
2679}
2680
2681
2682/******************************************************************************
2683 *
2684 * Private functions
2685 *
2686 */
2687
2688/*****************************************************************************
2689 *
2690 * PnmiVar - Gets, presets, and sets single OIDs
2691 *
2692 * Description:
2693 *	Looks up the requested OID, calls the corresponding handler
2694 *	function, and passes the parameters with the get, preset, or
2695 *	set command. The function is called by SkGePnmiGetVar,
2696 *	SkGePnmiPreSetVar, or SkGePnmiSetVar.
2697 *
2698 * Returns:
2699 *	SK_PNMI_ERR_XXX. For details have a look to the description of the
2700 *	calling functions.
2701 *	SK_PNMI_ERR_UNKNOWN_NET  The requested NetIndex doesn't exist
2702 */
2703
2704static int PnmiVar(
2705SK_AC *pAC,		/* Pointer to adapter context */
2706SK_IOC IoC,		/* IO context handle */
2707int Action,		/* Get/PreSet/Set action */
2708SK_U32 Id,		/* Object ID that is to be processed */
2709char *pBuf,		/* Buffer which stores the mgmt data to be set */
2710unsigned int *pLen,	/* Total length of mgmt data */
2711SK_U32 Instance,	/* Instance (1..n) that is to be set or -1 */
2712SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode allways zero */
2713{
2714	unsigned int	TableIndex;
2715	int		Ret;
2716
2717
2718	if ((TableIndex = LookupId(Id)) == (unsigned int)(-1)) {
2719
2720		*pLen = 0;
2721		return (SK_PNMI_ERR_UNKNOWN_OID);
2722	}
2723
2724    /*
2725     * Check NetIndex
2726     */
2727	if (NetIndex >= pAC->Rlmt.NumNets) {
2728		return (SK_PNMI_ERR_UNKNOWN_NET);
2729	}
2730
2731	SK_PNMI_CHECKFLAGS("PnmiVar: On call");
2732
2733	Ret = IdTable[TableIndex].Func(pAC, IoC, Action, Id, pBuf, pLen,
2734		Instance, TableIndex, NetIndex);
2735
2736	SK_PNMI_CHECKFLAGS("PnmiVar: On return");
2737
2738	return (Ret);
2739}
2740
2741/*****************************************************************************
2742 *
2743 * PnmiStruct - Presets and Sets data in structure SK_PNMI_STRUCT_DATA
2744 *
2745 * Description:
2746 *	The return value of the function will also be stored in
2747 *	SK_PNMI_STRUCT_DATA if the passed buffer has the minimum size of
2748 *	SK_PNMI_MIN_STRUCT_SIZE. The sub-function runs through the IdTable,
2749 *	checks which OIDs are able to set, and calls the handler function of
2750 *	the OID to perform the set. The return value of the function will
2751 *	also be stored in SK_PNMI_STRUCT_DATA if the passed buffer has the
2752 *	minimum size of SK_PNMI_MIN_STRUCT_SIZE. The function is called
2753 *	by SkGePnmiPreSetStruct and SkGePnmiSetStruct.
2754 *
2755 * Returns:
2756 *	SK_PNMI_ERR_XXX. The codes are described in the calling functions.
2757 *	SK_PNMI_ERR_UNKNOWN_NET  The requested NetIndex doesn't exist
2758 */
2759
2760static int PnmiStruct(
2761SK_AC *pAC,		/* Pointer to adapter context */
2762SK_IOC IoC,		/* IO context handle */
2763int  Action,		/* Set action to be performed */
2764char *pBuf,		/* Buffer which contains the data to be set */
2765unsigned int *pLen,	/* Length of buffer */
2766SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode allways zero */
2767{
2768	int		Ret;
2769	unsigned int	TableIndex;
2770	unsigned int	DstOffset;
2771	unsigned int	Len;
2772	unsigned int	InstanceNo;
2773	unsigned int	InstanceCnt;
2774	SK_U32		Instance;
2775	SK_U32		Id;
2776
2777
2778	/* Check if the passed buffer has the right size */
2779	if (*pLen < SK_PNMI_STRUCT_SIZE) {
2780
2781		/* Check if we can return the error within the buffer */
2782		if (*pLen >= SK_PNMI_MIN_STRUCT_SIZE) {
2783
2784			SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_TOO_SHORT,
2785				(SK_U32)(-1));
2786		}
2787
2788		*pLen = SK_PNMI_STRUCT_SIZE;
2789		return (SK_PNMI_ERR_TOO_SHORT);
2790	}
2791
2792    /*
2793     * Check NetIndex
2794     */
2795	if (NetIndex >= pAC->Rlmt.NumNets) {
2796		return (SK_PNMI_ERR_UNKNOWN_NET);
2797	}
2798
2799	SK_PNMI_CHECKFLAGS("PnmiStruct: On call");
2800
2801	/*
2802	 * Update the values of RLMT and SIRQ and increment semaphores to
2803	 * indicate that an update was already done.
2804	 */
2805	if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) {
2806
2807		SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
2808		*pLen = SK_PNMI_MIN_STRUCT_SIZE;
2809		return (Ret);
2810	}
2811
2812	if ((Ret = SirqUpdate(pAC, IoC)) != SK_PNMI_ERR_OK) {
2813
2814		SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
2815		*pLen = SK_PNMI_MIN_STRUCT_SIZE;
2816		return (Ret);
2817	}
2818
2819	pAC->Pnmi.RlmtUpdatedFlag ++;
2820	pAC->Pnmi.SirqUpdatedFlag ++;
2821
2822	/* Preset/Set values */
2823	for (TableIndex = 0; TableIndex < sizeof(IdTable)/sizeof(IdTable[0]);
2824		TableIndex ++) {
2825
2826		if (IdTable[TableIndex].Access != SK_PNMI_RW) {
2827
2828			continue;
2829		}
2830
2831		InstanceNo = IdTable[TableIndex].InstanceNo;
2832		Id = IdTable[TableIndex].Id;
2833
2834		for (InstanceCnt = 1; InstanceCnt <= InstanceNo;
2835			InstanceCnt ++) {
2836
2837			DstOffset = IdTable[TableIndex].Offset +
2838				(InstanceCnt - 1) *
2839				IdTable[TableIndex].StructSize;
2840
2841			/*
2842			 * Because VPD multiple instance variables are
2843			 * not setable we do not need to evaluate VPD
2844			 * instances. Have a look to VPD instance
2845			 * calculation in SkPnmiGetStruct().
2846			 */
2847			Instance = (SK_U32)InstanceCnt;
2848
2849			/*
2850			 * Evaluate needed buffer length
2851			 */
2852			Len = 0;
2853			Ret = IdTable[TableIndex].Func(pAC, IoC,
2854				SK_PNMI_GET, IdTable[TableIndex].Id,
2855				NULL, &Len, Instance, TableIndex, NetIndex);
2856
2857			if (Ret == SK_PNMI_ERR_UNKNOWN_INST) {
2858
2859				break;
2860			}
2861			if (Ret != SK_PNMI_ERR_TOO_SHORT) {
2862
2863				pAC->Pnmi.RlmtUpdatedFlag --;
2864				pAC->Pnmi.SirqUpdatedFlag --;
2865
2866				SK_PNMI_CHECKFLAGS("PnmiStruct: On return");
2867				SK_PNMI_SET_STAT(pBuf,
2868					SK_PNMI_ERR_GENERAL, DstOffset);
2869				*pLen = SK_PNMI_MIN_STRUCT_SIZE;
2870				return (SK_PNMI_ERR_GENERAL);
2871			}
2872			if (Id == OID_SKGE_VPD_ACTION) {
2873
2874				switch (*(pBuf + DstOffset)) {
2875
2876				case SK_PNMI_VPD_CREATE:
2877					Len = 3 + *(pBuf + DstOffset + 3);
2878					break;
2879
2880				case SK_PNMI_VPD_DELETE:
2881					Len = 3;
2882					break;
2883
2884				default:
2885					Len = 1;
2886					break;
2887				}
2888			}
2889
2890			/* Call the OID handler function */
2891			Ret = IdTable[TableIndex].Func(pAC, IoC, Action,
2892				IdTable[TableIndex].Id, pBuf + DstOffset,
2893				&Len, Instance, TableIndex, NetIndex);
2894
2895			if (Ret != SK_PNMI_ERR_OK) {
2896
2897				pAC->Pnmi.RlmtUpdatedFlag --;
2898				pAC->Pnmi.SirqUpdatedFlag --;
2899
2900				SK_PNMI_CHECKFLAGS("PnmiStruct: On return");
2901				SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_BAD_VALUE,
2902					DstOffset);
2903				*pLen = SK_PNMI_MIN_STRUCT_SIZE;
2904				return (SK_PNMI_ERR_BAD_VALUE);
2905			}
2906		}
2907	}
2908
2909	pAC->Pnmi.RlmtUpdatedFlag --;
2910	pAC->Pnmi.SirqUpdatedFlag --;
2911
2912	SK_PNMI_CHECKFLAGS("PnmiStruct: On return");
2913	SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_OK, (SK_U32)(-1));
2914	return (SK_PNMI_ERR_OK);
2915}
2916
2917/*****************************************************************************
2918 *
2919 * LookupId - Lookup an OID in the IdTable
2920 *
2921 * Description:
2922 *	Scans the IdTable to find the table entry of an OID.
2923 *
2924 * Returns:
2925 *	The table index or -1 if not found.
2926 */
2927
2928static int LookupId(
2929SK_U32 Id)		/* Object identifier to be searched */
2930{
2931	int i;
2932	int Len = sizeof(IdTable)/sizeof(IdTable[0]);
2933
2934	for (i=0; i<Len; i++) {
2935
2936		if (IdTable[i].Id == Id) {
2937
2938			return i;
2939		}
2940	}
2941
2942	return (-1);
2943}
2944
2945/*****************************************************************************
2946 *
2947 * OidStruct - Handler of OID_SKGE_ALL_DATA
2948 *
2949 * Description:
2950 *	This OID performs a Get/Preset/SetStruct call and returns all data
2951 *	in a SK_PNMI_STRUCT_DATA structure.
2952 *
2953 * Returns:
2954 *	SK_PNMI_ERR_OK           The request was successfully performed.
2955 *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
2956 *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
2957 *	                         the correct data (e.g. a 32bit value is
2958 *	                         needed, but a 16 bit value was passed).
2959 *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
2960 *	                         value range.
2961 *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
2962 *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
2963 *                               exist (e.g. port instance 3 on a two port
2964 *	                         adapter.
2965 */
2966
2967static int OidStruct(
2968SK_AC *pAC,		/* Pointer to adapter context */
2969SK_IOC IoC,		/* IO context handle */
2970int Action,		/* Get/PreSet/Set action */
2971SK_U32 Id,		/* Object ID that is to be processed */
2972char *pBuf,		/* Buffer to which to mgmt data will be retrieved */
2973unsigned int *pLen,	/* On call: buffer length. On return: used buffer */
2974SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
2975unsigned int TableIndex, /* Index to the Id table */
2976SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode allways zero */
2977{
2978	if (Id != OID_SKGE_ALL_DATA) {
2979
2980		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR003,
2981			SK_PNMI_ERR003MSG);
2982
2983		*pLen = 0;
2984		return (SK_PNMI_ERR_GENERAL);
2985	}
2986
2987	/*
2988	 * Check instance. We only handle single instance variables
2989	 */
2990	if (Instance != (SK_U32)(-1) && Instance != 1) {
2991
2992		*pLen = 0;
2993		return (SK_PNMI_ERR_UNKNOWN_INST);
2994	}
2995
2996	switch (Action) {
2997
2998	case SK_PNMI_GET:
2999		return (SkPnmiGetStruct(pAC, IoC, pBuf, pLen, NetIndex));
3000
3001	case SK_PNMI_PRESET:
3002		return (SkPnmiPreSetStruct(pAC, IoC, pBuf, pLen, NetIndex));
3003
3004	case SK_PNMI_SET:
3005		return (SkPnmiSetStruct(pAC, IoC, pBuf, pLen, NetIndex));
3006	}
3007
3008	SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR004, SK_PNMI_ERR004MSG);
3009
3010	*pLen = 0;
3011	return (SK_PNMI_ERR_GENERAL);
3012}
3013
3014/*****************************************************************************
3015 *
3016 * Perform - OID handler of OID_SKGE_ACTION
3017 *
3018 * Description:
3019 *	None.
3020 *
3021 * Returns:
3022 *	SK_PNMI_ERR_OK           The request was successfully performed.
3023 *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
3024 *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
3025 *	                         the correct data (e.g. a 32bit value is
3026 *	                         needed, but a 16 bit value was passed).
3027 *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
3028 *	                         value range.
3029 *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
3030 *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
3031 *                               exist (e.g. port instance 3 on a two port
3032 *	                         adapter.
3033 */
3034
3035static int Perform(
3036SK_AC *pAC,		/* Pointer to adapter context */
3037SK_IOC IoC,		/* IO context handle */
3038int Action,		/* Get/PreSet/Set action */
3039SK_U32 Id,		/* Object ID that is to be processed */
3040char *pBuf,		/* Buffer to which to mgmt data will be retrieved */
3041unsigned int *pLen,	/* On call: buffer length. On return: used buffer */
3042SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
3043unsigned int TableIndex, /* Index to the Id table */
3044SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode allways zero */
3045{
3046	int	Ret;
3047	SK_U32	ActionOp;
3048
3049
3050	/*
3051	 * Check instance. We only handle single instance variables
3052	 */
3053	if (Instance != (SK_U32)(-1) && Instance != 1) {
3054
3055		*pLen = 0;
3056		return (SK_PNMI_ERR_UNKNOWN_INST);
3057	}
3058
3059	if (*pLen < sizeof(SK_U32)) {
3060
3061		*pLen = sizeof(SK_U32);
3062		return (SK_PNMI_ERR_TOO_SHORT);
3063	}
3064
3065	/* Check if a get should be performed */
3066	if (Action == SK_PNMI_GET) {
3067
3068		/* A get is easy. We always return the same value */
3069		ActionOp = (SK_U32)SK_PNMI_ACT_IDLE;
3070		SK_PNMI_STORE_U32(pBuf, ActionOp);
3071		*pLen = sizeof(SK_U32);
3072
3073		return (SK_PNMI_ERR_OK);
3074	}
3075
3076	/* Continue with PRESET/SET action */
3077	if (*pLen > sizeof(SK_U32)) {
3078
3079		return (SK_PNMI_ERR_BAD_VALUE);
3080	}
3081
3082	/* Check if the command is a known one */
3083	SK_PNMI_READ_U32(pBuf, ActionOp);
3084	if (*pLen > sizeof(SK_U32) ||
3085		(ActionOp != SK_PNMI_ACT_IDLE &&
3086		ActionOp != SK_PNMI_ACT_RESET &&
3087		ActionOp != SK_PNMI_ACT_SELFTEST &&
3088		ActionOp != SK_PNMI_ACT_RESETCNT)) {
3089
3090		*pLen = 0;
3091		return (SK_PNMI_ERR_BAD_VALUE);
3092	}
3093
3094	/* A preset ends here */
3095	if (Action == SK_PNMI_PRESET) {
3096
3097		return (SK_PNMI_ERR_OK);
3098	}
3099
3100	switch (ActionOp) {
3101
3102	case SK_PNMI_ACT_IDLE:
3103		/* Nothing to do */
3104		break;
3105
3106	case SK_PNMI_ACT_RESET:
3107		/*
3108		 * Perform a driver reset or something that comes near
3109		 * to this.
3110		 */
3111		Ret = SK_DRIVER_RESET(pAC, IoC);
3112		if (Ret != 0) {
3113
3114			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR005,
3115				SK_PNMI_ERR005MSG);
3116
3117			return (SK_PNMI_ERR_GENERAL);
3118		}
3119		break;
3120
3121	case SK_PNMI_ACT_SELFTEST:
3122		/*
3123		 * Perform a driver selftest or something similar to this.
3124		 * Currently this feature is not used and will probably
3125		 * implemented in another way.
3126		 */
3127		Ret = SK_DRIVER_SELFTEST(pAC, IoC);
3128		pAC->Pnmi.TestResult = Ret;
3129		break;
3130
3131	case SK_PNMI_ACT_RESETCNT:
3132		/* Set all counters and timestamps to zero */
3133		ResetCounter(pAC, IoC, NetIndex);
3134		break;
3135
3136	default:
3137		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR006,
3138			SK_PNMI_ERR006MSG);
3139
3140		return (SK_PNMI_ERR_GENERAL);
3141	}
3142
3143	return (SK_PNMI_ERR_OK);
3144}
3145
3146/*****************************************************************************
3147 *
3148 * Mac8023Stat - OID handler of OID_GEN_XXX and OID_802_3_XXX
3149 *
3150 * Description:
3151 *	Retrieves the statistic values of the virtual port (logical
3152 *	index 0). Only special OIDs of NDIS are handled which consist
3153 *	of a 32 bit instead of a 64 bit value. The OIDs are public
3154 *	because perhaps some other platform can use them too.
3155 *
3156 * Returns:
3157 *	SK_PNMI_ERR_OK           The request was successfully performed.
3158 *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
3159 *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
3160 *	                         the correct data (e.g. a 32bit value is
3161 *	                         needed, but a 16 bit value was passed).
3162 *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
3163 *                               exist (e.g. port instance 3 on a two port
3164 *	                         adapter.
3165 */
3166
3167static int Mac8023Stat(
3168SK_AC *pAC,		/* Pointer to adapter context */
3169SK_IOC IoC,		/* IO context handle */
3170int Action,		/* Get/PreSet/Set action */
3171SK_U32 Id,		/* Object ID that is to be processed */
3172char *pBuf,		/* Buffer to which to mgmt data will be retrieved */
3173unsigned int *pLen,	/* On call: buffer length. On return: used buffer */
3174SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
3175unsigned int TableIndex,	/* Index to the Id table */
3176SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode allways zero */
3177{
3178	int    Ret;
3179	SK_U64 StatVal;
3180	SK_BOOL Is64BitReq = SK_FALSE;
3181
3182	/*
3183	 * Only the active Mac is returned
3184	 */
3185	if (Instance != (SK_U32)(-1) && Instance != 1) {
3186
3187		*pLen = 0;
3188		return (SK_PNMI_ERR_UNKNOWN_INST);
3189	}
3190
3191	/*
3192	 * Check action type
3193	 */
3194	if (Action != SK_PNMI_GET) {
3195
3196		*pLen = 0;
3197		return (SK_PNMI_ERR_READ_ONLY);
3198	}
3199
3200	/*
3201	 * Check length
3202	 */
3203	switch (Id) {
3204
3205	case OID_802_3_PERMANENT_ADDRESS:
3206	case OID_802_3_CURRENT_ADDRESS:
3207		if (*pLen < sizeof(SK_MAC_ADDR)) {
3208
3209			*pLen = sizeof(SK_MAC_ADDR);
3210			return (SK_PNMI_ERR_TOO_SHORT);
3211		}
3212		break;
3213
3214	default:
3215#ifndef SK_NDIS_64BIT_CTR
3216		if (*pLen < sizeof(SK_U32)) {
3217			*pLen = sizeof(SK_U32);
3218			return (SK_PNMI_ERR_TOO_SHORT);
3219		}
3220
3221#else /* SK_NDIS_64BIT_CTR */
3222
3223		/*
3224		 * for compatibility, at least 32bit are required for oid
3225		 */
3226		if (*pLen < sizeof(SK_U32)) {
3227			/*
3228			* but indicate handling for 64bit values,
3229			* if insufficient space is provided
3230			*/
3231			*pLen = sizeof(SK_U64);
3232			return (SK_PNMI_ERR_TOO_SHORT);
3233		}
3234
3235		Is64BitReq = (*pLen < sizeof(SK_U64)) ? SK_FALSE : SK_TRUE;
3236#endif /* SK_NDIS_64BIT_CTR */
3237		break;
3238	}
3239
3240	/*
3241	 * Update all statistics, because we retrieve virtual MAC, which
3242	 * consists of multiple physical statistics and increment semaphore
3243	 * to indicate that an update was already done.
3244	 */
3245	Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1);
3246	if ( Ret != SK_PNMI_ERR_OK) {
3247
3248		*pLen = 0;
3249		return (Ret);
3250	}
3251	pAC->Pnmi.MacUpdatedFlag ++;
3252
3253	/*
3254	 * Get value (MAC Index 0 identifies the virtual MAC)
3255	 */
3256	switch (Id) {
3257
3258	case OID_802_3_PERMANENT_ADDRESS:
3259		CopyMac(pBuf, &pAC->Addr.Net[NetIndex].PermanentMacAddress);
3260		*pLen = sizeof(SK_MAC_ADDR);
3261		break;
3262
3263	case OID_802_3_CURRENT_ADDRESS:
3264		CopyMac(pBuf, &pAC->Addr.Net[NetIndex].CurrentMacAddress);
3265		*pLen = sizeof(SK_MAC_ADDR);
3266		break;
3267
3268	default:
3269		StatVal = GetStatVal(pAC, IoC, 0, IdTable[TableIndex].Param, NetIndex);
3270
3271		/*
3272		 * by default 32bit values are evaluated
3273		 */
3274		if (!Is64BitReq) {
3275			SK_U32	StatVal32;
3276			StatVal32 = (SK_U32)StatVal;
3277			SK_PNMI_STORE_U32(pBuf, StatVal32);
3278			*pLen = sizeof(SK_U32);
3279		}
3280		else {
3281			SK_PNMI_STORE_U64(pBuf, StatVal);
3282			*pLen = sizeof(SK_U64);
3283		}
3284		break;
3285	}
3286
3287	pAC->Pnmi.MacUpdatedFlag --;
3288
3289	return (SK_PNMI_ERR_OK);
3290}
3291
3292/*****************************************************************************
3293 *
3294 * MacPrivateStat - OID handler function of OID_SKGE_STAT_XXX
3295 *
3296 * Description:
3297 *	Retrieves the XMAC statistic data.
3298 *
3299 * Returns:
3300 *	SK_PNMI_ERR_OK           The request was successfully performed.
3301 *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
3302 *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
3303 *	                         the correct data (e.g. a 32bit value is
3304 *	                         needed, but a 16 bit value was passed).
3305 *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
3306 *                               exist (e.g. port instance 3 on a two port
3307 *	                         adapter.
3308 */
3309
3310static int MacPrivateStat(
3311SK_AC *pAC,		/* Pointer to adapter context */
3312SK_IOC IoC,		/* IO context handle */
3313int Action,		/* Get/PreSet/Set action */
3314SK_U32 Id,		/* Object ID that is to be processed */
3315char *pBuf,		/* Buffer to which to mgmt data will be retrieved */
3316unsigned int *pLen,	/* On call: buffer length. On return: used buffer */
3317SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
3318unsigned int TableIndex, /* Index to the Id table */
3319SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode allways zero */
3320{
3321	unsigned int	LogPortMax;
3322	unsigned int	LogPortIndex;
3323	unsigned int	PhysPortMax;
3324	unsigned int	Limit;
3325	unsigned int	Offset;
3326	int		Ret;
3327	SK_U64		StatVal;
3328
3329
3330	/*
3331	 * Calculate instance if wished. MAC index 0 is the virtual
3332	 * MAC.
3333	 */
3334	PhysPortMax = pAC->GIni.GIMacsFound;
3335	LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax);
3336
3337	if(pAC->Pnmi.DualNetActiveFlag == SK_TRUE){ /* Dual net mode */
3338		LogPortMax--;
3339	}
3340
3341	if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried */
3342		/* Check instance range */
3343		if ((Instance < 1) || (Instance > LogPortMax)) {
3344
3345			*pLen = 0;
3346			return (SK_PNMI_ERR_UNKNOWN_INST);
3347		}
3348		LogPortIndex = SK_PNMI_PORT_INST2LOG(Instance);
3349		Limit = LogPortIndex + 1;
3350	}
3351
3352	else { /* Instance == (SK_U32)(-1), get all Instances of that OID */
3353
3354		LogPortIndex = 0;
3355		Limit = LogPortMax;
3356	}
3357
3358
3359	/*
3360	 * Check action
3361	 */
3362	if (Action != SK_PNMI_GET) {
3363
3364		*pLen = 0;
3365		return (SK_PNMI_ERR_READ_ONLY);
3366	}
3367
3368	/*
3369	 * Check length
3370	 */
3371	if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U64)) {
3372
3373		*pLen = (Limit - LogPortIndex) * sizeof(SK_U64);
3374		return (SK_PNMI_ERR_TOO_SHORT);
3375	}
3376
3377	/*
3378	 * Update XMAC statistic and increment semaphore to indicate that
3379	 * an update was already done.
3380	 */
3381	Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1);
3382	if (Ret != SK_PNMI_ERR_OK) {
3383
3384		*pLen = 0;
3385		return (Ret);
3386	}
3387	pAC->Pnmi.MacUpdatedFlag ++;
3388
3389	/*
3390	 * Get value
3391	 */
3392	Offset = 0;
3393	for (; LogPortIndex < Limit; LogPortIndex ++) {
3394
3395		switch (Id) {
3396
3397		/*
3398		 * Frames longer than IEEE 802.3 frame max size are counted
3399		 * by XMAC in frame_too_long counter even reception of long
3400		 * frames was enabled and the frame was correct.
3401		 * So correct the value by subtracting RxLongFrame counter.
3402		 */
3403		case OID_SKGE_STAT_RX_TOO_LONG:
3404			StatVal = GetStatVal(pAC, IoC, LogPortIndex,
3405					     IdTable[TableIndex].Param, NetIndex) -
3406				GetStatVal(pAC, IoC, LogPortIndex,
3407					   SK_PNMI_HRX_LONGFRAMES, NetIndex);
3408			SK_PNMI_STORE_U64(pBuf + Offset, StatVal);
3409			break;
3410
3411		default:
3412			StatVal = GetStatVal(pAC, IoC, LogPortIndex,
3413				IdTable[TableIndex].Param, NetIndex);
3414			SK_PNMI_STORE_U64(pBuf + Offset, StatVal);
3415			break;
3416		}
3417
3418		Offset += sizeof(SK_U64);
3419	}
3420	*pLen = Offset;
3421
3422	pAC->Pnmi.MacUpdatedFlag --;
3423
3424	return (SK_PNMI_ERR_OK);
3425}
3426
3427/*****************************************************************************
3428 *
3429 * Addr - OID handler function of OID_SKGE_PHYS_CUR_ADDR and _FAC_ADDR
3430 *
3431 * Description:
3432 *	Get/Presets/Sets the current and factory MAC address. The MAC
3433 *	address of the virtual port, which is reported to the OS, may
3434 *	not be changed, but the physical ones. A set to the virtual port
3435 *	will be ignored. No error should be reported because otherwise
3436 *	a multiple instance set (-1) would always fail.
3437 *
3438 * Returns:
3439 *	SK_PNMI_ERR_OK           The request was successfully performed.
3440 *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
3441 *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
3442 *	                         the correct data (e.g. a 32bit value is
3443 *	                         needed, but a 16 bit value was passed).
3444 *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
3445 *	                         value range.
3446 *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
3447 *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
3448 *                               exist (e.g. port instance 3 on a two port
3449 *	                         adapter.
3450 */
3451
3452static int Addr(
3453SK_AC *pAC,		/* Pointer to adapter context */
3454SK_IOC IoC,		/* IO context handle */
3455int Action,		/* Get/PreSet/Set action */
3456SK_U32 Id,		/* Object ID that is to be processed */
3457char *pBuf,		/* Buffer to which to mgmt data will be retrieved */
3458unsigned int *pLen,	/* On call: buffer length. On return: used buffer */
3459SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
3460unsigned int TableIndex, /* Index to the Id table */
3461SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode allways zero */
3462{
3463	int		Ret;
3464	unsigned int	LogPortMax;
3465	unsigned int	PhysPortMax;
3466	unsigned int	LogPortIndex;
3467	unsigned int	PhysPortIndex;
3468	unsigned int	Limit;
3469	unsigned int	Offset = 0;
3470
3471
3472
3473	/*
3474	 * Calculate instance if wished. MAC index 0 is the virtual
3475	 * MAC.
3476	 */
3477	PhysPortMax = pAC->GIni.GIMacsFound;
3478	LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax);
3479
3480	if(pAC->Pnmi.DualNetActiveFlag == SK_TRUE){ /* Dual net mode */
3481		LogPortMax--;
3482	}
3483
3484	if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried */
3485		/* Check instance range */
3486		if ((Instance < 1) || (Instance > LogPortMax)) {
3487
3488			*pLen = 0;
3489			return (SK_PNMI_ERR_UNKNOWN_INST);
3490		}
3491		LogPortIndex = SK_PNMI_PORT_INST2LOG(Instance);
3492		Limit = LogPortIndex + 1;
3493	}
3494
3495	else { /* Instance == (SK_U32)(-1), get all Instances of that OID */
3496
3497		LogPortIndex = 0;
3498		Limit = LogPortMax;
3499	}
3500
3501	/*
3502	 * Perform Action
3503	 */
3504	if (Action == SK_PNMI_GET) {
3505
3506		/*
3507		 * Check length
3508		*/
3509		if (*pLen < (Limit - LogPortIndex) * 6) {
3510
3511			*pLen = (Limit - LogPortIndex) * 6;
3512			return (SK_PNMI_ERR_TOO_SHORT);
3513		}
3514
3515		/*
3516		 * Get value
3517		 */
3518		for (; LogPortIndex < Limit; LogPortIndex ++) {
3519
3520			switch (Id) {
3521
3522			case OID_SKGE_PHYS_CUR_ADDR:
3523				if (LogPortIndex == 0) {
3524					CopyMac(pBuf + Offset, &pAC->Addr.Net[NetIndex].CurrentMacAddress);
3525				}
3526				else {
3527					PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex);
3528
3529					CopyMac(pBuf + Offset,
3530						&pAC->Addr.Port[PhysPortIndex].CurrentMacAddress);
3531				}
3532				Offset += 6;
3533				break;
3534
3535			case OID_SKGE_PHYS_FAC_ADDR:
3536				if (LogPortIndex == 0) {
3537					CopyMac(pBuf + Offset,
3538						&pAC->Addr.Net[NetIndex].PermanentMacAddress);
3539				}
3540				else {
3541					PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
3542						pAC, LogPortIndex);
3543
3544					CopyMac(pBuf + Offset,
3545						&pAC->Addr.Port[PhysPortIndex].PermanentMacAddress);
3546				}
3547				Offset += 6;
3548				break;
3549
3550			default:
3551				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR008,
3552					SK_PNMI_ERR008MSG);
3553
3554				*pLen = 0;
3555				return (SK_PNMI_ERR_GENERAL);
3556			}
3557		}
3558
3559		*pLen = Offset;
3560	}
3561	else {
3562		/*
3563		 * The logical MAC address may not be changed only
3564		 * the physical ones
3565		 */
3566		if (Id == OID_SKGE_PHYS_FAC_ADDR) {
3567
3568			*pLen = 0;
3569			return (SK_PNMI_ERR_READ_ONLY);
3570		}
3571
3572		/*
3573		 * Only the current address may be changed
3574		 */
3575		if (Id != OID_SKGE_PHYS_CUR_ADDR) {
3576
3577			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR009,
3578				SK_PNMI_ERR009MSG);
3579
3580			*pLen = 0;
3581			return (SK_PNMI_ERR_GENERAL);
3582		}
3583
3584		/*
3585		 * Check length
3586		*/
3587		if (*pLen < (Limit - LogPortIndex) * 6) {
3588
3589			*pLen = (Limit - LogPortIndex) * 6;
3590			return (SK_PNMI_ERR_TOO_SHORT);
3591		}
3592		if (*pLen > (Limit - LogPortIndex) * 6) {
3593
3594			*pLen = 0;
3595			return (SK_PNMI_ERR_BAD_VALUE);
3596		}
3597
3598		/*
3599		 * Check Action
3600		 */
3601		if (Action == SK_PNMI_PRESET) {
3602
3603			*pLen = 0;
3604			return (SK_PNMI_ERR_OK);
3605		}
3606
3607		/*
3608		 * Set OID_SKGE_MAC_CUR_ADDR
3609		 */
3610		for (; LogPortIndex < Limit; LogPortIndex ++, Offset += 6) {
3611
3612			/*
3613			 * A set to virtual port and set of broadcast
3614			 * address will be ignored
3615			 */
3616			if (LogPortIndex == 0 || SK_MEMCMP(pBuf + Offset,
3617				"\xff\xff\xff\xff\xff\xff", 6) == 0) {
3618
3619				continue;
3620			}
3621
3622			PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC,
3623				LogPortIndex);
3624
3625			Ret = SkAddrOverride(pAC, IoC, PhysPortIndex,
3626				(SK_MAC_ADDR *)(pBuf + Offset),
3627				(LogPortIndex == 0 ? SK_ADDR_VIRTUAL_ADDRESS :
3628				SK_ADDR_PHYSICAL_ADDRESS));
3629			if (Ret != SK_ADDR_OVERRIDE_SUCCESS) {
3630
3631				return (SK_PNMI_ERR_GENERAL);
3632			}
3633		}
3634		*pLen = Offset;
3635	}
3636
3637	return (SK_PNMI_ERR_OK);
3638}
3639
3640/*****************************************************************************
3641 *
3642 * CsumStat - OID handler function of OID_SKGE_CHKSM_XXX
3643 *
3644 * Description:
3645 *	Retrieves the statistic values of the CSUM module. The CSUM data
3646 *	structure must be available in the SK_AC even if the CSUM module
3647 *	is not included, because PNMI reads the statistic data from the
3648 *	CSUM part of SK_AC directly.
3649 *
3650 * Returns:
3651 *	SK_PNMI_ERR_OK           The request was successfully performed.
3652 *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
3653 *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
3654 *	                         the correct data (e.g. a 32bit value is
3655 *	                         needed, but a 16 bit value was passed).
3656 *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
3657 *                               exist (e.g. port instance 3 on a two port
3658 *	                         adapter.
3659 */
3660
3661static int CsumStat(
3662SK_AC *pAC,		/* Pointer to adapter context */
3663SK_IOC IoC,		/* IO context handle */
3664int Action,		/* Get/PreSet/Set action */
3665SK_U32 Id,		/* Object ID that is to be processed */
3666char *pBuf,		/* Buffer to which to mgmt data will be retrieved */
3667unsigned int *pLen,	/* On call: buffer length. On return: used buffer */
3668SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
3669unsigned int TableIndex, /* Index to the Id table */
3670SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode allways zero */
3671{
3672	unsigned int	Index;
3673	unsigned int	Limit;
3674	unsigned int	Offset = 0;
3675	SK_U64		StatVal;
3676
3677
3678	/*
3679	 * Calculate instance if wished
3680	 */
3681	if (Instance != (SK_U32)(-1)) {
3682
3683		if ((Instance < 1) || (Instance > SKCS_NUM_PROTOCOLS)) {
3684
3685			*pLen = 0;
3686			return (SK_PNMI_ERR_UNKNOWN_INST);
3687		}
3688		Index = (unsigned int)Instance - 1;
3689		Limit = Index + 1;
3690	}
3691	else {
3692		Index = 0;
3693		Limit = SKCS_NUM_PROTOCOLS;
3694	}
3695
3696	/*
3697	 * Check action
3698	 */
3699	if (Action != SK_PNMI_GET) {
3700
3701		*pLen = 0;
3702		return (SK_PNMI_ERR_READ_ONLY);
3703	}
3704
3705	/*
3706	 * Check length
3707	 */
3708	if (*pLen < (Limit - Index) * sizeof(SK_U64)) {
3709
3710		*pLen = (Limit - Index) * sizeof(SK_U64);
3711		return (SK_PNMI_ERR_TOO_SHORT);
3712	}
3713
3714	/*
3715	 * Get value
3716	 */
3717	for (; Index < Limit; Index ++) {
3718
3719		switch (Id) {
3720
3721		case OID_SKGE_CHKSM_RX_OK_CTS:
3722			StatVal = pAC->Csum.ProtoStats[NetIndex][Index].RxOkCts;
3723			break;
3724
3725		case OID_SKGE_CHKSM_RX_UNABLE_CTS:
3726			StatVal = pAC->Csum.ProtoStats[NetIndex][Index].RxUnableCts;
3727			break;
3728
3729		case OID_SKGE_CHKSM_RX_ERR_CTS:
3730			StatVal = pAC->Csum.ProtoStats[NetIndex][Index].RxErrCts;
3731			break;
3732
3733		case OID_SKGE_CHKSM_TX_OK_CTS:
3734			StatVal = pAC->Csum.ProtoStats[NetIndex][Index].TxOkCts;
3735			break;
3736
3737		case OID_SKGE_CHKSM_TX_UNABLE_CTS:
3738			StatVal = pAC->Csum.ProtoStats[NetIndex][Index].TxUnableCts;
3739			break;
3740
3741		default:
3742			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR010,
3743				SK_PNMI_ERR010MSG);
3744
3745			*pLen = 0;
3746			return (SK_PNMI_ERR_GENERAL);
3747		}
3748
3749		SK_PNMI_STORE_U64(pBuf + Offset, StatVal);
3750		Offset += sizeof(SK_U64);
3751	}
3752
3753	/*
3754	 * Store used buffer space
3755	 */
3756	*pLen = Offset;
3757
3758	return (SK_PNMI_ERR_OK);
3759}
3760
3761/*****************************************************************************
3762 *
3763 * SensorStat - OID handler function of OID_SKGE_SENSOR_XXX
3764 *
3765 * Description:
3766 *	Retrieves the statistic values of the I2C module, which handles
3767 *	the temperature and voltage sensors.
3768 *
3769 * Returns:
3770 *	SK_PNMI_ERR_OK           The request was successfully performed.
3771 *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
3772 *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
3773 *	                         the correct data (e.g. a 32bit value is
3774 *	                         needed, but a 16 bit value was passed).
3775 *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
3776 *                               exist (e.g. port instance 3 on a two port
3777 *	                         adapter.
3778 */
3779
3780static int SensorStat(
3781SK_AC *pAC,		/* Pointer to adapter context */
3782SK_IOC IoC,		/* IO context handle */
3783int Action,		/* Get/PreSet/Set action */
3784SK_U32 Id,		/* Object ID that is to be processed */
3785char *pBuf,		/* Buffer to which to mgmt data will be retrieved */
3786unsigned int *pLen,	/* On call: buffer length. On return: used buffer */
3787SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
3788unsigned int TableIndex, /* Index to the Id table */
3789SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode allways zero */
3790{
3791	unsigned int	i;
3792	unsigned int	Index;
3793	unsigned int	Limit;
3794	unsigned int	Offset;
3795	unsigned int	Len;
3796	SK_U32		Val32;
3797	SK_U64		Val64;
3798
3799
3800	/*
3801	 * Calculate instance if wished
3802	 */
3803	if ((Instance != (SK_U32)(-1))) {
3804
3805		if ((Instance < 1) || (Instance > (SK_U32)pAC->I2c.MaxSens)) {
3806
3807			*pLen = 0;
3808			return (SK_PNMI_ERR_UNKNOWN_INST);
3809		}
3810
3811		Index = (unsigned int)Instance -1;
3812		Limit = (unsigned int)Instance;
3813	}
3814	else {
3815		Index = 0;
3816		Limit = (unsigned int) pAC->I2c.MaxSens;
3817	}
3818
3819	/*
3820	 * Check action
3821	 */
3822	if (Action != SK_PNMI_GET) {
3823
3824		*pLen = 0;
3825		return (SK_PNMI_ERR_READ_ONLY);
3826	}
3827
3828	/*
3829	 * Check length
3830	 */
3831	switch (Id) {
3832
3833	case OID_SKGE_SENSOR_VALUE:
3834	case OID_SKGE_SENSOR_WAR_THRES_LOW:
3835	case OID_SKGE_SENSOR_WAR_THRES_UPP:
3836	case OID_SKGE_SENSOR_ERR_THRES_LOW:
3837	case OID_SKGE_SENSOR_ERR_THRES_UPP:
3838		if (*pLen < (Limit - Index) * sizeof(SK_U32)) {
3839
3840			*pLen = (Limit - Index) * sizeof(SK_U32);
3841			return (SK_PNMI_ERR_TOO_SHORT);
3842		}
3843		break;
3844
3845	case OID_SKGE_SENSOR_DESCR:
3846		for (Offset = 0, i = Index; i < Limit; i ++) {
3847
3848			Len = (unsigned int)
3849				SK_STRLEN(pAC->I2c.SenTable[i].SenDesc) + 1;
3850			if (Len >= SK_PNMI_STRINGLEN2) {
3851
3852				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR011,
3853					SK_PNMI_ERR011MSG);
3854
3855				*pLen = 0;
3856				return (SK_PNMI_ERR_GENERAL);
3857			}
3858			Offset += Len;
3859		}
3860		if (*pLen < Offset) {
3861
3862			*pLen = Offset;
3863			return (SK_PNMI_ERR_TOO_SHORT);
3864		}
3865		break;
3866
3867	case OID_SKGE_SENSOR_INDEX:
3868	case OID_SKGE_SENSOR_TYPE:
3869	case OID_SKGE_SENSOR_STATUS:
3870		if (*pLen < Limit - Index) {
3871
3872			*pLen = Limit - Index;
3873			return (SK_PNMI_ERR_TOO_SHORT);
3874		}
3875		break;
3876
3877	case OID_SKGE_SENSOR_WAR_CTS:
3878	case OID_SKGE_SENSOR_WAR_TIME:
3879	case OID_SKGE_SENSOR_ERR_CTS:
3880	case OID_SKGE_SENSOR_ERR_TIME:
3881		if (*pLen < (Limit - Index) * sizeof(SK_U64)) {
3882
3883			*pLen = (Limit - Index) * sizeof(SK_U64);
3884			return (SK_PNMI_ERR_TOO_SHORT);
3885		}
3886		break;
3887
3888	default:
3889		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR012,
3890			SK_PNMI_ERR012MSG);
3891
3892		*pLen = 0;
3893		return (SK_PNMI_ERR_GENERAL);
3894
3895	}
3896
3897	/*
3898	 * Get value
3899	 */
3900	for (Offset = 0; Index < Limit; Index ++) {
3901
3902		switch (Id) {
3903
3904		case OID_SKGE_SENSOR_INDEX:
3905			*(pBuf + Offset) = (char)Index;
3906			Offset += sizeof(char);
3907			break;
3908
3909		case OID_SKGE_SENSOR_DESCR:
3910			Len = SK_STRLEN(pAC->I2c.SenTable[Index].SenDesc);
3911			SK_MEMCPY(pBuf + Offset + 1,
3912				pAC->I2c.SenTable[Index].SenDesc, Len);
3913			*(pBuf + Offset) = (char)Len;
3914			Offset += Len + 1;
3915			break;
3916
3917		case OID_SKGE_SENSOR_TYPE:
3918			*(pBuf + Offset) =
3919				(char)pAC->I2c.SenTable[Index].SenType;
3920			Offset += sizeof(char);
3921			break;
3922
3923		case OID_SKGE_SENSOR_VALUE:
3924			Val32 = (SK_U32)pAC->I2c.SenTable[Index].SenValue;
3925			SK_PNMI_STORE_U32(pBuf + Offset, Val32);
3926			Offset += sizeof(SK_U32);
3927			break;
3928
3929		case OID_SKGE_SENSOR_WAR_THRES_LOW:
3930			Val32 = (SK_U32)pAC->I2c.SenTable[Index].
3931				SenThreWarnLow;
3932			SK_PNMI_STORE_U32(pBuf + Offset, Val32);
3933			Offset += sizeof(SK_U32);
3934			break;
3935
3936		case OID_SKGE_SENSOR_WAR_THRES_UPP:
3937			Val32 = (SK_U32)pAC->I2c.SenTable[Index].
3938				SenThreWarnHigh;
3939			SK_PNMI_STORE_U32(pBuf + Offset, Val32);
3940			Offset += sizeof(SK_U32);
3941			break;
3942
3943		case OID_SKGE_SENSOR_ERR_THRES_LOW:
3944			Val32 = (SK_U32)pAC->I2c.SenTable[Index].
3945				SenThreErrLow;
3946			SK_PNMI_STORE_U32(pBuf + Offset, Val32);
3947			Offset += sizeof(SK_U32);
3948			break;
3949
3950		case OID_SKGE_SENSOR_ERR_THRES_UPP:
3951			Val32 = pAC->I2c.SenTable[Index].SenThreErrHigh;
3952			SK_PNMI_STORE_U32(pBuf + Offset, Val32);
3953			Offset += sizeof(SK_U32);
3954			break;
3955
3956		case OID_SKGE_SENSOR_STATUS:
3957			*(pBuf + Offset) =
3958				(char)pAC->I2c.SenTable[Index].SenErrFlag;
3959			Offset += sizeof(char);
3960			break;
3961
3962		case OID_SKGE_SENSOR_WAR_CTS:
3963			Val64 = pAC->I2c.SenTable[Index].SenWarnCts;
3964			SK_PNMI_STORE_U64(pBuf + Offset, Val64);
3965			Offset += sizeof(SK_U64);
3966			break;
3967
3968		case OID_SKGE_SENSOR_ERR_CTS:
3969			Val64 = pAC->I2c.SenTable[Index].SenErrCts;
3970			SK_PNMI_STORE_U64(pBuf + Offset, Val64);
3971			Offset += sizeof(SK_U64);
3972			break;
3973
3974		case OID_SKGE_SENSOR_WAR_TIME:
3975			Val64 = SK_PNMI_HUNDREDS_SEC(pAC->I2c.SenTable[Index].
3976				SenBegWarnTS);
3977			SK_PNMI_STORE_U64(pBuf + Offset, Val64);
3978			Offset += sizeof(SK_U64);
3979			break;
3980
3981		case OID_SKGE_SENSOR_ERR_TIME:
3982			Val64 = SK_PNMI_HUNDREDS_SEC(pAC->I2c.SenTable[Index].
3983				SenBegErrTS);
3984			SK_PNMI_STORE_U64(pBuf + Offset, Val64);
3985			Offset += sizeof(SK_U64);
3986			break;
3987
3988		default:
3989			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR013,
3990				SK_PNMI_ERR013MSG);
3991
3992			return (SK_PNMI_ERR_GENERAL);
3993		}
3994	}
3995
3996	/*
3997	 * Store used buffer space
3998	 */
3999	*pLen = Offset;
4000
4001	return (SK_PNMI_ERR_OK);
4002}
4003
4004/*****************************************************************************
4005 *
4006 * Vpd - OID handler function of OID_SKGE_VPD_XXX
4007 *
4008 * Description:
4009 *	Get/preset/set of VPD data. As instance the name of a VPD key
4010 *	can be passed. The Instance parameter is a SK_U32 and can be
4011 *	used as a string buffer for the VPD key, because their maximum
4012 *	length is 4 byte.
4013 *
4014 * Returns:
4015 *	SK_PNMI_ERR_OK           The request was successfully performed.
4016 *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
4017 *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
4018 *	                         the correct data (e.g. a 32bit value is
4019 *	                         needed, but a 16 bit value was passed).
4020 *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
4021 *	                         value range.
4022 *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
4023 *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
4024 *                               exist (e.g. port instance 3 on a two port
4025 *	                         adapter.
4026 */
4027
4028static int Vpd(
4029SK_AC *pAC,		/* Pointer to adapter context */
4030SK_IOC IoC,		/* IO context handle */
4031int Action,		/* Get/PreSet/Set action */
4032SK_U32 Id,		/* Object ID that is to be processed */
4033char *pBuf,		/* Buffer to which to mgmt data will be retrieved */
4034unsigned int *pLen,	/* On call: buffer length. On return: used buffer */
4035SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
4036unsigned int TableIndex, /* Index to the Id table */
4037SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode allways zero */
4038{
4039	SK_VPD_STATUS	*pVpdStatus;
4040	unsigned int	BufLen;
4041	char		Buf[256];
4042	char		KeyArr[SK_PNMI_VPD_ENTRIES][SK_PNMI_VPD_KEY_SIZE];
4043	char		KeyStr[SK_PNMI_VPD_KEY_SIZE];
4044	unsigned int	KeyNo;
4045	unsigned int	Offset;
4046	unsigned int	Index;
4047	unsigned int	FirstIndex;
4048	unsigned int	LastIndex;
4049	unsigned int	Len;
4050	int		Ret;
4051	SK_U32		Val32;
4052
4053	/*
4054	 * Get array of all currently stored VPD keys
4055	 */
4056	Ret = GetVpdKeyArr(pAC, IoC, &KeyArr[0][0], sizeof(KeyArr),
4057		&KeyNo);
4058	if (Ret != SK_PNMI_ERR_OK) {
4059		*pLen = 0;
4060		return (Ret);
4061	}
4062
4063	/*
4064	 * If instance is not -1, try to find the requested VPD key for
4065	 * the multiple instance variables. The other OIDs as for example
4066	 * OID VPD_ACTION are single instance variables and must be
4067	 * handled separatly.
4068	 */
4069	FirstIndex = 0;
4070	LastIndex = KeyNo;
4071
4072	if ((Instance != (SK_U32)(-1))) {
4073
4074		if (Id == OID_SKGE_VPD_KEY || Id == OID_SKGE_VPD_VALUE ||
4075			Id == OID_SKGE_VPD_ACCESS) {
4076
4077			SK_STRNCPY(KeyStr, (char *)&Instance, 4);
4078			KeyStr[4] = 0;
4079
4080			for (Index = 0; Index < KeyNo; Index ++) {
4081
4082				if (SK_STRCMP(KeyStr, KeyArr[Index]) == 0) {
4083					FirstIndex = Index;
4084					LastIndex = Index+1;
4085					break;
4086				}
4087			}
4088			if (Index == KeyNo) {
4089
4090				*pLen = 0;
4091				return (SK_PNMI_ERR_UNKNOWN_INST);
4092			}
4093		}
4094		else if (Instance != 1) {
4095
4096			*pLen = 0;
4097			return (SK_PNMI_ERR_UNKNOWN_INST);
4098		}
4099	}
4100
4101	/*
4102	 * Get value, if a query should be performed
4103	 */
4104	if (Action == SK_PNMI_GET) {
4105
4106		switch (Id) {
4107
4108		case OID_SKGE_VPD_FREE_BYTES:
4109			/* Check length of buffer */
4110			if (*pLen < sizeof(SK_U32)) {
4111
4112				*pLen = sizeof(SK_U32);
4113				return (SK_PNMI_ERR_TOO_SHORT);
4114			}
4115			/* Get number of free bytes */
4116			pVpdStatus = VpdStat(pAC, IoC);
4117			if (pVpdStatus == NULL) {
4118
4119				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR017,
4120					SK_PNMI_ERR017MSG);
4121
4122				*pLen = 0;
4123				return (SK_PNMI_ERR_GENERAL);
4124			}
4125			if ((pVpdStatus->vpd_status & VPD_VALID) == 0) {
4126
4127				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR018,
4128					SK_PNMI_ERR018MSG);
4129
4130				*pLen = 0;
4131				return (SK_PNMI_ERR_GENERAL);
4132			}
4133
4134			Val32 = (SK_U32)pVpdStatus->vpd_free_rw;
4135			SK_PNMI_STORE_U32(pBuf, Val32);
4136			*pLen = sizeof(SK_U32);
4137			break;
4138
4139		case OID_SKGE_VPD_ENTRIES_LIST:
4140			/* Check length */
4141			for (Len = 0, Index = 0; Index < KeyNo; Index ++) {
4142
4143				Len += SK_STRLEN(KeyArr[Index]) + 1;
4144			}
4145			if (*pLen < Len) {
4146
4147				*pLen = Len;
4148				return (SK_PNMI_ERR_TOO_SHORT);
4149			}
4150
4151			/* Get value */
4152			*(pBuf) = (char)Len - 1;
4153			for (Offset = 1, Index = 0; Index < KeyNo; Index ++) {
4154
4155				Len = SK_STRLEN(KeyArr[Index]);
4156				SK_MEMCPY(pBuf + Offset, KeyArr[Index], Len);
4157
4158				Offset += Len;
4159
4160				if (Index < KeyNo - 1) {
4161
4162					*(pBuf + Offset) = ' ';
4163					Offset ++;
4164				}
4165			}
4166			*pLen = Offset;
4167			break;
4168
4169		case OID_SKGE_VPD_ENTRIES_NUMBER:
4170			/* Check length */
4171			if (*pLen < sizeof(SK_U32)) {
4172
4173				*pLen = sizeof(SK_U32);
4174				return (SK_PNMI_ERR_TOO_SHORT);
4175			}
4176
4177			Val32 = (SK_U32)KeyNo;
4178			SK_PNMI_STORE_U32(pBuf, Val32);
4179			*pLen = sizeof(SK_U32);
4180			break;
4181
4182		case OID_SKGE_VPD_KEY:
4183			/* Check buffer length, if it is large enough */
4184			for (Len = 0, Index = FirstIndex;
4185				Index < LastIndex; Index ++) {
4186
4187				Len += SK_STRLEN(KeyArr[Index]) + 1;
4188			}
4189			if (*pLen < Len) {
4190
4191				*pLen = Len;
4192				return (SK_PNMI_ERR_TOO_SHORT);
4193			}
4194
4195			/*
4196			 * Get the key to an intermediate buffer, because
4197			 * we have to prepend a length byte.
4198			 */
4199			for (Offset = 0, Index = FirstIndex;
4200				Index < LastIndex; Index ++) {
4201
4202				Len = SK_STRLEN(KeyArr[Index]);
4203
4204				*(pBuf + Offset) = (char)Len;
4205				SK_MEMCPY(pBuf + Offset + 1, KeyArr[Index],
4206					Len);
4207				Offset += Len + 1;
4208			}
4209			*pLen = Offset;
4210			break;
4211
4212		case OID_SKGE_VPD_VALUE:
4213			/* Check the buffer length if it is large enough */
4214			for (Offset = 0, Index = FirstIndex;
4215				Index < LastIndex; Index ++) {
4216
4217				BufLen = 256;
4218				if (VpdRead(pAC, IoC, KeyArr[Index], Buf,
4219					(int *)&BufLen) > 0 ||
4220					BufLen >= SK_PNMI_VPD_DATALEN) {
4221
4222					SK_ERR_LOG(pAC, SK_ERRCL_SW,
4223						SK_PNMI_ERR021,
4224						SK_PNMI_ERR021MSG);
4225
4226					return (SK_PNMI_ERR_GENERAL);
4227				}
4228				Offset += BufLen + 1;
4229			}
4230			if (*pLen < Offset) {
4231
4232				*pLen = Offset;
4233				return (SK_PNMI_ERR_TOO_SHORT);
4234			}
4235
4236			/*
4237			 * Get the value to an intermediate buffer, because
4238			 * we have to prepend a length byte.
4239			 */
4240			for (Offset = 0, Index = FirstIndex;
4241				Index < LastIndex; Index ++) {
4242
4243				BufLen = 256;
4244				if (VpdRead(pAC, IoC, KeyArr[Index], Buf,
4245					(int *)&BufLen) > 0 ||
4246					BufLen >= SK_PNMI_VPD_DATALEN) {
4247
4248					SK_ERR_LOG(pAC, SK_ERRCL_SW,
4249						SK_PNMI_ERR022,
4250						SK_PNMI_ERR022MSG);
4251
4252					*pLen = 0;
4253					return (SK_PNMI_ERR_GENERAL);
4254				}
4255
4256				*(pBuf + Offset) = (char)BufLen;
4257				SK_MEMCPY(pBuf + Offset + 1, Buf, BufLen);
4258				Offset += BufLen + 1;
4259			}
4260			*pLen = Offset;
4261			break;
4262
4263		case OID_SKGE_VPD_ACCESS:
4264			if (*pLen < LastIndex - FirstIndex) {
4265
4266				*pLen = LastIndex - FirstIndex;
4267				return (SK_PNMI_ERR_TOO_SHORT);
4268			}
4269
4270			for (Offset = 0, Index = FirstIndex;
4271				Index < LastIndex; Index ++) {
4272
4273				if (VpdMayWrite(KeyArr[Index])) {
4274
4275					*(pBuf + Offset) = SK_PNMI_VPD_RW;
4276				}
4277				else {
4278					*(pBuf + Offset) = SK_PNMI_VPD_RO;
4279				}
4280				Offset ++;
4281			}
4282			*pLen = Offset;
4283			break;
4284
4285		case OID_SKGE_VPD_ACTION:
4286			Offset = LastIndex - FirstIndex;
4287			if (*pLen < Offset) {
4288
4289				*pLen = Offset;
4290				return (SK_PNMI_ERR_TOO_SHORT);
4291			}
4292			SK_MEMSET(pBuf, 0, Offset);
4293			*pLen = Offset;
4294			break;
4295
4296		default:
4297			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR023,
4298				SK_PNMI_ERR023MSG);
4299
4300			*pLen = 0;
4301			return (SK_PNMI_ERR_GENERAL);
4302		}
4303	}
4304	else {
4305		/* The only OID which can be set is VPD_ACTION */
4306		if (Id != OID_SKGE_VPD_ACTION) {
4307
4308			if (Id == OID_SKGE_VPD_FREE_BYTES ||
4309				Id == OID_SKGE_VPD_ENTRIES_LIST ||
4310				Id == OID_SKGE_VPD_ENTRIES_NUMBER ||
4311				Id == OID_SKGE_VPD_KEY ||
4312				Id == OID_SKGE_VPD_VALUE ||
4313				Id == OID_SKGE_VPD_ACCESS) {
4314
4315				*pLen = 0;
4316				return (SK_PNMI_ERR_READ_ONLY);
4317			}
4318
4319			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR024,
4320				SK_PNMI_ERR024MSG);
4321
4322			*pLen = 0;
4323			return (SK_PNMI_ERR_GENERAL);
4324		}
4325
4326		/*
4327		 * From this point we handle VPD_ACTION. Check the buffer
4328		 * length. It should at least have the size of one byte.
4329		 */
4330		if (*pLen < 1) {
4331
4332			*pLen = 1;
4333			return (SK_PNMI_ERR_TOO_SHORT);
4334		}
4335
4336		/*
4337		 * The first byte contains the VPD action type we should
4338		 * perform.
4339		 */
4340		switch (*pBuf) {
4341
4342		case SK_PNMI_VPD_IGNORE:
4343			/* Nothing to do */
4344			break;
4345
4346		case SK_PNMI_VPD_CREATE:
4347			/*
4348			 * We have to create a new VPD entry or we modify
4349			 * an existing one. Check first the buffer length.
4350			 */
4351			if (*pLen < 4) {
4352
4353				*pLen = 4;
4354				return (SK_PNMI_ERR_TOO_SHORT);
4355			}
4356			KeyStr[0] = pBuf[1];
4357			KeyStr[1] = pBuf[2];
4358			KeyStr[2] = 0;
4359
4360			/*
4361			 * Is the entry writable or does it belong to the
4362			 * read-only area?
4363			 */
4364			if (!VpdMayWrite(KeyStr)) {
4365
4366				*pLen = 0;
4367				return (SK_PNMI_ERR_BAD_VALUE);
4368			}
4369
4370			Offset = (int)pBuf[3] & 0xFF;
4371
4372			SK_MEMCPY(Buf, pBuf + 4, Offset);
4373			Buf[Offset] = 0;
4374
4375			/* A preset ends here */
4376			if (Action == SK_PNMI_PRESET) {
4377
4378				return (SK_PNMI_ERR_OK);
4379			}
4380
4381			/* Write the new entry or modify an existing one */
4382			Ret = VpdWrite(pAC, IoC, KeyStr, Buf);
4383			if (Ret == SK_PNMI_VPD_NOWRITE ) {
4384
4385				*pLen = 0;
4386				return (SK_PNMI_ERR_BAD_VALUE);
4387			}
4388			else if (Ret != SK_PNMI_VPD_OK) {
4389
4390				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR025,
4391					SK_PNMI_ERR025MSG);
4392
4393				*pLen = 0;
4394				return (SK_PNMI_ERR_GENERAL);
4395			}
4396
4397			/*
4398			 * Perform an update of the VPD data. This is
4399			 * not mandantory, but just to be sure.
4400			 */
4401			Ret = VpdUpdate(pAC, IoC);
4402			if (Ret != SK_PNMI_VPD_OK) {
4403
4404				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR026,
4405					SK_PNMI_ERR026MSG);
4406
4407				*pLen = 0;
4408				return (SK_PNMI_ERR_GENERAL);
4409			}
4410			break;
4411
4412		case SK_PNMI_VPD_DELETE:
4413			/* Check if the buffer size is plausible */
4414			if (*pLen < 3) {
4415
4416				*pLen = 3;
4417				return (SK_PNMI_ERR_TOO_SHORT);
4418			}
4419			if (*pLen > 3) {
4420
4421				*pLen = 0;
4422				return (SK_PNMI_ERR_BAD_VALUE);
4423			}
4424			KeyStr[0] = pBuf[1];
4425			KeyStr[1] = pBuf[2];
4426			KeyStr[2] = 0;
4427
4428			/* Find the passed key in the array */
4429			for (Index = 0; Index < KeyNo; Index ++) {
4430
4431				if (SK_STRCMP(KeyStr, KeyArr[Index]) == 0) {
4432
4433					break;
4434				}
4435			}
4436			/*
4437			 * If we cannot find the key it is wrong, so we
4438			 * return an appropriate error value.
4439			 */
4440			if (Index == KeyNo) {
4441
4442				*pLen = 0;
4443				return (SK_PNMI_ERR_BAD_VALUE);
4444			}
4445
4446			if (Action == SK_PNMI_PRESET) {
4447
4448				return (SK_PNMI_ERR_OK);
4449			}
4450
4451			/* Ok, you wanted it and you will get it */
4452			Ret = VpdDelete(pAC, IoC, KeyStr);
4453			if (Ret != SK_PNMI_VPD_OK) {
4454
4455				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR027,
4456					SK_PNMI_ERR027MSG);
4457
4458				*pLen = 0;
4459				return (SK_PNMI_ERR_GENERAL);
4460			}
4461
4462			/*
4463			 * Perform an update of the VPD data. This is
4464			 * not mandantory, but just to be sure.
4465			 */
4466			Ret = VpdUpdate(pAC, IoC);
4467			if (Ret != SK_PNMI_VPD_OK) {
4468
4469				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR028,
4470					SK_PNMI_ERR028MSG);
4471
4472				*pLen = 0;
4473				return (SK_PNMI_ERR_GENERAL);
4474			}
4475			break;
4476
4477		default:
4478			*pLen = 0;
4479			return (SK_PNMI_ERR_BAD_VALUE);
4480		}
4481	}
4482
4483	return (SK_PNMI_ERR_OK);
4484}
4485
4486/*****************************************************************************
4487 *
4488 * General - OID handler function of various single instance OIDs
4489 *
4490 * Description:
4491 *	The code is simple. No description necessary.
4492 *
4493 * Returns:
4494 *	SK_PNMI_ERR_OK           The request was successfully performed.
4495 *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
4496 *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
4497 *	                         the correct data (e.g. a 32bit value is
4498 *	                         needed, but a 16 bit value was passed).
4499 *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
4500 *                               exist (e.g. port instance 3 on a two port
4501 *	                         adapter.
4502 */
4503
4504static int General(
4505SK_AC *pAC,		/* Pointer to adapter context */
4506SK_IOC IoC,		/* IO context handle */
4507int Action,		/* Get/PreSet/Set action */
4508SK_U32 Id,		/* Object ID that is to be processed */
4509char *pBuf,		/* Buffer to which to mgmt data will be retrieved */
4510unsigned int *pLen,	/* On call: buffer length. On return: used buffer */
4511SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
4512unsigned int TableIndex, /* Index to the Id table */
4513SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode allways zero */
4514{
4515	int		Ret;
4516	unsigned int	Index;
4517	unsigned int	Len;
4518	unsigned int	Offset;
4519	unsigned int	Val;
4520	SK_U8		Val8;
4521	SK_U16		Val16;
4522	SK_U32		Val32;
4523	SK_U64		Val64;
4524	SK_U64		Val64RxHwErrs = 0;
4525	SK_U64		Val64TxHwErrs = 0;
4526	SK_BOOL		Is64BitReq = SK_FALSE;
4527	char		Buf[256];
4528
4529
4530	/*
4531	 * Check instance. We only handle single instance variables
4532	 */
4533	if (Instance != (SK_U32)(-1) && Instance != 1) {
4534
4535		*pLen = 0;
4536		return (SK_PNMI_ERR_UNKNOWN_INST);
4537	}
4538
4539	/*
4540	 * Check action. We only allow get requests.
4541	 */
4542	if (Action != SK_PNMI_GET) {
4543
4544		*pLen = 0;
4545		return (SK_PNMI_ERR_READ_ONLY);
4546	}
4547
4548	/*
4549	 * Check length for the various supported OIDs
4550	 */
4551	switch (Id) {
4552
4553	case OID_GEN_XMIT_ERROR:
4554	case OID_GEN_RCV_ERROR:
4555	case OID_GEN_RCV_NO_BUFFER:
4556#ifndef SK_NDIS_64BIT_CTR
4557		if (*pLen < sizeof(SK_U32)) {
4558			*pLen = sizeof(SK_U32);
4559			return (SK_PNMI_ERR_TOO_SHORT);
4560		}
4561
4562#else /* SK_NDIS_64BIT_CTR */
4563
4564		/*
4565		 * for compatibility, at least 32bit are required for oid
4566		 */
4567		if (*pLen < sizeof(SK_U32)) {
4568			/*
4569			* but indicate handling for 64bit values,
4570			* if insufficient space is provided
4571			*/
4572			*pLen = sizeof(SK_U64);
4573			return (SK_PNMI_ERR_TOO_SHORT);
4574		}
4575
4576		Is64BitReq = (*pLen < sizeof(SK_U64)) ? SK_FALSE : SK_TRUE;
4577#endif /* SK_NDIS_64BIT_CTR */
4578		break;
4579
4580	case OID_SKGE_PORT_NUMBER:
4581	case OID_SKGE_DEVICE_TYPE:
4582	case OID_SKGE_RESULT:
4583	case OID_SKGE_RLMT_MONITOR_NUMBER:
4584	case OID_GEN_TRANSMIT_QUEUE_LENGTH:
4585	case OID_SKGE_TRAP_NUMBER:
4586	case OID_SKGE_MDB_VERSION:
4587		if (*pLen < sizeof(SK_U32)) {
4588
4589			*pLen = sizeof(SK_U32);
4590			return (SK_PNMI_ERR_TOO_SHORT);
4591		}
4592		break;
4593
4594	case OID_SKGE_CHIPSET:
4595		if (*pLen < sizeof(SK_U16)) {
4596
4597			*pLen = sizeof(SK_U16);
4598			return (SK_PNMI_ERR_TOO_SHORT);
4599		}
4600		break;
4601
4602	case OID_SKGE_BUS_TYPE:
4603	case OID_SKGE_BUS_SPEED:
4604	case OID_SKGE_BUS_WIDTH:
4605	case OID_SKGE_SENSOR_NUMBER:
4606	case OID_SKGE_CHKSM_NUMBER:
4607		if (*pLen < sizeof(SK_U8)) {
4608
4609			*pLen = sizeof(SK_U8);
4610			return (SK_PNMI_ERR_TOO_SHORT);
4611		}
4612		break;
4613
4614	case OID_SKGE_TX_SW_QUEUE_LEN:
4615	case OID_SKGE_TX_SW_QUEUE_MAX:
4616	case OID_SKGE_TX_RETRY:
4617	case OID_SKGE_RX_INTR_CTS:
4618	case OID_SKGE_TX_INTR_CTS:
4619	case OID_SKGE_RX_NO_BUF_CTS:
4620	case OID_SKGE_TX_NO_BUF_CTS:
4621	case OID_SKGE_TX_USED_DESCR_NO:
4622	case OID_SKGE_RX_DELIVERED_CTS:
4623	case OID_SKGE_RX_OCTETS_DELIV_CTS:
4624	case OID_SKGE_RX_HW_ERROR_CTS:
4625	case OID_SKGE_TX_HW_ERROR_CTS:
4626	case OID_SKGE_IN_ERRORS_CTS:
4627	case OID_SKGE_OUT_ERROR_CTS:
4628	case OID_SKGE_ERR_RECOVERY_CTS:
4629	case OID_SKGE_SYSUPTIME:
4630		if (*pLen < sizeof(SK_U64)) {
4631
4632			*pLen = sizeof(SK_U64);
4633			return (SK_PNMI_ERR_TOO_SHORT);
4634		}
4635		break;
4636
4637	default:
4638		/* Checked later */
4639		break;
4640	}
4641
4642	/* Update statistic */
4643	if (Id == OID_SKGE_RX_HW_ERROR_CTS ||
4644		Id == OID_SKGE_TX_HW_ERROR_CTS ||
4645		Id == OID_SKGE_IN_ERRORS_CTS ||
4646		Id == OID_SKGE_OUT_ERROR_CTS ||
4647		Id == OID_GEN_XMIT_ERROR ||
4648		Id == OID_GEN_RCV_ERROR) {
4649
4650		/* Force the XMAC to update its statistic counters and
4651		 * Increment semaphore to indicate that an update was
4652		 * already done.
4653		 */
4654		Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1);
4655		if (Ret != SK_PNMI_ERR_OK) {
4656
4657			*pLen = 0;
4658			return (Ret);
4659		}
4660		pAC->Pnmi.MacUpdatedFlag ++;
4661
4662		/*
4663		 * Some OIDs consist of multiple hardware counters. Those
4664		 * values which are contained in all of them will be added
4665		 * now.
4666		 */
4667		switch (Id) {
4668
4669		case OID_SKGE_RX_HW_ERROR_CTS:
4670		case OID_SKGE_IN_ERRORS_CTS:
4671		case OID_GEN_RCV_ERROR:
4672			Val64RxHwErrs =
4673				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_MISSED, NetIndex) +
4674				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_FRAMING, NetIndex) +
4675				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_OVERFLOW, NetIndex)+
4676				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_JABBER, NetIndex) +
4677				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_CARRIER, NetIndex) +
4678				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_IRLENGTH, NetIndex)+
4679				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_SYMBOL, NetIndex) +
4680				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_SHORTS, NetIndex) +
4681				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_RUNT, NetIndex) +
4682				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_TOO_LONG, NetIndex)-
4683				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_LONGFRAMES, NetIndex)+
4684				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_FCS, NetIndex) +
4685				GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_CEXT, NetIndex);
4686	        break;
4687
4688		case OID_SKGE_TX_HW_ERROR_CTS:
4689		case OID_SKGE_OUT_ERROR_CTS:
4690		case OID_GEN_XMIT_ERROR:
4691			Val64TxHwErrs =
4692				GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_EXCESS_COL, NetIndex) +
4693				GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_LATE_COL, NetIndex)+
4694				GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_UNDERRUN, NetIndex)+
4695				GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_CARRIER, NetIndex)+
4696				GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_EXCESS_COL, NetIndex);
4697			break;
4698		}
4699	}
4700
4701	/*
4702	 * Retrieve value
4703	 */
4704	switch (Id) {
4705
4706	case OID_SKGE_SUPPORTED_LIST:
4707		Len = sizeof(IdTable)/sizeof(IdTable[0]) * sizeof(SK_U32);
4708		if (*pLen < Len) {
4709
4710			*pLen = Len;
4711			return (SK_PNMI_ERR_TOO_SHORT);
4712		}
4713		for (Offset = 0, Index = 0; Offset < Len;
4714			Offset += sizeof(SK_U32), Index ++) {
4715
4716			Val32 = (SK_U32)IdTable[Index].Id;
4717			SK_PNMI_STORE_U32(pBuf + Offset, Val32);
4718		}
4719		*pLen = Len;
4720		break;
4721
4722	case OID_SKGE_PORT_NUMBER:
4723		Val32 = (SK_U32)pAC->GIni.GIMacsFound;
4724		SK_PNMI_STORE_U32(pBuf, Val32);
4725		*pLen = sizeof(SK_U32);
4726		break;
4727
4728	case OID_SKGE_DEVICE_TYPE:
4729		Val32 = (SK_U32)pAC->Pnmi.DeviceType;
4730		SK_PNMI_STORE_U32(pBuf, Val32);
4731		*pLen = sizeof(SK_U32);
4732		break;
4733
4734	case OID_SKGE_DRIVER_DESCR:
4735		if (pAC->Pnmi.pDriverDescription == NULL) {
4736
4737			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR007,
4738				SK_PNMI_ERR007MSG);
4739
4740			*pLen = 0;
4741			return (SK_PNMI_ERR_GENERAL);
4742		}
4743
4744		Len = SK_STRLEN(pAC->Pnmi.pDriverDescription) + 1;
4745		if (Len > SK_PNMI_STRINGLEN1) {
4746
4747			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR029,
4748				SK_PNMI_ERR029MSG);
4749
4750			*pLen = 0;
4751			return (SK_PNMI_ERR_GENERAL);
4752		}
4753
4754		if (*pLen < Len) {
4755
4756			*pLen = Len;
4757			return (SK_PNMI_ERR_TOO_SHORT);
4758		}
4759		*pBuf = (char)(Len - 1);
4760		SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverDescription, Len - 1);
4761		*pLen = Len;
4762		break;
4763
4764	case OID_SKGE_DRIVER_VERSION:
4765		if (pAC->Pnmi.pDriverVersion == NULL) {
4766
4767			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR030,
4768				SK_PNMI_ERR030MSG);
4769
4770			*pLen = 0;
4771			return (SK_PNMI_ERR_GENERAL);
4772		}
4773
4774		Len = SK_STRLEN(pAC->Pnmi.pDriverVersion) + 1;
4775		if (Len > SK_PNMI_STRINGLEN1) {
4776
4777			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR031,
4778				SK_PNMI_ERR031MSG);
4779
4780			*pLen = 0;
4781			return (SK_PNMI_ERR_GENERAL);
4782		}
4783
4784		if (*pLen < Len) {
4785
4786			*pLen = Len;
4787			return (SK_PNMI_ERR_TOO_SHORT);
4788		}
4789		*pBuf = (char)(Len - 1);
4790		SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverVersion, Len - 1);
4791		*pLen = Len;
4792		break;
4793
4794	case OID_SKGE_HW_DESCR:
4795		/*
4796		 * The hardware description is located in the VPD. This
4797		 * query may move to the initialisation routine. But
4798		 * the VPD data is cached and therefore a call here
4799		 * will not make much difference.
4800		 */
4801		Len = 256;
4802		if (VpdRead(pAC, IoC, VPD_NAME, Buf, (int *)&Len) > 0) {
4803
4804			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR032,
4805				SK_PNMI_ERR032MSG);
4806
4807			*pLen = 0;
4808			return (SK_PNMI_ERR_GENERAL);
4809		}
4810		Len ++;
4811		if (Len > SK_PNMI_STRINGLEN1) {
4812
4813			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR033,
4814				SK_PNMI_ERR033MSG);
4815
4816			*pLen = 0;
4817			return (SK_PNMI_ERR_GENERAL);
4818		}
4819		if (*pLen < Len) {
4820
4821			*pLen = Len;
4822			return (SK_PNMI_ERR_TOO_SHORT);
4823		}
4824		*pBuf = (char)(Len - 1);
4825		SK_MEMCPY(pBuf + 1, Buf, Len - 1);
4826		*pLen = Len;
4827		break;
4828
4829	case OID_SKGE_HW_VERSION:
4830		/* Oh, I love to do some string manipulation */
4831		if (*pLen < 5) {
4832
4833			*pLen = 5;
4834			return (SK_PNMI_ERR_TOO_SHORT);
4835		}
4836		Val8 = (SK_U8)pAC->GIni.GIPciHwRev;
4837		pBuf[0] = 4;
4838		pBuf[1] = 'v';
4839		pBuf[2] = (char)(0x30 | ((Val8 >> 4) & 0x0F));
4840		pBuf[3] = '.';
4841		pBuf[4] = (char)(0x30 | (Val8 & 0x0F));
4842		*pLen = 5;
4843		break;
4844
4845	case OID_SKGE_CHIPSET:
4846		Val16 = SK_PNMI_CHIPSET;
4847		SK_PNMI_STORE_U16(pBuf, Val16);
4848		*pLen = sizeof(SK_U16);
4849		break;
4850
4851	case OID_SKGE_BUS_TYPE:
4852		*pBuf = (char)SK_PNMI_BUS_PCI;
4853		*pLen = sizeof(char);
4854		break;
4855
4856	case OID_SKGE_BUS_SPEED:
4857		*pBuf = pAC->Pnmi.PciBusSpeed;
4858		*pLen = sizeof(char);
4859		break;
4860
4861	case OID_SKGE_BUS_WIDTH:
4862		*pBuf = pAC->Pnmi.PciBusWidth;
4863		*pLen = sizeof(char);
4864		break;
4865
4866	case OID_SKGE_RESULT:
4867		Val32 = pAC->Pnmi.TestResult;
4868		SK_PNMI_STORE_U32(pBuf, Val32);
4869		*pLen = sizeof(SK_U32);
4870		break;
4871
4872	case OID_SKGE_SENSOR_NUMBER:
4873		*pBuf = (char)pAC->I2c.MaxSens;
4874		*pLen = sizeof(char);
4875		break;
4876
4877	case OID_SKGE_CHKSM_NUMBER:
4878		*pBuf = SKCS_NUM_PROTOCOLS;
4879		*pLen = sizeof(char);
4880		break;
4881
4882	case OID_SKGE_TRAP_NUMBER:
4883		GetTrapQueueLen(pAC, &Len, &Val);
4884		Val32 = (SK_U32)Val;
4885		SK_PNMI_STORE_U32(pBuf, Val32);
4886		*pLen = sizeof(SK_U32);
4887		break;
4888
4889	case OID_SKGE_TRAP:
4890		GetTrapQueueLen(pAC, &Len, &Val);
4891		if (*pLen < Len) {
4892
4893			*pLen = Len;
4894			return (SK_PNMI_ERR_TOO_SHORT);
4895		}
4896		CopyTrapQueue(pAC, pBuf);
4897		*pLen = Len;
4898		break;
4899
4900	case OID_SKGE_RLMT_MONITOR_NUMBER:
4901		Val32 = 0;
4902		SK_PNMI_STORE_U32(pBuf, Val32);
4903		*pLen = sizeof(SK_U32);
4904		break;
4905
4906	case OID_SKGE_TX_SW_QUEUE_LEN:
4907		/* Dual net mode */
4908		if(pAC->Pnmi.DualNetActiveFlag == SK_TRUE){
4909			Val64 = pAC->Pnmi.Port[NetIndex].TxSwQueueLen;
4910		}
4911		/* Single net mode */
4912		else {
4913			Val64 =  pAC->Pnmi.Port[0].TxSwQueueLen +
4914				pAC->Pnmi.Port[1].TxSwQueueLen;
4915		}
4916		SK_PNMI_STORE_U64(pBuf, Val64);
4917		*pLen = sizeof(SK_U64);
4918		break;
4919
4920
4921	case OID_SKGE_TX_SW_QUEUE_MAX:
4922		/* Dual net mode */
4923		if(pAC->Pnmi.DualNetActiveFlag == SK_TRUE){
4924			Val64 = pAC->Pnmi.Port[NetIndex].TxSwQueueMax;
4925		}
4926		/* Single net mode */
4927		else {
4928			Val64 = pAC->Pnmi.Port[0].TxSwQueueMax +
4929				pAC->Pnmi.Port[1].TxSwQueueMax;
4930		}
4931		SK_PNMI_STORE_U64(pBuf, Val64);
4932		*pLen = sizeof(SK_U64);
4933		break;
4934
4935	case OID_SKGE_TX_RETRY:
4936		/* Dual net mode */
4937		if(pAC->Pnmi.DualNetActiveFlag == SK_TRUE){
4938			Val64 = pAC->Pnmi.Port[NetIndex].TxRetryCts;
4939		}
4940		/* Single net mode */
4941		else {
4942			Val64 = pAC->Pnmi.Port[0].TxRetryCts +
4943				pAC->Pnmi.Port[1].TxRetryCts;
4944		}
4945		SK_PNMI_STORE_U64(pBuf, Val64);
4946		*pLen = sizeof(SK_U64);
4947		break;
4948
4949	case OID_SKGE_RX_INTR_CTS:
4950		/* Dual net mode */
4951		if(pAC->Pnmi.DualNetActiveFlag == SK_TRUE){
4952			Val64 = pAC->Pnmi.Port[NetIndex].RxIntrCts;
4953		}
4954		/* Single net mode */
4955		else {
4956			Val64 = pAC->Pnmi.Port[0].RxIntrCts +
4957				pAC->Pnmi.Port[1].RxIntrCts;
4958		}
4959		SK_PNMI_STORE_U64(pBuf, Val64);
4960		*pLen = sizeof(SK_U64);
4961		break;
4962
4963	case OID_SKGE_TX_INTR_CTS:
4964		/* Dual net mode */
4965		if(pAC->Pnmi.DualNetActiveFlag == SK_TRUE){
4966			Val64 = pAC->Pnmi.Port[NetIndex].TxIntrCts;
4967		}
4968		/* Single net mode */
4969		else {
4970			Val64 = pAC->Pnmi.Port[0].TxIntrCts +
4971				pAC->Pnmi.Port[1].TxIntrCts;
4972		}
4973		SK_PNMI_STORE_U64(pBuf, Val64);
4974		*pLen = sizeof(SK_U64);
4975		break;
4976
4977	case OID_SKGE_RX_NO_BUF_CTS:
4978		/* Dual net mode */
4979		if(pAC->Pnmi.DualNetActiveFlag == SK_TRUE){
4980			Val64 = pAC->Pnmi.Port[NetIndex].RxNoBufCts;
4981		}
4982		/* Single net mode */
4983		else {
4984			Val64 = pAC->Pnmi.Port[0].RxNoBufCts +
4985				pAC->Pnmi.Port[1].RxNoBufCts;
4986		}
4987		SK_PNMI_STORE_U64(pBuf, Val64);
4988		*pLen = sizeof(SK_U64);
4989		break;
4990
4991	case OID_SKGE_TX_NO_BUF_CTS:
4992		/* Dual net mode */
4993		if(pAC->Pnmi.DualNetActiveFlag == SK_TRUE){
4994			Val64 = pAC->Pnmi.Port[NetIndex].TxNoBufCts;
4995		}
4996		/* Single net mode */
4997		else {
4998			Val64 = pAC->Pnmi.Port[0].TxNoBufCts +
4999				pAC->Pnmi.Port[1].TxNoBufCts;
5000		}
5001		SK_PNMI_STORE_U64(pBuf, Val64);
5002		*pLen = sizeof(SK_U64);
5003		break;
5004
5005	case OID_SKGE_TX_USED_DESCR_NO:
5006		/* Dual net mode */
5007		if(pAC->Pnmi.DualNetActiveFlag == SK_TRUE){
5008			Val64 = pAC->Pnmi.Port[NetIndex].TxUsedDescrNo;
5009		}
5010		/* Single net mode */
5011		else {
5012			Val64 = pAC->Pnmi.Port[0].TxUsedDescrNo +
5013				pAC->Pnmi.Port[1].TxUsedDescrNo;
5014		}
5015		SK_PNMI_STORE_U64(pBuf, Val64);
5016		*pLen = sizeof(SK_U64);
5017		break;
5018
5019	case OID_SKGE_RX_DELIVERED_CTS:
5020		/* Dual net mode */
5021		if(pAC->Pnmi.DualNetActiveFlag == SK_TRUE){
5022			Val64 = pAC->Pnmi.Port[NetIndex].RxDeliveredCts;
5023		}
5024		/* Single net mode */
5025		else {
5026			Val64 = pAC->Pnmi.Port[0].RxDeliveredCts +
5027				pAC->Pnmi.Port[1].RxDeliveredCts;
5028		}
5029		SK_PNMI_STORE_U64(pBuf, Val64);
5030		*pLen = sizeof(SK_U64);
5031		break;
5032
5033	case OID_SKGE_RX_OCTETS_DELIV_CTS:
5034		/* Dual net mode */
5035		if(pAC->Pnmi.DualNetActiveFlag == SK_TRUE){
5036			Val64 = pAC->Pnmi.Port[NetIndex].RxOctetsDeliveredCts;
5037		}
5038		/* Single net mode */
5039		else {
5040			Val64 = pAC->Pnmi.Port[0].RxOctetsDeliveredCts +
5041				pAC->Pnmi.Port[1].RxOctetsDeliveredCts;
5042		}
5043		SK_PNMI_STORE_U64(pBuf, Val64);
5044		*pLen = sizeof(SK_U64);
5045		break;
5046
5047	case OID_SKGE_RX_HW_ERROR_CTS:
5048		SK_PNMI_STORE_U64(pBuf, Val64RxHwErrs);
5049		*pLen = sizeof(SK_U64);
5050		break;
5051
5052	case OID_SKGE_TX_HW_ERROR_CTS:
5053		SK_PNMI_STORE_U64(pBuf, Val64TxHwErrs);
5054		*pLen = sizeof(SK_U64);
5055		break;
5056
5057	case OID_SKGE_IN_ERRORS_CTS:
5058		/* Dual net mode */
5059		if(pAC->Pnmi.DualNetActiveFlag == SK_TRUE){
5060			Val64 = Val64RxHwErrs + pAC->Pnmi.Port[NetIndex].RxNoBufCts;
5061		}
5062		/* Single net mode */
5063		else {
5064			Val64 = Val64RxHwErrs +
5065				pAC->Pnmi.Port[0].RxNoBufCts +
5066				pAC->Pnmi.Port[1].RxNoBufCts;
5067		}
5068		SK_PNMI_STORE_U64(pBuf, Val64);
5069		*pLen = sizeof(SK_U64);
5070		break;
5071
5072	case OID_SKGE_OUT_ERROR_CTS:
5073		/* Dual net mode */
5074		if(pAC->Pnmi.DualNetActiveFlag == SK_TRUE){
5075			Val64 = Val64TxHwErrs + pAC->Pnmi.Port[NetIndex].TxNoBufCts;
5076		}
5077		/* Single net mode */
5078		else {
5079			Val64 = Val64TxHwErrs +
5080				pAC->Pnmi.Port[0].TxNoBufCts +
5081				pAC->Pnmi.Port[1].TxNoBufCts;
5082		}
5083		SK_PNMI_STORE_U64(pBuf, Val64);
5084		*pLen = sizeof(SK_U64);
5085		break;
5086
5087	case OID_SKGE_ERR_RECOVERY_CTS:
5088		/* Dual net mode */
5089		if(pAC->Pnmi.DualNetActiveFlag == SK_TRUE){
5090			Val64 = pAC->Pnmi.Port[NetIndex].ErrRecoveryCts;
5091		}
5092		/* Single net mode */
5093		else {
5094			Val64 = pAC->Pnmi.Port[0].ErrRecoveryCts +
5095				pAC->Pnmi.Port[1].ErrRecoveryCts;
5096		}
5097		SK_PNMI_STORE_U64(pBuf, Val64);
5098		*pLen = sizeof(SK_U64);
5099		break;
5100
5101	case OID_SKGE_SYSUPTIME:
5102		Val64 = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC));
5103		Val64 -= pAC->Pnmi.StartUpTime;
5104		SK_PNMI_STORE_U64(pBuf, Val64);
5105		*pLen = sizeof(SK_U64);
5106		break;
5107
5108	case OID_SKGE_MDB_VERSION:
5109		Val32 = SK_PNMI_MDB_VERSION;
5110		SK_PNMI_STORE_U32(pBuf, Val32);
5111		*pLen = sizeof(SK_U32);
5112		break;
5113
5114	case OID_GEN_RCV_ERROR:
5115		Val64 = Val64RxHwErrs + pAC->Pnmi.Port[NetIndex].RxNoBufCts;
5116
5117		/*
5118		 * by default 32bit values are evaluated
5119		 */
5120		if (!Is64BitReq) {
5121			Val32 = (SK_U32)Val64;
5122			SK_PNMI_STORE_U32(pBuf, Val32);
5123			*pLen = sizeof(SK_U32);
5124		}
5125		else {
5126			SK_PNMI_STORE_U64(pBuf, Val64);
5127			*pLen = sizeof(SK_U64);
5128		}
5129		break;
5130
5131	case OID_GEN_XMIT_ERROR:
5132		Val64 = Val64TxHwErrs + pAC->Pnmi.Port[NetIndex].TxNoBufCts;
5133
5134		/*
5135		 * by default 32bit values are evaluated
5136		 */
5137		if (!Is64BitReq) {
5138			Val32 = (SK_U32)Val64;
5139			SK_PNMI_STORE_U32(pBuf, Val32);
5140			*pLen = sizeof(SK_U32);
5141		}
5142		else {
5143			SK_PNMI_STORE_U64(pBuf, Val64);
5144			*pLen = sizeof(SK_U64);
5145		}
5146		break;
5147
5148	case OID_GEN_RCV_NO_BUFFER:
5149		Val64 = pAC->Pnmi.Port[NetIndex].RxNoBufCts;
5150
5151		/*
5152		 * by default 32bit values are evaluated
5153		 */
5154		if (!Is64BitReq) {
5155			Val32 = (SK_U32)Val64;
5156			SK_PNMI_STORE_U32(pBuf, Val32);
5157			*pLen = sizeof(SK_U32);
5158		}
5159		else {
5160			SK_PNMI_STORE_U64(pBuf, Val64);
5161			*pLen = sizeof(SK_U64);
5162		}
5163		break;
5164
5165	case OID_GEN_TRANSMIT_QUEUE_LENGTH:
5166		Val32 = (SK_U32)pAC->Pnmi.Port[NetIndex].TxSwQueueLen;
5167		SK_PNMI_STORE_U32(pBuf, Val32);
5168		*pLen = sizeof(SK_U32);
5169		break;
5170
5171	default:
5172		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR034,
5173			SK_PNMI_ERR034MSG);
5174
5175		*pLen = 0;
5176		return (SK_PNMI_ERR_GENERAL);
5177	}
5178
5179	if (Id == OID_SKGE_RX_HW_ERROR_CTS ||
5180		Id == OID_SKGE_TX_HW_ERROR_CTS ||
5181		Id == OID_SKGE_IN_ERRORS_CTS ||
5182		Id == OID_SKGE_OUT_ERROR_CTS ||
5183		Id == OID_GEN_XMIT_ERROR ||
5184		Id == OID_GEN_RCV_ERROR) {
5185
5186		pAC->Pnmi.MacUpdatedFlag --;
5187	}
5188
5189	return (SK_PNMI_ERR_OK);
5190}
5191
5192/*****************************************************************************
5193 *
5194 * Rlmt - OID handler function of OID_SKGE_RLMT_XXX single instance.
5195 *
5196 * Description:
5197 *	Get/Presets/Sets the RLMT OIDs.
5198 *
5199 * Returns:
5200 *	SK_PNMI_ERR_OK           The request was successfully performed.
5201 *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
5202 *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
5203 *	                         the correct data (e.g. a 32bit value is
5204 *	                         needed, but a 16 bit value was passed).
5205 *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
5206 *	                         value range.
5207 *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
5208 *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
5209 *                               exist (e.g. port instance 3 on a two port
5210 *	                         adapter.
5211 */
5212
5213static int Rlmt(
5214SK_AC *pAC,		/* Pointer to adapter context */
5215SK_IOC IoC,		/* IO context handle */
5216int Action,		/* Get/PreSet/Set action */
5217SK_U32 Id,		/* Object ID that is to be processed */
5218char *pBuf,		/* Buffer to which to mgmt data will be retrieved */
5219unsigned int *pLen,	/* On call: buffer length. On return: used buffer */
5220SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
5221unsigned int TableIndex, /* Index to the Id table */
5222SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode allways zero */
5223{
5224	int		Ret;
5225	unsigned int	PhysPortIndex;
5226	unsigned int	PhysPortMax;
5227	SK_EVPARA	EventParam;
5228	SK_U32		Val32;
5229	SK_U64		Val64;
5230
5231
5232	/*
5233	 * Check instance. Only single instance OIDs are allowed here.
5234	 */
5235	if (Instance != (SK_U32)(-1) && Instance != 1) {
5236
5237		*pLen = 0;
5238		return (SK_PNMI_ERR_UNKNOWN_INST);
5239	}
5240
5241	/*
5242	 * Perform the requested action
5243	 */
5244	if (Action == SK_PNMI_GET) {
5245
5246		/*
5247		 * Check if the buffer length is large enough.
5248		 */
5249
5250		switch (Id) {
5251
5252		case OID_SKGE_RLMT_MODE:
5253		case OID_SKGE_RLMT_PORT_ACTIVE:
5254		case OID_SKGE_RLMT_PORT_PREFERRED:
5255			if (*pLen < sizeof(SK_U8)) {
5256
5257				*pLen = sizeof(SK_U8);
5258				return (SK_PNMI_ERR_TOO_SHORT);
5259			}
5260			break;
5261
5262		case OID_SKGE_RLMT_PORT_NUMBER:
5263			if (*pLen < sizeof(SK_U32)) {
5264
5265				*pLen = sizeof(SK_U32);
5266				return (SK_PNMI_ERR_TOO_SHORT);
5267			}
5268			break;
5269
5270		case OID_SKGE_RLMT_CHANGE_CTS:
5271		case OID_SKGE_RLMT_CHANGE_TIME:
5272		case OID_SKGE_RLMT_CHANGE_ESTIM:
5273		case OID_SKGE_RLMT_CHANGE_THRES:
5274			if (*pLen < sizeof(SK_U64)) {
5275
5276				*pLen = sizeof(SK_U64);
5277				return (SK_PNMI_ERR_TOO_SHORT);
5278			}
5279			break;
5280
5281		default:
5282			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR035,
5283				SK_PNMI_ERR035MSG);
5284
5285			*pLen = 0;
5286			return (SK_PNMI_ERR_GENERAL);
5287		}
5288
5289		/*
5290		 * Update RLMT statistic and increment semaphores to indicate
5291		 * that an update was already done. Maybe RLMT will hold its
5292		 * statistic always up to date some time. Then we can
5293		 * remove this type of call.
5294		 */
5295		if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) {
5296
5297			*pLen = 0;
5298			return (Ret);
5299		}
5300		pAC->Pnmi.RlmtUpdatedFlag ++;
5301
5302		/*
5303		 * Retrieve Value
5304		*/
5305		switch (Id) {
5306
5307		case OID_SKGE_RLMT_MODE:
5308			*pBuf = (char)pAC->Rlmt.Net[0].RlmtMode;
5309			*pLen = sizeof(char);
5310			break;
5311
5312		case OID_SKGE_RLMT_PORT_NUMBER:
5313			Val32 = (SK_U32)pAC->GIni.GIMacsFound;
5314			SK_PNMI_STORE_U32(pBuf, Val32);
5315			*pLen = sizeof(SK_U32);
5316			break;
5317
5318		case OID_SKGE_RLMT_PORT_ACTIVE:
5319			*pBuf = 0;
5320			/*
5321			 * If multiple ports may become active this OID
5322			 * doesn't make sense any more. A new variable in
5323			 * the port structure should be created. However,
5324			 * for this variable the first active port is
5325			 * returned.
5326			 */
5327			PhysPortMax = pAC->GIni.GIMacsFound;
5328
5329			for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax;
5330				PhysPortIndex ++) {
5331
5332				if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
5333
5334					*pBuf = (char)SK_PNMI_PORT_PHYS2LOG(PhysPortIndex);
5335					break;
5336				}
5337			}
5338			*pLen = sizeof(char);
5339			break;
5340
5341		case OID_SKGE_RLMT_PORT_PREFERRED:
5342			*pBuf = (char)SK_PNMI_PORT_PHYS2LOG(pAC->Rlmt.Net[NetIndex].Preference);
5343			*pLen = sizeof(char);
5344			break;
5345
5346		case OID_SKGE_RLMT_CHANGE_CTS:
5347			Val64 = pAC->Pnmi.RlmtChangeCts;
5348			SK_PNMI_STORE_U64(pBuf, Val64);
5349			*pLen = sizeof(SK_U64);
5350			break;
5351
5352		case OID_SKGE_RLMT_CHANGE_TIME:
5353			Val64 = pAC->Pnmi.RlmtChangeTime;
5354			SK_PNMI_STORE_U64(pBuf, Val64);
5355			*pLen = sizeof(SK_U64);
5356			break;
5357
5358		case OID_SKGE_RLMT_CHANGE_ESTIM:
5359			Val64 = pAC->Pnmi.RlmtChangeEstimate.Estimate;
5360			SK_PNMI_STORE_U64(pBuf, Val64);
5361			*pLen = sizeof(SK_U64);
5362			break;
5363
5364		case OID_SKGE_RLMT_CHANGE_THRES:
5365			Val64 = pAC->Pnmi.RlmtChangeThreshold;
5366			SK_PNMI_STORE_U64(pBuf, Val64);
5367			*pLen = sizeof(SK_U64);
5368			break;
5369
5370		default:
5371			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR036,
5372				SK_PNMI_ERR036MSG);
5373
5374			pAC->Pnmi.RlmtUpdatedFlag --;
5375			*pLen = 0;
5376			return (SK_PNMI_ERR_GENERAL);
5377		}
5378
5379		pAC->Pnmi.RlmtUpdatedFlag --;
5380	}
5381	else {
5382		/* Perform a preset or set */
5383		switch (Id) {
5384
5385		case OID_SKGE_RLMT_MODE:
5386			/* Check if the buffer length is plausible */
5387			if (*pLen < sizeof(char)) {
5388
5389				*pLen = sizeof(char);
5390				return (SK_PNMI_ERR_TOO_SHORT);
5391			}
5392			/* Check if the value range is correct */
5393			if (*pLen != sizeof(char) ||
5394				(*pBuf & SK_PNMI_RLMT_MODE_CHK_LINK) == 0 ||
5395				*(SK_U8 *)pBuf > 15) {
5396
5397				*pLen = 0;
5398				return (SK_PNMI_ERR_BAD_VALUE);
5399			}
5400			/* The preset ends here */
5401			if (Action == SK_PNMI_PRESET) {
5402
5403				*pLen = 0;
5404				return (SK_PNMI_ERR_OK);
5405			}
5406			/* Send an event to RLMT to change the mode */
5407			SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
5408			EventParam.Para32[0] |= (SK_U32)(*pBuf);
5409			EventParam.Para32[1] = 0;
5410			if (SkRlmtEvent(pAC, IoC, SK_RLMT_MODE_CHANGE,
5411				EventParam) > 0) {
5412
5413				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR037,
5414					SK_PNMI_ERR037MSG);
5415
5416				*pLen = 0;
5417				return (SK_PNMI_ERR_GENERAL);
5418			}
5419			break;
5420
5421		case OID_SKGE_RLMT_PORT_PREFERRED:
5422			/* Check if the buffer length is plausible */
5423			if (*pLen < sizeof(char)) {
5424
5425				*pLen = sizeof(char);
5426				return (SK_PNMI_ERR_TOO_SHORT);
5427			}
5428			/* Check if the value range is correct */
5429			if (*pLen != sizeof(char) || *(SK_U8 *)pBuf >
5430				(SK_U8)pAC->GIni.GIMacsFound) {
5431
5432				*pLen = 0;
5433				return (SK_PNMI_ERR_BAD_VALUE);
5434			}
5435			/* The preset ends here */
5436			if (Action == SK_PNMI_PRESET) {
5437
5438				*pLen = 0;
5439				return (SK_PNMI_ERR_OK);
5440			}
5441
5442			/*
5443			 * Send an event to RLMT change the preferred port.
5444			 * A param of -1 means automatic mode. RLMT will
5445			 * make the decision which is the preferred port.
5446			 */
5447			SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
5448			EventParam.Para32[0] = (SK_U32)(*pBuf) - 1;
5449			EventParam.Para32[1] = NetIndex;
5450			if (SkRlmtEvent(pAC, IoC, SK_RLMT_PREFPORT_CHANGE,
5451				EventParam) > 0) {
5452
5453				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR038,
5454					SK_PNMI_ERR038MSG);
5455
5456				*pLen = 0;
5457				return (SK_PNMI_ERR_GENERAL);
5458			}
5459			break;
5460
5461		case OID_SKGE_RLMT_CHANGE_THRES:
5462			/* Check if the buffer length is plausible */
5463			if (*pLen < sizeof(SK_U64)) {
5464
5465				*pLen = sizeof(SK_U64);
5466				return (SK_PNMI_ERR_TOO_SHORT);
5467			}
5468			/*
5469			 * There are not many restrictions to the
5470			 * value range.
5471			 */
5472			if (*pLen != sizeof(SK_U64)) {
5473
5474				*pLen = 0;
5475				return (SK_PNMI_ERR_BAD_VALUE);
5476			}
5477			/* A preset ends here */
5478			if (Action == SK_PNMI_PRESET) {
5479
5480				*pLen = 0;
5481				return (SK_PNMI_ERR_OK);
5482			}
5483			/*
5484			 * Store the new threshold, which will be taken
5485			 * on the next timer event.
5486			 */
5487			SK_PNMI_READ_U64(pBuf, Val64);
5488			pAC->Pnmi.RlmtChangeThreshold = Val64;
5489			break;
5490
5491		default:
5492			/* The other OIDs are not be able for set */
5493			*pLen = 0;
5494			return (SK_PNMI_ERR_READ_ONLY);
5495		}
5496	}
5497
5498	return (SK_PNMI_ERR_OK);
5499}
5500
5501/*****************************************************************************
5502 *
5503 * RlmtStat - OID handler function of OID_SKGE_RLMT_XXX multiple instance.
5504 *
5505 * Description:
5506 *	Performs get requests on multiple instance variables.
5507 *
5508 * Returns:
5509 *	SK_PNMI_ERR_OK           The request was successfully performed.
5510 *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
5511 *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
5512 *	                         the correct data (e.g. a 32bit value is
5513 *	                         needed, but a 16 bit value was passed).
5514 *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
5515 *                               exist (e.g. port instance 3 on a two port
5516 *	                         adapter.
5517 */
5518
5519static int RlmtStat(
5520SK_AC *pAC,		/* Pointer to adapter context */
5521SK_IOC IoC,		/* IO context handle */
5522int Action,		/* Get/PreSet/Set action */
5523SK_U32 Id,		/* Object ID that is to be processed */
5524char *pBuf,		/* Buffer to which to mgmt data will be retrieved */
5525unsigned int *pLen,	/* On call: buffer length. On return: used buffer */
5526SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
5527unsigned int TableIndex, /* Index to the Id table */
5528SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode allways zero */
5529{
5530	unsigned int	PhysPortMax;
5531	unsigned int	PhysPortIndex;
5532	unsigned int	Limit;
5533	unsigned int	Offset;
5534	int		Ret;
5535	SK_U32		Val32;
5536	SK_U64		Val64;
5537
5538	/*
5539	 * Calculate the port indexes from the instance
5540	 */
5541	PhysPortMax = pAC->GIni.GIMacsFound;
5542
5543	if ((Instance != (SK_U32)(-1))) {
5544		/* Check instance range */
5545		if ((Instance < 1) || (Instance > PhysPortMax)) {
5546
5547			*pLen = 0;
5548			return (SK_PNMI_ERR_UNKNOWN_INST);
5549		}
5550
5551		/* Single net mode */
5552		PhysPortIndex = Instance - 1;
5553
5554		/* Dual net mode */
5555		if(pAC->Pnmi.DualNetActiveFlag == SK_TRUE){
5556			PhysPortIndex = NetIndex;
5557		}
5558
5559		/* Both net modes */
5560		Limit = PhysPortIndex + 1;
5561	}
5562	else {
5563		/* Single net mode */
5564		PhysPortIndex = 0;
5565		Limit = PhysPortMax;
5566
5567		/* Dual net mode */
5568		if(pAC->Pnmi.DualNetActiveFlag == SK_TRUE){
5569			PhysPortIndex = NetIndex;
5570			Limit = PhysPortIndex + 1;
5571		}
5572	}
5573
5574	/*
5575	 * Currently only get requests are allowed.
5576	 */
5577	if (Action != SK_PNMI_GET) {
5578
5579		*pLen = 0;
5580		return (SK_PNMI_ERR_READ_ONLY);
5581	}
5582
5583	/*
5584	 * Check if the buffer length is large enough.
5585	 */
5586	switch (Id) {
5587
5588	case OID_SKGE_RLMT_PORT_INDEX:
5589	case OID_SKGE_RLMT_STATUS:
5590		if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U32)) {
5591
5592			*pLen = (Limit - PhysPortIndex) * sizeof(SK_U32);
5593			return (SK_PNMI_ERR_TOO_SHORT);
5594		}
5595		break;
5596
5597	case OID_SKGE_RLMT_TX_HELLO_CTS:
5598	case OID_SKGE_RLMT_RX_HELLO_CTS:
5599	case OID_SKGE_RLMT_TX_SP_REQ_CTS:
5600	case OID_SKGE_RLMT_RX_SP_CTS:
5601		if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U64)) {
5602
5603			*pLen = (Limit - PhysPortIndex) * sizeof(SK_U64);
5604			return (SK_PNMI_ERR_TOO_SHORT);
5605		}
5606		break;
5607
5608	default:
5609		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR039,
5610			SK_PNMI_ERR039MSG);
5611
5612		*pLen = 0;
5613		return (SK_PNMI_ERR_GENERAL);
5614
5615	}
5616
5617	/*
5618	 * Update statistic and increment semaphores to indicate that
5619	 * an update was already done.
5620	 */
5621	if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) {
5622
5623		*pLen = 0;
5624		return (Ret);
5625	}
5626	pAC->Pnmi.RlmtUpdatedFlag ++;
5627
5628	/*
5629	 * Get value
5630	 */
5631	Offset = 0;
5632	for (; PhysPortIndex < Limit; PhysPortIndex ++) {
5633
5634		switch (Id) {
5635
5636		case OID_SKGE_RLMT_PORT_INDEX:
5637			Val32 = PhysPortIndex;
5638			SK_PNMI_STORE_U32(pBuf + Offset, Val32);
5639			Offset += sizeof(SK_U32);
5640			break;
5641
5642		case OID_SKGE_RLMT_STATUS:
5643			if (pAC->Rlmt.Port[PhysPortIndex].PortState ==
5644				SK_RLMT_PS_INIT ||
5645				pAC->Rlmt.Port[PhysPortIndex].PortState ==
5646				SK_RLMT_PS_DOWN) {
5647
5648				Val32 = SK_PNMI_RLMT_STATUS_ERROR;
5649			}
5650			else if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
5651
5652				Val32 = SK_PNMI_RLMT_STATUS_ACTIVE;
5653			}
5654			else {
5655				Val32 = SK_PNMI_RLMT_STATUS_STANDBY;
5656			}
5657			SK_PNMI_STORE_U32(pBuf + Offset, Val32);
5658			Offset += sizeof(SK_U32);
5659			break;
5660
5661		case OID_SKGE_RLMT_TX_HELLO_CTS:
5662			Val64 = pAC->Rlmt.Port[PhysPortIndex].TxHelloCts;
5663			SK_PNMI_STORE_U64(pBuf + Offset, Val64);
5664			Offset += sizeof(SK_U64);
5665			break;
5666
5667		case OID_SKGE_RLMT_RX_HELLO_CTS:
5668			Val64 = pAC->Rlmt.Port[PhysPortIndex].RxHelloCts;
5669			SK_PNMI_STORE_U64(pBuf + Offset, Val64);
5670			Offset += sizeof(SK_U64);
5671			break;
5672
5673		case OID_SKGE_RLMT_TX_SP_REQ_CTS:
5674			Val64 = pAC->Rlmt.Port[PhysPortIndex].TxSpHelloReqCts;
5675			SK_PNMI_STORE_U64(pBuf + Offset, Val64);
5676			Offset += sizeof(SK_U64);
5677			break;
5678
5679		case OID_SKGE_RLMT_RX_SP_CTS:
5680			Val64 = pAC->Rlmt.Port[PhysPortIndex].RxSpHelloCts;
5681			SK_PNMI_STORE_U64(pBuf + Offset, Val64);
5682			Offset += sizeof(SK_U64);
5683			break;
5684
5685		default:
5686			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR040,
5687				SK_PNMI_ERR040MSG);
5688
5689			pAC->Pnmi.RlmtUpdatedFlag --;
5690			*pLen = 0;
5691			return (SK_PNMI_ERR_GENERAL);
5692		}
5693	}
5694	*pLen = Offset;
5695
5696	pAC->Pnmi.RlmtUpdatedFlag --;
5697
5698	return (SK_PNMI_ERR_OK);
5699}
5700
5701/*****************************************************************************
5702 *
5703 * MacPrivateConf - OID handler function of OIDs concerning the configuration
5704 *
5705 * Description:
5706 *	Get/Presets/Sets the OIDs concerning the configuration.
5707 *
5708 * Returns:
5709 *	SK_PNMI_ERR_OK           The request was successfully performed.
5710 *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
5711 *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
5712 *	                         the correct data (e.g. a 32bit value is
5713 *	                         needed, but a 16 bit value was passed).
5714 *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
5715 *	                         value range.
5716 *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
5717 *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
5718 *                               exist (e.g. port instance 3 on a two port
5719 *	                         adapter.
5720 */
5721
5722static int MacPrivateConf(
5723SK_AC *pAC,		/* Pointer to adapter context */
5724SK_IOC IoC,		/* IO context handle */
5725int Action,		/* Get/PreSet/Set action */
5726SK_U32 Id,		/* Object ID that is to be processed */
5727char *pBuf,		/* Buffer to which to mgmt data will be retrieved */
5728unsigned int *pLen,	/* On call: buffer length. On return: used buffer */
5729SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
5730unsigned int TableIndex, /* Index to the Id table */
5731SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode allways zero */
5732{
5733	unsigned int	PhysPortMax;
5734	unsigned int	PhysPortIndex;
5735	unsigned int	LogPortMax;
5736	unsigned int	LogPortIndex;
5737	unsigned int	Limit;
5738	unsigned int	Offset;
5739	char		Val8;
5740	int		Ret;
5741	SK_EVPARA	EventParam;
5742	SK_U32		Val32;
5743
5744
5745	/*
5746	 * Calculate instance if wished. MAC index 0 is the virtual
5747	 * MAC.
5748	 */
5749	PhysPortMax = pAC->GIni.GIMacsFound;
5750	LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax);
5751
5752	if(pAC->Pnmi.DualNetActiveFlag == SK_TRUE){ /* Dual net mode */
5753		LogPortMax--;
5754	}
5755
5756	if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried */
5757		/* Check instance range */
5758		if ((Instance < 1) || (Instance > LogPortMax)) {
5759
5760			*pLen = 0;
5761			return (SK_PNMI_ERR_UNKNOWN_INST);
5762		}
5763		LogPortIndex = SK_PNMI_PORT_INST2LOG(Instance);
5764		Limit = LogPortIndex + 1;
5765	}
5766
5767	else { /* Instance == (SK_U32)(-1), get all Instances of that OID */
5768
5769		LogPortIndex = 0;
5770		Limit = LogPortMax;
5771	}
5772
5773	/*
5774	 * Perform action
5775	 */
5776	if (Action == SK_PNMI_GET) {
5777
5778		/*
5779		 * Check length
5780		 */
5781		switch (Id) {
5782
5783		case OID_SKGE_PMD:
5784		case OID_SKGE_CONNECTOR:
5785		case OID_SKGE_LINK_CAP:
5786		case OID_SKGE_LINK_MODE:
5787		case OID_SKGE_LINK_MODE_STATUS:
5788		case OID_SKGE_LINK_STATUS:
5789		case OID_SKGE_FLOWCTRL_CAP:
5790		case OID_SKGE_FLOWCTRL_MODE:
5791		case OID_SKGE_FLOWCTRL_STATUS:
5792		case OID_SKGE_PHY_OPERATION_CAP:
5793		case OID_SKGE_PHY_OPERATION_MODE:
5794		case OID_SKGE_PHY_OPERATION_STATUS:
5795			if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U8)) {
5796
5797				*pLen = (Limit - LogPortIndex) *
5798					sizeof(SK_U8);
5799				return (SK_PNMI_ERR_TOO_SHORT);
5800			}
5801			break;
5802
5803        case OID_SKGE_MTU:
5804			if (*pLen < sizeof(SK_U32)) {
5805
5806				*pLen = sizeof(SK_U32);
5807				return (SK_PNMI_ERR_TOO_SHORT);
5808			}
5809			break;
5810
5811		default:
5812			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR041,
5813				SK_PNMI_ERR041MSG);
5814			*pLen = 0;
5815			return (SK_PNMI_ERR_GENERAL);
5816		}
5817
5818		/*
5819		 * Update statistic and increment semaphore to indicate
5820		 * that an update was already done.
5821		 */
5822		if ((Ret = SirqUpdate(pAC, IoC)) != SK_PNMI_ERR_OK) {
5823
5824			*pLen = 0;
5825			return (Ret);
5826		}
5827		pAC->Pnmi.SirqUpdatedFlag ++;
5828
5829		/*
5830		 * Get value
5831		 */
5832		Offset = 0;
5833		for (; LogPortIndex < Limit; LogPortIndex ++) {
5834
5835			switch (Id) {
5836
5837			case OID_SKGE_PMD:
5838				*(pBuf + Offset) = pAC->Pnmi.PMD;
5839				Offset += sizeof(char);
5840				break;
5841
5842			case OID_SKGE_CONNECTOR:
5843				*(pBuf + Offset) = pAC->Pnmi.Connector;
5844				Offset += sizeof(char);
5845				break;
5846
5847			case OID_SKGE_LINK_CAP:
5848				if (LogPortIndex == 0) {
5849
5850					/* Get value for virtual port */
5851					VirtualConf(pAC, IoC, Id, pBuf +
5852						Offset);
5853				}
5854				else {
5855					/* Get value for physical ports */
5856					PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
5857						pAC, LogPortIndex);
5858
5859					*(pBuf + Offset) = pAC->GIni.GP[
5860						PhysPortIndex].PLinkCap;
5861				}
5862				Offset += sizeof(char);
5863				break;
5864
5865			case OID_SKGE_LINK_MODE:
5866				if (LogPortIndex == 0) {
5867
5868					/* Get value for virtual port */
5869					VirtualConf(pAC, IoC, Id, pBuf +
5870						Offset);
5871				}
5872				else {
5873					/* Get value for physical ports */
5874					PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
5875						pAC, LogPortIndex);
5876
5877					*(pBuf + Offset) = pAC->GIni.GP[
5878						PhysPortIndex].PLinkModeConf;
5879				}
5880
5881				Offset += sizeof(char);
5882				break;
5883
5884			case OID_SKGE_LINK_MODE_STATUS:
5885				if (LogPortIndex == 0) {
5886
5887					/* Get value for virtual port */
5888					VirtualConf(pAC, IoC, Id, pBuf +
5889						Offset);
5890				}
5891				else {
5892					/* Get value for physical port */
5893					PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
5894						pAC, LogPortIndex);
5895
5896					*(pBuf + Offset) =
5897						CalculateLinkModeStatus(pAC,
5898							IoC, PhysPortIndex);
5899				}
5900				Offset += sizeof(char);
5901				break;
5902
5903			case OID_SKGE_LINK_STATUS:
5904				if (LogPortIndex == 0) {
5905
5906					/* Get value for virtual port */
5907					VirtualConf(pAC, IoC, Id, pBuf +
5908						Offset);
5909				}
5910				else {
5911					/* Get value for physical ports */
5912					PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
5913						pAC, LogPortIndex);
5914
5915					*(pBuf + Offset) =
5916						CalculateLinkStatus(pAC,
5917							IoC, PhysPortIndex);
5918				}
5919				Offset += sizeof(char);
5920				break;
5921
5922			case OID_SKGE_FLOWCTRL_CAP:
5923				if (LogPortIndex == 0) {
5924
5925					/* Get value for virtual port */
5926					VirtualConf(pAC, IoC, Id, pBuf +
5927						Offset);
5928				}
5929				else {
5930					/* Get value for physical ports */
5931					PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
5932						pAC, LogPortIndex);
5933
5934					*(pBuf + Offset) = pAC->GIni.GP[
5935						PhysPortIndex].PFlowCtrlCap;
5936				}
5937				Offset += sizeof(char);
5938				break;
5939
5940			case OID_SKGE_FLOWCTRL_MODE:
5941				if (LogPortIndex == 0) {
5942
5943					/* Get value for virtual port */
5944					VirtualConf(pAC, IoC, Id, pBuf +
5945						Offset);
5946				}
5947				else {
5948					/* Get value for physical port */
5949					PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
5950						pAC, LogPortIndex);
5951
5952					*(pBuf + Offset) = pAC->GIni.GP[
5953						PhysPortIndex].PFlowCtrlMode;
5954				}
5955				Offset += sizeof(char);
5956				break;
5957
5958			case OID_SKGE_FLOWCTRL_STATUS:
5959				if (LogPortIndex == 0) {
5960
5961					/* Get value for virtual port */
5962					VirtualConf(pAC, IoC, Id, pBuf +
5963						Offset);
5964				}
5965				else {
5966					/* Get value for physical port */
5967					PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
5968						pAC, LogPortIndex);
5969
5970					*(pBuf + Offset) = pAC->GIni.GP[
5971						PhysPortIndex].PFlowCtrlStatus;
5972				}
5973				Offset += sizeof(char);
5974				break;
5975
5976			case OID_SKGE_PHY_OPERATION_CAP:
5977				if (LogPortIndex == 0) {
5978
5979					/* Get value for virtual port */
5980					VirtualConf(pAC, IoC, Id, pBuf +
5981						Offset);
5982				}
5983				else {
5984					/* Get value for physical ports */
5985					PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
5986						pAC, LogPortIndex);
5987
5988					*(pBuf + Offset) = pAC->GIni.GP[
5989						PhysPortIndex].PMSCap;
5990				}
5991				Offset += sizeof(char);
5992				break;
5993
5994			case OID_SKGE_PHY_OPERATION_MODE:
5995				if (LogPortIndex == 0) {
5996
5997					/* Get value for virtual port */
5998					VirtualConf(pAC, IoC, Id, pBuf +
5999						Offset);
6000				}
6001				else {
6002					/* Get value for physical port */
6003					PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
6004						pAC, LogPortIndex);
6005
6006					*(pBuf + Offset) = pAC->GIni.GP[
6007						PhysPortIndex].PMSMode;
6008				}
6009				Offset += sizeof(char);
6010				break;
6011
6012			case OID_SKGE_PHY_OPERATION_STATUS:
6013				if (LogPortIndex == 0) {
6014
6015					/* Get value for virtual port */
6016					VirtualConf(pAC, IoC, Id, pBuf +
6017						Offset);
6018				}
6019				else {
6020					/* Get value for physical port */
6021					PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
6022						pAC, LogPortIndex);
6023
6024					*(pBuf + Offset) = pAC->GIni.GP[
6025						PhysPortIndex].PMSStatus;
6026				}
6027				Offset += sizeof(char);
6028				break;
6029
6030			case OID_SKGE_MTU:
6031				Val32 = SK_DRIVER_GET_MTU(pAC, IoC, NetIndex);
6032				SK_PNMI_STORE_U32(pBuf + Offset, Val32);
6033				Offset += sizeof(SK_U32);
6034				break;
6035
6036			default:
6037				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR042,
6038					SK_PNMI_ERR042MSG);
6039
6040				pAC->Pnmi.SirqUpdatedFlag --;
6041				return (SK_PNMI_ERR_GENERAL);
6042			}
6043		}
6044		*pLen = Offset;
6045		pAC->Pnmi.SirqUpdatedFlag --;
6046
6047		return (SK_PNMI_ERR_OK);
6048	}
6049
6050	/*
6051	 * From here SET or PRESET action. Check if the passed
6052	 * buffer length is plausible.
6053	 */
6054	switch (Id) {
6055
6056	case OID_SKGE_LINK_MODE:
6057	case OID_SKGE_FLOWCTRL_MODE:
6058	case OID_SKGE_PHY_OPERATION_MODE:
6059		if (*pLen < Limit - LogPortIndex) {
6060
6061			*pLen = Limit - LogPortIndex;
6062			return (SK_PNMI_ERR_TOO_SHORT);
6063		}
6064		if (*pLen != Limit - LogPortIndex) {
6065
6066			*pLen = 0;
6067			return (SK_PNMI_ERR_BAD_VALUE);
6068		}
6069		break;
6070
6071	case OID_SKGE_MTU:
6072		if (*pLen < sizeof(SK_U32)) {
6073
6074			*pLen = sizeof(SK_U32);
6075			return (SK_PNMI_ERR_TOO_SHORT);
6076		}
6077		if (*pLen != sizeof(SK_U32)) {
6078
6079			*pLen = 0;
6080			return (SK_PNMI_ERR_BAD_VALUE);
6081		}
6082		break;
6083
6084    default:
6085		*pLen = 0;
6086		return (SK_PNMI_ERR_READ_ONLY);
6087	}
6088
6089	/*
6090	 * Perform preset or set
6091	 */
6092	Offset = 0;
6093	for (; LogPortIndex < Limit; LogPortIndex ++) {
6094
6095		switch (Id) {
6096
6097		case OID_SKGE_LINK_MODE:
6098			/* Check the value range */
6099			Val8 = *(pBuf + Offset);
6100			if (Val8 == 0) {
6101
6102				Offset += sizeof(char);
6103				break;
6104			}
6105			if (Val8 < SK_LMODE_HALF ||
6106				(LogPortIndex != 0 && Val8 > SK_LMODE_AUTOSENSE) ||
6107				(LogPortIndex == 0 && Val8 > SK_LMODE_INDETERMINATED)) {
6108
6109				*pLen = 0;
6110				return (SK_PNMI_ERR_BAD_VALUE);
6111			}
6112
6113			/* The preset ends here */
6114			if (Action == SK_PNMI_PRESET) {
6115
6116				return (SK_PNMI_ERR_OK);
6117			}
6118
6119			if (LogPortIndex == 0) {
6120
6121				/*
6122				 * The virtual port consists of all currently
6123				 * active ports. Find them and send an event
6124				 * with the new link mode to SIRQ.
6125				 */
6126				for (PhysPortIndex = 0;
6127					PhysPortIndex < PhysPortMax;
6128					PhysPortIndex ++) {
6129
6130					if (!pAC->Pnmi.Port[PhysPortIndex].
6131						ActiveFlag) {
6132
6133						continue;
6134					}
6135
6136					EventParam.Para32[0] = PhysPortIndex;
6137					EventParam.Para32[1] = (SK_U32)Val8;
6138					if (SkGeSirqEvent(pAC, IoC,
6139						SK_HWEV_SET_LMODE,
6140						EventParam) > 0) {
6141
6142						SK_ERR_LOG(pAC, SK_ERRCL_SW,
6143							SK_PNMI_ERR043,
6144							SK_PNMI_ERR043MSG);
6145
6146						*pLen = 0;
6147						return (SK_PNMI_ERR_GENERAL);
6148					}
6149				}
6150			}
6151			else {
6152				/*
6153				 * Send an event with the new link mode to
6154				 * the SIRQ module.
6155				 */
6156				EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS(
6157					pAC, LogPortIndex);
6158				EventParam.Para32[1] = (SK_U32)Val8;
6159				if (SkGeSirqEvent(pAC, IoC, SK_HWEV_SET_LMODE,
6160					EventParam) > 0) {
6161
6162					SK_ERR_LOG(pAC, SK_ERRCL_SW,
6163						SK_PNMI_ERR043,
6164						SK_PNMI_ERR043MSG);
6165
6166					*pLen = 0;
6167					return (SK_PNMI_ERR_GENERAL);
6168				}
6169			}
6170			Offset += sizeof(char);
6171			break;
6172
6173		case OID_SKGE_FLOWCTRL_MODE:
6174			/* Check the value range */
6175			Val8 = *(pBuf + Offset);
6176			if (Val8 == 0) {
6177
6178				Offset += sizeof(char);
6179				break;
6180			}
6181			if (Val8 < SK_FLOW_MODE_NONE ||
6182				(LogPortIndex != 0 && Val8 > SK_FLOW_MODE_SYM_OR_REM) ||
6183				(LogPortIndex == 0 && Val8 > SK_FLOW_MODE_INDETERMINATED)) {
6184
6185				*pLen = 0;
6186				return (SK_PNMI_ERR_BAD_VALUE);
6187			}
6188
6189			/* The preset ends here */
6190			if (Action == SK_PNMI_PRESET) {
6191
6192				return (SK_PNMI_ERR_OK);
6193			}
6194
6195			if (LogPortIndex == 0) {
6196
6197				/*
6198				 * The virtual port consists of all currently
6199				 * active ports. Find them and send an event
6200				 * with the new flow control mode to SIRQ.
6201				 */
6202				for (PhysPortIndex = 0;
6203					PhysPortIndex < PhysPortMax;
6204					PhysPortIndex ++) {
6205
6206					if (!pAC->Pnmi.Port[PhysPortIndex].
6207						ActiveFlag) {
6208
6209						continue;
6210					}
6211
6212					EventParam.Para32[0] = PhysPortIndex;
6213					EventParam.Para32[1] = (SK_U32)Val8;
6214					if (SkGeSirqEvent(pAC, IoC,
6215						SK_HWEV_SET_FLOWMODE,
6216						EventParam) > 0) {
6217
6218						SK_ERR_LOG(pAC, SK_ERRCL_SW,
6219							SK_PNMI_ERR044,
6220							SK_PNMI_ERR044MSG);
6221
6222						*pLen = 0;
6223						return (SK_PNMI_ERR_GENERAL);
6224					}
6225				}
6226			}
6227			else {
6228				/*
6229				 * Send an event with the new flow control
6230				 * mode to the SIRQ module.
6231				 */
6232				EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS(
6233					pAC, LogPortIndex);
6234				EventParam.Para32[1] = (SK_U32)Val8;
6235				if (SkGeSirqEvent(pAC, IoC,
6236					SK_HWEV_SET_FLOWMODE, EventParam)
6237					> 0) {
6238
6239					SK_ERR_LOG(pAC, SK_ERRCL_SW,
6240						SK_PNMI_ERR044,
6241						SK_PNMI_ERR044MSG);
6242
6243					*pLen = 0;
6244					return (SK_PNMI_ERR_GENERAL);
6245				}
6246			}
6247			Offset += sizeof(char);
6248			break;
6249
6250		case OID_SKGE_PHY_OPERATION_MODE :
6251			/* Check the value range */
6252			Val8 = *(pBuf + Offset);
6253			if (Val8 == 0) {
6254				/* mode of this port remains unchanged */
6255				Offset += sizeof(char);
6256				break;
6257			}
6258			if (Val8 < SK_MS_MODE_AUTO ||
6259				(LogPortIndex != 0 && Val8 > SK_MS_MODE_SLAVE) ||
6260				(LogPortIndex == 0 && Val8 > SK_MS_MODE_INDETERMINATED)) {
6261
6262				*pLen = 0;
6263				return (SK_PNMI_ERR_BAD_VALUE);
6264			}
6265
6266			/* The preset ends here */
6267			if (Action == SK_PNMI_PRESET) {
6268
6269				return (SK_PNMI_ERR_OK);
6270			}
6271
6272			if (LogPortIndex == 0) {
6273
6274				/*
6275				 * The virtual port consists of all currently
6276				 * active ports. Find them and send an event
6277				 * with new master/slave (role) mode to SIRQ.
6278				 */
6279				for (PhysPortIndex = 0;
6280					PhysPortIndex < PhysPortMax;
6281					PhysPortIndex ++) {
6282
6283					if (!pAC->Pnmi.Port[PhysPortIndex].
6284						ActiveFlag) {
6285
6286						continue;
6287					}
6288
6289					EventParam.Para32[0] = PhysPortIndex;
6290					EventParam.Para32[1] = (SK_U32)Val8;
6291					if (SkGeSirqEvent(pAC, IoC,
6292						SK_HWEV_SET_ROLE,
6293						EventParam) > 0) {
6294
6295						SK_ERR_LOG(pAC, SK_ERRCL_SW,
6296							SK_PNMI_ERR052,
6297							SK_PNMI_ERR052MSG);
6298
6299						*pLen = 0;
6300						return (SK_PNMI_ERR_GENERAL);
6301					}
6302				}
6303			}
6304			else {
6305				/*
6306				 * Send an event with the new master/slave
6307				 * (role) mode to the SIRQ module.
6308				 */
6309				EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS(
6310					pAC, LogPortIndex);
6311				EventParam.Para32[1] = (SK_U32)Val8;
6312				if (SkGeSirqEvent(pAC, IoC,
6313					SK_HWEV_SET_ROLE, EventParam) > 0) {
6314
6315					SK_ERR_LOG(pAC, SK_ERRCL_SW,
6316						SK_PNMI_ERR052,
6317						SK_PNMI_ERR052MSG);
6318
6319					*pLen = 0;
6320					return (SK_PNMI_ERR_GENERAL);
6321				}
6322			}
6323
6324			Offset += sizeof(char);
6325			break;
6326
6327		case OID_SKGE_MTU :
6328			/* Check the value range */
6329			Val32 = *(SK_U32*)(pBuf + Offset);
6330			if (Val32 == 0) {
6331				/* mtu of this port remains unchanged */
6332				Offset += sizeof(SK_U32);
6333				break;
6334			}
6335			if (SK_DRIVER_PRESET_MTU(pAC, IoC, NetIndex, Val32) != 0) {
6336				*pLen = 0;
6337				return (SK_PNMI_ERR_BAD_VALUE);
6338			}
6339
6340			/* The preset ends here */
6341			if (Action == SK_PNMI_PRESET) {
6342				return (SK_PNMI_ERR_OK);
6343			}
6344
6345			if (SK_DRIVER_SET_MTU(pAC, IoC, NetIndex, Val32) != 0) {
6346				return (SK_PNMI_ERR_GENERAL);
6347			}
6348
6349			Offset += sizeof(SK_U32);
6350			break;
6351
6352		default:
6353			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR045,
6354				SK_PNMI_ERR045MSG);
6355
6356			*pLen = 0;
6357			return (SK_PNMI_ERR_GENERAL);
6358		}
6359	}
6360
6361	return (SK_PNMI_ERR_OK);
6362}
6363
6364/*****************************************************************************
6365 *
6366 * Monitor - OID handler function for RLMT_MONITOR_XXX
6367 *
6368 * Description:
6369 *	Because RLMT currently does not support the monitoring of
6370 *	remote adapter cards, we return always an empty table.
6371 *
6372 * Returns:
6373 *	SK_PNMI_ERR_OK           The request was successfully performed.
6374 *	SK_PNMI_ERR_GENERAL      A general severe internal error occured.
6375 *	SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
6376 *	                         the correct data (e.g. a 32bit value is
6377 *	                         needed, but a 16 bit value was passed).
6378 *	SK_PNMI_ERR_BAD_VALUE    The passed value is not in the valid
6379 *	                         value range.
6380 *	SK_PNMI_ERR_READ_ONLY    The OID is read-only and cannot be set.
6381 *	SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
6382 *                               exist (e.g. port instance 3 on a two port
6383 *	                         adapter.
6384 */
6385
6386static int Monitor(
6387SK_AC *pAC,		/* Pointer to adapter context */
6388SK_IOC IoC,		/* IO context handle */
6389int Action,		/* Get/PreSet/Set action */
6390SK_U32 Id,		/* Object ID that is to be processed */
6391char *pBuf,		/* Buffer to which to mgmt data will be retrieved */
6392unsigned int *pLen,	/* On call: buffer length. On return: used buffer */
6393SK_U32 Instance,	/* Instance (1..n) that is to be queried or -1 */
6394unsigned int TableIndex, /* Index to the Id table */
6395SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode allways zero */
6396{
6397	unsigned int	Index;
6398	unsigned int	Limit;
6399	unsigned int	Offset;
6400	unsigned int	Entries;
6401
6402
6403	/*
6404	 * Calculate instance if wished.
6405	 */
6406	Entries = 0;
6407
6408	if ((Instance != (SK_U32)(-1))) {
6409
6410		if ((Instance < 1) || (Instance > Entries)) {
6411
6412			*pLen = 0;
6413			return (SK_PNMI_ERR_UNKNOWN_INST);
6414		}
6415
6416		Index = (unsigned int)Instance - 1;
6417		Limit = (unsigned int)Instance;
6418	}
6419	else {
6420		Index = 0;
6421		Limit = Entries;
6422	}
6423
6424	/*
6425	 * Get/Set value
6426	*/
6427	if (Action == SK_PNMI_GET) {
6428
6429		for (Offset=0; Index < Limit; Index ++) {
6430
6431			switch (Id) {
6432
6433			case OID_SKGE_RLMT_MONITOR_INDEX:
6434			case OID_SKGE_RLMT_MONITOR_ADDR:
6435			case OID_SKGE_RLMT_MONITOR_ERRS:
6436			case OID_SKGE_RLMT_MONITOR_TIMESTAMP:
6437			case OID_SKGE_RLMT_MONITOR_ADMIN:
6438				break;
6439
6440			default:
6441				SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR046,
6442					SK_PNMI_ERR046MSG);
6443
6444				*pLen = 0;
6445				return (SK_PNMI_ERR_GENERAL);
6446			}
6447		}
6448		*pLen = Offset;
6449	}
6450	else {
6451		/* Only MONITOR_ADMIN can be set */
6452		if (Id != OID_SKGE_RLMT_MONITOR_ADMIN) {
6453
6454			*pLen = 0;
6455			return (SK_PNMI_ERR_READ_ONLY);
6456		}
6457
6458		/* Check if the length is plausible */
6459		if (*pLen < (Limit - Index)) {
6460
6461			return (SK_PNMI_ERR_TOO_SHORT);
6462		}
6463		/* Okay, we have a wide value range */
6464		if (*pLen != (Limit - Index)) {
6465
6466			*pLen = 0;
6467			return (SK_PNMI_ERR_BAD_VALUE);
6468		}
6469/*
6470		for (Offset=0; Index < Limit; Index ++) {
6471		}
6472*/
6473		*pLen = 0;
6474		return (SK_PNMI_ERR_BAD_VALUE);
6475	}
6476
6477	return (SK_PNMI_ERR_OK);
6478}
6479
6480/*****************************************************************************
6481 *
6482 * VirtualConf - Calculates the values of configuration OIDs for virtual port
6483 *
6484 * Description:
6485 *	We handle here the get of the configuration group OIDs, which are
6486 *	a little bit complicated. The virtual port consists of all currently
6487 *	active physical ports. If multiple ports are active and configured
6488 *	differently we get in some trouble to return a single value. So we
6489 *	get the value of the first active port and compare it with that of
6490 *	the other active ports. If they are not the same, we return a value
6491 *	that indicates that the state is indeterminated.
6492 *
6493 * Returns:
6494 *	Nothing
6495 */
6496
6497static void VirtualConf(
6498SK_AC *pAC,		/* Pointer to adapter context */
6499SK_IOC IoC,		/* IO context handle */
6500SK_U32 Id,		/* Object ID that is to be processed */
6501char *pBuf)		/* Buffer to which to mgmt data will be retrieved */
6502{
6503	unsigned int	PhysPortMax;
6504	unsigned int	PhysPortIndex;
6505	SK_U8		Val8;
6506	SK_BOOL		PortActiveFlag;
6507
6508
6509	*pBuf = 0;
6510	PortActiveFlag = SK_FALSE;
6511	PhysPortMax = pAC->GIni.GIMacsFound;
6512
6513	for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax;
6514		PhysPortIndex ++) {
6515
6516		/* Check if the physical port is active */
6517		if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
6518
6519			continue;
6520		}
6521
6522		PortActiveFlag = SK_TRUE;
6523
6524		switch (Id) {
6525
6526		case OID_SKGE_LINK_CAP:
6527
6528			/*
6529			 * Different capabilities should not happen, but
6530			 * in the case of the cases OR them all together.
6531			 * From a curious point of view the virtual port
6532			 * is capable of all found capabilities.
6533			 */
6534			*pBuf |= pAC->GIni.GP[PhysPortIndex].PLinkCap;
6535			break;
6536
6537		case OID_SKGE_LINK_MODE:
6538			/* Check if it is the first active port */
6539			if (*pBuf == 0) {
6540
6541				*pBuf = pAC->GIni.GP[PhysPortIndex].
6542					PLinkModeConf;
6543				continue;
6544			}
6545
6546			/*
6547			 * If we find an active port with a different link
6548			 * mode than the first one we return a value that
6549			 * indicates that the link mode is indeterminated.
6550			 */
6551			if (*pBuf != pAC->GIni.GP[PhysPortIndex].PLinkModeConf
6552				) {
6553
6554				*pBuf = SK_LMODE_INDETERMINATED;
6555			}
6556			break;
6557
6558		case OID_SKGE_LINK_MODE_STATUS:
6559			/* Get the link mode of the physical port */
6560			Val8 = CalculateLinkModeStatus(pAC, IoC,
6561				PhysPortIndex);
6562
6563			/* Check if it is the first active port */
6564			if (*pBuf == 0) {
6565
6566				*pBuf = Val8;
6567				continue;
6568			}
6569
6570			/*
6571			 * If we find an active port with a different link
6572			 * mode status than the first one we return a value
6573			 * that indicates that the link mode status is
6574			 * indeterminated.
6575			 */
6576			if (*pBuf != Val8) {
6577
6578				*pBuf = SK_LMODE_STAT_INDETERMINATED;
6579			}
6580			break;
6581
6582		case OID_SKGE_LINK_STATUS:
6583			/* Get the link status of the physical port */
6584			Val8 = CalculateLinkStatus(pAC, IoC, PhysPortIndex);
6585
6586			/* Check if it is the first active port */
6587			if (*pBuf == 0) {
6588
6589				*pBuf = Val8;
6590				continue;
6591			}
6592
6593			/*
6594			 * If we find an active port with a different link
6595			 * status than the first one, we return a value
6596			 * that indicates that the link status is
6597			 * indeterminated.
6598			 */
6599			if (*pBuf != Val8) {
6600
6601				*pBuf = SK_PNMI_RLMT_LSTAT_INDETERMINATED;
6602			}
6603			break;
6604
6605		case OID_SKGE_FLOWCTRL_CAP:
6606			/* Check if it is the first active port */
6607			if (*pBuf == 0) {
6608
6609				*pBuf = pAC->GIni.GP[PhysPortIndex].
6610					PFlowCtrlCap;
6611				continue;
6612			}
6613
6614			/*
6615			 * From a curious point of view the virtual port
6616			 * is capable of all found capabilities.
6617			 */
6618			*pBuf |= pAC->GIni.GP[PhysPortIndex].PFlowCtrlCap;
6619			break;
6620
6621		case OID_SKGE_FLOWCTRL_MODE:
6622			/* Check if it is the first active port */
6623			if (*pBuf == 0) {
6624
6625				*pBuf = pAC->GIni.GP[PhysPortIndex].
6626					PFlowCtrlMode;
6627				continue;
6628			}
6629
6630			/*
6631			 * If we find an active port with a different flow
6632			 * control mode than the first one, we return a value
6633			 * that indicates that the mode is indeterminated.
6634			 */
6635			if (*pBuf != pAC->GIni.GP[PhysPortIndex].
6636				PFlowCtrlMode) {
6637
6638				*pBuf = SK_FLOW_MODE_INDETERMINATED;
6639			}
6640			break;
6641
6642		case OID_SKGE_FLOWCTRL_STATUS:
6643			/* Check if it is the first active port */
6644			if (*pBuf == 0) {
6645
6646				*pBuf = pAC->GIni.GP[PhysPortIndex].
6647					PFlowCtrlStatus;
6648				continue;
6649			}
6650
6651			/*
6652			 * If we find an active port with a different flow
6653			 * control status than the first one, we return a
6654			 * value that indicates that the status is
6655			 * indeterminated.
6656			 */
6657			if (*pBuf != pAC->GIni.GP[PhysPortIndex].
6658				PFlowCtrlStatus) {
6659
6660				*pBuf = SK_FLOW_STAT_INDETERMINATED;
6661			}
6662			break;
6663		case OID_SKGE_PHY_OPERATION_CAP:
6664			/* Check if it is the first active port */
6665			if (*pBuf == 0) {
6666
6667				*pBuf = pAC->GIni.GP[PhysPortIndex].
6668					PMSCap;
6669				continue;
6670			}
6671
6672			/*
6673			 * From a curious point of view the virtual port
6674			 * is capable of all found capabilities.
6675			 */
6676			*pBuf |= pAC->GIni.GP[PhysPortIndex].PMSCap;
6677			break;
6678
6679		case OID_SKGE_PHY_OPERATION_MODE:
6680			/* Check if it is the first active port */
6681			if (*pBuf == 0) {
6682
6683				*pBuf = pAC->GIni.GP[PhysPortIndex].
6684					PMSMode;
6685				continue;
6686			}
6687
6688			/*
6689			 * If we find an active port with a different master/
6690			 * slave mode than the first one, we return a value
6691			 * that indicates that the mode is indeterminated.
6692			 */
6693			if (*pBuf != pAC->GIni.GP[PhysPortIndex].
6694				PMSMode) {
6695
6696				*pBuf = SK_MS_MODE_INDETERMINATED;
6697			}
6698			break;
6699
6700		case OID_SKGE_PHY_OPERATION_STATUS:
6701			/* Check if it is the first active port */
6702			if (*pBuf == 0) {
6703
6704				*pBuf = pAC->GIni.GP[PhysPortIndex].
6705					PMSStatus;
6706				continue;
6707			}
6708
6709			/*
6710			 * If we find an active port with a different master/
6711			 * slave status than the first one, we return a
6712			 * value that indicates that the status is
6713			 * indeterminated.
6714			 */
6715			if (*pBuf != pAC->GIni.GP[PhysPortIndex].
6716				PMSStatus) {
6717
6718				*pBuf = SK_MS_STAT_INDETERMINATED;
6719			}
6720			break;
6721		}
6722	}
6723
6724	/*
6725	 * If no port is active return an indeterminated answer
6726	 */
6727	if (!PortActiveFlag) {
6728
6729		switch (Id) {
6730
6731		case OID_SKGE_LINK_CAP:
6732			*pBuf = SK_LMODE_CAP_INDETERMINATED;
6733			break;
6734
6735		case OID_SKGE_LINK_MODE:
6736			*pBuf = SK_LMODE_INDETERMINATED;
6737			break;
6738
6739		case OID_SKGE_LINK_MODE_STATUS:
6740			*pBuf = SK_LMODE_STAT_INDETERMINATED;
6741			break;
6742
6743		case OID_SKGE_LINK_STATUS:
6744			*pBuf = SK_PNMI_RLMT_LSTAT_INDETERMINATED;
6745			break;
6746
6747		case OID_SKGE_FLOWCTRL_CAP:
6748		case OID_SKGE_FLOWCTRL_MODE:
6749			*pBuf = SK_FLOW_MODE_INDETERMINATED;
6750			break;
6751
6752		case OID_SKGE_FLOWCTRL_STATUS:
6753			*pBuf = SK_FLOW_STAT_INDETERMINATED;
6754			break;
6755
6756		case OID_SKGE_PHY_OPERATION_CAP:
6757			*pBuf = SK_MS_CAP_INDETERMINATED;
6758			break;
6759
6760		case OID_SKGE_PHY_OPERATION_MODE:
6761			*pBuf = SK_MS_MODE_INDETERMINATED;
6762			break;
6763
6764		case OID_SKGE_PHY_OPERATION_STATUS:
6765			*pBuf = SK_MS_STAT_INDETERMINATED;
6766			break;
6767		}
6768	}
6769}
6770
6771/*****************************************************************************
6772 *
6773 * CalculateLinkStatus - Determins the link status of a physical port
6774 *
6775 * Description:
6776 *	Determins the link status the following way:
6777 *	  LSTAT_PHY_DOWN:  Link is down
6778 *	  LSTAT_AUTONEG:   Auto-negotiation failed
6779 *	  LSTAT_LOG_DOWN:  Link is up but RLMT did not yet put the port
6780 *	                   logically up.
6781 *	  LSTAT_LOG_UP:    RLMT marked the port as up
6782 *
6783 * Returns:
6784 *	Link status of physical port
6785 */
6786
6787static SK_U8 CalculateLinkStatus(
6788SK_AC *pAC,			/* Pointer to adapter context */
6789SK_IOC IoC,			/* IO context handle */
6790unsigned int PhysPortIndex)	/* Physical port index */
6791{
6792	SK_U8	Result;
6793
6794
6795	if (!pAC->GIni.GP[PhysPortIndex].PHWLinkUp) {
6796
6797		Result = SK_PNMI_RLMT_LSTAT_PHY_DOWN;
6798	}
6799	else if (pAC->GIni.GP[PhysPortIndex].PAutoNegFail > 0) {
6800
6801		Result = SK_PNMI_RLMT_LSTAT_AUTONEG;
6802				}
6803	else if (!pAC->Rlmt.Port[PhysPortIndex].PortDown) {
6804
6805		Result = SK_PNMI_RLMT_LSTAT_LOG_UP;
6806	}
6807	else {
6808		Result = SK_PNMI_RLMT_LSTAT_LOG_DOWN;
6809	}
6810
6811	return (Result);
6812}
6813
6814/*****************************************************************************
6815 *
6816 * CalculateLinkModeStatus - Determins the link mode status of a phys. port
6817 *
6818 * Description:
6819 *	The COMMON module only tells us if the mode is half or full duplex.
6820 *	But in the decade of auto sensing it is usefull for the user to
6821 *	know if the mode was negotiated or forced. Therefore we have a
6822 *	look to the mode, which was last used by the negotiation process.
6823 *
6824 * Returns:
6825 *	The link mode status
6826 */
6827
6828static SK_U8 CalculateLinkModeStatus(
6829SK_AC *pAC,			/* Pointer to adapter context */
6830SK_IOC IoC,			/* IO context handle */
6831unsigned int PhysPortIndex)	/* Physical port index */
6832{
6833	SK_U8	Result;
6834
6835
6836	/* Get the current mode, which can be full or half duplex */
6837	Result = pAC->GIni.GP[PhysPortIndex].PLinkModeStatus;
6838
6839	/* Check if no valid mode could be found (link is down) */
6840	if (Result < SK_LMODE_STAT_HALF) {
6841
6842		Result = SK_LMODE_STAT_UNKNOWN;
6843	}
6844	else if (pAC->GIni.GP[PhysPortIndex].PLinkMode >= SK_LMODE_AUTOHALF) {
6845
6846		/*
6847		 * Auto-negotiation was used to bring up the link. Change
6848		 * the already found duplex status that it indicates
6849		 * auto-negotiation was involved.
6850		 */
6851		if (Result == SK_LMODE_STAT_HALF) {
6852
6853			Result = SK_LMODE_STAT_AUTOHALF;
6854		}
6855		else if (Result == SK_LMODE_STAT_FULL) {
6856
6857			Result = SK_LMODE_STAT_AUTOFULL;
6858		}
6859	}
6860
6861	return (Result);
6862}
6863
6864/*****************************************************************************
6865 *
6866 * GetVpdKeyArr - Obtain an array of VPD keys
6867 *
6868 * Description:
6869 *	Read the VPD keys and build an array of VPD keys, which are
6870 *	easy to access.
6871 *
6872 * Returns:
6873 *	SK_PNMI_ERR_OK	     Task successfully performed.
6874 *	SK_PNMI_ERR_GENERAL  Something went wrong.
6875 */
6876
6877static int GetVpdKeyArr(
6878SK_AC *pAC,		/* Pointer to adapter context */
6879SK_IOC IoC,		/* IO context handle */
6880char *pKeyArr,		/* Ptr KeyArray */
6881unsigned int KeyArrLen,	/* Length of array in bytes */
6882unsigned int *pKeyNo)	/* Number of keys */
6883{
6884	unsigned int		BufKeysLen = SK_PNMI_VPD_BUFSIZE;
6885	char			BufKeys[SK_PNMI_VPD_BUFSIZE];
6886	unsigned int		StartOffset;
6887	unsigned int		Offset;
6888	int			Index;
6889	int			Ret;
6890
6891
6892	SK_MEMSET(pKeyArr, 0, KeyArrLen);
6893
6894	/*
6895	 * Get VPD key list
6896	 */
6897	Ret = VpdKeys(pAC, IoC, (char *)&BufKeys, (int *)&BufKeysLen,
6898		(int *)pKeyNo);
6899	if (Ret > 0) {
6900
6901		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR014,
6902			SK_PNMI_ERR014MSG);
6903
6904		return (SK_PNMI_ERR_GENERAL);
6905	}
6906	/* If no keys are available return now */
6907	if (*pKeyNo == 0 || BufKeysLen == 0) {
6908
6909		return (SK_PNMI_ERR_OK);
6910	}
6911	/*
6912	 * If the key list is too long for us trunc it and give a
6913	 * errorlog notification. This case should not happen because
6914	 * the maximum number of keys is limited due to RAM limitations
6915	 */
6916	if (*pKeyNo > SK_PNMI_VPD_ENTRIES) {
6917
6918		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR015,
6919			SK_PNMI_ERR015MSG);
6920
6921		*pKeyNo = SK_PNMI_VPD_ENTRIES;
6922	}
6923
6924	/*
6925	 * Now build an array of fixed string length size and copy
6926	 * the keys together.
6927	 */
6928	for (Index = 0, StartOffset = 0, Offset = 0; Offset < BufKeysLen;
6929		Offset ++) {
6930
6931		if (BufKeys[Offset] != 0) {
6932
6933			continue;
6934		}
6935
6936		if (Offset - StartOffset > SK_PNMI_VPD_KEY_SIZE) {
6937
6938			SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR016,
6939				SK_PNMI_ERR016MSG);
6940			return (SK_PNMI_ERR_GENERAL);
6941		}
6942
6943		SK_STRNCPY(pKeyArr + Index * SK_PNMI_VPD_KEY_SIZE,
6944			&BufKeys[StartOffset], SK_PNMI_VPD_KEY_SIZE);
6945
6946		Index ++;
6947		StartOffset = Offset + 1;
6948	}
6949
6950	/* Last key not zero terminated? Get it anyway */
6951	if (StartOffset < Offset) {
6952
6953		SK_STRNCPY(pKeyArr + Index * SK_PNMI_VPD_KEY_SIZE,
6954			&BufKeys[StartOffset], SK_PNMI_VPD_KEY_SIZE);
6955	}
6956
6957	return (SK_PNMI_ERR_OK);
6958}
6959
6960/*****************************************************************************
6961 *
6962 * SirqUpdate - Let the SIRQ update its internal values
6963 *
6964 * Description:
6965 *	Just to be sure that the SIRQ module holds its internal data
6966 *	structures up to date, we send an update event before we make
6967 *	any access.
6968 *
6969 * Returns:
6970 *	SK_PNMI_ERR_OK	     Task successfully performed.
6971 *	SK_PNMI_ERR_GENERAL  Something went wrong.
6972 */
6973
6974static int SirqUpdate(
6975SK_AC *pAC,	/* Pointer to adapter context */
6976SK_IOC IoC)	/* IO context handle */
6977{
6978	SK_EVPARA	EventParam;
6979
6980
6981	/* Was the module already updated during the current PNMI call? */
6982	if (pAC->Pnmi.SirqUpdatedFlag > 0) {
6983
6984		return (SK_PNMI_ERR_OK);
6985	}
6986
6987	/* Send an synchronuous update event to the module */
6988	SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
6989	if (SkGeSirqEvent(pAC, IoC, SK_HWEV_UPDATE_STAT, EventParam) > 0) {
6990
6991		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR047,
6992			SK_PNMI_ERR047MSG);
6993
6994		return (SK_PNMI_ERR_GENERAL);
6995	}
6996
6997	return (SK_PNMI_ERR_OK);
6998}
6999
7000/*****************************************************************************
7001 *
7002 * RlmtUpdate - Let the RLMT update its internal values
7003 *
7004 * Description:
7005 *	Just to be sure that the RLMT module holds its internal data
7006 *	structures up to date, we send an update event before we make
7007 *	any access.
7008 *
7009 * Returns:
7010 *	SK_PNMI_ERR_OK	     Task successfully performed.
7011 *	SK_PNMI_ERR_GENERAL  Something went wrong.
7012 */
7013
7014static int RlmtUpdate(
7015SK_AC *pAC,	/* Pointer to adapter context */
7016SK_IOC IoC,	/* IO context handle */
7017SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode allways zero */
7018{
7019	SK_EVPARA	EventParam;
7020
7021
7022	/* Was the module already updated during the current PNMI call? */
7023	if (pAC->Pnmi.RlmtUpdatedFlag > 0) {
7024
7025		return (SK_PNMI_ERR_OK);
7026	}
7027
7028	/* Send an synchronuous update event to the module */
7029	SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
7030	EventParam.Para32[0] = NetIndex;
7031	EventParam.Para32[1] = (SK_U32)-1;
7032	if (SkRlmtEvent(pAC, IoC, SK_RLMT_STATS_UPDATE, EventParam) > 0) {
7033
7034		SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR048,
7035			SK_PNMI_ERR048MSG);
7036
7037		return (SK_PNMI_ERR_GENERAL);
7038	}
7039
7040	return (SK_PNMI_ERR_OK);
7041}
7042
7043/*****************************************************************************
7044 *
7045 * MacUpdate - Force the XMAC to output the current statistic
7046 *
7047 * Description:
7048 *	The XMAC holds its statistic internally. To obtain the current
7049 *	values we must send a command so that the statistic data will
7050 *	be written to a predefined memory area on the adapter.
7051 *
7052 * Returns:
7053 *	SK_PNMI_ERR_OK	     Task successfully performed.
7054 *	SK_PNMI_ERR_GENERAL  Something went wrong.
7055 */
7056
7057static int MacUpdate(
7058SK_AC *pAC,		/* Pointer to adapter context */
7059SK_IOC IoC,		/* IO context handle */
7060unsigned int FirstMac,	/* Index of the first Mac to be updated */
7061unsigned int LastMac)	/* Index of the last Mac to be updated */
7062{
7063	unsigned int	MacIndex;
7064	SK_U16		StatReg;
7065	unsigned int	WaitIndex;
7066
7067
7068	/*
7069	 * Were the statistics already updated during the
7070	 * current PNMI call?
7071	 */
7072	if (pAC->Pnmi.MacUpdatedFlag > 0) {
7073
7074		return (SK_PNMI_ERR_OK);
7075	}
7076
7077	/* Send an update command to all XMACs specified */
7078	for (MacIndex = FirstMac; MacIndex <= LastMac; MacIndex ++) {
7079
7080		StatReg = XM_SC_SNP_TXC | XM_SC_SNP_RXC;
7081		XM_OUT16(IoC, MacIndex, XM_STAT_CMD, StatReg);
7082
7083		/*
7084		 * It is an auto-clearing register. If the command bits
7085		 * went to zero again, the statistics are transfered.
7086		 * Normally the command should be executed immediately.
7087		 * But just to be sure we execute a loop.
7088		 */
7089		for (WaitIndex = 0; WaitIndex < 10; WaitIndex ++) {
7090
7091			XM_IN16(IoC, MacIndex, XM_STAT_CMD, &StatReg);
7092			if ((StatReg & (XM_SC_SNP_TXC | XM_SC_SNP_RXC)) ==
7093				0) {
7094
7095				break;
7096			}
7097		}
7098		if (WaitIndex == 10 ) {
7099
7100			SK_ERR_LOG(pAC, SK_ERRCL_HW, SK_PNMI_ERR050,
7101				SK_PNMI_ERR050MSG);
7102
7103			return (SK_PNMI_ERR_GENERAL);
7104		}
7105	}
7106
7107	return (SK_PNMI_ERR_OK);
7108}
7109
7110/*****************************************************************************
7111 *
7112 * GetStatVal - Retrieve an XMAC statistic counter
7113 *
7114 * Description:
7115 *	Retrieves the statistic counter of a virtual or physical port. The
7116 *	virtual port is identified by the index 0. It consists of all
7117 *	currently active ports. To obtain the counter value for this port
7118 *	we must add the statistic counter of all active ports. To grant
7119 *	continuous counter values for the virtual port even when port
7120 *	switches occur we must additionally add a delta value, which was
7121 *	calculated during a SK_PNMI_EVT_RLMT_ACTIVE_UP event.
7122 *
7123 * Returns:
7124 *	Requested statistic value
7125 */
7126
7127static SK_U64 GetStatVal(
7128SK_AC *pAC,					/* Pointer to adapter context */
7129SK_IOC IoC,					/* IO context handle */
7130unsigned int LogPortIndex,	/* Index of the logical Port to be processed */
7131unsigned int StatIndex,		/* Index to statistic value */
7132SK_U32 NetIndex)	/* NetIndex (0..n), in single net mode allways zero */
7133{
7134	unsigned int	PhysPortIndex;
7135	unsigned int	PhysPortMax;
7136	SK_U64		Val = 0;
7137
7138
7139	if(pAC->Pnmi.DualNetActiveFlag == SK_TRUE){	/* Dual net mode */
7140
7141		PhysPortIndex = NetIndex;
7142		Val = GetPhysStatVal(pAC, IoC, PhysPortIndex, StatIndex);
7143    }	/* end of dual net mode */
7144
7145	else { /* single net mode */
7146
7147		if (LogPortIndex == 0) {
7148
7149			PhysPortMax = pAC->GIni.GIMacsFound;
7150
7151			/* Add counter of all active ports */
7152			for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax;
7153				PhysPortIndex ++) {
7154
7155				if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
7156
7157					Val += GetPhysStatVal(pAC, IoC, PhysPortIndex,
7158						StatIndex);
7159				}
7160			}
7161
7162			/* Correct value because of port switches */
7163			Val += pAC->Pnmi.VirtualCounterOffset[StatIndex];
7164		}
7165		else {
7166			/* Get counter value of physical port */
7167			PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex);
7168			Val = GetPhysStatVal(pAC, IoC, PhysPortIndex, StatIndex);
7169		}
7170	} /* end of single net mode */
7171	return (Val);
7172}
7173
7174
7175static SK_U64 GetPhysStatVal(
7176SK_AC *pAC,					/* Pointer to adapter context */
7177SK_IOC IoC,					/* IO context handle */
7178unsigned int PhysPortIndex,	/* Index of the logical Port to be processed */
7179unsigned int StatIndex)		/* Index to statistic value */
7180{
7181	SK_U64		Val = 0;
7182	SK_U32		LowVal;
7183	SK_U32		HighVal;
7184
7185
7186	switch (StatIndex) {
7187
7188	case SK_PNMI_HTX_OCTET:
7189		XM_IN32(IoC, PhysPortIndex, XM_TXO_OK_LO, &LowVal);
7190		XM_IN32(IoC, PhysPortIndex, XM_TXO_OK_HI, &HighVal);
7191		break;
7192
7193	case SK_PNMI_HRX_OCTET:
7194		XM_IN32(IoC, PhysPortIndex, XM_RXO_OK_LO, &LowVal);
7195		XM_IN32(IoC, PhysPortIndex, XM_RXO_OK_HI, &HighVal);
7196		break;
7197
7198	case SK_PNMI_HTX_OCTETLOW:
7199	case SK_PNMI_HRX_OCTETLOW:
7200		return (Val);
7201
7202	case SK_PNMI_HTX_SYNC:
7203		LowVal = (SK_U32)pAC->Pnmi.Port[PhysPortIndex].StatSyncCts;
7204		HighVal = (SK_U32)
7205			(pAC->Pnmi.Port[PhysPortIndex].StatSyncCts >> 32);
7206		break;
7207
7208	case SK_PNMI_HTX_SYNC_OCTET:
7209		LowVal = (SK_U32)pAC->Pnmi.Port[PhysPortIndex].
7210			StatSyncOctetsCts;
7211		HighVal = (SK_U32)
7212			(pAC->Pnmi.Port[PhysPortIndex].StatSyncOctetsCts >>
7213			32);
7214		break;
7215
7216	case SK_PNMI_HRX_LONGFRAMES:
7217		LowVal = (SK_U32)pAC->Pnmi.Port[PhysPortIndex].StatRxLongFrameCts;
7218		HighVal = (SK_U32)
7219			(pAC->Pnmi.Port[PhysPortIndex].StatRxLongFrameCts >> 32);
7220		break;
7221
7222	case SK_PNMI_HRX_FCS:
7223		/*
7224		 * Broadcom filters fcs errors and counts it in
7225		 * Receive Error Counter register
7226		 */
7227		if (pAC->GIni.GP[PhysPortIndex].PhyType == SK_PHY_BCOM) {
7228			/* do not read while not initialized (PHY_READ hangs!)*/
7229			if (pAC->GIni.GP[PhysPortIndex].PState) {
7230				PHY_READ(IoC, &pAC->GIni.GP[PhysPortIndex],
7231					 PhysPortIndex, PHY_BCOM_RE_CTR,
7232					&LowVal);
7233			}
7234			else {
7235				LowVal = 0;
7236			}
7237			HighVal = pAC->Pnmi.Port[PhysPortIndex].CounterHigh[StatIndex];
7238		}
7239		else {
7240			XM_IN32(IoC, PhysPortIndex,
7241				StatAddress[StatIndex].Param, &LowVal);
7242			HighVal = pAC->Pnmi.Port[PhysPortIndex].CounterHigh[StatIndex];
7243		}
7244	default:
7245		XM_IN32(IoC, PhysPortIndex, StatAddress[StatIndex].Param,
7246			&LowVal);
7247		HighVal = pAC->Pnmi.Port[PhysPortIndex].CounterHigh[StatIndex];
7248		break;
7249	}
7250
7251	Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal);
7252
7253	/* Correct value because of possible XMAC reset. XMAC Errata #2 */
7254	Val += pAC->Pnmi.Port[PhysPortIndex].CounterOffset[StatIndex];
7255
7256	return (Val);
7257}
7258
7259/*****************************************************************************
7260 *
7261 * ResetCounter - Set all counters and timestamps to zero
7262 *
7263 * Description:
7264 *	Notifies other common modules which store statistic data to
7265 *	reset their counters and finally reset our own counters.
7266 *
7267 * Returns:
7268 *	Nothing
7269 */
7270
7271static void ResetCounter(
7272SK_AC *pAC,		/* Pointer to adapter context */
7273SK_IOC IoC,		/* IO context handle */
7274SK_U32 NetIndex)
7275{
7276	unsigned int	PhysPortIndex;
7277	SK_EVPARA	EventParam;
7278
7279
7280	SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
7281
7282	/* Notify sensor module */
7283	SkEventQueue(pAC, SKGE_I2C, SK_I2CEV_CLEAR, EventParam);
7284
7285	/* Notify RLMT module */
7286	EventParam.Para32[0] = NetIndex;
7287	EventParam.Para32[1] = (SK_U32)-1;
7288	SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STATS_CLEAR, EventParam);
7289	EventParam.Para32[1] = 0;
7290
7291	/* Notify SIRQ module */
7292	SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_CLEAR_STAT, EventParam);
7293
7294	/* Notify CSUM module */
7295#ifdef SK_USE_CSUM
7296	EventParam.Para64 = (SK_U64)(-1);
7297	SkEventQueue(pAC, SKGE_CSUM, SK_CSUM_EVENT_CLEAR_PROTO_STATS,
7298		EventParam);
7299#endif
7300
7301	/* Clear XMAC statistic */
7302	for (PhysPortIndex = 0; PhysPortIndex <
7303		(unsigned int)pAC->GIni.GIMacsFound; PhysPortIndex ++) {
7304
7305		XM_OUT16(IoC, PhysPortIndex, XM_STAT_CMD,
7306			XM_SC_CLR_RXC | XM_SC_CLR_TXC);
7307		/* Clear two times according to Errata #3 */
7308		XM_OUT16(IoC, PhysPortIndex, XM_STAT_CMD,
7309			XM_SC_CLR_RXC | XM_SC_CLR_TXC);
7310
7311		SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].CounterHigh,
7312			0, sizeof(pAC->Pnmi.Port[PhysPortIndex].CounterHigh));
7313		SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].
7314			CounterOffset, 0, sizeof(pAC->Pnmi.Port[
7315			PhysPortIndex].CounterOffset));
7316		SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].StatSyncCts,
7317			0, sizeof(pAC->Pnmi.Port[PhysPortIndex].StatSyncCts));
7318		SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].
7319			StatSyncOctetsCts, 0, sizeof(pAC->Pnmi.Port[
7320			PhysPortIndex].StatSyncOctetsCts));
7321		SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].
7322			StatRxLongFrameCts, 0, sizeof(pAC->Pnmi.Port[
7323			PhysPortIndex].StatRxLongFrameCts));
7324	}
7325
7326	/*
7327	 * Clear local statistics
7328	 */
7329	SK_MEMSET((char *)&pAC->Pnmi.VirtualCounterOffset, 0,
7330		  sizeof(pAC->Pnmi.VirtualCounterOffset));
7331	pAC->Pnmi.RlmtChangeCts = 0;
7332	pAC->Pnmi.RlmtChangeTime = 0;
7333	SK_MEMSET((char *)&pAC->Pnmi.RlmtChangeEstimate.EstValue[0], 0,
7334		sizeof(pAC->Pnmi.RlmtChangeEstimate.EstValue));
7335	pAC->Pnmi.RlmtChangeEstimate.EstValueIndex = 0;
7336	pAC->Pnmi.RlmtChangeEstimate.Estimate = 0;
7337	pAC->Pnmi.Port[NetIndex].TxSwQueueMax = 0;
7338	pAC->Pnmi.Port[NetIndex].TxRetryCts = 0;
7339	pAC->Pnmi.Port[NetIndex].RxIntrCts = 0;
7340	pAC->Pnmi.Port[NetIndex].TxIntrCts = 0;
7341	pAC->Pnmi.Port[NetIndex].RxNoBufCts = 0;
7342	pAC->Pnmi.Port[NetIndex].TxNoBufCts = 0;
7343	pAC->Pnmi.Port[NetIndex].TxUsedDescrNo = 0;
7344	pAC->Pnmi.Port[NetIndex].RxDeliveredCts = 0;
7345	pAC->Pnmi.Port[NetIndex].RxOctetsDeliveredCts = 0;
7346	pAC->Pnmi.Port[NetIndex].ErrRecoveryCts = 0;
7347}
7348
7349/*****************************************************************************
7350 *
7351 * GetTrapEntry - Get an entry in the trap buffer
7352 *
7353 * Description:
7354 *	The trap buffer stores various events. A user application somehow
7355 *	gets notified that an event occured and retrieves the trap buffer
7356 *	contens (or simply polls the buffer). The buffer is organized as
7357 *	a ring which stores the newest traps at the beginning. The oldest
7358 *	traps are overwritten by the newest ones. Each trap entry has a
7359 *	unique number, so that applications may detect new trap entries.
7360 *
7361 * Returns:
7362 *	A pointer to the trap entry
7363 */
7364
7365static char* GetTrapEntry(
7366SK_AC *pAC,		/* Pointer to adapter context */
7367SK_U32 TrapId,		/* SNMP ID of the trap */
7368unsigned int Size)	/* Space needed for trap entry */
7369{
7370	unsigned int		BufPad = pAC->Pnmi.TrapBufPad;
7371	unsigned int		BufFree = pAC->Pnmi.TrapBufFree;
7372	unsigned int		Beg = pAC->Pnmi.TrapQueueBeg;
7373	unsigned int		End = pAC->Pnmi.TrapQueueEnd;
7374	char			*pBuf = &pAC->Pnmi.TrapBuf[0];
7375	int			Wrap;
7376	unsigned int		NeededSpace;
7377	unsigned int		EntrySize;
7378	SK_U32			Val32;
7379	SK_U64			Val64;
7380
7381
7382	/* Last byte of entry will get a copy of the entry length */
7383	Size ++;
7384
7385	/*
7386	 * Calculate needed buffer space */
7387	if (Beg >= Size) {
7388
7389		NeededSpace = Size;
7390		Wrap = FALSE;
7391	}
7392	else {
7393		NeededSpace = Beg + Size;
7394		Wrap = TRUE;
7395	}
7396
7397	/*
7398	 * Check if enough buffer space is provided. Otherwise
7399	 * free some entries. Leave one byte space between begin
7400	 * and end of buffer to make it possible to detect whether
7401	 * the buffer is full or empty
7402	 */
7403	while (BufFree < NeededSpace + 1) {
7404
7405		if (End == 0) {
7406
7407			End = SK_PNMI_TRAP_QUEUE_LEN;
7408		}
7409
7410		EntrySize = (unsigned int)*((unsigned char *)pBuf + End - 1);
7411		BufFree += EntrySize;
7412		End -= EntrySize;
7413#ifdef DEBUG
7414		SK_MEMSET(pBuf + End, (char)(-1), EntrySize);
7415#endif
7416		if (End == BufPad) {
7417#ifdef DEBUG
7418			SK_MEMSET(pBuf, (char)(-1), End);
7419#endif
7420			BufFree += End;
7421			End = 0;
7422			BufPad = 0;
7423		}
7424	}
7425
7426	/*
7427	 * Insert new entry as first entry. Newest entries are
7428	 * stored at the beginning of the queue.
7429	 */
7430	if (Wrap) {
7431
7432		BufPad = Beg;
7433		Beg = SK_PNMI_TRAP_QUEUE_LEN - Size;
7434	}
7435	else {
7436		Beg = Beg - Size;
7437	}
7438	BufFree -= NeededSpace;
7439
7440	/* Save the current offsets */
7441	pAC->Pnmi.TrapQueueBeg = Beg;
7442	pAC->Pnmi.TrapQueueEnd = End;
7443	pAC->Pnmi.TrapBufPad = BufPad;
7444	pAC->Pnmi.TrapBufFree = BufFree;
7445
7446	/* Initialize the trap entry */
7447	*(pBuf + Beg + Size - 1) = (char)Size;
7448	*(pBuf + Beg) = (char)Size;
7449	Val32 = (pAC->Pnmi.TrapUnique) ++;
7450	SK_PNMI_STORE_U32(pBuf + Beg + 1, Val32);
7451	SK_PNMI_STORE_U32(pBuf + Beg + 1 + sizeof(SK_U32), TrapId);
7452	Val64 = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC));
7453	SK_PNMI_STORE_U64(pBuf + Beg + 1 + 2 * sizeof(SK_U32), Val64);
7454
7455	return (pBuf + Beg);
7456}
7457
7458/*****************************************************************************
7459 *
7460 * CopyTrapQueue - Copies the trap buffer for the TRAP OID
7461 *
7462 * Description:
7463 *	On a query of the TRAP OID the trap buffer contents will be
7464 *	copied continuously to the request buffer, which must be large
7465 *	enough. No length check is performed.
7466 *
7467 * Returns:
7468 *	Nothing
7469 */
7470
7471static void CopyTrapQueue(
7472SK_AC *pAC,		/* Pointer to adapter context */
7473char *pDstBuf)		/* Buffer to which the queued traps will be copied */
7474{
7475	unsigned int	BufPad = pAC->Pnmi.TrapBufPad;
7476	unsigned int	Trap = pAC->Pnmi.TrapQueueBeg;
7477	unsigned int	End = pAC->Pnmi.TrapQueueEnd;
7478	char		*pBuf = &pAC->Pnmi.TrapBuf[0];
7479	unsigned int	Len;
7480	unsigned int	DstOff = 0;
7481
7482
7483	while (Trap != End) {
7484
7485		Len = (unsigned int)*(pBuf + Trap);
7486
7487		/*
7488		 * Last byte containing a copy of the length will
7489		 * not be copied.
7490		 */
7491		*(pDstBuf + DstOff) = (char)(Len - 1);
7492		SK_MEMCPY(pDstBuf + DstOff + 1, pBuf + Trap + 1, Len - 2);
7493		DstOff += Len - 1;
7494
7495		Trap += Len;
7496		if (Trap == SK_PNMI_TRAP_QUEUE_LEN) {
7497
7498			Trap = BufPad;
7499		}
7500	}
7501}
7502
7503/*****************************************************************************
7504 *
7505 * GetTrapQueueLen - Get the length of the trap buffer
7506 *
7507 * Description:
7508 *	Evaluates the number of currently stored traps and the needed
7509 *	buffer size to retrieve them.
7510 *
7511 * Returns:
7512 *	Nothing
7513 */
7514
7515static void GetTrapQueueLen(
7516SK_AC *pAC,		/* Pointer to adapter context */
7517unsigned int *pLen,	/* Length in Bytes of all queued traps */
7518unsigned int *pEntries)	/* Returns number of trapes stored in queue */
7519{
7520	unsigned int	BufPad = pAC->Pnmi.TrapBufPad;
7521	unsigned int	Trap = pAC->Pnmi.TrapQueueBeg;
7522	unsigned int	End = pAC->Pnmi.TrapQueueEnd;
7523	char		*pBuf = &pAC->Pnmi.TrapBuf[0];
7524	unsigned int	Len;
7525	unsigned int	Entries = 0;
7526	unsigned int	TotalLen = 0;
7527
7528
7529	while (Trap != End) {
7530
7531		Len = (unsigned int)*(pBuf + Trap);
7532		TotalLen += Len - 1;
7533		Entries ++;
7534
7535		Trap += Len;
7536		if (Trap == SK_PNMI_TRAP_QUEUE_LEN) {
7537
7538			Trap = BufPad;
7539		}
7540	}
7541
7542	*pEntries = Entries;
7543	*pLen = TotalLen;
7544}
7545
7546/*****************************************************************************
7547 *
7548 * QueueSimpleTrap - Store a simple trap to the trap buffer
7549 *
7550 * Description:
7551 *	A simple trap is a trap with now additional data. It consists
7552 *	simply of a trap code.
7553 *
7554 * Returns:
7555 *	Nothing
7556 */
7557
7558static void QueueSimpleTrap(
7559SK_AC *pAC,		/* Pointer to adapter context */
7560SK_U32 TrapId)		/* Type of sensor trap */
7561{
7562	GetTrapEntry(pAC, TrapId, SK_PNMI_TRAP_SIMPLE_LEN);
7563}
7564
7565/*****************************************************************************
7566 *
7567 * QueueSensorTrap - Stores a sensor trap in the trap buffer
7568 *
7569 * Description:
7570 *	Gets an entry in the trap buffer and fills it with sensor related
7571 *	data.
7572 *
7573 * Returns:
7574 *	Nothing
7575 */
7576
7577static void QueueSensorTrap(
7578SK_AC *pAC,			/* Pointer to adapter context */
7579SK_U32 TrapId,			/* Type of sensor trap */
7580unsigned int SensorIndex)	/* Index of sensor which caused the trap */
7581{
7582	char		*pBuf;
7583	unsigned int	Offset;
7584	unsigned int	DescrLen;
7585	SK_U32		Val32;
7586
7587
7588	/* Get trap buffer entry */
7589	DescrLen = SK_STRLEN(pAC->I2c.SenTable[SensorIndex].SenDesc);
7590	pBuf = GetTrapEntry(pAC, TrapId,
7591		SK_PNMI_TRAP_SENSOR_LEN_BASE + DescrLen);
7592	Offset = SK_PNMI_TRAP_SIMPLE_LEN;
7593
7594	/* Store additionally sensor trap related data */
7595	Val32 = OID_SKGE_SENSOR_INDEX;
7596	SK_PNMI_STORE_U32(pBuf + Offset, Val32);
7597	*(pBuf + Offset + 4) = 4;
7598	Val32 = (SK_U32)SensorIndex;
7599	SK_PNMI_STORE_U32(pBuf + Offset + 5, Val32);
7600	Offset += 9;
7601
7602	Val32 = (SK_U32)OID_SKGE_SENSOR_DESCR;
7603	SK_PNMI_STORE_U32(pBuf + Offset, Val32);
7604	*(pBuf + Offset + 4) = (char)DescrLen;
7605	SK_MEMCPY(pBuf + Offset + 5, pAC->I2c.SenTable[SensorIndex].SenDesc,
7606		DescrLen);
7607	Offset += DescrLen + 5;
7608
7609	Val32 = OID_SKGE_SENSOR_TYPE;
7610	SK_PNMI_STORE_U32(pBuf + Offset, Val32);
7611	*(pBuf + Offset + 4) = 1;
7612	*(pBuf + Offset + 5) = (char)pAC->I2c.SenTable[SensorIndex].SenType;
7613	Offset += 6;
7614
7615	Val32 = OID_SKGE_SENSOR_VALUE;
7616	SK_PNMI_STORE_U32(pBuf + Offset, Val32);
7617	*(pBuf + Offset + 4) = 4;
7618	Val32 = (SK_U32)pAC->I2c.SenTable[SensorIndex].SenValue;
7619	SK_PNMI_STORE_U32(pBuf + Offset + 5, Val32);
7620}
7621
7622/*****************************************************************************
7623 *
7624 * QueueRlmtNewMacTrap - Store a port switch trap in the trap buffer
7625 *
7626 * Description:
7627 *	Nothing further to explain.
7628 *
7629 * Returns:
7630 *	Nothing
7631 */
7632
7633static void QueueRlmtNewMacTrap(
7634SK_AC *pAC,		/* Pointer to adapter context */
7635unsigned int ActiveMac)	/* Index (0..n) of the currently active port */
7636{
7637	char	*pBuf;
7638	SK_U32	Val32;
7639
7640
7641	pBuf = GetTrapEntry(pAC, OID_SKGE_TRAP_RLMT_CHANGE_PORT,
7642		SK_PNMI_TRAP_RLMT_CHANGE_LEN);
7643
7644	Val32 = OID_SKGE_RLMT_PORT_ACTIVE;
7645	SK_PNMI_STORE_U32(pBuf + SK_PNMI_TRAP_SIMPLE_LEN, Val32);
7646	*(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 4) = 1;
7647	*(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 5) = (char)ActiveMac;
7648}
7649
7650/*****************************************************************************
7651 *
7652 * QueueRlmtPortTrap - Store port related RLMT trap to trap buffer
7653 *
7654 * Description:
7655 *	Nothing further to explain.
7656 *
7657 * Returns:
7658 *	Nothing
7659 */
7660
7661static void QueueRlmtPortTrap(
7662SK_AC *pAC,		/* Pointer to adapter context */
7663SK_U32 TrapId,		/* Type of RLMT port trap */
7664unsigned int PortIndex)	/* Index of the port, which changed its state */
7665{
7666	char	*pBuf;
7667	SK_U32	Val32;
7668
7669
7670	pBuf = GetTrapEntry(pAC, TrapId, SK_PNMI_TRAP_RLMT_PORT_LEN);
7671
7672	Val32 = OID_SKGE_RLMT_PORT_INDEX;
7673	SK_PNMI_STORE_U32(pBuf + SK_PNMI_TRAP_SIMPLE_LEN, Val32);
7674	*(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 4) = 1;
7675	*(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 5) = (char)PortIndex;
7676}
7677
7678/*****************************************************************************
7679 *
7680 * CopyMac - Copies a MAC address
7681 *
7682 * Description:
7683 *	Nothing further to explain.
7684 *
7685 * Returns:
7686 *	Nothing
7687 */
7688
7689static void CopyMac(
7690char *pDst,		/* Pointer to destination buffer */
7691SK_MAC_ADDR *pMac)	/* Pointer of Source */
7692{
7693	int	i;
7694
7695
7696	for (i = 0; i < sizeof(SK_MAC_ADDR); i ++) {
7697
7698		*(pDst + i) = pMac->a[i];
7699	}
7700}
7701