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