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