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