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