Merge branch 'linux-2.6'
[linux-2.6] / drivers / net / sk98lin / skgepnmi.c
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
6926         case SK_PNMI_HRX_PMACC_ERR:
6927                 /* For GMAC the SW counter is managed by PNMI */
6928                 if (MacType == SK_MAC_GMAC) {
6929                         return (pPnmiPrt->StatRxPMaccErr);
6930                 }
6931                 
6932                 (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
6933                                                                           StatAddr[StatIndex][MacType].Reg,
6934                                                                           &LowVal);
6935                 HighVal = pPnmiPrt->CounterHigh[StatIndex];
6936                 break;
6937
6938         /* SW counter managed by PNMI */
6939         case SK_PNMI_HTX_SYNC:
6940                 LowVal = (SK_U32)pPnmiPrt->StatSyncCts;
6941                 HighVal = (SK_U32)(pPnmiPrt->StatSyncCts >> 32);
6942                 break;
6943
6944         /* SW counter managed by PNMI */
6945         case SK_PNMI_HTX_SYNC_OCTET:
6946                 LowVal = (SK_U32)pPnmiPrt->StatSyncOctetsCts;
6947                 HighVal = (SK_U32)(pPnmiPrt->StatSyncOctetsCts >> 32);
6948                 break;
6949
6950         case SK_PNMI_HRX_FCS:
6951                 /*
6952                  * Broadcom filters FCS errors and counts it in
6953                  * Receive Error Counter register
6954                  */
6955                 if (pPrt->PhyType == SK_PHY_BCOM) {
6956                         /* do not read while not initialized (PHY_READ hangs!)*/
6957                         if (pPrt->PState != SK_PRT_RESET) {
6958                                 SkXmPhyRead(pAC, IoC, PhysPortIndex, PHY_BCOM_RE_CTR, &Word);
6959                                 
6960                                 LowVal = Word;
6961                         }
6962                         HighVal = pPnmiPrt->CounterHigh[StatIndex];
6963                 }
6964                 else {
6965                         (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
6966                                                                                   StatAddr[StatIndex][MacType].Reg,
6967                                                                                   &LowVal);
6968                         HighVal = pPnmiPrt->CounterHigh[StatIndex];
6969                 }
6970                 break;
6971
6972         default:
6973                 (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
6974                                                                           StatAddr[StatIndex][MacType].Reg,
6975                                                                           &LowVal);
6976                 HighVal = pPnmiPrt->CounterHigh[StatIndex];
6977                 break;
6978         }
6979
6980         Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal);
6981
6982         /* Correct value because of possible XMAC reset. XMAC Errata #2 */
6983         Val += pPnmiPrt->CounterOffset[StatIndex];
6984
6985         return (Val);
6986 }
6987
6988 /*****************************************************************************
6989  *
6990  * ResetCounter - Set all counters and timestamps to zero
6991  *
6992  * Description:
6993  *      Notifies other common modules which store statistic data to
6994  *      reset their counters and finally reset our own counters.
6995  *
6996  * Returns:
6997  *      Nothing
6998  */
6999 PNMI_STATIC void ResetCounter(
7000 SK_AC *pAC,             /* Pointer to adapter context */
7001 SK_IOC IoC,             /* IO context handle */
7002 SK_U32 NetIndex)
7003 {
7004         unsigned int    PhysPortIndex;
7005         SK_EVPARA       EventParam;
7006
7007
7008         SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
7009
7010         /* Notify sensor module */
7011         SkEventQueue(pAC, SKGE_I2C, SK_I2CEV_CLEAR, EventParam);
7012
7013         /* Notify RLMT module */
7014         EventParam.Para32[0] = NetIndex;
7015         EventParam.Para32[1] = (SK_U32)-1;
7016         SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STATS_CLEAR, EventParam);
7017         EventParam.Para32[1] = 0;
7018
7019         /* Notify SIRQ module */
7020         SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_CLEAR_STAT, EventParam);
7021
7022         /* Notify CSUM module */
7023 #ifdef SK_USE_CSUM
7024         EventParam.Para32[0] = NetIndex;
7025         EventParam.Para32[1] = (SK_U32)-1;
7026         SkEventQueue(pAC, SKGE_CSUM, SK_CSUM_EVENT_CLEAR_PROTO_STATS,
7027                 EventParam);
7028 #endif /* SK_USE_CSUM */
7029         
7030         /* Clear XMAC statistic */
7031         for (PhysPortIndex = 0; PhysPortIndex <
7032                 (unsigned int)pAC->GIni.GIMacsFound; PhysPortIndex ++) {
7033
7034                 (void)pAC->GIni.GIFunc.pFnMacResetCounter(pAC, IoC, PhysPortIndex);
7035
7036                 SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].CounterHigh,
7037                         0, sizeof(pAC->Pnmi.Port[PhysPortIndex].CounterHigh));
7038                 SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].
7039                         CounterOffset, 0, sizeof(pAC->Pnmi.Port[
7040                         PhysPortIndex].CounterOffset));
7041                 SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].StatSyncCts,
7042                         0, sizeof(pAC->Pnmi.Port[PhysPortIndex].StatSyncCts));
7043                 SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].
7044                         StatSyncOctetsCts, 0, sizeof(pAC->Pnmi.Port[
7045                         PhysPortIndex].StatSyncOctetsCts));
7046                 SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].
7047                         StatRxLongFrameCts, 0, sizeof(pAC->Pnmi.Port[
7048                         PhysPortIndex].StatRxLongFrameCts));
7049                 SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].
7050                                   StatRxFrameTooLongCts, 0, sizeof(pAC->Pnmi.Port[
7051                         PhysPortIndex].StatRxFrameTooLongCts));
7052                 SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].
7053                                   StatRxPMaccErr, 0, sizeof(pAC->Pnmi.Port[
7054                         PhysPortIndex].StatRxPMaccErr));
7055         }
7056
7057         /*
7058          * Clear local statistics
7059          */
7060         SK_MEMSET((char *)&pAC->Pnmi.VirtualCounterOffset, 0,
7061                   sizeof(pAC->Pnmi.VirtualCounterOffset));
7062         pAC->Pnmi.RlmtChangeCts = 0;
7063         pAC->Pnmi.RlmtChangeTime = 0;
7064         SK_MEMSET((char *)&pAC->Pnmi.RlmtChangeEstimate.EstValue[0], 0,
7065                 sizeof(pAC->Pnmi.RlmtChangeEstimate.EstValue));
7066         pAC->Pnmi.RlmtChangeEstimate.EstValueIndex = 0;
7067         pAC->Pnmi.RlmtChangeEstimate.Estimate = 0;
7068         pAC->Pnmi.Port[NetIndex].TxSwQueueMax = 0;
7069         pAC->Pnmi.Port[NetIndex].TxRetryCts = 0;
7070         pAC->Pnmi.Port[NetIndex].RxIntrCts = 0;
7071         pAC->Pnmi.Port[NetIndex].TxIntrCts = 0;
7072         pAC->Pnmi.Port[NetIndex].RxNoBufCts = 0;
7073         pAC->Pnmi.Port[NetIndex].TxNoBufCts = 0;
7074         pAC->Pnmi.Port[NetIndex].TxUsedDescrNo = 0;
7075         pAC->Pnmi.Port[NetIndex].RxDeliveredCts = 0;
7076         pAC->Pnmi.Port[NetIndex].RxOctetsDeliveredCts = 0;
7077         pAC->Pnmi.Port[NetIndex].ErrRecoveryCts = 0;
7078 }
7079
7080 /*****************************************************************************
7081  *
7082  * GetTrapEntry - Get an entry in the trap buffer
7083  *
7084  * Description:
7085  *      The trap buffer stores various events. A user application somehow
7086  *      gets notified that an event occured and retrieves the trap buffer
7087  *      contens (or simply polls the buffer). The buffer is organized as
7088  *      a ring which stores the newest traps at the beginning. The oldest
7089  *      traps are overwritten by the newest ones. Each trap entry has a
7090  *      unique number, so that applications may detect new trap entries.
7091  *
7092  * Returns:
7093  *      A pointer to the trap entry
7094  */
7095 PNMI_STATIC char* GetTrapEntry(
7096 SK_AC *pAC,             /* Pointer to adapter context */
7097 SK_U32 TrapId,          /* SNMP ID of the trap */
7098 unsigned int Size)      /* Space needed for trap entry */
7099 {
7100         unsigned int            BufPad = pAC->Pnmi.TrapBufPad;
7101         unsigned int            BufFree = pAC->Pnmi.TrapBufFree;
7102         unsigned int            Beg = pAC->Pnmi.TrapQueueBeg;
7103         unsigned int            End = pAC->Pnmi.TrapQueueEnd;
7104         char                    *pBuf = &pAC->Pnmi.TrapBuf[0];
7105         int                     Wrap;
7106         unsigned int            NeededSpace;
7107         unsigned int            EntrySize;
7108         SK_U32                  Val32;
7109         SK_U64                  Val64;
7110
7111
7112         /* Last byte of entry will get a copy of the entry length */
7113         Size ++;
7114
7115         /*
7116          * Calculate needed buffer space */
7117         if (Beg >= Size) {
7118
7119                 NeededSpace = Size;
7120                 Wrap = SK_FALSE;
7121         }
7122         else {
7123                 NeededSpace = Beg + Size;
7124                 Wrap = SK_TRUE;
7125         }
7126
7127         /*
7128          * Check if enough buffer space is provided. Otherwise
7129          * free some entries. Leave one byte space between begin
7130          * and end of buffer to make it possible to detect whether
7131          * the buffer is full or empty
7132          */
7133         while (BufFree < NeededSpace + 1) {
7134
7135                 if (End == 0) {
7136
7137                         End = SK_PNMI_TRAP_QUEUE_LEN;
7138                 }
7139
7140                 EntrySize = (unsigned int)*((unsigned char *)pBuf + End - 1);
7141                 BufFree += EntrySize;
7142                 End -= EntrySize;
7143 #ifdef DEBUG
7144                 SK_MEMSET(pBuf + End, (char)(-1), EntrySize);
7145 #endif /* DEBUG */
7146                 if (End == BufPad) {
7147 #ifdef DEBUG
7148                         SK_MEMSET(pBuf, (char)(-1), End);
7149 #endif /* DEBUG */
7150                         BufFree += End;
7151                         End = 0;
7152                         BufPad = 0;
7153                 }
7154         }
7155
7156         /*
7157          * Insert new entry as first entry. Newest entries are
7158          * stored at the beginning of the queue.
7159          */
7160         if (Wrap) {
7161
7162                 BufPad = Beg;
7163                 Beg = SK_PNMI_TRAP_QUEUE_LEN - Size;
7164         }
7165         else {
7166                 Beg = Beg - Size;
7167         }
7168         BufFree -= NeededSpace;
7169
7170         /* Save the current offsets */
7171         pAC->Pnmi.TrapQueueBeg = Beg;
7172         pAC->Pnmi.TrapQueueEnd = End;
7173         pAC->Pnmi.TrapBufPad = BufPad;
7174         pAC->Pnmi.TrapBufFree = BufFree;
7175
7176         /* Initialize the trap entry */
7177         *(pBuf + Beg + Size - 1) = (char)Size;
7178         *(pBuf + Beg) = (char)Size;
7179         Val32 = (pAC->Pnmi.TrapUnique) ++;
7180         SK_PNMI_STORE_U32(pBuf + Beg + 1, Val32);
7181         SK_PNMI_STORE_U32(pBuf + Beg + 1 + sizeof(SK_U32), TrapId);
7182         Val64 = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC));
7183         SK_PNMI_STORE_U64(pBuf + Beg + 1 + 2 * sizeof(SK_U32), Val64);
7184
7185         return (pBuf + Beg);
7186 }
7187
7188 /*****************************************************************************
7189  *
7190  * CopyTrapQueue - Copies the trap buffer for the TRAP OID
7191  *
7192  * Description:
7193  *      On a query of the TRAP OID the trap buffer contents will be
7194  *      copied continuously to the request buffer, which must be large
7195  *      enough. No length check is performed.
7196  *
7197  * Returns:
7198  *      Nothing
7199  */
7200 PNMI_STATIC void CopyTrapQueue(
7201 SK_AC *pAC,             /* Pointer to adapter context */
7202 char *pDstBuf)          /* Buffer to which the queued traps will be copied */
7203 {
7204         unsigned int    BufPad = pAC->Pnmi.TrapBufPad;
7205         unsigned int    Trap = pAC->Pnmi.TrapQueueBeg;
7206         unsigned int    End = pAC->Pnmi.TrapQueueEnd;
7207         char            *pBuf = &pAC->Pnmi.TrapBuf[0];
7208         unsigned int    Len;
7209         unsigned int    DstOff = 0;
7210
7211
7212         while (Trap != End) {
7213
7214                 Len = (unsigned int)*(pBuf + Trap);
7215
7216                 /*
7217                  * Last byte containing a copy of the length will
7218                  * not be copied.
7219                  */
7220                 *(pDstBuf + DstOff) = (char)(Len - 1);
7221                 SK_MEMCPY(pDstBuf + DstOff + 1, pBuf + Trap + 1, Len - 2);
7222                 DstOff += Len - 1;
7223
7224                 Trap += Len;
7225                 if (Trap == SK_PNMI_TRAP_QUEUE_LEN) {
7226
7227                         Trap = BufPad;
7228                 }
7229         }
7230 }
7231
7232 /*****************************************************************************
7233  *
7234  * GetTrapQueueLen - Get the length of the trap buffer
7235  *
7236  * Description:
7237  *      Evaluates the number of currently stored traps and the needed
7238  *      buffer size to retrieve them.
7239  *
7240  * Returns:
7241  *      Nothing
7242  */
7243 PNMI_STATIC void GetTrapQueueLen(
7244 SK_AC *pAC,             /* Pointer to adapter context */
7245 unsigned int *pLen,     /* Length in Bytes of all queued traps */
7246 unsigned int *pEntries) /* Returns number of trapes stored in queue */
7247 {
7248         unsigned int    BufPad = pAC->Pnmi.TrapBufPad;
7249         unsigned int    Trap = pAC->Pnmi.TrapQueueBeg;
7250         unsigned int    End = pAC->Pnmi.TrapQueueEnd;
7251         char            *pBuf = &pAC->Pnmi.TrapBuf[0];
7252         unsigned int    Len;
7253         unsigned int    Entries = 0;
7254         unsigned int    TotalLen = 0;
7255
7256
7257         while (Trap != End) {
7258
7259                 Len = (unsigned int)*(pBuf + Trap);
7260                 TotalLen += Len - 1;
7261                 Entries ++;
7262
7263                 Trap += Len;
7264                 if (Trap == SK_PNMI_TRAP_QUEUE_LEN) {
7265
7266                         Trap = BufPad;
7267                 }
7268         }
7269
7270         *pEntries = Entries;
7271         *pLen = TotalLen;
7272 }
7273
7274 /*****************************************************************************
7275  *
7276  * QueueSimpleTrap - Store a simple trap to the trap buffer
7277  *
7278  * Description:
7279  *      A simple trap is a trap with now additional data. It consists
7280  *      simply of a trap code.
7281  *
7282  * Returns:
7283  *      Nothing
7284  */
7285 PNMI_STATIC void QueueSimpleTrap(
7286 SK_AC *pAC,             /* Pointer to adapter context */
7287 SK_U32 TrapId)          /* Type of sensor trap */
7288 {
7289         GetTrapEntry(pAC, TrapId, SK_PNMI_TRAP_SIMPLE_LEN);
7290 }
7291
7292 /*****************************************************************************
7293  *
7294  * QueueSensorTrap - Stores a sensor trap in the trap buffer
7295  *
7296  * Description:
7297  *      Gets an entry in the trap buffer and fills it with sensor related
7298  *      data.
7299  *
7300  * Returns:
7301  *      Nothing
7302  */
7303 PNMI_STATIC void QueueSensorTrap(
7304 SK_AC *pAC,                     /* Pointer to adapter context */
7305 SK_U32 TrapId,                  /* Type of sensor trap */
7306 unsigned int SensorIndex)       /* Index of sensor which caused the trap */
7307 {
7308         char            *pBuf;
7309         unsigned int    Offset;
7310         unsigned int    DescrLen;
7311         SK_U32          Val32;
7312
7313
7314         /* Get trap buffer entry */
7315         DescrLen = SK_STRLEN(pAC->I2c.SenTable[SensorIndex].SenDesc);
7316         pBuf = GetTrapEntry(pAC, TrapId,
7317                 SK_PNMI_TRAP_SENSOR_LEN_BASE + DescrLen);
7318         Offset = SK_PNMI_TRAP_SIMPLE_LEN;
7319
7320         /* Store additionally sensor trap related data */
7321         Val32 = OID_SKGE_SENSOR_INDEX;
7322         SK_PNMI_STORE_U32(pBuf + Offset, Val32);
7323         *(pBuf + Offset + 4) = 4;
7324         Val32 = (SK_U32)SensorIndex;
7325         SK_PNMI_STORE_U32(pBuf + Offset + 5, Val32);
7326         Offset += 9;
7327         
7328         Val32 = (SK_U32)OID_SKGE_SENSOR_DESCR;
7329         SK_PNMI_STORE_U32(pBuf + Offset, Val32);
7330         *(pBuf + Offset + 4) = (char)DescrLen;
7331         SK_MEMCPY(pBuf + Offset + 5, pAC->I2c.SenTable[SensorIndex].SenDesc,
7332                 DescrLen);
7333         Offset += DescrLen + 5;
7334
7335         Val32 = OID_SKGE_SENSOR_TYPE;
7336         SK_PNMI_STORE_U32(pBuf + Offset, Val32);
7337         *(pBuf + Offset + 4) = 1;
7338         *(pBuf + Offset + 5) = (char)pAC->I2c.SenTable[SensorIndex].SenType;
7339         Offset += 6;
7340
7341         Val32 = OID_SKGE_SENSOR_VALUE;
7342         SK_PNMI_STORE_U32(pBuf + Offset, Val32);
7343         *(pBuf + Offset + 4) = 4;
7344         Val32 = (SK_U32)pAC->I2c.SenTable[SensorIndex].SenValue;
7345         SK_PNMI_STORE_U32(pBuf + Offset + 5, Val32);
7346 }
7347
7348 /*****************************************************************************
7349  *
7350  * QueueRlmtNewMacTrap - Store a port switch trap in the trap buffer
7351  *
7352  * Description:
7353  *      Nothing further to explain.
7354  *
7355  * Returns:
7356  *      Nothing
7357  */
7358 PNMI_STATIC void QueueRlmtNewMacTrap(
7359 SK_AC *pAC,             /* Pointer to adapter context */
7360 unsigned int ActiveMac) /* Index (0..n) of the currently active port */
7361 {
7362         char    *pBuf;
7363         SK_U32  Val32;
7364
7365
7366         pBuf = GetTrapEntry(pAC, OID_SKGE_TRAP_RLMT_CHANGE_PORT,
7367                 SK_PNMI_TRAP_RLMT_CHANGE_LEN);
7368
7369         Val32 = OID_SKGE_RLMT_PORT_ACTIVE;
7370         SK_PNMI_STORE_U32(pBuf + SK_PNMI_TRAP_SIMPLE_LEN, Val32);
7371         *(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 4) = 1;
7372         *(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 5) = (char)ActiveMac;
7373 }
7374
7375 /*****************************************************************************
7376  *
7377  * QueueRlmtPortTrap - Store port related RLMT trap to trap buffer
7378  *
7379  * Description:
7380  *      Nothing further to explain.
7381  *
7382  * Returns:
7383  *      Nothing
7384  */
7385 PNMI_STATIC void QueueRlmtPortTrap(
7386 SK_AC *pAC,             /* Pointer to adapter context */
7387 SK_U32 TrapId,          /* Type of RLMT port trap */
7388 unsigned int PortIndex) /* Index of the port, which changed its state */
7389 {
7390         char    *pBuf;
7391         SK_U32  Val32;
7392
7393
7394         pBuf = GetTrapEntry(pAC, TrapId, SK_PNMI_TRAP_RLMT_PORT_LEN);
7395
7396         Val32 = OID_SKGE_RLMT_PORT_INDEX;
7397         SK_PNMI_STORE_U32(pBuf + SK_PNMI_TRAP_SIMPLE_LEN, Val32);
7398         *(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 4) = 1;
7399         *(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 5) = (char)PortIndex;
7400 }
7401
7402 /*****************************************************************************
7403  *
7404  * CopyMac - Copies a MAC address
7405  *
7406  * Description:
7407  *      Nothing further to explain.
7408  *
7409  * Returns:
7410  *      Nothing
7411  */
7412 PNMI_STATIC void CopyMac(
7413 char *pDst,             /* Pointer to destination buffer */
7414 SK_MAC_ADDR *pMac)      /* Pointer of Source */
7415 {
7416         int     i;
7417
7418
7419         for (i = 0; i < sizeof(SK_MAC_ADDR); i ++) {
7420
7421                 *(pDst + i) = pMac->a[i];
7422         }
7423 }
7424
7425 #ifdef SK_POWER_MGMT
7426 /*****************************************************************************
7427  *
7428  * PowerManagement - OID handler function of PowerManagement OIDs
7429  *
7430  * Description:
7431  *      The code is simple. No description necessary.
7432  *
7433  * Returns:
7434  *      SK_PNMI_ERR_OK           The request was successfully performed.
7435  *      SK_PNMI_ERR_GENERAL      A general severe internal error occured.
7436  *      SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
7437  *                               the correct data (e.g. a 32bit value is
7438  *                               needed, but a 16 bit value was passed).
7439  *      SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
7440  *                               exist (e.g. port instance 3 on a two port
7441  *                               adapter.
7442  */
7443
7444 PNMI_STATIC int PowerManagement(
7445 SK_AC *pAC,             /* Pointer to adapter context */
7446 SK_IOC IoC,             /* IO context handle */
7447 int Action,             /* Get/PreSet/Set action */
7448 SK_U32 Id,              /* Object ID that is to be processed */
7449 char *pBuf,             /* Buffer to which to mgmt data will be retrieved */
7450 unsigned int *pLen,     /* On call: buffer length. On return: used buffer */
7451 SK_U32 Instance,        /* Instance (1..n) that is to be queried or -1 */
7452 unsigned int TableIndex, /* Index to the Id table */
7453 SK_U32 NetIndex)        /* NetIndex (0..n), in single net mode allways zero */
7454 {
7455         
7456         SK_U32  RetCode = SK_PNMI_ERR_GENERAL;
7457
7458         /*
7459          * Check instance. We only handle single instance variables
7460          */
7461         if (Instance != (SK_U32)(-1) && Instance != 1) {
7462
7463                 *pLen = 0;
7464                 return (SK_PNMI_ERR_UNKNOWN_INST);
7465         }
7466         
7467     
7468     /* Check length */
7469     switch (Id) {
7470
7471     case OID_PNP_CAPABILITIES:
7472         if (*pLen < sizeof(SK_PNP_CAPABILITIES)) {
7473
7474             *pLen = sizeof(SK_PNP_CAPABILITIES);
7475             return (SK_PNMI_ERR_TOO_SHORT);
7476         }
7477         break;
7478
7479         case OID_PNP_SET_POWER:
7480     case OID_PNP_QUERY_POWER:
7481         if (*pLen < sizeof(SK_DEVICE_POWER_STATE))
7482         {
7483                 *pLen = sizeof(SK_DEVICE_POWER_STATE);
7484                 return (SK_PNMI_ERR_TOO_SHORT);
7485         }
7486         break;
7487
7488     case OID_PNP_ADD_WAKE_UP_PATTERN:
7489     case OID_PNP_REMOVE_WAKE_UP_PATTERN:
7490                 if (*pLen < sizeof(SK_PM_PACKET_PATTERN)) {
7491
7492                         *pLen = sizeof(SK_PM_PACKET_PATTERN);
7493                         return (SK_PNMI_ERR_TOO_SHORT);
7494                 }
7495                 break;
7496
7497     case OID_PNP_ENABLE_WAKE_UP:
7498         if (*pLen < sizeof(SK_U32)) {
7499
7500             *pLen = sizeof(SK_U32);
7501             return (SK_PNMI_ERR_TOO_SHORT);
7502         }
7503         break;
7504     }
7505         
7506     /*
7507          * Perform action
7508          */
7509         if (Action == SK_PNMI_GET) {
7510
7511                 /*
7512                  * Get value
7513                  */
7514                 switch (Id) {
7515
7516                 case OID_PNP_CAPABILITIES:
7517                         RetCode = SkPowerQueryPnPCapabilities(pAC, IoC, pBuf, pLen);
7518                         break;
7519
7520                 case OID_PNP_QUERY_POWER:
7521                         /* The Windows DDK describes: An OID_PNP_QUERY_POWER requests
7522                          the miniport to indicate whether it can transition its NIC
7523                          to the low-power state.
7524                          A miniport driver must always return NDIS_STATUS_SUCCESS
7525                          to a query of OID_PNP_QUERY_POWER. */
7526                         *pLen = sizeof(SK_DEVICE_POWER_STATE);
7527             RetCode = SK_PNMI_ERR_OK;
7528                         break;
7529
7530                         /* NDIS handles these OIDs as write-only.
7531                          * So in case of get action the buffer with written length = 0
7532                          * is returned
7533                          */
7534                 case OID_PNP_SET_POWER:
7535                 case OID_PNP_ADD_WAKE_UP_PATTERN:
7536                 case OID_PNP_REMOVE_WAKE_UP_PATTERN:
7537                         *pLen = 0;      
7538             RetCode = SK_PNMI_ERR_NOT_SUPPORTED;
7539                         break;
7540
7541                 case OID_PNP_ENABLE_WAKE_UP:
7542                         RetCode = SkPowerGetEnableWakeUp(pAC, IoC, pBuf, pLen);
7543                         break;
7544
7545                 default:
7546                         RetCode = SK_PNMI_ERR_GENERAL;
7547                         break;
7548                 }
7549
7550                 return (RetCode);
7551         }
7552         
7553
7554         /*
7555          * Perform preset or set
7556          */
7557         
7558         /* POWER module does not support PRESET action */
7559         if (Action == SK_PNMI_PRESET) {
7560                 return (SK_PNMI_ERR_OK);
7561         }
7562
7563         switch (Id) {
7564         case OID_PNP_SET_POWER:
7565                 RetCode = SkPowerSetPower(pAC, IoC, pBuf, pLen);        
7566                 break;
7567
7568         case OID_PNP_ADD_WAKE_UP_PATTERN:
7569                 RetCode = SkPowerAddWakeUpPattern(pAC, IoC, pBuf, pLen);        
7570                 break;
7571                 
7572         case OID_PNP_REMOVE_WAKE_UP_PATTERN:
7573                 RetCode = SkPowerRemoveWakeUpPattern(pAC, IoC, pBuf, pLen);     
7574                 break;
7575                 
7576         case OID_PNP_ENABLE_WAKE_UP:
7577                 RetCode = SkPowerSetEnableWakeUp(pAC, IoC, pBuf, pLen);
7578                 break;
7579                 
7580         default:
7581                 RetCode = SK_PNMI_ERR_READ_ONLY;
7582         }
7583         
7584         return (RetCode);
7585 }
7586 #endif /* SK_POWER_MGMT */
7587
7588 #ifdef SK_DIAG_SUPPORT
7589 /*****************************************************************************
7590  *
7591  * DiagActions - OID handler function of Diagnostic driver 
7592  *
7593  * Description:
7594  *      The code is simple. No description necessary.
7595  *
7596  * Returns:
7597  *      SK_PNMI_ERR_OK           The request was successfully performed.
7598  *      SK_PNMI_ERR_GENERAL      A general severe internal error occured.
7599  *      SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
7600  *                               the correct data (e.g. a 32bit value is
7601  *                               needed, but a 16 bit value was passed).
7602  *      SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
7603  *                           exist (e.g. port instance 3 on a two port
7604  *                               adapter.
7605  */
7606
7607 PNMI_STATIC int DiagActions(
7608 SK_AC *pAC,             /* Pointer to adapter context */
7609 SK_IOC IoC,             /* IO context handle */
7610 int Action,             /* GET/PRESET/SET action */
7611 SK_U32 Id,              /* Object ID that is to be processed */
7612 char *pBuf,             /* Buffer used for the management data transfer */
7613 unsigned int *pLen,     /* On call: pBuf buffer length. On return: used buffer */
7614 SK_U32 Instance,        /* Instance (1..n) that is to be queried or -1 */
7615 unsigned int TableIndex, /* Index to the Id table */
7616 SK_U32 NetIndex)        /* NetIndex (0..n), in single net mode always zero */
7617 {
7618
7619         SK_U32  DiagStatus;
7620         SK_U32  RetCode = SK_PNMI_ERR_GENERAL;
7621
7622         /*
7623          * Check instance. We only handle single instance variables.
7624          */
7625         if (Instance != (SK_U32)(-1) && Instance != 1) {
7626
7627                 *pLen = 0;
7628                 return (SK_PNMI_ERR_UNKNOWN_INST);
7629         }
7630
7631         /*
7632          * Check length.
7633          */
7634         switch (Id) {
7635
7636         case OID_SKGE_DIAG_MODE:
7637                 if (*pLen < sizeof(SK_U32)) {
7638
7639                         *pLen = sizeof(SK_U32);
7640                         return (SK_PNMI_ERR_TOO_SHORT);
7641                 }
7642                 break;
7643
7644         default:
7645                 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR040, SK_PNMI_ERR040MSG);
7646                 *pLen = 0;
7647                 return (SK_PNMI_ERR_GENERAL);
7648         }
7649
7650         /* Perform action. */
7651
7652         /* GET value. */
7653         if (Action == SK_PNMI_GET) {
7654
7655                 switch (Id) {
7656
7657                 case OID_SKGE_DIAG_MODE:
7658                         DiagStatus = pAC->Pnmi.DiagAttached;
7659                         SK_PNMI_STORE_U32(pBuf, DiagStatus);
7660                         *pLen = sizeof(SK_U32); 
7661                         RetCode = SK_PNMI_ERR_OK;
7662                         break;
7663
7664                 default:
7665                         *pLen = 0;      
7666                         RetCode = SK_PNMI_ERR_GENERAL;
7667                         break;
7668                 }
7669                 return (RetCode); 
7670         }
7671
7672         /* From here SET or PRESET value. */
7673         
7674         /* PRESET value is not supported. */
7675         if (Action == SK_PNMI_PRESET) {
7676                 return (SK_PNMI_ERR_OK); 
7677         }
7678
7679         /* SET value. */
7680         switch (Id) {
7681                 case OID_SKGE_DIAG_MODE:
7682
7683                         /* Handle the SET. */
7684                         switch (*pBuf) {
7685
7686                                 /* Attach the DIAG to this adapter. */
7687                                 case SK_DIAG_ATTACHED:
7688                                         /* Check if we come from running */
7689                                         if (pAC->Pnmi.DiagAttached == SK_DIAG_RUNNING) {
7690
7691                                                 RetCode = SkDrvLeaveDiagMode(pAC);
7692
7693                                         }
7694                                         else if (pAC->Pnmi.DiagAttached == SK_DIAG_IDLE) {
7695
7696                                                 RetCode = SK_PNMI_ERR_OK;
7697                                         }       
7698                                         
7699                                         else {
7700
7701                                                 RetCode = SK_PNMI_ERR_GENERAL;
7702
7703                                         }
7704                                         
7705                                         if (RetCode == SK_PNMI_ERR_OK) {
7706
7707                                                 pAC->Pnmi.DiagAttached = SK_DIAG_ATTACHED;
7708                                         }
7709                                         break;
7710
7711                                 /* Enter the DIAG mode in the driver. */
7712                                 case SK_DIAG_RUNNING:
7713                                         RetCode = SK_PNMI_ERR_OK;
7714                                         
7715                                         /*
7716                                          * If DiagAttached is set, we can tell the driver
7717                                          * to enter the DIAG mode.
7718                                          */
7719                                         if (pAC->Pnmi.DiagAttached == SK_DIAG_ATTACHED) {
7720                                                 /* If DiagMode is not active, we can enter it. */
7721                                                 if (!pAC->DiagModeActive) {
7722
7723                                                         RetCode = SkDrvEnterDiagMode(pAC); 
7724                                                 }
7725                                                 else {
7726
7727                                                         RetCode = SK_PNMI_ERR_GENERAL;
7728                                                 }
7729                                         }
7730                                         else {
7731
7732                                                 RetCode = SK_PNMI_ERR_GENERAL;
7733                                         }
7734                                         
7735                                         if (RetCode == SK_PNMI_ERR_OK) {
7736
7737                                                 pAC->Pnmi.DiagAttached = SK_DIAG_RUNNING;
7738                                         }
7739                                         break;
7740
7741                                 case SK_DIAG_IDLE:
7742                                         /* Check if we come from running */
7743                                         if (pAC->Pnmi.DiagAttached == SK_DIAG_RUNNING) {
7744
7745                                                 RetCode = SkDrvLeaveDiagMode(pAC);
7746
7747                                         }
7748                                         else if (pAC->Pnmi.DiagAttached == SK_DIAG_ATTACHED) {
7749
7750                                                 RetCode = SK_PNMI_ERR_OK;
7751                                         }       
7752                                         
7753                                         else {
7754
7755                                                 RetCode = SK_PNMI_ERR_GENERAL;
7756
7757                                         }
7758
7759                                         if (RetCode == SK_PNMI_ERR_OK) {
7760
7761                                                 pAC->Pnmi.DiagAttached = SK_DIAG_IDLE;
7762                                         }
7763                                         break;
7764
7765                                 default:
7766                                         RetCode = SK_PNMI_ERR_BAD_VALUE;
7767                                         break;
7768                         }
7769                         break;
7770
7771                 default:
7772                         RetCode = SK_PNMI_ERR_GENERAL;
7773         }
7774
7775         if (RetCode == SK_PNMI_ERR_OK) {
7776                 *pLen = sizeof(SK_U32);
7777         }
7778         else {
7779
7780                 *pLen = 0;
7781         }
7782         return (RetCode);
7783 }
7784 #endif /* SK_DIAG_SUPPORT */
7785
7786 /*****************************************************************************
7787  *
7788  * Vct - OID handler function of  OIDs
7789  *
7790  * Description:
7791  *      The code is simple. No description necessary.
7792  *
7793  * Returns:
7794  *      SK_PNMI_ERR_OK           The request was performed successfully.
7795  *      SK_PNMI_ERR_GENERAL      A general severe internal error occured.
7796  *      SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to contain
7797  *                               the correct data (e.g. a 32bit value is
7798  *                               needed, but a 16 bit value was passed).
7799  *      SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
7800  *                           exist (e.g. port instance 3 on a two port
7801  *                               adapter).
7802  *      SK_PNMI_ERR_READ_ONLY    Only the Get action is allowed.
7803  *
7804  */
7805
7806 PNMI_STATIC int Vct(
7807 SK_AC *pAC,             /* Pointer to adapter context */
7808 SK_IOC IoC,             /* IO context handle */
7809 int Action,             /* GET/PRESET/SET action */
7810 SK_U32 Id,              /* Object ID that is to be processed */
7811 char *pBuf,             /* Buffer used for the management data transfer */
7812 unsigned int *pLen,     /* On call: pBuf buffer length. On return: used buffer */
7813 SK_U32 Instance,        /* Instance (-1,2..n) that is to be queried */
7814 unsigned int TableIndex, /* Index to the Id table */
7815 SK_U32 NetIndex)        /* NetIndex (0..n), in single net mode always zero */
7816 {
7817         SK_GEPORT       *pPrt;
7818         SK_PNMI_VCT     *pVctBackupData;
7819         SK_U32          LogPortMax;
7820         SK_U32          PhysPortMax;
7821         SK_U32          PhysPortIndex;
7822         SK_U32          Limit;
7823         SK_U32          Offset;
7824         SK_BOOL         Link;
7825         SK_U32          RetCode = SK_PNMI_ERR_GENERAL;
7826         int             i;
7827         SK_EVPARA       Para;
7828         SK_U32          CableLength;
7829         
7830         /*
7831          * Calculate the port indexes from the instance.
7832          */
7833         PhysPortMax = pAC->GIni.GIMacsFound;
7834         LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax);
7835         
7836         /* Dual net mode? */
7837         if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
7838                 LogPortMax--;
7839         }
7840         
7841         if ((Instance != (SK_U32) (-1))) {
7842                 /* Check instance range. */
7843                 if ((Instance < 2) || (Instance > LogPortMax)) {
7844                         *pLen = 0;
7845                         return (SK_PNMI_ERR_UNKNOWN_INST);
7846                 }
7847                 
7848                 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
7849                         PhysPortIndex = NetIndex;
7850                 }
7851                 else {
7852                         PhysPortIndex = Instance - 2;
7853                 }
7854                 Limit = PhysPortIndex + 1;
7855         }
7856         else {
7857                 /*
7858                  * Instance == (SK_U32) (-1), get all Instances of that OID.
7859                  *
7860                  * Not implemented yet. May be used in future releases.
7861                  */
7862                 PhysPortIndex = 0;
7863                 Limit = PhysPortMax;
7864         }
7865         
7866         pPrt = &pAC->GIni.GP[PhysPortIndex];
7867         if (pPrt->PHWLinkUp) {
7868                 Link = SK_TRUE;
7869         }
7870         else {
7871                 Link = SK_FALSE;
7872         }
7873         
7874         /* Check MAC type */
7875         if (pPrt->PhyType != SK_PHY_MARV_COPPER) {
7876                 *pLen = 0;
7877                 return (SK_PNMI_ERR_GENERAL);
7878         }
7879         
7880         /* Initialize backup data pointer. */
7881         pVctBackupData = &pAC->Pnmi.VctBackup[PhysPortIndex];
7882         
7883         /* Check action type */
7884         if (Action == SK_PNMI_GET) {
7885                 /* Check length */
7886                 switch (Id) {
7887                 
7888                 case OID_SKGE_VCT_GET:
7889                         if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_PNMI_VCT)) {
7890                                 *pLen = (Limit - PhysPortIndex) * sizeof(SK_PNMI_VCT);
7891                                 return (SK_PNMI_ERR_TOO_SHORT);
7892                         }
7893                         break;
7894                 
7895                 case OID_SKGE_VCT_STATUS:
7896                         if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U8)) {
7897                                 *pLen = (Limit - PhysPortIndex) * sizeof(SK_U8);
7898                                 return (SK_PNMI_ERR_TOO_SHORT);
7899                         }
7900                         break;
7901                 
7902                 default:
7903                         *pLen = 0;
7904                         return (SK_PNMI_ERR_GENERAL);
7905                 }       
7906                 
7907                 /* Get value */
7908                 Offset = 0;
7909                 for (; PhysPortIndex < Limit; PhysPortIndex++) {
7910                         switch (Id) {
7911                         
7912                         case OID_SKGE_VCT_GET:
7913                                 if ((Link == SK_FALSE) &&
7914                                         (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING)) {
7915                                         RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_FALSE);
7916                                         if (RetCode == 0) {
7917                                                 pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_PENDING;
7918                                                 pAC->Pnmi.VctStatus[PhysPortIndex] |=
7919                                                         (SK_PNMI_VCT_NEW_VCT_DATA | SK_PNMI_VCT_TEST_DONE);
7920                                                 
7921                                                 /* Copy results for later use to PNMI struct. */
7922                                                 for (i = 0; i < 4; i++)  {
7923                                                         if (pPrt->PMdiPairSts[i] == SK_PNMI_VCT_NORMAL_CABLE) {
7924                                                                 if ((pPrt->PMdiPairLen[i] > 35) && (pPrt->PMdiPairLen[i] < 0xff)) {
7925                                                                         pPrt->PMdiPairSts[i] = SK_PNMI_VCT_IMPEDANCE_MISMATCH;
7926                                                                 }
7927                                                         }
7928                                                         if ((pPrt->PMdiPairLen[i] > 35) && (pPrt->PMdiPairLen[i] != 0xff)) {
7929                                                                 CableLength = 1000 * (((175 * pPrt->PMdiPairLen[i]) / 210) - 28);
7930                                                         }
7931                                                         else {
7932                                                                 CableLength = 0;
7933                                                         }
7934                                                         pVctBackupData->PMdiPairLen[i] = CableLength;
7935                                                         pVctBackupData->PMdiPairSts[i] = pPrt->PMdiPairSts[i];
7936                                                 }
7937
7938                                                 Para.Para32[0] = PhysPortIndex;
7939                                                 Para.Para32[1] = -1;
7940                                                 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para);
7941                                                 SkEventDispatcher(pAC, IoC);
7942                                         }
7943                                         else {
7944                                                 ; /* VCT test is running. */
7945                                         }
7946                                 }
7947                                 
7948                                 /* Get all results. */
7949                                 CheckVctStatus(pAC, IoC, pBuf, Offset, PhysPortIndex);
7950                                 Offset += sizeof(SK_U8);
7951                                 *(pBuf + Offset) = pPrt->PCableLen;
7952                                 Offset += sizeof(SK_U8);
7953                                 for (i = 0; i < 4; i++)  {
7954                                         SK_PNMI_STORE_U32((pBuf + Offset), pVctBackupData->PMdiPairLen[i]);
7955                                         Offset += sizeof(SK_U32);
7956                                 }
7957                                 for (i = 0; i < 4; i++)  {
7958                                         *(pBuf + Offset) = pVctBackupData->PMdiPairSts[i];
7959                                         Offset += sizeof(SK_U8);
7960                                 }
7961                                 
7962                                 RetCode = SK_PNMI_ERR_OK;
7963                                 break;
7964                 
7965                         case OID_SKGE_VCT_STATUS:
7966                                 CheckVctStatus(pAC, IoC, pBuf, Offset, PhysPortIndex);
7967                                 Offset += sizeof(SK_U8);
7968                                 RetCode = SK_PNMI_ERR_OK;
7969                                 break;
7970                         
7971                         default:
7972                                 *pLen = 0;
7973                                 return (SK_PNMI_ERR_GENERAL);
7974                         }
7975                 } /* for */
7976                 *pLen = Offset;
7977                 return (RetCode);
7978         
7979         } /* if SK_PNMI_GET */
7980         
7981         /*
7982          * From here SET or PRESET action. Check if the passed
7983          * buffer length is plausible.
7984          */
7985         
7986         /* Check length */
7987         switch (Id) {
7988         case OID_SKGE_VCT_SET:
7989                 if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U32)) {
7990                         *pLen = (Limit - PhysPortIndex) * sizeof(SK_U32);
7991                         return (SK_PNMI_ERR_TOO_SHORT);
7992                 }
7993                 break;
7994         
7995         default:
7996                 *pLen = 0;
7997                 return (SK_PNMI_ERR_GENERAL);
7998         }
7999         
8000         /*
8001          * Perform preset or set.
8002          */
8003         
8004         /* VCT does not support PRESET action. */
8005         if (Action == SK_PNMI_PRESET) {
8006                 return (SK_PNMI_ERR_OK);
8007         }
8008         
8009         Offset = 0;
8010         for (; PhysPortIndex < Limit; PhysPortIndex++) {
8011                 switch (Id) {
8012                 case OID_SKGE_VCT_SET: /* Start VCT test. */
8013                         if (Link == SK_FALSE) {
8014                                 SkGeStopPort(pAC, IoC, PhysPortIndex, SK_STOP_ALL, SK_SOFT_RST);
8015                                 
8016                                 RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_TRUE);
8017                                 if (RetCode == 0) { /* RetCode: 0 => Start! */
8018                                         pAC->Pnmi.VctStatus[PhysPortIndex] |= SK_PNMI_VCT_PENDING;
8019                                         pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_NEW_VCT_DATA;
8020                                         pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_LINK;
8021                                         
8022                                         /*
8023                                          * Start VCT timer counter.
8024                                          */
8025                                         SK_MEMSET((char *) &Para, 0, sizeof(Para));
8026                                         Para.Para32[0] = PhysPortIndex;
8027                                         Para.Para32[1] = -1;
8028                                         SkTimerStart(pAC, IoC, &pAC->Pnmi.VctTimeout[PhysPortIndex].VctTimer,
8029                                                 4000000, SKGE_PNMI, SK_PNMI_EVT_VCT_RESET, Para);
8030                                         SK_PNMI_STORE_U32((pBuf + Offset), RetCode);
8031                                         RetCode = SK_PNMI_ERR_OK;
8032                                 }
8033                                 else { /* RetCode: 2 => Running! */
8034                                         SK_PNMI_STORE_U32((pBuf + Offset), RetCode);
8035                                         RetCode = SK_PNMI_ERR_OK;
8036                                 }
8037                         }
8038                         else { /* RetCode: 4 => Link! */
8039                                 RetCode = 4;
8040                                 SK_PNMI_STORE_U32((pBuf + Offset), RetCode);
8041                                 RetCode = SK_PNMI_ERR_OK;
8042                         }
8043                         Offset += sizeof(SK_U32);
8044                         break;
8045         
8046                 default:
8047                         *pLen = 0;
8048                         return (SK_PNMI_ERR_GENERAL);
8049                 }
8050         } /* for */
8051         *pLen = Offset;
8052         return (RetCode);
8053
8054 } /* Vct */
8055
8056
8057 PNMI_STATIC void CheckVctStatus(
8058 SK_AC           *pAC,
8059 SK_IOC          IoC,
8060 char            *pBuf,
8061 SK_U32          Offset,
8062 SK_U32          PhysPortIndex)
8063 {
8064         SK_GEPORT       *pPrt;
8065         SK_PNMI_VCT     *pVctData;
8066         SK_U32          RetCode;
8067         
8068         pPrt = &pAC->GIni.GP[PhysPortIndex];
8069         
8070         pVctData = (SK_PNMI_VCT *) (pBuf + Offset);
8071         pVctData->VctStatus = SK_PNMI_VCT_NONE;
8072         
8073         if (!pPrt->PHWLinkUp) {
8074                 
8075                 /* Was a VCT test ever made before? */
8076                 if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_TEST_DONE) {
8077                         if ((pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_LINK)) {
8078                                 pVctData->VctStatus |= SK_PNMI_VCT_OLD_VCT_DATA;
8079                         }
8080                         else {
8081                                 pVctData->VctStatus |= SK_PNMI_VCT_NEW_VCT_DATA;
8082                         }
8083                 }
8084                 
8085                 /* Check VCT test status. */
8086                 RetCode = SkGmCableDiagStatus(pAC,IoC, PhysPortIndex, SK_FALSE);
8087                 if (RetCode == 2) { /* VCT test is running. */
8088                         pVctData->VctStatus |= SK_PNMI_VCT_RUNNING;
8089                 }
8090                 else { /* VCT data was copied to pAC here. Check PENDING state. */
8091                         if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING) {
8092                                 pVctData->VctStatus |= SK_PNMI_VCT_NEW_VCT_DATA;
8093                         }
8094                 }
8095                 
8096                 if (pPrt->PCableLen != 0xff) { /* Old DSP value. */
8097                         pVctData->VctStatus |= SK_PNMI_VCT_OLD_DSP_DATA;
8098                 }
8099         }
8100         else {
8101                 
8102                 /* Was a VCT test ever made before? */
8103                 if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_TEST_DONE) {
8104                         pVctData->VctStatus &= ~SK_PNMI_VCT_NEW_VCT_DATA;
8105                         pVctData->VctStatus |= SK_PNMI_VCT_OLD_VCT_DATA;
8106                 }
8107                 
8108                 /* DSP only valid in 100/1000 modes. */
8109                 if (pAC->GIni.GP[PhysPortIndex].PLinkSpeedUsed !=
8110                         SK_LSPEED_STAT_10MBPS) {        
8111                         pVctData->VctStatus |= SK_PNMI_VCT_NEW_DSP_DATA;
8112                 }
8113         }
8114 } /* CheckVctStatus */
8115
8116
8117 /*****************************************************************************
8118  *
8119  *      SkPnmiGenIoctl - Handles new generic PNMI IOCTL, calls the needed
8120  *                       PNMI function depending on the subcommand and
8121  *                       returns all data belonging to the complete database
8122  *                       or OID request.
8123  *
8124  * Description:
8125  *      Looks up the requested subcommand, calls the corresponding handler
8126  *      function and passes all required parameters to it.
8127  *      The function is called by the driver. It is needed to handle the new
8128  *  generic PNMI IOCTL. This IOCTL is given to the driver and contains both
8129  *  the OID and a subcommand to decide what kind of request has to be done.
8130  *
8131  * Returns:
8132  *      SK_PNMI_ERR_OK           The request was successfully performed
8133  *      SK_PNMI_ERR_GENERAL      A general severe internal error occured
8134  *      SK_PNMI_ERR_TOO_SHORT    The passed buffer is too short to take
8135  *                               the data.
8136  *      SK_PNMI_ERR_UNKNOWN_OID  The requested OID is unknown
8137  *      SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
8138  *                           exist (e.g. port instance 3 on a two port
8139  *                               adapter.
8140  */
8141 int SkPnmiGenIoctl(
8142 SK_AC           *pAC,           /* Pointer to adapter context struct */
8143 SK_IOC          IoC,            /* I/O context */
8144 void            *pBuf,          /* Buffer used for the management data transfer */
8145 unsigned int *pLen,             /* Length of buffer */
8146 SK_U32          NetIndex)       /* NetIndex (0..n), in single net mode always zero */
8147 {
8148 SK_I32  Mode;                   /* Store value of subcommand. */
8149 SK_U32  Oid;                    /* Store value of OID. */
8150 int             ReturnCode;             /* Store return value to show status of PNMI action. */
8151 int     HeaderLength;   /* Length of desired action plus OID. */
8152
8153         ReturnCode = SK_PNMI_ERR_GENERAL;
8154         
8155         SK_MEMCPY(&Mode, pBuf, sizeof(SK_I32));
8156         SK_MEMCPY(&Oid, (char *) pBuf + sizeof(SK_I32), sizeof(SK_U32));
8157         HeaderLength = sizeof(SK_I32) + sizeof(SK_U32);
8158         *pLen = *pLen - HeaderLength;
8159         SK_MEMCPY((char *) pBuf + sizeof(SK_I32), (char *) pBuf + HeaderLength, *pLen);
8160         
8161         switch(Mode) {
8162         case SK_GET_SINGLE_VAR:
8163                 ReturnCode = SkPnmiGetVar(pAC, IoC, Oid, 
8164                                 (char *) pBuf + sizeof(SK_I32), pLen,
8165                                 ((SK_U32) (-1)), NetIndex);
8166                 SK_PNMI_STORE_U32(pBuf, ReturnCode);
8167                 *pLen = *pLen + sizeof(SK_I32);
8168                 break;
8169         case SK_PRESET_SINGLE_VAR:
8170                 ReturnCode = SkPnmiPreSetVar(pAC, IoC, Oid, 
8171                                 (char *) pBuf + sizeof(SK_I32), pLen,
8172                                 ((SK_U32) (-1)), NetIndex);
8173                 SK_PNMI_STORE_U32(pBuf, ReturnCode);
8174                 *pLen = *pLen + sizeof(SK_I32);
8175                 break;
8176         case SK_SET_SINGLE_VAR:
8177                 ReturnCode = SkPnmiSetVar(pAC, IoC, Oid, 
8178                                 (char *) pBuf + sizeof(SK_I32), pLen,
8179                                 ((SK_U32) (-1)), NetIndex);
8180                 SK_PNMI_STORE_U32(pBuf, ReturnCode);
8181                 *pLen = *pLen + sizeof(SK_I32);
8182                 break;
8183         case SK_GET_FULL_MIB:
8184                 ReturnCode = SkPnmiGetStruct(pAC, IoC, pBuf, pLen, NetIndex);
8185                 break;
8186         case SK_PRESET_FULL_MIB:
8187                 ReturnCode = SkPnmiPreSetStruct(pAC, IoC, pBuf, pLen, NetIndex);
8188                 break;
8189         case SK_SET_FULL_MIB:
8190                 ReturnCode = SkPnmiSetStruct(pAC, IoC, pBuf, pLen, NetIndex);
8191                 break;
8192         default:
8193                 break;
8194         }
8195         
8196         return (ReturnCode);
8197
8198 } /* SkGeIocGen */