Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

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