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