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