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  */
SkPnmiInit(SK_AC * pAC,SK_IOC IoC,int Level)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  */
SkPnmiGetVar(SK_AC * pAC,SK_IOC IoC,SK_U32 Id,void * pBuf,unsigned int * pLen,SK_U32 Instance,SK_U32 NetIndex)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  */
SkPnmiPreSetVar(SK_AC * pAC,SK_IOC IoC,SK_U32 Id,void * pBuf,unsigned int * pLen,SK_U32 Instance,SK_U32 NetIndex)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  */
SkPnmiSetVar(SK_AC * pAC,SK_IOC IoC,SK_U32 Id,void * pBuf,unsigned int * pLen,SK_U32 Instance,SK_U32 NetIndex)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  */
SkPnmiGetStruct(SK_AC * pAC,SK_IOC IoC,void * pBuf,unsigned int * pLen,SK_U32 NetIndex)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  */
SkPnmiPreSetStruct(SK_AC * pAC,SK_IOC IoC,void * pBuf,unsigned int * pLen,SK_U32 NetIndex)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  */
SkPnmiSetStruct(SK_AC * pAC,SK_IOC IoC,void * pBuf,unsigned int * pLen,SK_U32 NetIndex)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  */
SkPnmiEvent(SK_AC * pAC,SK_IOC IoC,SK_U32 Event,SK_EVPARA Param)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  */
PnmiVar(SK_AC * pAC,SK_IOC IoC,int Action,SK_U32 Id,char * pBuf,unsigned int * pLen,SK_U32 Instance,SK_U32 NetIndex)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  */
PnmiStruct(SK_AC * pAC,SK_IOC IoC,int Action,char * pBuf,unsigned int * pLen,SK_U32 NetIndex)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  */
LookupId(SK_U32 Id)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  */
OidStruct(SK_AC * pAC,SK_IOC IoC,int Action,SK_U32 Id,char * pBuf,unsigned int * pLen,SK_U32 Instance,unsigned int TableIndex,SK_U32 NetIndex)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  */
Perform(SK_AC * pAC,SK_IOC IoC,int Action,SK_U32 Id,char * pBuf,unsigned int * pLen,SK_U32 Instance,unsigned int TableIndex,SK_U32 NetIndex)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  */
Mac8023Stat(SK_AC * pAC,SK_IOC IoC,int Action,SK_U32 Id,char * pBuf,unsigned int * pLen,SK_U32 Instance,unsigned int TableIndex,SK_U32 NetIndex)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  */
MacPrivateStat(SK_AC * pAC,SK_IOC IoC,int Action,SK_U32 Id,char * pBuf,unsigned int * pLen,SK_U32 Instance,unsigned int TableIndex,SK_U32 NetIndex)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  */
Addr(SK_AC * pAC,SK_IOC IoC,int Action,SK_U32 Id,char * pBuf,unsigned int * pLen,SK_U32 Instance,unsigned int TableIndex,SK_U32 NetIndex)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  */
CsumStat(SK_AC * pAC,SK_IOC IoC,int Action,SK_U32 Id,char * pBuf,unsigned int * pLen,SK_U32 Instance,unsigned int TableIndex,SK_U32 NetIndex)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  */
SensorStat(SK_AC * pAC,SK_IOC IoC,int Action,SK_U32 Id,char * pBuf,unsigned int * pLen,SK_U32 Instance,unsigned int TableIndex,SK_U32 NetIndex)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  */
Vpd(SK_AC * pAC,SK_IOC IoC,int Action,SK_U32 Id,char * pBuf,unsigned int * pLen,SK_U32 Instance,unsigned int TableIndex,SK_U32 NetIndex)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  */
General(SK_AC * pAC,SK_IOC IoC,int Action,SK_U32 Id,char * pBuf,unsigned int * pLen,SK_U32 Instance,unsigned int TableIndex,SK_U32 NetIndex)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  */
Rlmt(SK_AC * pAC,SK_IOC IoC,int Action,SK_U32 Id,char * pBuf,unsigned int * pLen,SK_U32 Instance,unsigned int TableIndex,SK_U32 NetIndex)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  */
RlmtStat(SK_AC * pAC,SK_IOC IoC,int Action,SK_U32 Id,char * pBuf,unsigned int * pLen,SK_U32 Instance,unsigned int TableIndex,SK_U32 NetIndex)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  */
MacPrivateConf(SK_AC * pAC,SK_IOC IoC,int Action,SK_U32 Id,char * pBuf,unsigned int * pLen,SK_U32 Instance,unsigned int TableIndex,SK_U32 NetIndex)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  */
Monitor(SK_AC * pAC,SK_IOC IoC,int Action,SK_U32 Id,char * pBuf,unsigned int * pLen,SK_U32 Instance,unsigned int TableIndex,SK_U32 NetIndex)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  */
VirtualConf(SK_AC * pAC,SK_IOC IoC,SK_U32 Id,char * pBuf)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  */
CalculateLinkStatus(SK_AC * pAC,SK_IOC IoC,unsigned int PhysPortIndex)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  */
CalculateLinkModeStatus(SK_AC * pAC,SK_IOC IoC,unsigned int PhysPortIndex)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  */
GetVpdKeyArr(SK_AC * pAC,SK_IOC IoC,char * pKeyArr,unsigned int KeyArrLen,unsigned int * pKeyNo)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  */
SirqUpdate(SK_AC * pAC,SK_IOC IoC)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  */
RlmtUpdate(SK_AC * pAC,SK_IOC IoC,SK_U32 NetIndex)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  */
MacUpdate(SK_AC * pAC,SK_IOC IoC,unsigned int FirstMac,unsigned int LastMac)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  */
GetStatVal(SK_AC * pAC,SK_IOC IoC,unsigned int LogPortIndex,unsigned int StatIndex,SK_U32 NetIndex)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  */
GetPhysStatVal(SK_AC * pAC,SK_IOC IoC,unsigned int PhysPortIndex,unsigned int StatIndex)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  */
ResetCounter(SK_AC * pAC,SK_IOC IoC,SK_U32 NetIndex)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  */
GetTrapEntry(SK_AC * pAC,SK_U32 TrapId,unsigned int Size)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  */
CopyTrapQueue(SK_AC * pAC,char * pDstBuf)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  */
GetTrapQueueLen(SK_AC * pAC,unsigned int * pLen,unsigned int * pEntries)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  */
QueueSimpleTrap(SK_AC * pAC,SK_U32 TrapId)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  */
QueueSensorTrap(SK_AC * pAC,SK_U32 TrapId,unsigned int SensorIndex)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  */
QueueRlmtNewMacTrap(SK_AC * pAC,unsigned int ActiveMac)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  */
QueueRlmtPortTrap(SK_AC * pAC,SK_U32 TrapId,unsigned int PortIndex)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  */
CopyMac(char * pDst,SK_MAC_ADDR * pMac)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 
PowerManagement(SK_AC * pAC,SK_IOC IoC,int Action,SK_U32 Id,char * pBuf,unsigned int * pLen,SK_U32 Instance,unsigned int TableIndex,SK_U32 NetIndex)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 
DiagActions(SK_AC * pAC,SK_IOC IoC,int Action,SK_U32 Id,char * pBuf,unsigned int * pLen,SK_U32 Instance,unsigned int TableIndex,SK_U32 NetIndex)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 
Vct(SK_AC * pAC,SK_IOC IoC,int Action,SK_U32 Id,char * pBuf,unsigned int * pLen,SK_U32 Instance,unsigned int TableIndex,SK_U32 NetIndex)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 
CheckVctStatus(SK_AC * pAC,SK_IOC IoC,char * pBuf,SK_U32 Offset,SK_U32 PhysPortIndex)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  */
SkPnmiGenIoctl(SK_AC * pAC,SK_IOC IoC,void * pBuf,unsigned int * pLen,SK_U32 NetIndex)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 */
8357