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