[TG3]: Add tagged status support.
[linux-2.6/verdex.git] / drivers / net / sk98lin / skgepnmi.c
blob58e1a5be913f2ae7d26d6e72ab4d95cd8a9449d4
1 /*****************************************************************************
3 * Name: skgepnmi.c
4 * Project: GEnesis, PCI Gigabit Ethernet Adapter
5 * Version: $Revision: 1.111 $
6 * Date: $Date: 2003/09/15 13:35:35 $
7 * Purpose: Private Network Management Interface
9 ****************************************************************************/
11 /******************************************************************************
13 * (C)Copyright 1998-2002 SysKonnect GmbH.
14 * (C)Copyright 2002-2003 Marvell.
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
21 * The information in this file is provided "AS IS" without warranty.
23 ******************************************************************************/
26 #ifndef _lint
27 static const char SysKonnectFileId[] =
28 "@(#) $Id: skgepnmi.c,v 1.111 2003/09/15 13:35:35 tschilli Exp $ (C) Marvell.";
29 #endif /* !_lint */
31 #include "h/skdrv1st.h"
32 #include "h/sktypes.h"
33 #include "h/xmac_ii.h"
34 #include "h/skdebug.h"
35 #include "h/skqueue.h"
36 #include "h/skgepnmi.h"
37 #include "h/skgesirq.h"
38 #include "h/skcsum.h"
39 #include "h/skvpd.h"
40 #include "h/skgehw.h"
41 #include "h/skgeinit.h"
42 #include "h/skdrv2nd.h"
43 #include "h/skgepnm2.h"
44 #ifdef SK_POWER_MGMT
45 #include "h/skgepmgt.h"
46 #endif
47 /* defines *******************************************************************/
49 #ifndef DEBUG
50 #define PNMI_STATIC static
51 #else /* DEBUG */
52 #define PNMI_STATIC
53 #endif /* DEBUG */
56 * Public Function prototypes
58 int SkPnmiInit(SK_AC *pAC, SK_IOC IoC, int level);
59 int SkPnmiGetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, void *pBuf,
60 unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex);
61 int SkPnmiPreSetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, void *pBuf,
62 unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex);
63 int SkPnmiSetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, void *pBuf,
64 unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex);
65 int SkPnmiGetStruct(SK_AC *pAC, SK_IOC IoC, void *pBuf,
66 unsigned int *pLen, SK_U32 NetIndex);
67 int SkPnmiPreSetStruct(SK_AC *pAC, SK_IOC IoC, void *pBuf,
68 unsigned int *pLen, SK_U32 NetIndex);
69 int SkPnmiSetStruct(SK_AC *pAC, SK_IOC IoC, void *pBuf,
70 unsigned int *pLen, SK_U32 NetIndex);
71 int SkPnmiEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event, SK_EVPARA Param);
72 int SkPnmiGenIoctl(SK_AC *pAC, SK_IOC IoC, void * pBuf,
73 unsigned int * pLen, SK_U32 NetIndex);
77 * Private Function prototypes
80 PNMI_STATIC SK_U8 CalculateLinkModeStatus(SK_AC *pAC, SK_IOC IoC, unsigned int
81 PhysPortIndex);
82 PNMI_STATIC SK_U8 CalculateLinkStatus(SK_AC *pAC, SK_IOC IoC, unsigned int
83 PhysPortIndex);
84 PNMI_STATIC void CopyMac(char *pDst, SK_MAC_ADDR *pMac);
85 PNMI_STATIC void CopyTrapQueue(SK_AC *pAC, char *pDstBuf);
86 PNMI_STATIC SK_U64 GetPhysStatVal(SK_AC *pAC, SK_IOC IoC,
87 unsigned int PhysPortIndex, unsigned int StatIndex);
88 PNMI_STATIC SK_U64 GetStatVal(SK_AC *pAC, SK_IOC IoC, unsigned int LogPortIndex,
89 unsigned int StatIndex, SK_U32 NetIndex);
90 PNMI_STATIC char* GetTrapEntry(SK_AC *pAC, SK_U32 TrapId, unsigned int Size);
91 PNMI_STATIC void GetTrapQueueLen(SK_AC *pAC, unsigned int *pLen,
92 unsigned int *pEntries);
93 PNMI_STATIC int GetVpdKeyArr(SK_AC *pAC, SK_IOC IoC, char *pKeyArr,
94 unsigned int KeyArrLen, unsigned int *pKeyNo);
95 PNMI_STATIC int LookupId(SK_U32 Id);
96 PNMI_STATIC int MacUpdate(SK_AC *pAC, SK_IOC IoC, unsigned int FirstMac,
97 unsigned int LastMac);
98 PNMI_STATIC int PnmiStruct(SK_AC *pAC, SK_IOC IoC, int Action, char *pBuf,
99 unsigned int *pLen, SK_U32 NetIndex);
100 PNMI_STATIC int PnmiVar(SK_AC *pAC, SK_IOC IoC, int Action, SK_U32 Id,
101 char *pBuf, unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex);
102 PNMI_STATIC void QueueRlmtNewMacTrap(SK_AC *pAC, unsigned int ActiveMac);
103 PNMI_STATIC void QueueRlmtPortTrap(SK_AC *pAC, SK_U32 TrapId,
104 unsigned int PortIndex);
105 PNMI_STATIC void QueueSensorTrap(SK_AC *pAC, SK_U32 TrapId,
106 unsigned int SensorIndex);
107 PNMI_STATIC void QueueSimpleTrap(SK_AC *pAC, SK_U32 TrapId);
108 PNMI_STATIC void ResetCounter(SK_AC *pAC, SK_IOC IoC, SK_U32 NetIndex);
109 PNMI_STATIC int RlmtUpdate(SK_AC *pAC, SK_IOC IoC, SK_U32 NetIndex);
110 PNMI_STATIC int SirqUpdate(SK_AC *pAC, SK_IOC IoC);
111 PNMI_STATIC void VirtualConf(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, char *pBuf);
112 PNMI_STATIC int Vct(SK_AC *pAC, SK_IOC IoC, int Action, SK_U32 Id, char *pBuf,
113 unsigned int *pLen, SK_U32 Instance, unsigned int TableIndex, SK_U32 NetIndex);
114 PNMI_STATIC void CheckVctStatus(SK_AC *, SK_IOC, char *, SK_U32, SK_U32);
117 * Table to correlate OID with handler function and index to
118 * hardware register stored in StatAddress if applicable.
120 #include "skgemib.c"
122 /* global variables **********************************************************/
125 * Overflow status register bit table and corresponding counter
126 * dependent on MAC type - the number relates to the size of overflow
127 * mask returned by the pFnMacOverflow function
129 PNMI_STATIC const SK_U16 StatOvrflwBit[][SK_PNMI_MAC_TYPES] = {
130 /* Bit0 */ { SK_PNMI_HTX, SK_PNMI_HTX_UNICAST},
131 /* Bit1 */ { SK_PNMI_HTX_OCTETHIGH, SK_PNMI_HTX_BROADCAST},
132 /* Bit2 */ { SK_PNMI_HTX_OCTETLOW, SK_PNMI_HTX_PMACC},
133 /* Bit3 */ { SK_PNMI_HTX_BROADCAST, SK_PNMI_HTX_MULTICAST},
134 /* Bit4 */ { SK_PNMI_HTX_MULTICAST, SK_PNMI_HTX_OCTETLOW},
135 /* Bit5 */ { SK_PNMI_HTX_UNICAST, SK_PNMI_HTX_OCTETHIGH},
136 /* Bit6 */ { SK_PNMI_HTX_LONGFRAMES, SK_PNMI_HTX_64},
137 /* Bit7 */ { SK_PNMI_HTX_BURST, SK_PNMI_HTX_127},
138 /* Bit8 */ { SK_PNMI_HTX_PMACC, SK_PNMI_HTX_255},
139 /* Bit9 */ { SK_PNMI_HTX_MACC, SK_PNMI_HTX_511},
140 /* Bit10 */ { SK_PNMI_HTX_SINGLE_COL, SK_PNMI_HTX_1023},
141 /* Bit11 */ { SK_PNMI_HTX_MULTI_COL, SK_PNMI_HTX_MAX},
142 /* Bit12 */ { SK_PNMI_HTX_EXCESS_COL, SK_PNMI_HTX_LONGFRAMES},
143 /* Bit13 */ { SK_PNMI_HTX_LATE_COL, SK_PNMI_HTX_RESERVED},
144 /* Bit14 */ { SK_PNMI_HTX_DEFFERAL, SK_PNMI_HTX_COL},
145 /* Bit15 */ { SK_PNMI_HTX_EXCESS_DEF, SK_PNMI_HTX_LATE_COL},
146 /* Bit16 */ { SK_PNMI_HTX_UNDERRUN, SK_PNMI_HTX_EXCESS_COL},
147 /* Bit17 */ { SK_PNMI_HTX_CARRIER, SK_PNMI_HTX_MULTI_COL},
148 /* Bit18 */ { SK_PNMI_HTX_UTILUNDER, SK_PNMI_HTX_SINGLE_COL},
149 /* Bit19 */ { SK_PNMI_HTX_UTILOVER, SK_PNMI_HTX_UNDERRUN},
150 /* Bit20 */ { SK_PNMI_HTX_64, SK_PNMI_HTX_RESERVED},
151 /* Bit21 */ { SK_PNMI_HTX_127, SK_PNMI_HTX_RESERVED},
152 /* Bit22 */ { SK_PNMI_HTX_255, SK_PNMI_HTX_RESERVED},
153 /* Bit23 */ { SK_PNMI_HTX_511, SK_PNMI_HTX_RESERVED},
154 /* Bit24 */ { SK_PNMI_HTX_1023, SK_PNMI_HTX_RESERVED},
155 /* Bit25 */ { SK_PNMI_HTX_MAX, SK_PNMI_HTX_RESERVED},
156 /* Bit26 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED},
157 /* Bit27 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED},
158 /* Bit28 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED},
159 /* Bit29 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED},
160 /* Bit30 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED},
161 /* Bit31 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED},
162 /* Bit32 */ { SK_PNMI_HRX, SK_PNMI_HRX_UNICAST},
163 /* Bit33 */ { SK_PNMI_HRX_OCTETHIGH, SK_PNMI_HRX_BROADCAST},
164 /* Bit34 */ { SK_PNMI_HRX_OCTETLOW, SK_PNMI_HRX_PMACC},
165 /* Bit35 */ { SK_PNMI_HRX_BROADCAST, SK_PNMI_HRX_MULTICAST},
166 /* Bit36 */ { SK_PNMI_HRX_MULTICAST, SK_PNMI_HRX_FCS},
167 /* Bit37 */ { SK_PNMI_HRX_UNICAST, SK_PNMI_HRX_RESERVED},
168 /* Bit38 */ { SK_PNMI_HRX_PMACC, SK_PNMI_HRX_OCTETLOW},
169 /* Bit39 */ { SK_PNMI_HRX_MACC, SK_PNMI_HRX_OCTETHIGH},
170 /* Bit40 */ { SK_PNMI_HRX_PMACC_ERR, SK_PNMI_HRX_BADOCTETLOW},
171 /* Bit41 */ { SK_PNMI_HRX_MACC_UNKWN, SK_PNMI_HRX_BADOCTETHIGH},
172 /* Bit42 */ { SK_PNMI_HRX_BURST, SK_PNMI_HRX_UNDERSIZE},
173 /* Bit43 */ { SK_PNMI_HRX_MISSED, SK_PNMI_HRX_RUNT},
174 /* Bit44 */ { SK_PNMI_HRX_FRAMING, SK_PNMI_HRX_64},
175 /* Bit45 */ { SK_PNMI_HRX_OVERFLOW, SK_PNMI_HRX_127},
176 /* Bit46 */ { SK_PNMI_HRX_JABBER, SK_PNMI_HRX_255},
177 /* Bit47 */ { SK_PNMI_HRX_CARRIER, SK_PNMI_HRX_511},
178 /* Bit48 */ { SK_PNMI_HRX_IRLENGTH, SK_PNMI_HRX_1023},
179 /* Bit49 */ { SK_PNMI_HRX_SYMBOL, SK_PNMI_HRX_MAX},
180 /* Bit50 */ { SK_PNMI_HRX_SHORTS, SK_PNMI_HRX_LONGFRAMES},
181 /* Bit51 */ { SK_PNMI_HRX_RUNT, SK_PNMI_HRX_TOO_LONG},
182 /* Bit52 */ { SK_PNMI_HRX_TOO_LONG, SK_PNMI_HRX_JABBER},
183 /* Bit53 */ { SK_PNMI_HRX_FCS, SK_PNMI_HRX_RESERVED},
184 /* Bit54 */ { SK_PNMI_HRX_RESERVED, SK_PNMI_HRX_OVERFLOW},
185 /* Bit55 */ { SK_PNMI_HRX_CEXT, SK_PNMI_HRX_RESERVED},
186 /* Bit56 */ { SK_PNMI_HRX_UTILUNDER, SK_PNMI_HRX_RESERVED},
187 /* Bit57 */ { SK_PNMI_HRX_UTILOVER, SK_PNMI_HRX_RESERVED},
188 /* Bit58 */ { SK_PNMI_HRX_64, SK_PNMI_HRX_RESERVED},
189 /* Bit59 */ { SK_PNMI_HRX_127, SK_PNMI_HRX_RESERVED},
190 /* Bit60 */ { SK_PNMI_HRX_255, SK_PNMI_HRX_RESERVED},
191 /* Bit61 */ { SK_PNMI_HRX_511, SK_PNMI_HRX_RESERVED},
192 /* Bit62 */ { SK_PNMI_HRX_1023, SK_PNMI_HRX_RESERVED},
193 /* Bit63 */ { SK_PNMI_HRX_MAX, SK_PNMI_HRX_RESERVED}
197 * Table for hardware register saving on resets and port switches
199 PNMI_STATIC const SK_PNMI_STATADDR StatAddr[SK_PNMI_MAX_IDX][SK_PNMI_MAC_TYPES] = {
200 /* SK_PNMI_HTX */
201 {{XM_TXF_OK, SK_TRUE}, {0, SK_FALSE}},
202 /* SK_PNMI_HTX_OCTETHIGH */
203 {{XM_TXO_OK_HI, SK_TRUE}, {GM_TXO_OK_HI, SK_TRUE}},
204 /* SK_PNMI_HTX_OCTETLOW */
205 {{XM_TXO_OK_LO, SK_FALSE}, {GM_TXO_OK_LO, SK_FALSE}},
206 /* SK_PNMI_HTX_BROADCAST */
207 {{XM_TXF_BC_OK, SK_TRUE}, {GM_TXF_BC_OK, SK_TRUE}},
208 /* SK_PNMI_HTX_MULTICAST */
209 {{XM_TXF_MC_OK, SK_TRUE}, {GM_TXF_MC_OK, SK_TRUE}},
210 /* SK_PNMI_HTX_UNICAST */
211 {{XM_TXF_UC_OK, SK_TRUE}, {GM_TXF_UC_OK, SK_TRUE}},
212 /* SK_PNMI_HTX_BURST */
213 {{XM_TXE_BURST, SK_TRUE}, {0, SK_FALSE}},
214 /* SK_PNMI_HTX_PMACC */
215 {{XM_TXF_MPAUSE, SK_TRUE}, {GM_TXF_MPAUSE, SK_TRUE}},
216 /* SK_PNMI_HTX_MACC */
217 {{XM_TXF_MCTRL, SK_TRUE}, {0, SK_FALSE}},
218 /* SK_PNMI_HTX_COL */
219 {{0, SK_FALSE}, {GM_TXF_COL, SK_TRUE}},
220 /* SK_PNMI_HTX_SINGLE_COL */
221 {{XM_TXF_SNG_COL, SK_TRUE}, {GM_TXF_SNG_COL, SK_TRUE}},
222 /* SK_PNMI_HTX_MULTI_COL */
223 {{XM_TXF_MUL_COL, SK_TRUE}, {GM_TXF_MUL_COL, SK_TRUE}},
224 /* SK_PNMI_HTX_EXCESS_COL */
225 {{XM_TXF_ABO_COL, SK_TRUE}, {GM_TXF_ABO_COL, SK_TRUE}},
226 /* SK_PNMI_HTX_LATE_COL */
227 {{XM_TXF_LAT_COL, SK_TRUE}, {GM_TXF_LAT_COL, SK_TRUE}},
228 /* SK_PNMI_HTX_DEFFERAL */
229 {{XM_TXF_DEF, SK_TRUE}, {0, SK_FALSE}},
230 /* SK_PNMI_HTX_EXCESS_DEF */
231 {{XM_TXF_EX_DEF, SK_TRUE}, {0, SK_FALSE}},
232 /* SK_PNMI_HTX_UNDERRUN */
233 {{XM_TXE_FIFO_UR, SK_TRUE}, {GM_TXE_FIFO_UR, SK_TRUE}},
234 /* SK_PNMI_HTX_CARRIER */
235 {{XM_TXE_CS_ERR, SK_TRUE}, {0, SK_FALSE}},
236 /* SK_PNMI_HTX_UTILUNDER */
237 {{0, SK_FALSE}, {0, SK_FALSE}},
238 /* SK_PNMI_HTX_UTILOVER */
239 {{0, SK_FALSE}, {0, SK_FALSE}},
240 /* SK_PNMI_HTX_64 */
241 {{XM_TXF_64B, SK_TRUE}, {GM_TXF_64B, SK_TRUE}},
242 /* SK_PNMI_HTX_127 */
243 {{XM_TXF_127B, SK_TRUE}, {GM_TXF_127B, SK_TRUE}},
244 /* SK_PNMI_HTX_255 */
245 {{XM_TXF_255B, SK_TRUE}, {GM_TXF_255B, SK_TRUE}},
246 /* SK_PNMI_HTX_511 */
247 {{XM_TXF_511B, SK_TRUE}, {GM_TXF_511B, SK_TRUE}},
248 /* SK_PNMI_HTX_1023 */
249 {{XM_TXF_1023B, SK_TRUE}, {GM_TXF_1023B, SK_TRUE}},
250 /* SK_PNMI_HTX_MAX */
251 {{XM_TXF_MAX_SZ, SK_TRUE}, {GM_TXF_1518B, SK_TRUE}},
252 /* SK_PNMI_HTX_LONGFRAMES */
253 {{XM_TXF_LONG, SK_TRUE}, {GM_TXF_MAX_SZ, SK_TRUE}},
254 /* SK_PNMI_HTX_SYNC */
255 {{0, SK_FALSE}, {0, SK_FALSE}},
256 /* SK_PNMI_HTX_SYNC_OCTET */
257 {{0, SK_FALSE}, {0, SK_FALSE}},
258 /* SK_PNMI_HTX_RESERVED */
259 {{0, SK_FALSE}, {0, SK_FALSE}},
260 /* SK_PNMI_HRX */
261 {{XM_RXF_OK, SK_TRUE}, {0, SK_FALSE}},
262 /* SK_PNMI_HRX_OCTETHIGH */
263 {{XM_RXO_OK_HI, SK_TRUE}, {GM_RXO_OK_HI, SK_TRUE}},
264 /* SK_PNMI_HRX_OCTETLOW */
265 {{XM_RXO_OK_LO, SK_FALSE}, {GM_RXO_OK_LO, SK_FALSE}},
266 /* SK_PNMI_HRX_BADOCTETHIGH */
267 {{0, SK_FALSE}, {GM_RXO_ERR_HI, SK_TRUE}},
268 /* SK_PNMI_HRX_BADOCTETLOW */
269 {{0, SK_FALSE}, {GM_RXO_ERR_LO, SK_TRUE}},
270 /* SK_PNMI_HRX_BROADCAST */
271 {{XM_RXF_BC_OK, SK_TRUE}, {GM_RXF_BC_OK, SK_TRUE}},
272 /* SK_PNMI_HRX_MULTICAST */
273 {{XM_RXF_MC_OK, SK_TRUE}, {GM_RXF_MC_OK, SK_TRUE}},
274 /* SK_PNMI_HRX_UNICAST */
275 {{XM_RXF_UC_OK, SK_TRUE}, {GM_RXF_UC_OK, SK_TRUE}},
276 /* SK_PNMI_HRX_PMACC */
277 {{XM_RXF_MPAUSE, SK_TRUE}, {GM_RXF_MPAUSE, SK_TRUE}},
278 /* SK_PNMI_HRX_MACC */
279 {{XM_RXF_MCTRL, SK_TRUE}, {0, SK_FALSE}},
280 /* SK_PNMI_HRX_PMACC_ERR */
281 {{XM_RXF_INV_MP, SK_TRUE}, {0, SK_FALSE}},
282 /* SK_PNMI_HRX_MACC_UNKWN */
283 {{XM_RXF_INV_MOC, SK_TRUE}, {0, SK_FALSE}},
284 /* SK_PNMI_HRX_BURST */
285 {{XM_RXE_BURST, SK_TRUE}, {0, SK_FALSE}},
286 /* SK_PNMI_HRX_MISSED */
287 {{XM_RXE_FMISS, SK_TRUE}, {0, SK_FALSE}},
288 /* SK_PNMI_HRX_FRAMING */
289 {{XM_RXF_FRA_ERR, SK_TRUE}, {0, SK_FALSE}},
290 /* SK_PNMI_HRX_UNDERSIZE */
291 {{0, SK_FALSE}, {GM_RXF_SHT, SK_TRUE}},
292 /* SK_PNMI_HRX_OVERFLOW */
293 {{XM_RXE_FIFO_OV, SK_TRUE}, {GM_RXE_FIFO_OV, SK_TRUE}},
294 /* SK_PNMI_HRX_JABBER */
295 {{XM_RXF_JAB_PKT, SK_TRUE}, {GM_RXF_JAB_PKT, SK_TRUE}},
296 /* SK_PNMI_HRX_CARRIER */
297 {{XM_RXE_CAR_ERR, SK_TRUE}, {0, SK_FALSE}},
298 /* SK_PNMI_HRX_IRLENGTH */
299 {{XM_RXF_LEN_ERR, SK_TRUE}, {0, SK_FALSE}},
300 /* SK_PNMI_HRX_SYMBOL */
301 {{XM_RXE_SYM_ERR, SK_TRUE}, {0, SK_FALSE}},
302 /* SK_PNMI_HRX_SHORTS */
303 {{XM_RXE_SHT_ERR, SK_TRUE}, {0, SK_FALSE}},
304 /* SK_PNMI_HRX_RUNT */
305 {{XM_RXE_RUNT, SK_TRUE}, {GM_RXE_FRAG, SK_TRUE}},
306 /* SK_PNMI_HRX_TOO_LONG */
307 {{XM_RXF_LNG_ERR, SK_TRUE}, {GM_RXF_LNG_ERR, SK_TRUE}},
308 /* SK_PNMI_HRX_FCS */
309 {{XM_RXF_FCS_ERR, SK_TRUE}, {GM_RXF_FCS_ERR, SK_TRUE}},
310 /* SK_PNMI_HRX_CEXT */
311 {{XM_RXF_CEX_ERR, SK_TRUE}, {0, SK_FALSE}},
312 /* SK_PNMI_HRX_UTILUNDER */
313 {{0, SK_FALSE}, {0, SK_FALSE}},
314 /* SK_PNMI_HRX_UTILOVER */
315 {{0, SK_FALSE}, {0, SK_FALSE}},
316 /* SK_PNMI_HRX_64 */
317 {{XM_RXF_64B, SK_TRUE}, {GM_RXF_64B, SK_TRUE}},
318 /* SK_PNMI_HRX_127 */
319 {{XM_RXF_127B, SK_TRUE}, {GM_RXF_127B, SK_TRUE}},
320 /* SK_PNMI_HRX_255 */
321 {{XM_RXF_255B, SK_TRUE}, {GM_RXF_255B, SK_TRUE}},
322 /* SK_PNMI_HRX_511 */
323 {{XM_RXF_511B, SK_TRUE}, {GM_RXF_511B, SK_TRUE}},
324 /* SK_PNMI_HRX_1023 */
325 {{XM_RXF_1023B, SK_TRUE}, {GM_RXF_1023B, SK_TRUE}},
326 /* SK_PNMI_HRX_MAX */
327 {{XM_RXF_MAX_SZ, SK_TRUE}, {GM_RXF_1518B, SK_TRUE}},
328 /* SK_PNMI_HRX_LONGFRAMES */
329 {{0, SK_FALSE}, {GM_RXF_MAX_SZ, SK_TRUE}},
330 /* SK_PNMI_HRX_RESERVED */
331 {{0, SK_FALSE}, {0, SK_FALSE}}
335 /*****************************************************************************
337 * Public functions
341 /*****************************************************************************
343 * SkPnmiInit - Init function of PNMI
345 * Description:
346 * SK_INIT_DATA: Initialises the data structures
347 * SK_INIT_IO: Resets the XMAC statistics, determines the device and
348 * connector type.
349 * SK_INIT_RUN: Starts a timer event for port switch per hour
350 * calculation.
352 * Returns:
353 * Always 0
355 int SkPnmiInit(
356 SK_AC *pAC, /* Pointer to adapter context */
357 SK_IOC IoC, /* IO context handle */
358 int Level) /* Initialization level */
360 unsigned int PortMax; /* Number of ports */
361 unsigned int PortIndex; /* Current port index in loop */
362 SK_U16 Val16; /* Multiple purpose 16 bit variable */
363 SK_U8 Val8; /* Mulitple purpose 8 bit variable */
364 SK_EVPARA EventParam; /* Event struct for timer event */
365 SK_PNMI_VCT *pVctBackupData;
368 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
369 ("PNMI: SkPnmiInit: Called, level=%d\n", Level));
371 switch (Level) {
373 case SK_INIT_DATA:
374 SK_MEMSET((char *)&pAC->Pnmi, 0, sizeof(pAC->Pnmi));
375 pAC->Pnmi.TrapBufFree = SK_PNMI_TRAP_QUEUE_LEN;
376 pAC->Pnmi.StartUpTime = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC));
377 pAC->Pnmi.RlmtChangeThreshold = SK_PNMI_DEF_RLMT_CHG_THRES;
378 for (PortIndex = 0; PortIndex < SK_MAX_MACS; PortIndex ++) {
380 pAC->Pnmi.Port[PortIndex].ActiveFlag = SK_FALSE;
381 pAC->Pnmi.DualNetActiveFlag = SK_FALSE;
384 #ifdef SK_PNMI_CHECK
385 if (SK_PNMI_MAX_IDX != SK_PNMI_CNT_NO) {
387 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR049, SK_PNMI_ERR049MSG);
389 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_INIT | SK_DBGCAT_FATAL,
390 ("CounterOffset struct size (%d) differs from"
391 "SK_PNMI_MAX_IDX (%d)\n",
392 SK_PNMI_CNT_NO, SK_PNMI_MAX_IDX));
395 if (SK_PNMI_MAX_IDX !=
396 (sizeof(StatAddr) / (sizeof(SK_PNMI_STATADDR) * SK_PNMI_MAC_TYPES))) {
398 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR050, SK_PNMI_ERR050MSG);
400 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_INIT | SK_DBGCAT_FATAL,
401 ("StatAddr table size (%d) differs from "
402 "SK_PNMI_MAX_IDX (%d)\n",
403 (sizeof(StatAddr) /
404 (sizeof(SK_PNMI_STATADDR) * SK_PNMI_MAC_TYPES)),
405 SK_PNMI_MAX_IDX));
407 #endif /* SK_PNMI_CHECK */
408 break;
410 case SK_INIT_IO:
412 * Reset MAC counters
414 PortMax = pAC->GIni.GIMacsFound;
416 for (PortIndex = 0; PortIndex < PortMax; PortIndex ++) {
418 pAC->GIni.GIFunc.pFnMacResetCounter(pAC, IoC, PortIndex);
421 /* Initialize DSP variables for Vct() to 0xff => Never written! */
422 for (PortIndex = 0; PortIndex < PortMax; PortIndex ++) {
423 pAC->GIni.GP[PortIndex].PCableLen = 0xff;
424 pVctBackupData = &pAC->Pnmi.VctBackup[PortIndex];
425 pVctBackupData->PCableLen = 0xff;
429 * Get pci bus speed
431 SK_IN16(IoC, B0_CTST, &Val16);
432 if ((Val16 & CS_BUS_CLOCK) == 0) {
434 pAC->Pnmi.PciBusSpeed = 33;
436 else {
437 pAC->Pnmi.PciBusSpeed = 66;
441 * Get pci bus width
443 SK_IN16(IoC, B0_CTST, &Val16);
444 if ((Val16 & CS_BUS_SLOT_SZ) == 0) {
446 pAC->Pnmi.PciBusWidth = 32;
448 else {
449 pAC->Pnmi.PciBusWidth = 64;
453 * Get chipset
455 switch (pAC->GIni.GIChipId) {
456 case CHIP_ID_GENESIS:
457 pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_XMAC;
458 break;
460 case CHIP_ID_YUKON:
461 pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_YUKON;
462 break;
464 default:
465 break;
469 * Get PMD and DeviceType
471 SK_IN8(IoC, B2_PMD_TYP, &Val8);
472 switch (Val8) {
473 case 'S':
474 pAC->Pnmi.PMD = 3;
475 if (pAC->GIni.GIMacsFound > 1) {
477 pAC->Pnmi.DeviceType = 0x00020002;
479 else {
480 pAC->Pnmi.DeviceType = 0x00020001;
482 break;
484 case 'L':
485 pAC->Pnmi.PMD = 2;
486 if (pAC->GIni.GIMacsFound > 1) {
488 pAC->Pnmi.DeviceType = 0x00020004;
490 else {
491 pAC->Pnmi.DeviceType = 0x00020003;
493 break;
495 case 'C':
496 pAC->Pnmi.PMD = 4;
497 if (pAC->GIni.GIMacsFound > 1) {
499 pAC->Pnmi.DeviceType = 0x00020006;
501 else {
502 pAC->Pnmi.DeviceType = 0x00020005;
504 break;
506 case 'T':
507 pAC->Pnmi.PMD = 5;
508 if (pAC->GIni.GIMacsFound > 1) {
510 pAC->Pnmi.DeviceType = 0x00020008;
512 else {
513 pAC->Pnmi.DeviceType = 0x00020007;
515 break;
517 default :
518 pAC->Pnmi.PMD = 1;
519 pAC->Pnmi.DeviceType = 0;
520 break;
524 * Get connector
526 SK_IN8(IoC, B2_CONN_TYP, &Val8);
527 switch (Val8) {
528 case 'C':
529 pAC->Pnmi.Connector = 2;
530 break;
532 case 'D':
533 pAC->Pnmi.Connector = 3;
534 break;
536 case 'F':
537 pAC->Pnmi.Connector = 4;
538 break;
540 case 'J':
541 pAC->Pnmi.Connector = 5;
542 break;
544 case 'V':
545 pAC->Pnmi.Connector = 6;
546 break;
548 default:
549 pAC->Pnmi.Connector = 1;
550 break;
552 break;
554 case SK_INIT_RUN:
556 * Start timer for RLMT change counter
558 SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
559 SkTimerStart(pAC, IoC, &pAC->Pnmi.RlmtChangeEstimate.EstTimer,
560 28125000, SKGE_PNMI, SK_PNMI_EVT_CHG_EST_TIMER,
561 EventParam);
562 break;
564 default:
565 break; /* Nothing todo */
568 return (0);
571 /*****************************************************************************
573 * SkPnmiGetVar - Retrieves the value of a single OID
575 * Description:
576 * Calls a general sub-function for all this stuff. If the instance
577 * -1 is passed, the values of all instances are returned in an
578 * array of values.
580 * Returns:
581 * SK_PNMI_ERR_OK The request was successfully performed
582 * SK_PNMI_ERR_GENERAL A general severe internal error occured
583 * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to take
584 * the data.
585 * SK_PNMI_ERR_UNKNOWN_OID The requested OID is unknown
586 * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
587 * exist (e.g. port instance 3 on a two port
588 * adapter.
590 int SkPnmiGetVar(
591 SK_AC *pAC, /* Pointer to adapter context */
592 SK_IOC IoC, /* IO context handle */
593 SK_U32 Id, /* Object ID that is to be processed */
594 void *pBuf, /* Buffer to which the management data will be copied */
595 unsigned int *pLen, /* On call: buffer length. On return: used buffer */
596 SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
597 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
599 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
600 ("PNMI: SkPnmiGetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n",
601 Id, *pLen, Instance, NetIndex));
603 return (PnmiVar(pAC, IoC, SK_PNMI_GET, Id, (char *)pBuf, pLen,
604 Instance, NetIndex));
607 /*****************************************************************************
609 * SkPnmiPreSetVar - Presets the value of a single OID
611 * Description:
612 * Calls a general sub-function for all this stuff. The preset does
613 * the same as a set, but returns just before finally setting the
614 * new value. This is usefull to check if a set might be successfull.
615 * If the instance -1 is passed, an array of values is supposed and
616 * all instances of the OID will be set.
618 * Returns:
619 * SK_PNMI_ERR_OK The request was successfully performed.
620 * SK_PNMI_ERR_GENERAL A general severe internal error occured.
621 * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
622 * the correct data (e.g. a 32bit value is
623 * needed, but a 16 bit value was passed).
624 * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
625 * value range.
626 * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set.
627 * SK_PNMI_ERR_UNKNOWN_OID The requested OID is unknown.
628 * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
629 * exist (e.g. port instance 3 on a two port
630 * adapter.
632 int SkPnmiPreSetVar(
633 SK_AC *pAC, /* Pointer to adapter context */
634 SK_IOC IoC, /* IO context handle */
635 SK_U32 Id, /* Object ID that is to be processed */
636 void *pBuf, /* Buffer to which the management data will be copied */
637 unsigned int *pLen, /* Total length of management data */
638 SK_U32 Instance, /* Instance (1..n) that is to be set or -1 */
639 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
641 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
642 ("PNMI: SkPnmiPreSetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n",
643 Id, *pLen, Instance, NetIndex));
646 return (PnmiVar(pAC, IoC, SK_PNMI_PRESET, Id, (char *)pBuf, pLen,
647 Instance, NetIndex));
650 /*****************************************************************************
652 * SkPnmiSetVar - Sets the value of a single OID
654 * Description:
655 * Calls a general sub-function for all this stuff. The preset does
656 * the same as a set, but returns just before finally setting the
657 * new value. This is usefull to check if a set might be successfull.
658 * If the instance -1 is passed, an array of values is supposed and
659 * all instances of the OID will be set.
661 * Returns:
662 * SK_PNMI_ERR_OK The request was successfully performed.
663 * SK_PNMI_ERR_GENERAL A general severe internal error occured.
664 * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
665 * the correct data (e.g. a 32bit value is
666 * needed, but a 16 bit value was passed).
667 * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
668 * value range.
669 * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set.
670 * SK_PNMI_ERR_UNKNOWN_OID The requested OID is unknown.
671 * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
672 * exist (e.g. port instance 3 on a two port
673 * adapter.
675 int SkPnmiSetVar(
676 SK_AC *pAC, /* Pointer to adapter context */
677 SK_IOC IoC, /* IO context handle */
678 SK_U32 Id, /* Object ID that is to be processed */
679 void *pBuf, /* Buffer to which the management data will be copied */
680 unsigned int *pLen, /* Total length of management data */
681 SK_U32 Instance, /* Instance (1..n) that is to be set or -1 */
682 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
684 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
685 ("PNMI: SkPnmiSetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n",
686 Id, *pLen, Instance, NetIndex));
688 return (PnmiVar(pAC, IoC, SK_PNMI_SET, Id, (char *)pBuf, pLen,
689 Instance, NetIndex));
692 /*****************************************************************************
694 * SkPnmiGetStruct - Retrieves the management database in SK_PNMI_STRUCT_DATA
696 * Description:
697 * Runs through the IdTable, queries the single OIDs and stores the
698 * returned data into the management database structure
699 * SK_PNMI_STRUCT_DATA. The offset of the OID in the structure
700 * is stored in the IdTable. The return value of the function will also
701 * be stored in SK_PNMI_STRUCT_DATA if the passed buffer has the
702 * minimum size of SK_PNMI_MIN_STRUCT_SIZE.
704 * Returns:
705 * SK_PNMI_ERR_OK The request was successfully performed
706 * SK_PNMI_ERR_GENERAL A general severe internal error occured
707 * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to take
708 * the data.
709 * SK_PNMI_ERR_UNKNOWN_NET The requested NetIndex doesn't exist
711 int SkPnmiGetStruct(
712 SK_AC *pAC, /* Pointer to adapter context */
713 SK_IOC IoC, /* IO context handle */
714 void *pBuf, /* Buffer to which the management data will be copied. */
715 unsigned int *pLen, /* Length of buffer */
716 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
718 int Ret;
719 unsigned int TableIndex;
720 unsigned int DstOffset;
721 unsigned int InstanceNo;
722 unsigned int InstanceCnt;
723 SK_U32 Instance;
724 unsigned int TmpLen;
725 char KeyArr[SK_PNMI_VPD_ENTRIES][SK_PNMI_VPD_KEY_SIZE];
728 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
729 ("PNMI: SkPnmiGetStruct: Called, BufLen=%d, NetIndex=%d\n",
730 *pLen, NetIndex));
732 if (*pLen < SK_PNMI_STRUCT_SIZE) {
734 if (*pLen >= SK_PNMI_MIN_STRUCT_SIZE) {
736 SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_TOO_SHORT,
737 (SK_U32)(-1));
740 *pLen = SK_PNMI_STRUCT_SIZE;
741 return (SK_PNMI_ERR_TOO_SHORT);
745 * Check NetIndex
747 if (NetIndex >= pAC->Rlmt.NumNets) {
748 return (SK_PNMI_ERR_UNKNOWN_NET);
751 /* Update statistic */
752 SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On call");
754 if ((Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1)) !=
755 SK_PNMI_ERR_OK) {
757 SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
758 *pLen = SK_PNMI_MIN_STRUCT_SIZE;
759 return (Ret);
762 if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) {
764 SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
765 *pLen = SK_PNMI_MIN_STRUCT_SIZE;
766 return (Ret);
769 if ((Ret = SirqUpdate(pAC, IoC)) != SK_PNMI_ERR_OK) {
771 SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
772 *pLen = SK_PNMI_MIN_STRUCT_SIZE;
773 return (Ret);
777 * Increment semaphores to indicate that an update was
778 * already done
780 pAC->Pnmi.MacUpdatedFlag ++;
781 pAC->Pnmi.RlmtUpdatedFlag ++;
782 pAC->Pnmi.SirqUpdatedFlag ++;
784 /* Get vpd keys for instance calculation */
785 Ret = GetVpdKeyArr(pAC, IoC, &KeyArr[0][0], sizeof(KeyArr), &TmpLen);
786 if (Ret != SK_PNMI_ERR_OK) {
788 pAC->Pnmi.MacUpdatedFlag --;
789 pAC->Pnmi.RlmtUpdatedFlag --;
790 pAC->Pnmi.SirqUpdatedFlag --;
792 SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return");
793 SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
794 *pLen = SK_PNMI_MIN_STRUCT_SIZE;
795 return (SK_PNMI_ERR_GENERAL);
798 /* Retrieve values */
799 SK_MEMSET((char *)pBuf, 0, SK_PNMI_STRUCT_SIZE);
800 for (TableIndex = 0; TableIndex < ID_TABLE_SIZE; TableIndex ++) {
802 InstanceNo = IdTable[TableIndex].InstanceNo;
803 for (InstanceCnt = 1; InstanceCnt <= InstanceNo;
804 InstanceCnt ++) {
806 DstOffset = IdTable[TableIndex].Offset +
807 (InstanceCnt - 1) *
808 IdTable[TableIndex].StructSize;
811 * For the VPD the instance is not an index number
812 * but the key itself. Determin with the instance
813 * counter the VPD key to be used.
815 if (IdTable[TableIndex].Id == OID_SKGE_VPD_KEY ||
816 IdTable[TableIndex].Id == OID_SKGE_VPD_VALUE ||
817 IdTable[TableIndex].Id == OID_SKGE_VPD_ACCESS ||
818 IdTable[TableIndex].Id == OID_SKGE_VPD_ACTION) {
820 SK_STRNCPY((char *)&Instance, KeyArr[InstanceCnt - 1], 4);
822 else {
823 Instance = (SK_U32)InstanceCnt;
826 TmpLen = *pLen - DstOffset;
827 Ret = IdTable[TableIndex].Func(pAC, IoC, SK_PNMI_GET,
828 IdTable[TableIndex].Id, (char *)pBuf +
829 DstOffset, &TmpLen, Instance, TableIndex, NetIndex);
832 * An unknown instance error means that we reached
833 * the last instance of that variable. Proceed with
834 * the next OID in the table and ignore the return
835 * code.
837 if (Ret == SK_PNMI_ERR_UNKNOWN_INST) {
839 break;
842 if (Ret != SK_PNMI_ERR_OK) {
844 pAC->Pnmi.MacUpdatedFlag --;
845 pAC->Pnmi.RlmtUpdatedFlag --;
846 pAC->Pnmi.SirqUpdatedFlag --;
848 SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return");
849 SK_PNMI_SET_STAT(pBuf, Ret, DstOffset);
850 *pLen = SK_PNMI_MIN_STRUCT_SIZE;
851 return (Ret);
856 pAC->Pnmi.MacUpdatedFlag --;
857 pAC->Pnmi.RlmtUpdatedFlag --;
858 pAC->Pnmi.SirqUpdatedFlag --;
860 *pLen = SK_PNMI_STRUCT_SIZE;
861 SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return");
862 SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_OK, (SK_U32)(-1));
863 return (SK_PNMI_ERR_OK);
866 /*****************************************************************************
868 * SkPnmiPreSetStruct - Presets the management database in SK_PNMI_STRUCT_DATA
870 * Description:
871 * Calls a general sub-function for all this set stuff. The preset does
872 * the same as a set, but returns just before finally setting the
873 * new value. This is usefull to check if a set might be successfull.
874 * The sub-function runs through the IdTable, checks which OIDs are able
875 * to set, and calls the handler function of the OID to perform the
876 * preset. The return value of the function will also be stored in
877 * SK_PNMI_STRUCT_DATA if the passed buffer has the minimum size of
878 * SK_PNMI_MIN_STRUCT_SIZE.
880 * Returns:
881 * SK_PNMI_ERR_OK The request was successfully performed.
882 * SK_PNMI_ERR_GENERAL A general severe internal error occured.
883 * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
884 * the correct data (e.g. a 32bit value is
885 * needed, but a 16 bit value was passed).
886 * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
887 * value range.
889 int SkPnmiPreSetStruct(
890 SK_AC *pAC, /* Pointer to adapter context */
891 SK_IOC IoC, /* IO context handle */
892 void *pBuf, /* Buffer which contains the data to be set */
893 unsigned int *pLen, /* Length of buffer */
894 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
896 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
897 ("PNMI: SkPnmiPreSetStruct: Called, BufLen=%d, NetIndex=%d\n",
898 *pLen, NetIndex));
900 return (PnmiStruct(pAC, IoC, SK_PNMI_PRESET, (char *)pBuf,
901 pLen, NetIndex));
904 /*****************************************************************************
906 * SkPnmiSetStruct - Sets the management database in SK_PNMI_STRUCT_DATA
908 * Description:
909 * Calls a general sub-function for all this set stuff. The return value
910 * of the function will also be stored in SK_PNMI_STRUCT_DATA if the
911 * passed buffer has the minimum size of SK_PNMI_MIN_STRUCT_SIZE.
912 * The sub-function runs through the IdTable, checks which OIDs are able
913 * to set, and calls the handler function of the OID to perform the
914 * set. The return value of the function will also be stored in
915 * SK_PNMI_STRUCT_DATA if the passed buffer has the minimum size of
916 * SK_PNMI_MIN_STRUCT_SIZE.
918 * Returns:
919 * SK_PNMI_ERR_OK The request was successfully performed.
920 * SK_PNMI_ERR_GENERAL A general severe internal error occured.
921 * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
922 * the correct data (e.g. a 32bit value is
923 * needed, but a 16 bit value was passed).
924 * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
925 * value range.
927 int SkPnmiSetStruct(
928 SK_AC *pAC, /* Pointer to adapter context */
929 SK_IOC IoC, /* IO context handle */
930 void *pBuf, /* Buffer which contains the data to be set */
931 unsigned int *pLen, /* Length of buffer */
932 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
934 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
935 ("PNMI: SkPnmiSetStruct: Called, BufLen=%d, NetIndex=%d\n",
936 *pLen, NetIndex));
938 return (PnmiStruct(pAC, IoC, SK_PNMI_SET, (char *)pBuf,
939 pLen, NetIndex));
942 /*****************************************************************************
944 * SkPnmiEvent - Event handler
946 * Description:
947 * Handles the following events:
948 * SK_PNMI_EVT_SIRQ_OVERFLOW When a hardware counter overflows an
949 * interrupt will be generated which is
950 * first handled by SIRQ which generates a
951 * this event. The event increments the
952 * upper 32 bit of the 64 bit counter.
953 * SK_PNMI_EVT_SEN_XXX The event is generated by the I2C module
954 * when a sensor reports a warning or
955 * error. The event will store a trap
956 * message in the trap buffer.
957 * SK_PNMI_EVT_CHG_EST_TIMER The timer event was initiated by this
958 * module and is used to calculate the
959 * port switches per hour.
960 * SK_PNMI_EVT_CLEAR_COUNTER The event clears all counters and
961 * timestamps.
962 * SK_PNMI_EVT_XMAC_RESET The event is generated by the driver
963 * before a hard reset of the XMAC is
964 * performed. All counters will be saved
965 * and added to the hardware counter
966 * values after reset to grant continuous
967 * counter values.
968 * SK_PNMI_EVT_RLMT_PORT_UP Generated by RLMT to notify that a port
969 * went logically up. A trap message will
970 * be stored to the trap buffer.
971 * SK_PNMI_EVT_RLMT_PORT_DOWN Generated by RLMT to notify that a port
972 * went logically down. A trap message will
973 * be stored to the trap buffer.
974 * SK_PNMI_EVT_RLMT_SEGMENTATION Generated by RLMT to notify that two
975 * spanning tree root bridges were
976 * detected. A trap message will be stored
977 * to the trap buffer.
978 * SK_PNMI_EVT_RLMT_ACTIVE_DOWN Notifies PNMI that an active port went
979 * down. PNMI will not further add the
980 * statistic values to the virtual port.
981 * SK_PNMI_EVT_RLMT_ACTIVE_UP Notifies PNMI that a port went up and
982 * is now an active port. PNMI will now
983 * add the statistic data of this port to
984 * the virtual port.
985 * SK_PNMI_EVT_RLMT_SET_NETS Notifies PNMI about the net mode. The first parameter
986 * contains the number of nets. 1 means single net, 2 means
987 * dual net. The second parameter is -1
989 * Returns:
990 * Always 0
992 int SkPnmiEvent(
993 SK_AC *pAC, /* Pointer to adapter context */
994 SK_IOC IoC, /* IO context handle */
995 SK_U32 Event, /* Event-Id */
996 SK_EVPARA Param) /* Event dependent parameter */
998 unsigned int PhysPortIndex;
999 unsigned int MaxNetNumber;
1000 int CounterIndex;
1001 int Ret;
1002 SK_U16 MacStatus;
1003 SK_U64 OverflowStatus;
1004 SK_U64 Mask;
1005 int MacType;
1006 SK_U64 Value;
1007 SK_U32 Val32;
1008 SK_U16 Register;
1009 SK_EVPARA EventParam;
1010 SK_U64 NewestValue;
1011 SK_U64 OldestValue;
1012 SK_U64 Delta;
1013 SK_PNMI_ESTIMATE *pEst;
1014 SK_U32 NetIndex;
1015 SK_GEPORT *pPrt;
1016 SK_PNMI_VCT *pVctBackupData;
1017 SK_U32 RetCode;
1018 int i;
1019 SK_U32 CableLength;
1022 #ifdef DEBUG
1023 if (Event != SK_PNMI_EVT_XMAC_RESET) {
1025 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
1026 ("PNMI: SkPnmiEvent: Called, Event=0x%x, Param=0x%x\n",
1027 (unsigned int)Event, (unsigned int)Param.Para64));
1029 #endif /* DEBUG */
1030 SK_PNMI_CHECKFLAGS("SkPnmiEvent: On call");
1032 MacType = pAC->GIni.GIMacType;
1034 switch (Event) {
1036 case SK_PNMI_EVT_SIRQ_OVERFLOW:
1037 PhysPortIndex = (int)Param.Para32[0];
1038 MacStatus = (SK_U16)Param.Para32[1];
1039 #ifdef DEBUG
1040 if (PhysPortIndex >= SK_MAX_MACS) {
1042 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
1043 ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SIRQ_OVERFLOW parameter"
1044 " wrong, PhysPortIndex=0x%x\n",
1045 PhysPortIndex));
1046 return (0);
1048 #endif /* DEBUG */
1049 OverflowStatus = 0;
1052 * Check which source caused an overflow interrupt.
1054 if ((pAC->GIni.GIFunc.pFnMacOverflow(pAC, IoC, PhysPortIndex,
1055 MacStatus, &OverflowStatus) != 0) ||
1056 (OverflowStatus == 0)) {
1058 SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
1059 return (0);
1063 * Check the overflow status register and increment
1064 * the upper dword of corresponding counter.
1066 for (CounterIndex = 0; CounterIndex < sizeof(Mask) * 8;
1067 CounterIndex ++) {
1069 Mask = (SK_U64)1 << CounterIndex;
1070 if ((OverflowStatus & Mask) == 0) {
1072 continue;
1075 switch (StatOvrflwBit[CounterIndex][MacType]) {
1077 case SK_PNMI_HTX_UTILUNDER:
1078 case SK_PNMI_HTX_UTILOVER:
1079 if (MacType == SK_MAC_XMAC) {
1080 XM_IN16(IoC, PhysPortIndex, XM_TX_CMD, &Register);
1081 Register |= XM_TX_SAM_LINE;
1082 XM_OUT16(IoC, PhysPortIndex, XM_TX_CMD, Register);
1084 break;
1086 case SK_PNMI_HRX_UTILUNDER:
1087 case SK_PNMI_HRX_UTILOVER:
1088 if (MacType == SK_MAC_XMAC) {
1089 XM_IN16(IoC, PhysPortIndex, XM_RX_CMD, &Register);
1090 Register |= XM_RX_SAM_LINE;
1091 XM_OUT16(IoC, PhysPortIndex, XM_RX_CMD, Register);
1093 break;
1095 case SK_PNMI_HTX_OCTETHIGH:
1096 case SK_PNMI_HTX_OCTETLOW:
1097 case SK_PNMI_HTX_RESERVED:
1098 case SK_PNMI_HRX_OCTETHIGH:
1099 case SK_PNMI_HRX_OCTETLOW:
1100 case SK_PNMI_HRX_IRLENGTH:
1101 case SK_PNMI_HRX_RESERVED:
1104 * the following counters aren't be handled (id > 63)
1106 case SK_PNMI_HTX_SYNC:
1107 case SK_PNMI_HTX_SYNC_OCTET:
1108 break;
1110 case SK_PNMI_HRX_LONGFRAMES:
1111 if (MacType == SK_MAC_GMAC) {
1112 pAC->Pnmi.Port[PhysPortIndex].
1113 CounterHigh[CounterIndex] ++;
1115 break;
1117 default:
1118 pAC->Pnmi.Port[PhysPortIndex].
1119 CounterHigh[CounterIndex] ++;
1122 break;
1124 case SK_PNMI_EVT_SEN_WAR_LOW:
1125 #ifdef DEBUG
1126 if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) {
1128 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
1129 ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_WAR_LOW parameter wrong, SensorIndex=%d\n",
1130 (unsigned int)Param.Para64));
1131 return (0);
1133 #endif /* DEBUG */
1136 * Store a trap message in the trap buffer and generate
1137 * an event for user space applications with the
1138 * SK_DRIVER_SENDEVENT macro.
1140 QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_WAR_LOW,
1141 (unsigned int)Param.Para64);
1142 (void)SK_DRIVER_SENDEVENT(pAC, IoC);
1143 break;
1145 case SK_PNMI_EVT_SEN_WAR_UPP:
1146 #ifdef DEBUG
1147 if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) {
1149 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
1150 ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_WAR_UPP parameter wrong, SensorIndex=%d\n",
1151 (unsigned int)Param.Para64));
1152 return (0);
1154 #endif /* DEBUG */
1157 * Store a trap message in the trap buffer and generate
1158 * an event for user space applications with the
1159 * SK_DRIVER_SENDEVENT macro.
1161 QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_WAR_UPP,
1162 (unsigned int)Param.Para64);
1163 (void)SK_DRIVER_SENDEVENT(pAC, IoC);
1164 break;
1166 case SK_PNMI_EVT_SEN_ERR_LOW:
1167 #ifdef DEBUG
1168 if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) {
1170 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
1171 ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_ERR_LOW parameter wrong, SensorIndex=%d\n",
1172 (unsigned int)Param.Para64));
1173 return (0);
1175 #endif /* DEBUG */
1178 * Store a trap message in the trap buffer and generate
1179 * an event for user space applications with the
1180 * SK_DRIVER_SENDEVENT macro.
1182 QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_ERR_LOW,
1183 (unsigned int)Param.Para64);
1184 (void)SK_DRIVER_SENDEVENT(pAC, IoC);
1185 break;
1187 case SK_PNMI_EVT_SEN_ERR_UPP:
1188 #ifdef DEBUG
1189 if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) {
1191 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
1192 ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_ERR_UPP parameter wrong, SensorIndex=%d\n",
1193 (unsigned int)Param.Para64));
1194 return (0);
1196 #endif /* DEBUG */
1199 * Store a trap message in the trap buffer and generate
1200 * an event for user space applications with the
1201 * SK_DRIVER_SENDEVENT macro.
1203 QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_ERR_UPP,
1204 (unsigned int)Param.Para64);
1205 (void)SK_DRIVER_SENDEVENT(pAC, IoC);
1206 break;
1208 case SK_PNMI_EVT_CHG_EST_TIMER:
1210 * Calculate port switch average on a per hour basis
1211 * Time interval for check : 28125 ms
1212 * Number of values for average : 8
1214 * Be careful in changing these values, on change check
1215 * - typedef of SK_PNMI_ESTIMATE (Size of EstValue
1216 * array one less than value number)
1217 * - Timer initialization SkTimerStart() in SkPnmiInit
1218 * - Delta value below must be multiplicated with
1219 * power of 2
1222 pEst = &pAC->Pnmi.RlmtChangeEstimate;
1223 CounterIndex = pEst->EstValueIndex + 1;
1224 if (CounterIndex == 7) {
1226 CounterIndex = 0;
1228 pEst->EstValueIndex = CounterIndex;
1230 NewestValue = pAC->Pnmi.RlmtChangeCts;
1231 OldestValue = pEst->EstValue[CounterIndex];
1232 pEst->EstValue[CounterIndex] = NewestValue;
1235 * Calculate average. Delta stores the number of
1236 * port switches per 28125 * 8 = 225000 ms
1238 if (NewestValue >= OldestValue) {
1240 Delta = NewestValue - OldestValue;
1242 else {
1243 /* Overflow situation */
1244 Delta = (SK_U64)(0 - OldestValue) + NewestValue;
1248 * Extrapolate delta to port switches per hour.
1249 * Estimate = Delta * (3600000 / 225000)
1250 * = Delta * 16
1251 * = Delta << 4
1253 pAC->Pnmi.RlmtChangeEstimate.Estimate = Delta << 4;
1256 * Check if threshold is exceeded. If the threshold is
1257 * permanently exceeded every 28125 ms an event will be
1258 * generated to remind the user of this condition.
1260 if ((pAC->Pnmi.RlmtChangeThreshold != 0) &&
1261 (pAC->Pnmi.RlmtChangeEstimate.Estimate >=
1262 pAC->Pnmi.RlmtChangeThreshold)) {
1264 QueueSimpleTrap(pAC, OID_SKGE_TRAP_RLMT_CHANGE_THRES);
1265 (void)SK_DRIVER_SENDEVENT(pAC, IoC);
1268 SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
1269 SkTimerStart(pAC, IoC, &pAC->Pnmi.RlmtChangeEstimate.EstTimer,
1270 28125000, SKGE_PNMI, SK_PNMI_EVT_CHG_EST_TIMER,
1271 EventParam);
1272 break;
1274 case SK_PNMI_EVT_CLEAR_COUNTER:
1276 * Param.Para32[0] contains the NetIndex (0 ..1).
1277 * Param.Para32[1] is reserved, contains -1.
1279 NetIndex = (SK_U32)Param.Para32[0];
1281 #ifdef DEBUG
1282 if (NetIndex >= pAC->Rlmt.NumNets) {
1284 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
1285 ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_CLEAR_COUNTER parameter wrong, NetIndex=%d\n",
1286 NetIndex));
1288 return (0);
1290 #endif /* DEBUG */
1293 * Set all counters and timestamps to zero.
1294 * The according NetIndex is required as a
1295 * parameter of the event.
1297 ResetCounter(pAC, IoC, NetIndex);
1298 break;
1300 case SK_PNMI_EVT_XMAC_RESET:
1302 * To grant continuous counter values store the current
1303 * XMAC statistic values to the entries 1..n of the
1304 * CounterOffset array. XMAC Errata #2
1306 #ifdef DEBUG
1307 if ((unsigned int)Param.Para64 >= SK_MAX_MACS) {
1309 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
1310 ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_XMAC_RESET parameter wrong, PhysPortIndex=%d\n",
1311 (unsigned int)Param.Para64));
1312 return (0);
1314 #endif
1315 PhysPortIndex = (unsigned int)Param.Para64;
1318 * Update XMAC statistic to get fresh values
1320 Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1);
1321 if (Ret != SK_PNMI_ERR_OK) {
1323 SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
1324 return (0);
1327 * Increment semaphore to indicate that an update was
1328 * already done
1330 pAC->Pnmi.MacUpdatedFlag ++;
1332 for (CounterIndex = 0; CounterIndex < SK_PNMI_MAX_IDX;
1333 CounterIndex ++) {
1335 if (!StatAddr[CounterIndex][MacType].GetOffset) {
1337 continue;
1340 pAC->Pnmi.Port[PhysPortIndex].CounterOffset[CounterIndex] =
1341 GetPhysStatVal(pAC, IoC, PhysPortIndex, CounterIndex);
1343 pAC->Pnmi.Port[PhysPortIndex].CounterHigh[CounterIndex] = 0;
1346 pAC->Pnmi.MacUpdatedFlag --;
1347 break;
1349 case SK_PNMI_EVT_RLMT_PORT_UP:
1350 PhysPortIndex = (unsigned int)Param.Para32[0];
1351 #ifdef DEBUG
1352 if (PhysPortIndex >= SK_MAX_MACS) {
1354 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
1355 ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_PORT_UP parameter"
1356 " wrong, PhysPortIndex=%d\n", PhysPortIndex));
1358 return (0);
1360 #endif /* DEBUG */
1363 * Store a trap message in the trap buffer and generate an event for
1364 * user space applications with the SK_DRIVER_SENDEVENT macro.
1366 QueueRlmtPortTrap(pAC, OID_SKGE_TRAP_RLMT_PORT_UP, PhysPortIndex);
1367 (void)SK_DRIVER_SENDEVENT(pAC, IoC);
1369 /* Bugfix for XMAC errata (#10620)*/
1370 if (MacType == SK_MAC_XMAC) {
1371 /* Add incremental difference to offset (#10620)*/
1372 (void)pAC->GIni.GIFunc.pFnMacStatistic(pAC, IoC, PhysPortIndex,
1373 XM_RXE_SHT_ERR, &Val32);
1375 Value = (((SK_U64)pAC->Pnmi.Port[PhysPortIndex].
1376 CounterHigh[SK_PNMI_HRX_SHORTS] << 32) | (SK_U64)Val32);
1377 pAC->Pnmi.Port[PhysPortIndex].CounterOffset[SK_PNMI_HRX_SHORTS] +=
1378 Value - pAC->Pnmi.Port[PhysPortIndex].RxShortZeroMark;
1381 /* Tell VctStatus() that a link was up meanwhile. */
1382 pAC->Pnmi.VctStatus[PhysPortIndex] |= SK_PNMI_VCT_LINK;
1383 break;
1385 case SK_PNMI_EVT_RLMT_PORT_DOWN:
1386 PhysPortIndex = (unsigned int)Param.Para32[0];
1388 #ifdef DEBUG
1389 if (PhysPortIndex >= SK_MAX_MACS) {
1391 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
1392 ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_PORT_DOWN parameter"
1393 " wrong, PhysPortIndex=%d\n", PhysPortIndex));
1395 return (0);
1397 #endif /* DEBUG */
1400 * Store a trap message in the trap buffer and generate an event for
1401 * user space applications with the SK_DRIVER_SENDEVENT macro.
1403 QueueRlmtPortTrap(pAC, OID_SKGE_TRAP_RLMT_PORT_DOWN, PhysPortIndex);
1404 (void)SK_DRIVER_SENDEVENT(pAC, IoC);
1406 /* Bugfix #10620 - get zero level for incremental difference */
1407 if (MacType == SK_MAC_XMAC) {
1409 (void)pAC->GIni.GIFunc.pFnMacStatistic(pAC, IoC, PhysPortIndex,
1410 XM_RXE_SHT_ERR, &Val32);
1412 pAC->Pnmi.Port[PhysPortIndex].RxShortZeroMark =
1413 (((SK_U64)pAC->Pnmi.Port[PhysPortIndex].
1414 CounterHigh[SK_PNMI_HRX_SHORTS] << 32) | (SK_U64)Val32);
1416 break;
1418 case SK_PNMI_EVT_RLMT_ACTIVE_DOWN:
1419 PhysPortIndex = (unsigned int)Param.Para32[0];
1420 NetIndex = (SK_U32)Param.Para32[1];
1422 #ifdef DEBUG
1423 if (PhysPortIndex >= SK_MAX_MACS) {
1425 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
1426 ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_DOWN parameter too high, PhysPort=%d\n",
1427 PhysPortIndex));
1430 if (NetIndex >= pAC->Rlmt.NumNets) {
1432 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
1433 ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_DOWN parameter too high, NetIndex=%d\n",
1434 NetIndex));
1436 #endif /* DEBUG */
1439 * For now, ignore event if NetIndex != 0.
1441 if (Param.Para32[1] != 0) {
1443 return (0);
1447 * Nothing to do if port is already inactive
1449 if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
1451 return (0);
1455 * Update statistic counters to calculate new offset for the virtual
1456 * port and increment semaphore to indicate that an update was already
1457 * done.
1459 if (MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1) !=
1460 SK_PNMI_ERR_OK) {
1462 SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
1463 return (0);
1465 pAC->Pnmi.MacUpdatedFlag ++;
1468 * Calculate new counter offset for virtual port to grant continous
1469 * counting on port switches. The virtual port consists of all currently
1470 * active ports. The port down event indicates that a port is removed
1471 * from the virtual port. Therefore add the counter value of the removed
1472 * port to the CounterOffset for the virtual port to grant the same
1473 * counter value.
1475 for (CounterIndex = 0; CounterIndex < SK_PNMI_MAX_IDX;
1476 CounterIndex ++) {
1478 if (!StatAddr[CounterIndex][MacType].GetOffset) {
1480 continue;
1483 Value = GetPhysStatVal(pAC, IoC, PhysPortIndex, CounterIndex);
1485 pAC->Pnmi.VirtualCounterOffset[CounterIndex] += Value;
1489 * Set port to inactive
1491 pAC->Pnmi.Port[PhysPortIndex].ActiveFlag = SK_FALSE;
1493 pAC->Pnmi.MacUpdatedFlag --;
1494 break;
1496 case SK_PNMI_EVT_RLMT_ACTIVE_UP:
1497 PhysPortIndex = (unsigned int)Param.Para32[0];
1498 NetIndex = (SK_U32)Param.Para32[1];
1500 #ifdef DEBUG
1501 if (PhysPortIndex >= SK_MAX_MACS) {
1503 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
1504 ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_UP parameter too high, PhysPort=%d\n",
1505 PhysPortIndex));
1508 if (NetIndex >= pAC->Rlmt.NumNets) {
1510 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
1511 ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_UP parameter too high, NetIndex=%d\n",
1512 NetIndex));
1514 #endif /* DEBUG */
1517 * For now, ignore event if NetIndex != 0.
1519 if (Param.Para32[1] != 0) {
1521 return (0);
1525 * Nothing to do if port is already active
1527 if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
1529 return (0);
1533 * Statistic maintenance
1535 pAC->Pnmi.RlmtChangeCts ++;
1536 pAC->Pnmi.RlmtChangeTime = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC));
1539 * Store a trap message in the trap buffer and generate an event for
1540 * user space applications with the SK_DRIVER_SENDEVENT macro.
1542 QueueRlmtNewMacTrap(pAC, PhysPortIndex);
1543 (void)SK_DRIVER_SENDEVENT(pAC, IoC);
1546 * Update statistic counters to calculate new offset for the virtual
1547 * port and increment semaphore to indicate that an update was
1548 * already done.
1550 if (MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1) !=
1551 SK_PNMI_ERR_OK) {
1553 SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
1554 return (0);
1556 pAC->Pnmi.MacUpdatedFlag ++;
1559 * Calculate new counter offset for virtual port to grant continous
1560 * counting on port switches. A new port is added to the virtual port.
1561 * Therefore substract the counter value of the new port from the
1562 * CounterOffset for the virtual port to grant the same value.
1564 for (CounterIndex = 0; CounterIndex < SK_PNMI_MAX_IDX;
1565 CounterIndex ++) {
1567 if (!StatAddr[CounterIndex][MacType].GetOffset) {
1569 continue;
1572 Value = GetPhysStatVal(pAC, IoC, PhysPortIndex, CounterIndex);
1574 pAC->Pnmi.VirtualCounterOffset[CounterIndex] -= Value;
1577 /* Set port to active */
1578 pAC->Pnmi.Port[PhysPortIndex].ActiveFlag = SK_TRUE;
1580 pAC->Pnmi.MacUpdatedFlag --;
1581 break;
1583 case SK_PNMI_EVT_RLMT_SEGMENTATION:
1585 * Para.Para32[0] contains the NetIndex.
1589 * Store a trap message in the trap buffer and generate an event for
1590 * user space applications with the SK_DRIVER_SENDEVENT macro.
1592 QueueSimpleTrap(pAC, OID_SKGE_TRAP_RLMT_SEGMENTATION);
1593 (void)SK_DRIVER_SENDEVENT(pAC, IoC);
1594 break;
1596 case SK_PNMI_EVT_RLMT_SET_NETS:
1598 * Param.Para32[0] contains the number of Nets.
1599 * Param.Para32[1] is reserved, contains -1.
1602 * Check number of nets
1604 MaxNetNumber = pAC->GIni.GIMacsFound;
1605 if (((unsigned int)Param.Para32[0] < 1)
1606 || ((unsigned int)Param.Para32[0] > MaxNetNumber)) {
1607 return (SK_PNMI_ERR_UNKNOWN_NET);
1610 if ((unsigned int)Param.Para32[0] == 1) { /* single net mode */
1611 pAC->Pnmi.DualNetActiveFlag = SK_FALSE;
1613 else { /* dual net mode */
1614 pAC->Pnmi.DualNetActiveFlag = SK_TRUE;
1616 break;
1618 case SK_PNMI_EVT_VCT_RESET:
1619 PhysPortIndex = Param.Para32[0];
1620 pPrt = &pAC->GIni.GP[PhysPortIndex];
1621 pVctBackupData = &pAC->Pnmi.VctBackup[PhysPortIndex];
1623 if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING) {
1624 RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_FALSE);
1625 if (RetCode == 2) {
1627 * VCT test is still running.
1628 * Start VCT timer counter again.
1630 SK_MEMSET((char *) &Param, 0, sizeof(Param));
1631 Param.Para32[0] = PhysPortIndex;
1632 Param.Para32[1] = -1;
1633 SkTimerStart(pAC, IoC,
1634 &pAC->Pnmi.VctTimeout[PhysPortIndex].VctTimer,
1635 4000000, SKGE_PNMI, SK_PNMI_EVT_VCT_RESET, Param);
1636 break;
1638 pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_PENDING;
1639 pAC->Pnmi.VctStatus[PhysPortIndex] |=
1640 (SK_PNMI_VCT_NEW_VCT_DATA | SK_PNMI_VCT_TEST_DONE);
1642 /* Copy results for later use to PNMI struct. */
1643 for (i = 0; i < 4; i++) {
1644 if (pPrt->PMdiPairSts[i] == SK_PNMI_VCT_NORMAL_CABLE) {
1645 if ((pPrt->PMdiPairLen[i] > 35) &&
1646 (pPrt->PMdiPairLen[i] < 0xff)) {
1647 pPrt->PMdiPairSts[i] = SK_PNMI_VCT_IMPEDANCE_MISMATCH;
1650 if ((pPrt->PMdiPairLen[i] > 35) &&
1651 (pPrt->PMdiPairLen[i] != 0xff)) {
1652 CableLength = 1000 *
1653 (((175 * pPrt->PMdiPairLen[i]) / 210) - 28);
1655 else {
1656 CableLength = 0;
1658 pVctBackupData->PMdiPairLen[i] = CableLength;
1659 pVctBackupData->PMdiPairSts[i] = pPrt->PMdiPairSts[i];
1662 Param.Para32[0] = PhysPortIndex;
1663 Param.Para32[1] = -1;
1664 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Param);
1665 SkEventDispatcher(pAC, IoC);
1668 break;
1670 default:
1671 break;
1674 SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
1675 return (0);
1679 /******************************************************************************
1681 * Private functions
1685 /*****************************************************************************
1687 * PnmiVar - Gets, presets, and sets single OIDs
1689 * Description:
1690 * Looks up the requested OID, calls the corresponding handler
1691 * function, and passes the parameters with the get, preset, or
1692 * set command. The function is called by SkGePnmiGetVar,
1693 * SkGePnmiPreSetVar, or SkGePnmiSetVar.
1695 * Returns:
1696 * SK_PNMI_ERR_XXX. For details have a look at the description of the
1697 * calling functions.
1698 * SK_PNMI_ERR_UNKNOWN_NET The requested NetIndex doesn't exist
1700 PNMI_STATIC int PnmiVar(
1701 SK_AC *pAC, /* Pointer to adapter context */
1702 SK_IOC IoC, /* IO context handle */
1703 int Action, /* GET/PRESET/SET action */
1704 SK_U32 Id, /* Object ID that is to be processed */
1705 char *pBuf, /* Buffer used for the management data transfer */
1706 unsigned int *pLen, /* Total length of pBuf management data */
1707 SK_U32 Instance, /* Instance (1..n) that is to be set or -1 */
1708 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
1710 unsigned int TableIndex;
1711 int Ret;
1714 if ((TableIndex = LookupId(Id)) == (unsigned int)(-1)) {
1716 *pLen = 0;
1717 return (SK_PNMI_ERR_UNKNOWN_OID);
1720 /* Check NetIndex */
1721 if (NetIndex >= pAC->Rlmt.NumNets) {
1722 return (SK_PNMI_ERR_UNKNOWN_NET);
1725 SK_PNMI_CHECKFLAGS("PnmiVar: On call");
1727 Ret = IdTable[TableIndex].Func(pAC, IoC, Action, Id, pBuf, pLen,
1728 Instance, TableIndex, NetIndex);
1730 SK_PNMI_CHECKFLAGS("PnmiVar: On return");
1732 return (Ret);
1735 /*****************************************************************************
1737 * PnmiStruct - Presets and Sets data in structure SK_PNMI_STRUCT_DATA
1739 * Description:
1740 * The return value of the function will also be stored in
1741 * SK_PNMI_STRUCT_DATA if the passed buffer has the minimum size of
1742 * SK_PNMI_MIN_STRUCT_SIZE. The sub-function runs through the IdTable,
1743 * checks which OIDs are able to set, and calls the handler function of
1744 * the OID to perform the set. The return value of the function will
1745 * also be stored in SK_PNMI_STRUCT_DATA if the passed buffer has the
1746 * minimum size of SK_PNMI_MIN_STRUCT_SIZE. The function is called
1747 * by SkGePnmiPreSetStruct and SkGePnmiSetStruct.
1749 * Returns:
1750 * SK_PNMI_ERR_XXX. The codes are described in the calling functions.
1751 * SK_PNMI_ERR_UNKNOWN_NET The requested NetIndex doesn't exist
1753 PNMI_STATIC int PnmiStruct(
1754 SK_AC *pAC, /* Pointer to adapter context */
1755 SK_IOC IoC, /* IO context handle */
1756 int Action, /* PRESET/SET action to be performed */
1757 char *pBuf, /* Buffer used for the management data transfer */
1758 unsigned int *pLen, /* Length of pBuf management data buffer */
1759 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
1761 int Ret;
1762 unsigned int TableIndex;
1763 unsigned int DstOffset;
1764 unsigned int Len;
1765 unsigned int InstanceNo;
1766 unsigned int InstanceCnt;
1767 SK_U32 Instance;
1768 SK_U32 Id;
1771 /* Check if the passed buffer has the right size */
1772 if (*pLen < SK_PNMI_STRUCT_SIZE) {
1774 /* Check if we can return the error within the buffer */
1775 if (*pLen >= SK_PNMI_MIN_STRUCT_SIZE) {
1777 SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_TOO_SHORT,
1778 (SK_U32)(-1));
1781 *pLen = SK_PNMI_STRUCT_SIZE;
1782 return (SK_PNMI_ERR_TOO_SHORT);
1785 /* Check NetIndex */
1786 if (NetIndex >= pAC->Rlmt.NumNets) {
1787 return (SK_PNMI_ERR_UNKNOWN_NET);
1790 SK_PNMI_CHECKFLAGS("PnmiStruct: On call");
1793 * Update the values of RLMT and SIRQ and increment semaphores to
1794 * indicate that an update was already done.
1796 if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) {
1798 SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
1799 *pLen = SK_PNMI_MIN_STRUCT_SIZE;
1800 return (Ret);
1803 if ((Ret = SirqUpdate(pAC, IoC)) != SK_PNMI_ERR_OK) {
1805 SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
1806 *pLen = SK_PNMI_MIN_STRUCT_SIZE;
1807 return (Ret);
1810 pAC->Pnmi.RlmtUpdatedFlag ++;
1811 pAC->Pnmi.SirqUpdatedFlag ++;
1813 /* Preset/Set values */
1814 for (TableIndex = 0; TableIndex < ID_TABLE_SIZE; TableIndex ++) {
1816 if ((IdTable[TableIndex].Access != SK_PNMI_RW) &&
1817 (IdTable[TableIndex].Access != SK_PNMI_WO)) {
1819 continue;
1822 InstanceNo = IdTable[TableIndex].InstanceNo;
1823 Id = IdTable[TableIndex].Id;
1825 for (InstanceCnt = 1; InstanceCnt <= InstanceNo;
1826 InstanceCnt ++) {
1828 DstOffset = IdTable[TableIndex].Offset +
1829 (InstanceCnt - 1) *
1830 IdTable[TableIndex].StructSize;
1833 * Because VPD multiple instance variables are
1834 * not setable we do not need to evaluate VPD
1835 * instances. Have a look to VPD instance
1836 * calculation in SkPnmiGetStruct().
1838 Instance = (SK_U32)InstanceCnt;
1841 * Evaluate needed buffer length
1843 Len = 0;
1844 Ret = IdTable[TableIndex].Func(pAC, IoC,
1845 SK_PNMI_GET, IdTable[TableIndex].Id,
1846 NULL, &Len, Instance, TableIndex, NetIndex);
1848 if (Ret == SK_PNMI_ERR_UNKNOWN_INST) {
1850 break;
1852 if (Ret != SK_PNMI_ERR_TOO_SHORT) {
1854 pAC->Pnmi.RlmtUpdatedFlag --;
1855 pAC->Pnmi.SirqUpdatedFlag --;
1857 SK_PNMI_CHECKFLAGS("PnmiStruct: On return");
1858 SK_PNMI_SET_STAT(pBuf,
1859 SK_PNMI_ERR_GENERAL, DstOffset);
1860 *pLen = SK_PNMI_MIN_STRUCT_SIZE;
1861 return (SK_PNMI_ERR_GENERAL);
1863 if (Id == OID_SKGE_VPD_ACTION) {
1865 switch (*(pBuf + DstOffset)) {
1867 case SK_PNMI_VPD_CREATE:
1868 Len = 3 + *(pBuf + DstOffset + 3);
1869 break;
1871 case SK_PNMI_VPD_DELETE:
1872 Len = 3;
1873 break;
1875 default:
1876 Len = 1;
1877 break;
1881 /* Call the OID handler function */
1882 Ret = IdTable[TableIndex].Func(pAC, IoC, Action,
1883 IdTable[TableIndex].Id, pBuf + DstOffset,
1884 &Len, Instance, TableIndex, NetIndex);
1886 if (Ret != SK_PNMI_ERR_OK) {
1888 pAC->Pnmi.RlmtUpdatedFlag --;
1889 pAC->Pnmi.SirqUpdatedFlag --;
1891 SK_PNMI_CHECKFLAGS("PnmiStruct: On return");
1892 SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_BAD_VALUE,
1893 DstOffset);
1894 *pLen = SK_PNMI_MIN_STRUCT_SIZE;
1895 return (SK_PNMI_ERR_BAD_VALUE);
1900 pAC->Pnmi.RlmtUpdatedFlag --;
1901 pAC->Pnmi.SirqUpdatedFlag --;
1903 SK_PNMI_CHECKFLAGS("PnmiStruct: On return");
1904 SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_OK, (SK_U32)(-1));
1905 return (SK_PNMI_ERR_OK);
1908 /*****************************************************************************
1910 * LookupId - Lookup an OID in the IdTable
1912 * Description:
1913 * Scans the IdTable to find the table entry of an OID.
1915 * Returns:
1916 * The table index or -1 if not found.
1918 PNMI_STATIC int LookupId(
1919 SK_U32 Id) /* Object identifier to be searched */
1921 int i;
1923 for (i = 0; i < ID_TABLE_SIZE; i++) {
1925 if (IdTable[i].Id == Id) {
1927 return i;
1931 return (-1);
1934 /*****************************************************************************
1936 * OidStruct - Handler of OID_SKGE_ALL_DATA
1938 * Description:
1939 * This OID performs a Get/Preset/SetStruct call and returns all data
1940 * in a SK_PNMI_STRUCT_DATA structure.
1942 * Returns:
1943 * SK_PNMI_ERR_OK The request was successfully performed.
1944 * SK_PNMI_ERR_GENERAL A general severe internal error occured.
1945 * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
1946 * the correct data (e.g. a 32bit value is
1947 * needed, but a 16 bit value was passed).
1948 * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
1949 * value range.
1950 * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set.
1951 * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
1952 * exist (e.g. port instance 3 on a two port
1953 * adapter.
1955 PNMI_STATIC int OidStruct(
1956 SK_AC *pAC, /* Pointer to adapter context */
1957 SK_IOC IoC, /* IO context handle */
1958 int Action, /* GET/PRESET/SET action */
1959 SK_U32 Id, /* Object ID that is to be processed */
1960 char *pBuf, /* Buffer used for the management data transfer */
1961 unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
1962 SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
1963 unsigned int TableIndex, /* Index to the Id table */
1964 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
1966 if (Id != OID_SKGE_ALL_DATA) {
1968 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR003,
1969 SK_PNMI_ERR003MSG);
1971 *pLen = 0;
1972 return (SK_PNMI_ERR_GENERAL);
1976 * Check instance. We only handle single instance variables
1978 if (Instance != (SK_U32)(-1) && Instance != 1) {
1980 *pLen = 0;
1981 return (SK_PNMI_ERR_UNKNOWN_INST);
1984 switch (Action) {
1986 case SK_PNMI_GET:
1987 return (SkPnmiGetStruct(pAC, IoC, pBuf, pLen, NetIndex));
1989 case SK_PNMI_PRESET:
1990 return (SkPnmiPreSetStruct(pAC, IoC, pBuf, pLen, NetIndex));
1992 case SK_PNMI_SET:
1993 return (SkPnmiSetStruct(pAC, IoC, pBuf, pLen, NetIndex));
1996 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR004, SK_PNMI_ERR004MSG);
1998 *pLen = 0;
1999 return (SK_PNMI_ERR_GENERAL);
2002 /*****************************************************************************
2004 * Perform - OID handler of OID_SKGE_ACTION
2006 * Description:
2007 * None.
2009 * Returns:
2010 * SK_PNMI_ERR_OK The request was successfully performed.
2011 * SK_PNMI_ERR_GENERAL A general severe internal error occured.
2012 * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
2013 * the correct data (e.g. a 32bit value is
2014 * needed, but a 16 bit value was passed).
2015 * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
2016 * value range.
2017 * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set.
2018 * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
2019 * exist (e.g. port instance 3 on a two port
2020 * adapter.
2022 PNMI_STATIC int Perform(
2023 SK_AC *pAC, /* Pointer to adapter context */
2024 SK_IOC IoC, /* IO context handle */
2025 int Action, /* GET/PRESET/SET action */
2026 SK_U32 Id, /* Object ID that is to be processed */
2027 char *pBuf, /* Buffer used for the management data transfer */
2028 unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
2029 SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
2030 unsigned int TableIndex, /* Index to the Id table */
2031 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
2033 int Ret;
2034 SK_U32 ActionOp;
2038 * Check instance. We only handle single instance variables
2040 if (Instance != (SK_U32)(-1) && Instance != 1) {
2042 *pLen = 0;
2043 return (SK_PNMI_ERR_UNKNOWN_INST);
2046 if (*pLen < sizeof(SK_U32)) {
2048 *pLen = sizeof(SK_U32);
2049 return (SK_PNMI_ERR_TOO_SHORT);
2052 /* Check if a get should be performed */
2053 if (Action == SK_PNMI_GET) {
2055 /* A get is easy. We always return the same value */
2056 ActionOp = (SK_U32)SK_PNMI_ACT_IDLE;
2057 SK_PNMI_STORE_U32(pBuf, ActionOp);
2058 *pLen = sizeof(SK_U32);
2060 return (SK_PNMI_ERR_OK);
2063 /* Continue with PRESET/SET action */
2064 if (*pLen > sizeof(SK_U32)) {
2066 return (SK_PNMI_ERR_BAD_VALUE);
2069 /* Check if the command is a known one */
2070 SK_PNMI_READ_U32(pBuf, ActionOp);
2071 if (*pLen > sizeof(SK_U32) ||
2072 (ActionOp != SK_PNMI_ACT_IDLE &&
2073 ActionOp != SK_PNMI_ACT_RESET &&
2074 ActionOp != SK_PNMI_ACT_SELFTEST &&
2075 ActionOp != SK_PNMI_ACT_RESETCNT)) {
2077 *pLen = 0;
2078 return (SK_PNMI_ERR_BAD_VALUE);
2081 /* A preset ends here */
2082 if (Action == SK_PNMI_PRESET) {
2084 return (SK_PNMI_ERR_OK);
2087 switch (ActionOp) {
2089 case SK_PNMI_ACT_IDLE:
2090 /* Nothing to do */
2091 break;
2093 case SK_PNMI_ACT_RESET:
2095 * Perform a driver reset or something that comes near
2096 * to this.
2098 Ret = SK_DRIVER_RESET(pAC, IoC);
2099 if (Ret != 0) {
2101 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR005,
2102 SK_PNMI_ERR005MSG);
2104 return (SK_PNMI_ERR_GENERAL);
2106 break;
2108 case SK_PNMI_ACT_SELFTEST:
2110 * Perform a driver selftest or something similar to this.
2111 * Currently this feature is not used and will probably
2112 * implemented in another way.
2114 Ret = SK_DRIVER_SELFTEST(pAC, IoC);
2115 pAC->Pnmi.TestResult = Ret;
2116 break;
2118 case SK_PNMI_ACT_RESETCNT:
2119 /* Set all counters and timestamps to zero */
2120 ResetCounter(pAC, IoC, NetIndex);
2121 break;
2123 default:
2124 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR006,
2125 SK_PNMI_ERR006MSG);
2127 return (SK_PNMI_ERR_GENERAL);
2130 return (SK_PNMI_ERR_OK);
2133 /*****************************************************************************
2135 * Mac8023Stat - OID handler of OID_GEN_XXX and OID_802_3_XXX
2137 * Description:
2138 * Retrieves the statistic values of the virtual port (logical
2139 * index 0). Only special OIDs of NDIS are handled which consist
2140 * of a 32 bit instead of a 64 bit value. The OIDs are public
2141 * because perhaps some other platform can use them too.
2143 * Returns:
2144 * SK_PNMI_ERR_OK The request was successfully performed.
2145 * SK_PNMI_ERR_GENERAL A general severe internal error occured.
2146 * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
2147 * the correct data (e.g. a 32bit value is
2148 * needed, but a 16 bit value was passed).
2149 * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
2150 * exist (e.g. port instance 3 on a two port
2151 * adapter.
2153 PNMI_STATIC int Mac8023Stat(
2154 SK_AC *pAC, /* Pointer to adapter context */
2155 SK_IOC IoC, /* IO context handle */
2156 int Action, /* GET/PRESET/SET action */
2157 SK_U32 Id, /* Object ID that is to be processed */
2158 char *pBuf, /* Buffer used for the management data transfer */
2159 unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
2160 SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
2161 unsigned int TableIndex, /* Index to the Id table */
2162 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
2164 int Ret;
2165 SK_U64 StatVal;
2166 SK_U32 StatVal32;
2167 SK_BOOL Is64BitReq = SK_FALSE;
2170 * Only the active Mac is returned
2172 if (Instance != (SK_U32)(-1) && Instance != 1) {
2174 *pLen = 0;
2175 return (SK_PNMI_ERR_UNKNOWN_INST);
2179 * Check action type
2181 if (Action != SK_PNMI_GET) {
2183 *pLen = 0;
2184 return (SK_PNMI_ERR_READ_ONLY);
2187 /* Check length */
2188 switch (Id) {
2190 case OID_802_3_PERMANENT_ADDRESS:
2191 case OID_802_3_CURRENT_ADDRESS:
2192 if (*pLen < sizeof(SK_MAC_ADDR)) {
2194 *pLen = sizeof(SK_MAC_ADDR);
2195 return (SK_PNMI_ERR_TOO_SHORT);
2197 break;
2199 default:
2200 #ifndef SK_NDIS_64BIT_CTR
2201 if (*pLen < sizeof(SK_U32)) {
2202 *pLen = sizeof(SK_U32);
2203 return (SK_PNMI_ERR_TOO_SHORT);
2206 #else /* SK_NDIS_64BIT_CTR */
2208 /* for compatibility, at least 32bit are required for OID */
2209 if (*pLen < sizeof(SK_U32)) {
2211 * but indicate handling for 64bit values,
2212 * if insufficient space is provided
2214 *pLen = sizeof(SK_U64);
2215 return (SK_PNMI_ERR_TOO_SHORT);
2218 Is64BitReq = (*pLen < sizeof(SK_U64)) ? SK_FALSE : SK_TRUE;
2219 #endif /* SK_NDIS_64BIT_CTR */
2220 break;
2224 * Update all statistics, because we retrieve virtual MAC, which
2225 * consists of multiple physical statistics and increment semaphore
2226 * to indicate that an update was already done.
2228 Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1);
2229 if ( Ret != SK_PNMI_ERR_OK) {
2231 *pLen = 0;
2232 return (Ret);
2234 pAC->Pnmi.MacUpdatedFlag ++;
2237 * Get value (MAC Index 0 identifies the virtual MAC)
2239 switch (Id) {
2241 case OID_802_3_PERMANENT_ADDRESS:
2242 CopyMac(pBuf, &pAC->Addr.Net[NetIndex].PermanentMacAddress);
2243 *pLen = sizeof(SK_MAC_ADDR);
2244 break;
2246 case OID_802_3_CURRENT_ADDRESS:
2247 CopyMac(pBuf, &pAC->Addr.Net[NetIndex].CurrentMacAddress);
2248 *pLen = sizeof(SK_MAC_ADDR);
2249 break;
2251 default:
2252 StatVal = GetStatVal(pAC, IoC, 0, IdTable[TableIndex].Param, NetIndex);
2254 /* by default 32bit values are evaluated */
2255 if (!Is64BitReq) {
2256 StatVal32 = (SK_U32)StatVal;
2257 SK_PNMI_STORE_U32(pBuf, StatVal32);
2258 *pLen = sizeof(SK_U32);
2260 else {
2261 SK_PNMI_STORE_U64(pBuf, StatVal);
2262 *pLen = sizeof(SK_U64);
2264 break;
2267 pAC->Pnmi.MacUpdatedFlag --;
2269 return (SK_PNMI_ERR_OK);
2272 /*****************************************************************************
2274 * MacPrivateStat - OID handler function of OID_SKGE_STAT_XXX
2276 * Description:
2277 * Retrieves the MAC statistic data.
2279 * Returns:
2280 * SK_PNMI_ERR_OK The request was successfully performed.
2281 * SK_PNMI_ERR_GENERAL A general severe internal error occured.
2282 * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
2283 * the correct data (e.g. a 32bit value is
2284 * needed, but a 16 bit value was passed).
2285 * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
2286 * exist (e.g. port instance 3 on a two port
2287 * adapter.
2289 PNMI_STATIC int MacPrivateStat(
2290 SK_AC *pAC, /* Pointer to adapter context */
2291 SK_IOC IoC, /* IO context handle */
2292 int Action, /* GET/PRESET/SET action */
2293 SK_U32 Id, /* Object ID that is to be processed */
2294 char *pBuf, /* Buffer used for the management data transfer */
2295 unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
2296 SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
2297 unsigned int TableIndex, /* Index to the Id table */
2298 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
2300 unsigned int LogPortMax;
2301 unsigned int LogPortIndex;
2302 unsigned int PhysPortMax;
2303 unsigned int Limit;
2304 unsigned int Offset;
2305 int MacType;
2306 int Ret;
2307 SK_U64 StatVal;
2311 /* Calculate instance if wished. MAC index 0 is the virtual MAC */
2312 PhysPortMax = pAC->GIni.GIMacsFound;
2313 LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax);
2315 MacType = pAC->GIni.GIMacType;
2317 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */
2318 LogPortMax--;
2321 if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried */
2322 /* Check instance range */
2323 if ((Instance < 1) || (Instance > LogPortMax)) {
2325 *pLen = 0;
2326 return (SK_PNMI_ERR_UNKNOWN_INST);
2328 LogPortIndex = SK_PNMI_PORT_INST2LOG(Instance);
2329 Limit = LogPortIndex + 1;
2332 else { /* Instance == (SK_U32)(-1), get all Instances of that OID */
2334 LogPortIndex = 0;
2335 Limit = LogPortMax;
2338 /* Check action */
2339 if (Action != SK_PNMI_GET) {
2341 *pLen = 0;
2342 return (SK_PNMI_ERR_READ_ONLY);
2345 /* Check length */
2346 if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U64)) {
2348 *pLen = (Limit - LogPortIndex) * sizeof(SK_U64);
2349 return (SK_PNMI_ERR_TOO_SHORT);
2353 * Update MAC statistic and increment semaphore to indicate that
2354 * an update was already done.
2356 Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1);
2357 if (Ret != SK_PNMI_ERR_OK) {
2359 *pLen = 0;
2360 return (Ret);
2362 pAC->Pnmi.MacUpdatedFlag ++;
2364 /* Get value */
2365 Offset = 0;
2366 for (; LogPortIndex < Limit; LogPortIndex ++) {
2368 switch (Id) {
2370 /* XXX not yet implemented due to XMAC problems
2371 case OID_SKGE_STAT_TX_UTIL:
2372 return (SK_PNMI_ERR_GENERAL);
2374 /* XXX not yet implemented due to XMAC problems
2375 case OID_SKGE_STAT_RX_UTIL:
2376 return (SK_PNMI_ERR_GENERAL);
2378 case OID_SKGE_STAT_RX:
2379 if (MacType == SK_MAC_GMAC) {
2380 StatVal =
2381 GetStatVal(pAC, IoC, LogPortIndex,
2382 SK_PNMI_HRX_BROADCAST, NetIndex) +
2383 GetStatVal(pAC, IoC, LogPortIndex,
2384 SK_PNMI_HRX_MULTICAST, NetIndex) +
2385 GetStatVal(pAC, IoC, LogPortIndex,
2386 SK_PNMI_HRX_UNICAST, NetIndex) +
2387 GetStatVal(pAC, IoC, LogPortIndex,
2388 SK_PNMI_HRX_UNDERSIZE, NetIndex);
2390 else {
2391 StatVal = GetStatVal(pAC, IoC, LogPortIndex,
2392 IdTable[TableIndex].Param, NetIndex);
2394 break;
2396 case OID_SKGE_STAT_TX:
2397 if (MacType == SK_MAC_GMAC) {
2398 StatVal =
2399 GetStatVal(pAC, IoC, LogPortIndex,
2400 SK_PNMI_HTX_BROADCAST, NetIndex) +
2401 GetStatVal(pAC, IoC, LogPortIndex,
2402 SK_PNMI_HTX_MULTICAST, NetIndex) +
2403 GetStatVal(pAC, IoC, LogPortIndex,
2404 SK_PNMI_HTX_UNICAST, NetIndex);
2406 else {
2407 StatVal = GetStatVal(pAC, IoC, LogPortIndex,
2408 IdTable[TableIndex].Param, NetIndex);
2410 break;
2412 default:
2413 StatVal = GetStatVal(pAC, IoC, LogPortIndex,
2414 IdTable[TableIndex].Param, NetIndex);
2416 SK_PNMI_STORE_U64(pBuf + Offset, StatVal);
2418 Offset += sizeof(SK_U64);
2420 *pLen = Offset;
2422 pAC->Pnmi.MacUpdatedFlag --;
2424 return (SK_PNMI_ERR_OK);
2427 /*****************************************************************************
2429 * Addr - OID handler function of OID_SKGE_PHYS_CUR_ADDR and _FAC_ADDR
2431 * Description:
2432 * Get/Presets/Sets the current and factory MAC address. The MAC
2433 * address of the virtual port, which is reported to the OS, may
2434 * not be changed, but the physical ones. A set to the virtual port
2435 * will be ignored. No error should be reported because otherwise
2436 * a multiple instance set (-1) would always fail.
2438 * Returns:
2439 * SK_PNMI_ERR_OK The request was successfully performed.
2440 * SK_PNMI_ERR_GENERAL A general severe internal error occured.
2441 * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
2442 * the correct data (e.g. a 32bit value is
2443 * needed, but a 16 bit value was passed).
2444 * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
2445 * value range.
2446 * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set.
2447 * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
2448 * exist (e.g. port instance 3 on a two port
2449 * adapter.
2451 PNMI_STATIC int Addr(
2452 SK_AC *pAC, /* Pointer to adapter context */
2453 SK_IOC IoC, /* IO context handle */
2454 int Action, /* GET/PRESET/SET action */
2455 SK_U32 Id, /* Object ID that is to be processed */
2456 char *pBuf, /* Buffer used for the management data transfer */
2457 unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
2458 SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
2459 unsigned int TableIndex, /* Index to the Id table */
2460 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
2462 int Ret;
2463 unsigned int LogPortMax;
2464 unsigned int PhysPortMax;
2465 unsigned int LogPortIndex;
2466 unsigned int PhysPortIndex;
2467 unsigned int Limit;
2468 unsigned int Offset = 0;
2471 * Calculate instance if wished. MAC index 0 is the virtual
2472 * MAC.
2474 PhysPortMax = pAC->GIni.GIMacsFound;
2475 LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax);
2477 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */
2478 LogPortMax--;
2481 if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried */
2482 /* Check instance range */
2483 if ((Instance < 1) || (Instance > LogPortMax)) {
2485 *pLen = 0;
2486 return (SK_PNMI_ERR_UNKNOWN_INST);
2488 LogPortIndex = SK_PNMI_PORT_INST2LOG(Instance);
2489 Limit = LogPortIndex + 1;
2491 else { /* Instance == (SK_U32)(-1), get all Instances of that OID */
2493 LogPortIndex = 0;
2494 Limit = LogPortMax;
2498 * Perform Action
2500 if (Action == SK_PNMI_GET) {
2502 /* Check length */
2503 if (*pLen < (Limit - LogPortIndex) * 6) {
2505 *pLen = (Limit - LogPortIndex) * 6;
2506 return (SK_PNMI_ERR_TOO_SHORT);
2510 * Get value
2512 for (; LogPortIndex < Limit; LogPortIndex ++) {
2514 switch (Id) {
2516 case OID_SKGE_PHYS_CUR_ADDR:
2517 if (LogPortIndex == 0) {
2518 CopyMac(pBuf + Offset, &pAC->Addr.Net[NetIndex].CurrentMacAddress);
2520 else {
2521 PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex);
2523 CopyMac(pBuf + Offset,
2524 &pAC->Addr.Port[PhysPortIndex].CurrentMacAddress);
2526 Offset += 6;
2527 break;
2529 case OID_SKGE_PHYS_FAC_ADDR:
2530 if (LogPortIndex == 0) {
2531 CopyMac(pBuf + Offset,
2532 &pAC->Addr.Net[NetIndex].PermanentMacAddress);
2534 else {
2535 PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
2536 pAC, LogPortIndex);
2538 CopyMac(pBuf + Offset,
2539 &pAC->Addr.Port[PhysPortIndex].PermanentMacAddress);
2541 Offset += 6;
2542 break;
2544 default:
2545 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR008,
2546 SK_PNMI_ERR008MSG);
2548 *pLen = 0;
2549 return (SK_PNMI_ERR_GENERAL);
2553 *pLen = Offset;
2555 else {
2557 * The logical MAC address may not be changed only
2558 * the physical ones
2560 if (Id == OID_SKGE_PHYS_FAC_ADDR) {
2562 *pLen = 0;
2563 return (SK_PNMI_ERR_READ_ONLY);
2567 * Only the current address may be changed
2569 if (Id != OID_SKGE_PHYS_CUR_ADDR) {
2571 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR009,
2572 SK_PNMI_ERR009MSG);
2574 *pLen = 0;
2575 return (SK_PNMI_ERR_GENERAL);
2578 /* Check length */
2579 if (*pLen < (Limit - LogPortIndex) * 6) {
2581 *pLen = (Limit - LogPortIndex) * 6;
2582 return (SK_PNMI_ERR_TOO_SHORT);
2584 if (*pLen > (Limit - LogPortIndex) * 6) {
2586 *pLen = 0;
2587 return (SK_PNMI_ERR_BAD_VALUE);
2591 * Check Action
2593 if (Action == SK_PNMI_PRESET) {
2595 *pLen = 0;
2596 return (SK_PNMI_ERR_OK);
2600 * Set OID_SKGE_MAC_CUR_ADDR
2602 for (; LogPortIndex < Limit; LogPortIndex ++, Offset += 6) {
2605 * A set to virtual port and set of broadcast
2606 * address will be ignored
2608 if (LogPortIndex == 0 || SK_MEMCMP(pBuf + Offset,
2609 "\xff\xff\xff\xff\xff\xff", 6) == 0) {
2611 continue;
2614 PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC,
2615 LogPortIndex);
2617 Ret = SkAddrOverride(pAC, IoC, PhysPortIndex,
2618 (SK_MAC_ADDR *)(pBuf + Offset),
2619 (LogPortIndex == 0 ? SK_ADDR_VIRTUAL_ADDRESS :
2620 SK_ADDR_PHYSICAL_ADDRESS));
2621 if (Ret != SK_ADDR_OVERRIDE_SUCCESS) {
2623 return (SK_PNMI_ERR_GENERAL);
2626 *pLen = Offset;
2629 return (SK_PNMI_ERR_OK);
2632 /*****************************************************************************
2634 * CsumStat - OID handler function of OID_SKGE_CHKSM_XXX
2636 * Description:
2637 * Retrieves the statistic values of the CSUM module. The CSUM data
2638 * structure must be available in the SK_AC even if the CSUM module
2639 * is not included, because PNMI reads the statistic data from the
2640 * CSUM part of SK_AC directly.
2642 * Returns:
2643 * SK_PNMI_ERR_OK The request was successfully performed.
2644 * SK_PNMI_ERR_GENERAL A general severe internal error occured.
2645 * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
2646 * the correct data (e.g. a 32bit value is
2647 * needed, but a 16 bit value was passed).
2648 * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
2649 * exist (e.g. port instance 3 on a two port
2650 * adapter.
2652 PNMI_STATIC int CsumStat(
2653 SK_AC *pAC, /* Pointer to adapter context */
2654 SK_IOC IoC, /* IO context handle */
2655 int Action, /* GET/PRESET/SET action */
2656 SK_U32 Id, /* Object ID that is to be processed */
2657 char *pBuf, /* Buffer used for the management data transfer */
2658 unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
2659 SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
2660 unsigned int TableIndex, /* Index to the Id table */
2661 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
2663 unsigned int Index;
2664 unsigned int Limit;
2665 unsigned int Offset = 0;
2666 SK_U64 StatVal;
2670 * Calculate instance if wished
2672 if (Instance != (SK_U32)(-1)) {
2674 if ((Instance < 1) || (Instance > SKCS_NUM_PROTOCOLS)) {
2676 *pLen = 0;
2677 return (SK_PNMI_ERR_UNKNOWN_INST);
2679 Index = (unsigned int)Instance - 1;
2680 Limit = Index + 1;
2682 else {
2683 Index = 0;
2684 Limit = SKCS_NUM_PROTOCOLS;
2688 * Check action
2690 if (Action != SK_PNMI_GET) {
2692 *pLen = 0;
2693 return (SK_PNMI_ERR_READ_ONLY);
2696 /* Check length */
2697 if (*pLen < (Limit - Index) * sizeof(SK_U64)) {
2699 *pLen = (Limit - Index) * sizeof(SK_U64);
2700 return (SK_PNMI_ERR_TOO_SHORT);
2704 * Get value
2706 for (; Index < Limit; Index ++) {
2708 switch (Id) {
2710 case OID_SKGE_CHKSM_RX_OK_CTS:
2711 StatVal = pAC->Csum.ProtoStats[NetIndex][Index].RxOkCts;
2712 break;
2714 case OID_SKGE_CHKSM_RX_UNABLE_CTS:
2715 StatVal = pAC->Csum.ProtoStats[NetIndex][Index].RxUnableCts;
2716 break;
2718 case OID_SKGE_CHKSM_RX_ERR_CTS:
2719 StatVal = pAC->Csum.ProtoStats[NetIndex][Index].RxErrCts;
2720 break;
2722 case OID_SKGE_CHKSM_TX_OK_CTS:
2723 StatVal = pAC->Csum.ProtoStats[NetIndex][Index].TxOkCts;
2724 break;
2726 case OID_SKGE_CHKSM_TX_UNABLE_CTS:
2727 StatVal = pAC->Csum.ProtoStats[NetIndex][Index].TxUnableCts;
2728 break;
2730 default:
2731 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR010,
2732 SK_PNMI_ERR010MSG);
2734 *pLen = 0;
2735 return (SK_PNMI_ERR_GENERAL);
2738 SK_PNMI_STORE_U64(pBuf + Offset, StatVal);
2739 Offset += sizeof(SK_U64);
2743 * Store used buffer space
2745 *pLen = Offset;
2747 return (SK_PNMI_ERR_OK);
2750 /*****************************************************************************
2752 * SensorStat - OID handler function of OID_SKGE_SENSOR_XXX
2754 * Description:
2755 * Retrieves the statistic values of the I2C module, which handles
2756 * the temperature and voltage sensors.
2758 * Returns:
2759 * SK_PNMI_ERR_OK The request was successfully performed.
2760 * SK_PNMI_ERR_GENERAL A general severe internal error occured.
2761 * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
2762 * the correct data (e.g. a 32bit value is
2763 * needed, but a 16 bit value was passed).
2764 * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
2765 * exist (e.g. port instance 3 on a two port
2766 * adapter.
2768 PNMI_STATIC int SensorStat(
2769 SK_AC *pAC, /* Pointer to adapter context */
2770 SK_IOC IoC, /* IO context handle */
2771 int Action, /* GET/PRESET/SET action */
2772 SK_U32 Id, /* Object ID that is to be processed */
2773 char *pBuf, /* Buffer used for the management data transfer */
2774 unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
2775 SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
2776 unsigned int TableIndex, /* Index to the Id table */
2777 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
2779 unsigned int i;
2780 unsigned int Index;
2781 unsigned int Limit;
2782 unsigned int Offset;
2783 unsigned int Len;
2784 SK_U32 Val32;
2785 SK_U64 Val64;
2789 * Calculate instance if wished
2791 if ((Instance != (SK_U32)(-1))) {
2793 if ((Instance < 1) || (Instance > (SK_U32)pAC->I2c.MaxSens)) {
2795 *pLen = 0;
2796 return (SK_PNMI_ERR_UNKNOWN_INST);
2799 Index = (unsigned int)Instance -1;
2800 Limit = (unsigned int)Instance;
2802 else {
2803 Index = 0;
2804 Limit = (unsigned int) pAC->I2c.MaxSens;
2808 * Check action
2810 if (Action != SK_PNMI_GET) {
2812 *pLen = 0;
2813 return (SK_PNMI_ERR_READ_ONLY);
2816 /* Check length */
2817 switch (Id) {
2819 case OID_SKGE_SENSOR_VALUE:
2820 case OID_SKGE_SENSOR_WAR_THRES_LOW:
2821 case OID_SKGE_SENSOR_WAR_THRES_UPP:
2822 case OID_SKGE_SENSOR_ERR_THRES_LOW:
2823 case OID_SKGE_SENSOR_ERR_THRES_UPP:
2824 if (*pLen < (Limit - Index) * sizeof(SK_U32)) {
2826 *pLen = (Limit - Index) * sizeof(SK_U32);
2827 return (SK_PNMI_ERR_TOO_SHORT);
2829 break;
2831 case OID_SKGE_SENSOR_DESCR:
2832 for (Offset = 0, i = Index; i < Limit; i ++) {
2834 Len = (unsigned int)
2835 SK_STRLEN(pAC->I2c.SenTable[i].SenDesc) + 1;
2836 if (Len >= SK_PNMI_STRINGLEN2) {
2838 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR011,
2839 SK_PNMI_ERR011MSG);
2841 *pLen = 0;
2842 return (SK_PNMI_ERR_GENERAL);
2844 Offset += Len;
2846 if (*pLen < Offset) {
2848 *pLen = Offset;
2849 return (SK_PNMI_ERR_TOO_SHORT);
2851 break;
2853 case OID_SKGE_SENSOR_INDEX:
2854 case OID_SKGE_SENSOR_TYPE:
2855 case OID_SKGE_SENSOR_STATUS:
2856 if (*pLen < Limit - Index) {
2858 *pLen = Limit - Index;
2859 return (SK_PNMI_ERR_TOO_SHORT);
2861 break;
2863 case OID_SKGE_SENSOR_WAR_CTS:
2864 case OID_SKGE_SENSOR_WAR_TIME:
2865 case OID_SKGE_SENSOR_ERR_CTS:
2866 case OID_SKGE_SENSOR_ERR_TIME:
2867 if (*pLen < (Limit - Index) * sizeof(SK_U64)) {
2869 *pLen = (Limit - Index) * sizeof(SK_U64);
2870 return (SK_PNMI_ERR_TOO_SHORT);
2872 break;
2874 default:
2875 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR012,
2876 SK_PNMI_ERR012MSG);
2878 *pLen = 0;
2879 return (SK_PNMI_ERR_GENERAL);
2884 * Get value
2886 for (Offset = 0; Index < Limit; Index ++) {
2888 switch (Id) {
2890 case OID_SKGE_SENSOR_INDEX:
2891 *(pBuf + Offset) = (char)Index;
2892 Offset += sizeof(char);
2893 break;
2895 case OID_SKGE_SENSOR_DESCR:
2896 Len = SK_STRLEN(pAC->I2c.SenTable[Index].SenDesc);
2897 SK_MEMCPY(pBuf + Offset + 1,
2898 pAC->I2c.SenTable[Index].SenDesc, Len);
2899 *(pBuf + Offset) = (char)Len;
2900 Offset += Len + 1;
2901 break;
2903 case OID_SKGE_SENSOR_TYPE:
2904 *(pBuf + Offset) =
2905 (char)pAC->I2c.SenTable[Index].SenType;
2906 Offset += sizeof(char);
2907 break;
2909 case OID_SKGE_SENSOR_VALUE:
2910 Val32 = (SK_U32)pAC->I2c.SenTable[Index].SenValue;
2911 SK_PNMI_STORE_U32(pBuf + Offset, Val32);
2912 Offset += sizeof(SK_U32);
2913 break;
2915 case OID_SKGE_SENSOR_WAR_THRES_LOW:
2916 Val32 = (SK_U32)pAC->I2c.SenTable[Index].
2917 SenThreWarnLow;
2918 SK_PNMI_STORE_U32(pBuf + Offset, Val32);
2919 Offset += sizeof(SK_U32);
2920 break;
2922 case OID_SKGE_SENSOR_WAR_THRES_UPP:
2923 Val32 = (SK_U32)pAC->I2c.SenTable[Index].
2924 SenThreWarnHigh;
2925 SK_PNMI_STORE_U32(pBuf + Offset, Val32);
2926 Offset += sizeof(SK_U32);
2927 break;
2929 case OID_SKGE_SENSOR_ERR_THRES_LOW:
2930 Val32 = (SK_U32)pAC->I2c.SenTable[Index].
2931 SenThreErrLow;
2932 SK_PNMI_STORE_U32(pBuf + Offset, Val32);
2933 Offset += sizeof(SK_U32);
2934 break;
2936 case OID_SKGE_SENSOR_ERR_THRES_UPP:
2937 Val32 = pAC->I2c.SenTable[Index].SenThreErrHigh;
2938 SK_PNMI_STORE_U32(pBuf + Offset, Val32);
2939 Offset += sizeof(SK_U32);
2940 break;
2942 case OID_SKGE_SENSOR_STATUS:
2943 *(pBuf + Offset) =
2944 (char)pAC->I2c.SenTable[Index].SenErrFlag;
2945 Offset += sizeof(char);
2946 break;
2948 case OID_SKGE_SENSOR_WAR_CTS:
2949 Val64 = pAC->I2c.SenTable[Index].SenWarnCts;
2950 SK_PNMI_STORE_U64(pBuf + Offset, Val64);
2951 Offset += sizeof(SK_U64);
2952 break;
2954 case OID_SKGE_SENSOR_ERR_CTS:
2955 Val64 = pAC->I2c.SenTable[Index].SenErrCts;
2956 SK_PNMI_STORE_U64(pBuf + Offset, Val64);
2957 Offset += sizeof(SK_U64);
2958 break;
2960 case OID_SKGE_SENSOR_WAR_TIME:
2961 Val64 = SK_PNMI_HUNDREDS_SEC(pAC->I2c.SenTable[Index].
2962 SenBegWarnTS);
2963 SK_PNMI_STORE_U64(pBuf + Offset, Val64);
2964 Offset += sizeof(SK_U64);
2965 break;
2967 case OID_SKGE_SENSOR_ERR_TIME:
2968 Val64 = SK_PNMI_HUNDREDS_SEC(pAC->I2c.SenTable[Index].
2969 SenBegErrTS);
2970 SK_PNMI_STORE_U64(pBuf + Offset, Val64);
2971 Offset += sizeof(SK_U64);
2972 break;
2974 default:
2975 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR,
2976 ("SensorStat: Unknown OID should be handled before"));
2978 return (SK_PNMI_ERR_GENERAL);
2983 * Store used buffer space
2985 *pLen = Offset;
2987 return (SK_PNMI_ERR_OK);
2990 /*****************************************************************************
2992 * Vpd - OID handler function of OID_SKGE_VPD_XXX
2994 * Description:
2995 * Get/preset/set of VPD data. As instance the name of a VPD key
2996 * can be passed. The Instance parameter is a SK_U32 and can be
2997 * used as a string buffer for the VPD key, because their maximum
2998 * length is 4 byte.
3000 * Returns:
3001 * SK_PNMI_ERR_OK The request was successfully performed.
3002 * SK_PNMI_ERR_GENERAL A general severe internal error occured.
3003 * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
3004 * the correct data (e.g. a 32bit value is
3005 * needed, but a 16 bit value was passed).
3006 * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
3007 * value range.
3008 * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set.
3009 * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
3010 * exist (e.g. port instance 3 on a two port
3011 * adapter.
3013 PNMI_STATIC int Vpd(
3014 SK_AC *pAC, /* Pointer to adapter context */
3015 SK_IOC IoC, /* IO context handle */
3016 int Action, /* GET/PRESET/SET action */
3017 SK_U32 Id, /* Object ID that is to be processed */
3018 char *pBuf, /* Buffer used for the management data transfer */
3019 unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
3020 SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
3021 unsigned int TableIndex, /* Index to the Id table */
3022 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
3024 SK_VPD_STATUS *pVpdStatus;
3025 unsigned int BufLen;
3026 char Buf[256];
3027 char KeyArr[SK_PNMI_VPD_ENTRIES][SK_PNMI_VPD_KEY_SIZE];
3028 char KeyStr[SK_PNMI_VPD_KEY_SIZE];
3029 unsigned int KeyNo;
3030 unsigned int Offset;
3031 unsigned int Index;
3032 unsigned int FirstIndex;
3033 unsigned int LastIndex;
3034 unsigned int Len;
3035 int Ret;
3036 SK_U32 Val32;
3039 * Get array of all currently stored VPD keys
3041 Ret = GetVpdKeyArr(pAC, IoC, &KeyArr[0][0], sizeof(KeyArr), &KeyNo);
3042 if (Ret != SK_PNMI_ERR_OK) {
3043 *pLen = 0;
3044 return (Ret);
3048 * If instance is not -1, try to find the requested VPD key for
3049 * the multiple instance variables. The other OIDs as for example
3050 * OID VPD_ACTION are single instance variables and must be
3051 * handled separatly.
3053 FirstIndex = 0;
3054 LastIndex = KeyNo;
3056 if ((Instance != (SK_U32)(-1))) {
3058 if (Id == OID_SKGE_VPD_KEY || Id == OID_SKGE_VPD_VALUE ||
3059 Id == OID_SKGE_VPD_ACCESS) {
3061 SK_STRNCPY(KeyStr, (char *)&Instance, 4);
3062 KeyStr[4] = 0;
3064 for (Index = 0; Index < KeyNo; Index ++) {
3066 if (SK_STRCMP(KeyStr, KeyArr[Index]) == 0) {
3067 FirstIndex = Index;
3068 LastIndex = Index+1;
3069 break;
3072 if (Index == KeyNo) {
3074 *pLen = 0;
3075 return (SK_PNMI_ERR_UNKNOWN_INST);
3078 else if (Instance != 1) {
3080 *pLen = 0;
3081 return (SK_PNMI_ERR_UNKNOWN_INST);
3086 * Get value, if a query should be performed
3088 if (Action == SK_PNMI_GET) {
3090 switch (Id) {
3092 case OID_SKGE_VPD_FREE_BYTES:
3093 /* Check length of buffer */
3094 if (*pLen < sizeof(SK_U32)) {
3096 *pLen = sizeof(SK_U32);
3097 return (SK_PNMI_ERR_TOO_SHORT);
3099 /* Get number of free bytes */
3100 pVpdStatus = VpdStat(pAC, IoC);
3101 if (pVpdStatus == NULL) {
3103 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR017,
3104 SK_PNMI_ERR017MSG);
3106 *pLen = 0;
3107 return (SK_PNMI_ERR_GENERAL);
3109 if ((pVpdStatus->vpd_status & VPD_VALID) == 0) {
3111 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR018,
3112 SK_PNMI_ERR018MSG);
3114 *pLen = 0;
3115 return (SK_PNMI_ERR_GENERAL);
3118 Val32 = (SK_U32)pVpdStatus->vpd_free_rw;
3119 SK_PNMI_STORE_U32(pBuf, Val32);
3120 *pLen = sizeof(SK_U32);
3121 break;
3123 case OID_SKGE_VPD_ENTRIES_LIST:
3124 /* Check length */
3125 for (Len = 0, Index = 0; Index < KeyNo; Index ++) {
3127 Len += SK_STRLEN(KeyArr[Index]) + 1;
3129 if (*pLen < Len) {
3131 *pLen = Len;
3132 return (SK_PNMI_ERR_TOO_SHORT);
3135 /* Get value */
3136 *(pBuf) = (char)Len - 1;
3137 for (Offset = 1, Index = 0; Index < KeyNo; Index ++) {
3139 Len = SK_STRLEN(KeyArr[Index]);
3140 SK_MEMCPY(pBuf + Offset, KeyArr[Index], Len);
3142 Offset += Len;
3144 if (Index < KeyNo - 1) {
3146 *(pBuf + Offset) = ' ';
3147 Offset ++;
3150 *pLen = Offset;
3151 break;
3153 case OID_SKGE_VPD_ENTRIES_NUMBER:
3154 /* Check length */
3155 if (*pLen < sizeof(SK_U32)) {
3157 *pLen = sizeof(SK_U32);
3158 return (SK_PNMI_ERR_TOO_SHORT);
3161 Val32 = (SK_U32)KeyNo;
3162 SK_PNMI_STORE_U32(pBuf, Val32);
3163 *pLen = sizeof(SK_U32);
3164 break;
3166 case OID_SKGE_VPD_KEY:
3167 /* Check buffer length, if it is large enough */
3168 for (Len = 0, Index = FirstIndex;
3169 Index < LastIndex; Index ++) {
3171 Len += SK_STRLEN(KeyArr[Index]) + 1;
3173 if (*pLen < Len) {
3175 *pLen = Len;
3176 return (SK_PNMI_ERR_TOO_SHORT);
3180 * Get the key to an intermediate buffer, because
3181 * we have to prepend a length byte.
3183 for (Offset = 0, Index = FirstIndex;
3184 Index < LastIndex; Index ++) {
3186 Len = SK_STRLEN(KeyArr[Index]);
3188 *(pBuf + Offset) = (char)Len;
3189 SK_MEMCPY(pBuf + Offset + 1, KeyArr[Index],
3190 Len);
3191 Offset += Len + 1;
3193 *pLen = Offset;
3194 break;
3196 case OID_SKGE_VPD_VALUE:
3197 /* Check the buffer length if it is large enough */
3198 for (Offset = 0, Index = FirstIndex;
3199 Index < LastIndex; Index ++) {
3201 BufLen = 256;
3202 if (VpdRead(pAC, IoC, KeyArr[Index], Buf,
3203 (int *)&BufLen) > 0 ||
3204 BufLen >= SK_PNMI_VPD_DATALEN) {
3206 SK_ERR_LOG(pAC, SK_ERRCL_SW,
3207 SK_PNMI_ERR021,
3208 SK_PNMI_ERR021MSG);
3210 return (SK_PNMI_ERR_GENERAL);
3212 Offset += BufLen + 1;
3214 if (*pLen < Offset) {
3216 *pLen = Offset;
3217 return (SK_PNMI_ERR_TOO_SHORT);
3221 * Get the value to an intermediate buffer, because
3222 * we have to prepend a length byte.
3224 for (Offset = 0, Index = FirstIndex;
3225 Index < LastIndex; Index ++) {
3227 BufLen = 256;
3228 if (VpdRead(pAC, IoC, KeyArr[Index], Buf,
3229 (int *)&BufLen) > 0 ||
3230 BufLen >= SK_PNMI_VPD_DATALEN) {
3232 SK_ERR_LOG(pAC, SK_ERRCL_SW,
3233 SK_PNMI_ERR022,
3234 SK_PNMI_ERR022MSG);
3236 *pLen = 0;
3237 return (SK_PNMI_ERR_GENERAL);
3240 *(pBuf + Offset) = (char)BufLen;
3241 SK_MEMCPY(pBuf + Offset + 1, Buf, BufLen);
3242 Offset += BufLen + 1;
3244 *pLen = Offset;
3245 break;
3247 case OID_SKGE_VPD_ACCESS:
3248 if (*pLen < LastIndex - FirstIndex) {
3250 *pLen = LastIndex - FirstIndex;
3251 return (SK_PNMI_ERR_TOO_SHORT);
3254 for (Offset = 0, Index = FirstIndex;
3255 Index < LastIndex; Index ++) {
3257 if (VpdMayWrite(KeyArr[Index])) {
3259 *(pBuf + Offset) = SK_PNMI_VPD_RW;
3261 else {
3262 *(pBuf + Offset) = SK_PNMI_VPD_RO;
3264 Offset ++;
3266 *pLen = Offset;
3267 break;
3269 case OID_SKGE_VPD_ACTION:
3270 Offset = LastIndex - FirstIndex;
3271 if (*pLen < Offset) {
3273 *pLen = Offset;
3274 return (SK_PNMI_ERR_TOO_SHORT);
3276 SK_MEMSET(pBuf, 0, Offset);
3277 *pLen = Offset;
3278 break;
3280 default:
3281 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR023,
3282 SK_PNMI_ERR023MSG);
3284 *pLen = 0;
3285 return (SK_PNMI_ERR_GENERAL);
3288 else {
3289 /* The only OID which can be set is VPD_ACTION */
3290 if (Id != OID_SKGE_VPD_ACTION) {
3292 if (Id == OID_SKGE_VPD_FREE_BYTES ||
3293 Id == OID_SKGE_VPD_ENTRIES_LIST ||
3294 Id == OID_SKGE_VPD_ENTRIES_NUMBER ||
3295 Id == OID_SKGE_VPD_KEY ||
3296 Id == OID_SKGE_VPD_VALUE ||
3297 Id == OID_SKGE_VPD_ACCESS) {
3299 *pLen = 0;
3300 return (SK_PNMI_ERR_READ_ONLY);
3303 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR024,
3304 SK_PNMI_ERR024MSG);
3306 *pLen = 0;
3307 return (SK_PNMI_ERR_GENERAL);
3311 * From this point we handle VPD_ACTION. Check the buffer
3312 * length. It should at least have the size of one byte.
3314 if (*pLen < 1) {
3316 *pLen = 1;
3317 return (SK_PNMI_ERR_TOO_SHORT);
3321 * The first byte contains the VPD action type we should
3322 * perform.
3324 switch (*pBuf) {
3326 case SK_PNMI_VPD_IGNORE:
3327 /* Nothing to do */
3328 break;
3330 case SK_PNMI_VPD_CREATE:
3332 * We have to create a new VPD entry or we modify
3333 * an existing one. Check first the buffer length.
3335 if (*pLen < 4) {
3337 *pLen = 4;
3338 return (SK_PNMI_ERR_TOO_SHORT);
3340 KeyStr[0] = pBuf[1];
3341 KeyStr[1] = pBuf[2];
3342 KeyStr[2] = 0;
3345 * Is the entry writable or does it belong to the
3346 * read-only area?
3348 if (!VpdMayWrite(KeyStr)) {
3350 *pLen = 0;
3351 return (SK_PNMI_ERR_BAD_VALUE);
3354 Offset = (int)pBuf[3] & 0xFF;
3356 SK_MEMCPY(Buf, pBuf + 4, Offset);
3357 Buf[Offset] = 0;
3359 /* A preset ends here */
3360 if (Action == SK_PNMI_PRESET) {
3362 return (SK_PNMI_ERR_OK);
3365 /* Write the new entry or modify an existing one */
3366 Ret = VpdWrite(pAC, IoC, KeyStr, Buf);
3367 if (Ret == SK_PNMI_VPD_NOWRITE ) {
3369 *pLen = 0;
3370 return (SK_PNMI_ERR_BAD_VALUE);
3372 else if (Ret != SK_PNMI_VPD_OK) {
3374 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR025,
3375 SK_PNMI_ERR025MSG);
3377 *pLen = 0;
3378 return (SK_PNMI_ERR_GENERAL);
3382 * Perform an update of the VPD data. This is
3383 * not mandantory, but just to be sure.
3385 Ret = VpdUpdate(pAC, IoC);
3386 if (Ret != SK_PNMI_VPD_OK) {
3388 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR026,
3389 SK_PNMI_ERR026MSG);
3391 *pLen = 0;
3392 return (SK_PNMI_ERR_GENERAL);
3394 break;
3396 case SK_PNMI_VPD_DELETE:
3397 /* Check if the buffer size is plausible */
3398 if (*pLen < 3) {
3400 *pLen = 3;
3401 return (SK_PNMI_ERR_TOO_SHORT);
3403 if (*pLen > 3) {
3405 *pLen = 0;
3406 return (SK_PNMI_ERR_BAD_VALUE);
3408 KeyStr[0] = pBuf[1];
3409 KeyStr[1] = pBuf[2];
3410 KeyStr[2] = 0;
3412 /* Find the passed key in the array */
3413 for (Index = 0; Index < KeyNo; Index ++) {
3415 if (SK_STRCMP(KeyStr, KeyArr[Index]) == 0) {
3417 break;
3421 * If we cannot find the key it is wrong, so we
3422 * return an appropriate error value.
3424 if (Index == KeyNo) {
3426 *pLen = 0;
3427 return (SK_PNMI_ERR_BAD_VALUE);
3430 if (Action == SK_PNMI_PRESET) {
3432 return (SK_PNMI_ERR_OK);
3435 /* Ok, you wanted it and you will get it */
3436 Ret = VpdDelete(pAC, IoC, KeyStr);
3437 if (Ret != SK_PNMI_VPD_OK) {
3439 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR027,
3440 SK_PNMI_ERR027MSG);
3442 *pLen = 0;
3443 return (SK_PNMI_ERR_GENERAL);
3447 * Perform an update of the VPD data. This is
3448 * not mandantory, but just to be sure.
3450 Ret = VpdUpdate(pAC, IoC);
3451 if (Ret != SK_PNMI_VPD_OK) {
3453 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR028,
3454 SK_PNMI_ERR028MSG);
3456 *pLen = 0;
3457 return (SK_PNMI_ERR_GENERAL);
3459 break;
3461 default:
3462 *pLen = 0;
3463 return (SK_PNMI_ERR_BAD_VALUE);
3467 return (SK_PNMI_ERR_OK);
3470 /*****************************************************************************
3472 * General - OID handler function of various single instance OIDs
3474 * Description:
3475 * The code is simple. No description necessary.
3477 * Returns:
3478 * SK_PNMI_ERR_OK The request was successfully performed.
3479 * SK_PNMI_ERR_GENERAL A general severe internal error occured.
3480 * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
3481 * the correct data (e.g. a 32bit value is
3482 * needed, but a 16 bit value was passed).
3483 * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
3484 * exist (e.g. port instance 3 on a two port
3485 * adapter.
3487 PNMI_STATIC int General(
3488 SK_AC *pAC, /* Pointer to adapter context */
3489 SK_IOC IoC, /* IO context handle */
3490 int Action, /* GET/PRESET/SET action */
3491 SK_U32 Id, /* Object ID that is to be processed */
3492 char *pBuf, /* Buffer used for the management data transfer */
3493 unsigned int *pLen, /* On call: buffer length. On return: used buffer */
3494 SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
3495 unsigned int TableIndex, /* Index to the Id table */
3496 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
3498 int Ret;
3499 unsigned int Index;
3500 unsigned int Len;
3501 unsigned int Offset;
3502 unsigned int Val;
3503 SK_U8 Val8;
3504 SK_U16 Val16;
3505 SK_U32 Val32;
3506 SK_U64 Val64;
3507 SK_U64 Val64RxHwErrs = 0;
3508 SK_U64 Val64TxHwErrs = 0;
3509 SK_BOOL Is64BitReq = SK_FALSE;
3510 char Buf[256];
3511 int MacType;
3514 * Check instance. We only handle single instance variables.
3516 if (Instance != (SK_U32)(-1) && Instance != 1) {
3518 *pLen = 0;
3519 return (SK_PNMI_ERR_UNKNOWN_INST);
3523 * Check action. We only allow get requests.
3525 if (Action != SK_PNMI_GET) {
3527 *pLen = 0;
3528 return (SK_PNMI_ERR_READ_ONLY);
3531 MacType = pAC->GIni.GIMacType;
3534 * Check length for the various supported OIDs
3536 switch (Id) {
3538 case OID_GEN_XMIT_ERROR:
3539 case OID_GEN_RCV_ERROR:
3540 case OID_GEN_RCV_NO_BUFFER:
3541 #ifndef SK_NDIS_64BIT_CTR
3542 if (*pLen < sizeof(SK_U32)) {
3543 *pLen = sizeof(SK_U32);
3544 return (SK_PNMI_ERR_TOO_SHORT);
3547 #else /* SK_NDIS_64BIT_CTR */
3550 * for compatibility, at least 32bit are required for oid
3552 if (*pLen < sizeof(SK_U32)) {
3554 * but indicate handling for 64bit values,
3555 * if insufficient space is provided
3557 *pLen = sizeof(SK_U64);
3558 return (SK_PNMI_ERR_TOO_SHORT);
3561 Is64BitReq = (*pLen < sizeof(SK_U64)) ? SK_FALSE : SK_TRUE;
3562 #endif /* SK_NDIS_64BIT_CTR */
3563 break;
3565 case OID_SKGE_PORT_NUMBER:
3566 case OID_SKGE_DEVICE_TYPE:
3567 case OID_SKGE_RESULT:
3568 case OID_SKGE_RLMT_MONITOR_NUMBER:
3569 case OID_GEN_TRANSMIT_QUEUE_LENGTH:
3570 case OID_SKGE_TRAP_NUMBER:
3571 case OID_SKGE_MDB_VERSION:
3572 case OID_SKGE_BOARDLEVEL:
3573 case OID_SKGE_CHIPID:
3574 case OID_SKGE_RAMSIZE:
3575 if (*pLen < sizeof(SK_U32)) {
3577 *pLen = sizeof(SK_U32);
3578 return (SK_PNMI_ERR_TOO_SHORT);
3580 break;
3582 case OID_SKGE_CHIPSET:
3583 if (*pLen < sizeof(SK_U16)) {
3585 *pLen = sizeof(SK_U16);
3586 return (SK_PNMI_ERR_TOO_SHORT);
3588 break;
3590 case OID_SKGE_BUS_TYPE:
3591 case OID_SKGE_BUS_SPEED:
3592 case OID_SKGE_BUS_WIDTH:
3593 case OID_SKGE_SENSOR_NUMBER:
3594 case OID_SKGE_CHKSM_NUMBER:
3595 case OID_SKGE_VAUXAVAIL:
3596 if (*pLen < sizeof(SK_U8)) {
3598 *pLen = sizeof(SK_U8);
3599 return (SK_PNMI_ERR_TOO_SHORT);
3601 break;
3603 case OID_SKGE_TX_SW_QUEUE_LEN:
3604 case OID_SKGE_TX_SW_QUEUE_MAX:
3605 case OID_SKGE_TX_RETRY:
3606 case OID_SKGE_RX_INTR_CTS:
3607 case OID_SKGE_TX_INTR_CTS:
3608 case OID_SKGE_RX_NO_BUF_CTS:
3609 case OID_SKGE_TX_NO_BUF_CTS:
3610 case OID_SKGE_TX_USED_DESCR_NO:
3611 case OID_SKGE_RX_DELIVERED_CTS:
3612 case OID_SKGE_RX_OCTETS_DELIV_CTS:
3613 case OID_SKGE_RX_HW_ERROR_CTS:
3614 case OID_SKGE_TX_HW_ERROR_CTS:
3615 case OID_SKGE_IN_ERRORS_CTS:
3616 case OID_SKGE_OUT_ERROR_CTS:
3617 case OID_SKGE_ERR_RECOVERY_CTS:
3618 case OID_SKGE_SYSUPTIME:
3619 if (*pLen < sizeof(SK_U64)) {
3621 *pLen = sizeof(SK_U64);
3622 return (SK_PNMI_ERR_TOO_SHORT);
3624 break;
3626 default:
3627 /* Checked later */
3628 break;
3631 /* Update statistic */
3632 if (Id == OID_SKGE_RX_HW_ERROR_CTS ||
3633 Id == OID_SKGE_TX_HW_ERROR_CTS ||
3634 Id == OID_SKGE_IN_ERRORS_CTS ||
3635 Id == OID_SKGE_OUT_ERROR_CTS ||
3636 Id == OID_GEN_XMIT_ERROR ||
3637 Id == OID_GEN_RCV_ERROR) {
3639 /* Force the XMAC to update its statistic counters and
3640 * Increment semaphore to indicate that an update was
3641 * already done.
3643 Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1);
3644 if (Ret != SK_PNMI_ERR_OK) {
3646 *pLen = 0;
3647 return (Ret);
3649 pAC->Pnmi.MacUpdatedFlag ++;
3652 * Some OIDs consist of multiple hardware counters. Those
3653 * values which are contained in all of them will be added
3654 * now.
3656 switch (Id) {
3658 case OID_SKGE_RX_HW_ERROR_CTS:
3659 case OID_SKGE_IN_ERRORS_CTS:
3660 case OID_GEN_RCV_ERROR:
3661 Val64RxHwErrs =
3662 GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_MISSED, NetIndex) +
3663 GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_FRAMING, NetIndex) +
3664 GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_OVERFLOW, NetIndex) +
3665 GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_JABBER, NetIndex) +
3666 GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_CARRIER, NetIndex) +
3667 GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_IRLENGTH, NetIndex) +
3668 GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_SYMBOL, NetIndex) +
3669 GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_SHORTS, NetIndex) +
3670 GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_RUNT, NetIndex) +
3671 GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_TOO_LONG, NetIndex) +
3672 GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_FCS, NetIndex) +
3673 GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_CEXT, NetIndex);
3674 break;
3676 case OID_SKGE_TX_HW_ERROR_CTS:
3677 case OID_SKGE_OUT_ERROR_CTS:
3678 case OID_GEN_XMIT_ERROR:
3679 Val64TxHwErrs =
3680 GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_EXCESS_COL, NetIndex) +
3681 GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_LATE_COL, NetIndex) +
3682 GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_UNDERRUN, NetIndex) +
3683 GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_CARRIER, NetIndex);
3684 break;
3689 * Retrieve value
3691 switch (Id) {
3693 case OID_SKGE_SUPPORTED_LIST:
3694 Len = ID_TABLE_SIZE * sizeof(SK_U32);
3695 if (*pLen < Len) {
3697 *pLen = Len;
3698 return (SK_PNMI_ERR_TOO_SHORT);
3700 for (Offset = 0, Index = 0; Offset < Len;
3701 Offset += sizeof(SK_U32), Index ++) {
3703 Val32 = (SK_U32)IdTable[Index].Id;
3704 SK_PNMI_STORE_U32(pBuf + Offset, Val32);
3706 *pLen = Len;
3707 break;
3709 case OID_SKGE_BOARDLEVEL:
3710 Val32 = (SK_U32)pAC->GIni.GILevel;
3711 SK_PNMI_STORE_U32(pBuf, Val32);
3712 *pLen = sizeof(SK_U32);
3713 break;
3715 case OID_SKGE_PORT_NUMBER:
3716 Val32 = (SK_U32)pAC->GIni.GIMacsFound;
3717 SK_PNMI_STORE_U32(pBuf, Val32);
3718 *pLen = sizeof(SK_U32);
3719 break;
3721 case OID_SKGE_DEVICE_TYPE:
3722 Val32 = (SK_U32)pAC->Pnmi.DeviceType;
3723 SK_PNMI_STORE_U32(pBuf, Val32);
3724 *pLen = sizeof(SK_U32);
3725 break;
3727 case OID_SKGE_DRIVER_DESCR:
3728 if (pAC->Pnmi.pDriverDescription == NULL) {
3730 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR007,
3731 SK_PNMI_ERR007MSG);
3733 *pLen = 0;
3734 return (SK_PNMI_ERR_GENERAL);
3737 Len = SK_STRLEN(pAC->Pnmi.pDriverDescription) + 1;
3738 if (Len > SK_PNMI_STRINGLEN1) {
3740 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR029,
3741 SK_PNMI_ERR029MSG);
3743 *pLen = 0;
3744 return (SK_PNMI_ERR_GENERAL);
3747 if (*pLen < Len) {
3749 *pLen = Len;
3750 return (SK_PNMI_ERR_TOO_SHORT);
3752 *pBuf = (char)(Len - 1);
3753 SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverDescription, Len - 1);
3754 *pLen = Len;
3755 break;
3757 case OID_SKGE_DRIVER_VERSION:
3758 if (pAC->Pnmi.pDriverVersion == NULL) {
3760 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR030,
3761 SK_PNMI_ERR030MSG);
3763 *pLen = 0;
3764 return (SK_PNMI_ERR_GENERAL);
3767 Len = SK_STRLEN(pAC->Pnmi.pDriverVersion) + 1;
3768 if (Len > SK_PNMI_STRINGLEN1) {
3770 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR031,
3771 SK_PNMI_ERR031MSG);
3773 *pLen = 0;
3774 return (SK_PNMI_ERR_GENERAL);
3777 if (*pLen < Len) {
3779 *pLen = Len;
3780 return (SK_PNMI_ERR_TOO_SHORT);
3782 *pBuf = (char)(Len - 1);
3783 SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverVersion, Len - 1);
3784 *pLen = Len;
3785 break;
3787 case OID_SKGE_DRIVER_RELDATE:
3788 if (pAC->Pnmi.pDriverReleaseDate == NULL) {
3790 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR030,
3791 SK_PNMI_ERR053MSG);
3793 *pLen = 0;
3794 return (SK_PNMI_ERR_GENERAL);
3797 Len = SK_STRLEN(pAC->Pnmi.pDriverReleaseDate) + 1;
3798 if (Len > SK_PNMI_STRINGLEN1) {
3800 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR031,
3801 SK_PNMI_ERR054MSG);
3803 *pLen = 0;
3804 return (SK_PNMI_ERR_GENERAL);
3807 if (*pLen < Len) {
3809 *pLen = Len;
3810 return (SK_PNMI_ERR_TOO_SHORT);
3812 *pBuf = (char)(Len - 1);
3813 SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverReleaseDate, Len - 1);
3814 *pLen = Len;
3815 break;
3817 case OID_SKGE_DRIVER_FILENAME:
3818 if (pAC->Pnmi.pDriverFileName == NULL) {
3820 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR030,
3821 SK_PNMI_ERR055MSG);
3823 *pLen = 0;
3824 return (SK_PNMI_ERR_GENERAL);
3827 Len = SK_STRLEN(pAC->Pnmi.pDriverFileName) + 1;
3828 if (Len > SK_PNMI_STRINGLEN1) {
3830 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR031,
3831 SK_PNMI_ERR056MSG);
3833 *pLen = 0;
3834 return (SK_PNMI_ERR_GENERAL);
3837 if (*pLen < Len) {
3839 *pLen = Len;
3840 return (SK_PNMI_ERR_TOO_SHORT);
3842 *pBuf = (char)(Len - 1);
3843 SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverFileName, Len - 1);
3844 *pLen = Len;
3845 break;
3847 case OID_SKGE_HW_DESCR:
3849 * The hardware description is located in the VPD. This
3850 * query may move to the initialisation routine. But
3851 * the VPD data is cached and therefore a call here
3852 * will not make much difference.
3854 Len = 256;
3855 if (VpdRead(pAC, IoC, VPD_NAME, Buf, (int *)&Len) > 0) {
3857 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR032,
3858 SK_PNMI_ERR032MSG);
3860 *pLen = 0;
3861 return (SK_PNMI_ERR_GENERAL);
3863 Len ++;
3864 if (Len > SK_PNMI_STRINGLEN1) {
3866 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR033,
3867 SK_PNMI_ERR033MSG);
3869 *pLen = 0;
3870 return (SK_PNMI_ERR_GENERAL);
3872 if (*pLen < Len) {
3874 *pLen = Len;
3875 return (SK_PNMI_ERR_TOO_SHORT);
3877 *pBuf = (char)(Len - 1);
3878 SK_MEMCPY(pBuf + 1, Buf, Len - 1);
3879 *pLen = Len;
3880 break;
3882 case OID_SKGE_HW_VERSION:
3883 /* Oh, I love to do some string manipulation */
3884 if (*pLen < 5) {
3886 *pLen = 5;
3887 return (SK_PNMI_ERR_TOO_SHORT);
3889 Val8 = (SK_U8)pAC->GIni.GIPciHwRev;
3890 pBuf[0] = 4;
3891 pBuf[1] = 'v';
3892 pBuf[2] = (char)(0x30 | ((Val8 >> 4) & 0x0F));
3893 pBuf[3] = '.';
3894 pBuf[4] = (char)(0x30 | (Val8 & 0x0F));
3895 *pLen = 5;
3896 break;
3898 case OID_SKGE_CHIPSET:
3899 Val16 = pAC->Pnmi.Chipset;
3900 SK_PNMI_STORE_U16(pBuf, Val16);
3901 *pLen = sizeof(SK_U16);
3902 break;
3904 case OID_SKGE_CHIPID:
3905 Val32 = pAC->GIni.GIChipId;
3906 SK_PNMI_STORE_U32(pBuf, Val32);
3907 *pLen = sizeof(SK_U32);
3908 break;
3910 case OID_SKGE_RAMSIZE:
3911 Val32 = pAC->GIni.GIRamSize;
3912 SK_PNMI_STORE_U32(pBuf, Val32);
3913 *pLen = sizeof(SK_U32);
3914 break;
3916 case OID_SKGE_VAUXAVAIL:
3917 *pBuf = (char) pAC->GIni.GIVauxAvail;
3918 *pLen = sizeof(char);
3919 break;
3921 case OID_SKGE_BUS_TYPE:
3922 *pBuf = (char) SK_PNMI_BUS_PCI;
3923 *pLen = sizeof(char);
3924 break;
3926 case OID_SKGE_BUS_SPEED:
3927 *pBuf = pAC->Pnmi.PciBusSpeed;
3928 *pLen = sizeof(char);
3929 break;
3931 case OID_SKGE_BUS_WIDTH:
3932 *pBuf = pAC->Pnmi.PciBusWidth;
3933 *pLen = sizeof(char);
3934 break;
3936 case OID_SKGE_RESULT:
3937 Val32 = pAC->Pnmi.TestResult;
3938 SK_PNMI_STORE_U32(pBuf, Val32);
3939 *pLen = sizeof(SK_U32);
3940 break;
3942 case OID_SKGE_SENSOR_NUMBER:
3943 *pBuf = (char)pAC->I2c.MaxSens;
3944 *pLen = sizeof(char);
3945 break;
3947 case OID_SKGE_CHKSM_NUMBER:
3948 *pBuf = SKCS_NUM_PROTOCOLS;
3949 *pLen = sizeof(char);
3950 break;
3952 case OID_SKGE_TRAP_NUMBER:
3953 GetTrapQueueLen(pAC, &Len, &Val);
3954 Val32 = (SK_U32)Val;
3955 SK_PNMI_STORE_U32(pBuf, Val32);
3956 *pLen = sizeof(SK_U32);
3957 break;
3959 case OID_SKGE_TRAP:
3960 GetTrapQueueLen(pAC, &Len, &Val);
3961 if (*pLen < Len) {
3963 *pLen = Len;
3964 return (SK_PNMI_ERR_TOO_SHORT);
3966 CopyTrapQueue(pAC, pBuf);
3967 *pLen = Len;
3968 break;
3970 case OID_SKGE_RLMT_MONITOR_NUMBER:
3971 /* XXX Not yet implemented by RLMT therefore we return zero elements */
3972 Val32 = 0;
3973 SK_PNMI_STORE_U32(pBuf, Val32);
3974 *pLen = sizeof(SK_U32);
3975 break;
3977 case OID_SKGE_TX_SW_QUEUE_LEN:
3978 /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
3979 if (MacType == SK_MAC_XMAC) {
3980 /* Dual net mode */
3981 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
3982 Val64 = pAC->Pnmi.BufPort[NetIndex].TxSwQueueLen;
3984 /* Single net mode */
3985 else {
3986 Val64 = pAC->Pnmi.BufPort[0].TxSwQueueLen +
3987 pAC->Pnmi.BufPort[1].TxSwQueueLen;
3990 else {
3991 /* Dual net mode */
3992 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
3993 Val64 = pAC->Pnmi.Port[NetIndex].TxSwQueueLen;
3995 /* Single net mode */
3996 else {
3997 Val64 = pAC->Pnmi.Port[0].TxSwQueueLen +
3998 pAC->Pnmi.Port[1].TxSwQueueLen;
4001 SK_PNMI_STORE_U64(pBuf, Val64);
4002 *pLen = sizeof(SK_U64);
4003 break;
4006 case OID_SKGE_TX_SW_QUEUE_MAX:
4007 /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
4008 if (MacType == SK_MAC_XMAC) {
4009 /* Dual net mode */
4010 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
4011 Val64 = pAC->Pnmi.BufPort[NetIndex].TxSwQueueMax;
4013 /* Single net mode */
4014 else {
4015 Val64 = pAC->Pnmi.BufPort[0].TxSwQueueMax +
4016 pAC->Pnmi.BufPort[1].TxSwQueueMax;
4019 else {
4020 /* Dual net mode */
4021 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
4022 Val64 = pAC->Pnmi.Port[NetIndex].TxSwQueueMax;
4024 /* Single net mode */
4025 else {
4026 Val64 = pAC->Pnmi.Port[0].TxSwQueueMax +
4027 pAC->Pnmi.Port[1].TxSwQueueMax;
4030 SK_PNMI_STORE_U64(pBuf, Val64);
4031 *pLen = sizeof(SK_U64);
4032 break;
4034 case OID_SKGE_TX_RETRY:
4035 /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
4036 if (MacType == SK_MAC_XMAC) {
4037 /* Dual net mode */
4038 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
4039 Val64 = pAC->Pnmi.BufPort[NetIndex].TxRetryCts;
4041 /* Single net mode */
4042 else {
4043 Val64 = pAC->Pnmi.BufPort[0].TxRetryCts +
4044 pAC->Pnmi.BufPort[1].TxRetryCts;
4047 else {
4048 /* Dual net mode */
4049 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
4050 Val64 = pAC->Pnmi.Port[NetIndex].TxRetryCts;
4052 /* Single net mode */
4053 else {
4054 Val64 = pAC->Pnmi.Port[0].TxRetryCts +
4055 pAC->Pnmi.Port[1].TxRetryCts;
4058 SK_PNMI_STORE_U64(pBuf, Val64);
4059 *pLen = sizeof(SK_U64);
4060 break;
4062 case OID_SKGE_RX_INTR_CTS:
4063 /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
4064 if (MacType == SK_MAC_XMAC) {
4065 /* Dual net mode */
4066 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
4067 Val64 = pAC->Pnmi.BufPort[NetIndex].RxIntrCts;
4069 /* Single net mode */
4070 else {
4071 Val64 = pAC->Pnmi.BufPort[0].RxIntrCts +
4072 pAC->Pnmi.BufPort[1].RxIntrCts;
4075 else {
4076 /* Dual net mode */
4077 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
4078 Val64 = pAC->Pnmi.Port[NetIndex].RxIntrCts;
4080 /* Single net mode */
4081 else {
4082 Val64 = pAC->Pnmi.Port[0].RxIntrCts +
4083 pAC->Pnmi.Port[1].RxIntrCts;
4086 SK_PNMI_STORE_U64(pBuf, Val64);
4087 *pLen = sizeof(SK_U64);
4088 break;
4090 case OID_SKGE_TX_INTR_CTS:
4091 /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
4092 if (MacType == SK_MAC_XMAC) {
4093 /* Dual net mode */
4094 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
4095 Val64 = pAC->Pnmi.BufPort[NetIndex].TxIntrCts;
4097 /* Single net mode */
4098 else {
4099 Val64 = pAC->Pnmi.BufPort[0].TxIntrCts +
4100 pAC->Pnmi.BufPort[1].TxIntrCts;
4103 else {
4104 /* Dual net mode */
4105 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
4106 Val64 = pAC->Pnmi.Port[NetIndex].TxIntrCts;
4108 /* Single net mode */
4109 else {
4110 Val64 = pAC->Pnmi.Port[0].TxIntrCts +
4111 pAC->Pnmi.Port[1].TxIntrCts;
4114 SK_PNMI_STORE_U64(pBuf, Val64);
4115 *pLen = sizeof(SK_U64);
4116 break;
4118 case OID_SKGE_RX_NO_BUF_CTS:
4119 /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
4120 if (MacType == SK_MAC_XMAC) {
4121 /* Dual net mode */
4122 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
4123 Val64 = pAC->Pnmi.BufPort[NetIndex].RxNoBufCts;
4125 /* Single net mode */
4126 else {
4127 Val64 = pAC->Pnmi.BufPort[0].RxNoBufCts +
4128 pAC->Pnmi.BufPort[1].RxNoBufCts;
4131 else {
4132 /* Dual net mode */
4133 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
4134 Val64 = pAC->Pnmi.Port[NetIndex].RxNoBufCts;
4136 /* Single net mode */
4137 else {
4138 Val64 = pAC->Pnmi.Port[0].RxNoBufCts +
4139 pAC->Pnmi.Port[1].RxNoBufCts;
4142 SK_PNMI_STORE_U64(pBuf, Val64);
4143 *pLen = sizeof(SK_U64);
4144 break;
4146 case OID_SKGE_TX_NO_BUF_CTS:
4147 /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
4148 if (MacType == SK_MAC_XMAC) {
4149 /* Dual net mode */
4150 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
4151 Val64 = pAC->Pnmi.BufPort[NetIndex].TxNoBufCts;
4153 /* Single net mode */
4154 else {
4155 Val64 = pAC->Pnmi.BufPort[0].TxNoBufCts +
4156 pAC->Pnmi.BufPort[1].TxNoBufCts;
4159 else {
4160 /* Dual net mode */
4161 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
4162 Val64 = pAC->Pnmi.Port[NetIndex].TxNoBufCts;
4164 /* Single net mode */
4165 else {
4166 Val64 = pAC->Pnmi.Port[0].TxNoBufCts +
4167 pAC->Pnmi.Port[1].TxNoBufCts;
4170 SK_PNMI_STORE_U64(pBuf, Val64);
4171 *pLen = sizeof(SK_U64);
4172 break;
4174 case OID_SKGE_TX_USED_DESCR_NO:
4175 /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
4176 if (MacType == SK_MAC_XMAC) {
4177 /* Dual net mode */
4178 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
4179 Val64 = pAC->Pnmi.BufPort[NetIndex].TxUsedDescrNo;
4181 /* Single net mode */
4182 else {
4183 Val64 = pAC->Pnmi.BufPort[0].TxUsedDescrNo +
4184 pAC->Pnmi.BufPort[1].TxUsedDescrNo;
4187 else {
4188 /* Dual net mode */
4189 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
4190 Val64 = pAC->Pnmi.Port[NetIndex].TxUsedDescrNo;
4192 /* Single net mode */
4193 else {
4194 Val64 = pAC->Pnmi.Port[0].TxUsedDescrNo +
4195 pAC->Pnmi.Port[1].TxUsedDescrNo;
4198 SK_PNMI_STORE_U64(pBuf, Val64);
4199 *pLen = sizeof(SK_U64);
4200 break;
4202 case OID_SKGE_RX_DELIVERED_CTS:
4203 /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
4204 if (MacType == SK_MAC_XMAC) {
4205 /* Dual net mode */
4206 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
4207 Val64 = pAC->Pnmi.BufPort[NetIndex].RxDeliveredCts;
4209 /* Single net mode */
4210 else {
4211 Val64 = pAC->Pnmi.BufPort[0].RxDeliveredCts +
4212 pAC->Pnmi.BufPort[1].RxDeliveredCts;
4215 else {
4216 /* Dual net mode */
4217 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
4218 Val64 = pAC->Pnmi.Port[NetIndex].RxDeliveredCts;
4220 /* Single net mode */
4221 else {
4222 Val64 = pAC->Pnmi.Port[0].RxDeliveredCts +
4223 pAC->Pnmi.Port[1].RxDeliveredCts;
4226 SK_PNMI_STORE_U64(pBuf, Val64);
4227 *pLen = sizeof(SK_U64);
4228 break;
4230 case OID_SKGE_RX_OCTETS_DELIV_CTS:
4231 /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
4232 if (MacType == SK_MAC_XMAC) {
4233 /* Dual net mode */
4234 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
4235 Val64 = pAC->Pnmi.BufPort[NetIndex].RxOctetsDeliveredCts;
4237 /* Single net mode */
4238 else {
4239 Val64 = pAC->Pnmi.BufPort[0].RxOctetsDeliveredCts +
4240 pAC->Pnmi.BufPort[1].RxOctetsDeliveredCts;
4243 else {
4244 /* Dual net mode */
4245 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
4246 Val64 = pAC->Pnmi.Port[NetIndex].RxOctetsDeliveredCts;
4248 /* Single net mode */
4249 else {
4250 Val64 = pAC->Pnmi.Port[0].RxOctetsDeliveredCts +
4251 pAC->Pnmi.Port[1].RxOctetsDeliveredCts;
4254 SK_PNMI_STORE_U64(pBuf, Val64);
4255 *pLen = sizeof(SK_U64);
4256 break;
4258 case OID_SKGE_RX_HW_ERROR_CTS:
4259 SK_PNMI_STORE_U64(pBuf, Val64RxHwErrs);
4260 *pLen = sizeof(SK_U64);
4261 break;
4263 case OID_SKGE_TX_HW_ERROR_CTS:
4264 SK_PNMI_STORE_U64(pBuf, Val64TxHwErrs);
4265 *pLen = sizeof(SK_U64);
4266 break;
4268 case OID_SKGE_IN_ERRORS_CTS:
4269 /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
4270 if (MacType == SK_MAC_XMAC) {
4271 /* Dual net mode */
4272 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
4273 Val64 = Val64RxHwErrs + pAC->Pnmi.BufPort[NetIndex].RxNoBufCts;
4275 /* Single net mode */
4276 else {
4277 Val64 = Val64RxHwErrs +
4278 pAC->Pnmi.BufPort[0].RxNoBufCts +
4279 pAC->Pnmi.BufPort[1].RxNoBufCts;
4282 else {
4283 /* Dual net mode */
4284 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
4285 Val64 = Val64RxHwErrs + pAC->Pnmi.Port[NetIndex].RxNoBufCts;
4287 /* Single net mode */
4288 else {
4289 Val64 = Val64RxHwErrs +
4290 pAC->Pnmi.Port[0].RxNoBufCts +
4291 pAC->Pnmi.Port[1].RxNoBufCts;
4294 SK_PNMI_STORE_U64(pBuf, Val64);
4295 *pLen = sizeof(SK_U64);
4296 break;
4298 case OID_SKGE_OUT_ERROR_CTS:
4299 /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
4300 if (MacType == SK_MAC_XMAC) {
4301 /* Dual net mode */
4302 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
4303 Val64 = Val64TxHwErrs + pAC->Pnmi.BufPort[NetIndex].TxNoBufCts;
4305 /* Single net mode */
4306 else {
4307 Val64 = Val64TxHwErrs +
4308 pAC->Pnmi.BufPort[0].TxNoBufCts +
4309 pAC->Pnmi.BufPort[1].TxNoBufCts;
4312 else {
4313 /* Dual net mode */
4314 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
4315 Val64 = Val64TxHwErrs + pAC->Pnmi.Port[NetIndex].TxNoBufCts;
4317 /* Single net mode */
4318 else {
4319 Val64 = Val64TxHwErrs +
4320 pAC->Pnmi.Port[0].TxNoBufCts +
4321 pAC->Pnmi.Port[1].TxNoBufCts;
4324 SK_PNMI_STORE_U64(pBuf, Val64);
4325 *pLen = sizeof(SK_U64);
4326 break;
4328 case OID_SKGE_ERR_RECOVERY_CTS:
4329 /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
4330 if (MacType == SK_MAC_XMAC) {
4331 /* Dual net mode */
4332 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
4333 Val64 = pAC->Pnmi.BufPort[NetIndex].ErrRecoveryCts;
4335 /* Single net mode */
4336 else {
4337 Val64 = pAC->Pnmi.BufPort[0].ErrRecoveryCts +
4338 pAC->Pnmi.BufPort[1].ErrRecoveryCts;
4341 else {
4342 /* Dual net mode */
4343 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
4344 Val64 = pAC->Pnmi.Port[NetIndex].ErrRecoveryCts;
4346 /* Single net mode */
4347 else {
4348 Val64 = pAC->Pnmi.Port[0].ErrRecoveryCts +
4349 pAC->Pnmi.Port[1].ErrRecoveryCts;
4352 SK_PNMI_STORE_U64(pBuf, Val64);
4353 *pLen = sizeof(SK_U64);
4354 break;
4356 case OID_SKGE_SYSUPTIME:
4357 Val64 = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC));
4358 Val64 -= pAC->Pnmi.StartUpTime;
4359 SK_PNMI_STORE_U64(pBuf, Val64);
4360 *pLen = sizeof(SK_U64);
4361 break;
4363 case OID_SKGE_MDB_VERSION:
4364 Val32 = SK_PNMI_MDB_VERSION;
4365 SK_PNMI_STORE_U32(pBuf, Val32);
4366 *pLen = sizeof(SK_U32);
4367 break;
4369 case OID_GEN_RCV_ERROR:
4370 /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
4371 if (MacType == SK_MAC_XMAC) {
4372 Val64 = Val64RxHwErrs + pAC->Pnmi.BufPort[NetIndex].RxNoBufCts;
4374 else {
4375 Val64 = Val64RxHwErrs + pAC->Pnmi.Port[NetIndex].RxNoBufCts;
4379 * by default 32bit values are evaluated
4381 if (!Is64BitReq) {
4382 Val32 = (SK_U32)Val64;
4383 SK_PNMI_STORE_U32(pBuf, Val32);
4384 *pLen = sizeof(SK_U32);
4386 else {
4387 SK_PNMI_STORE_U64(pBuf, Val64);
4388 *pLen = sizeof(SK_U64);
4390 break;
4392 case OID_GEN_XMIT_ERROR:
4393 /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
4394 if (MacType == SK_MAC_XMAC) {
4395 Val64 = Val64TxHwErrs + pAC->Pnmi.BufPort[NetIndex].TxNoBufCts;
4397 else {
4398 Val64 = Val64TxHwErrs + pAC->Pnmi.Port[NetIndex].TxNoBufCts;
4402 * by default 32bit values are evaluated
4404 if (!Is64BitReq) {
4405 Val32 = (SK_U32)Val64;
4406 SK_PNMI_STORE_U32(pBuf, Val32);
4407 *pLen = sizeof(SK_U32);
4409 else {
4410 SK_PNMI_STORE_U64(pBuf, Val64);
4411 *pLen = sizeof(SK_U64);
4413 break;
4415 case OID_GEN_RCV_NO_BUFFER:
4416 /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
4417 if (MacType == SK_MAC_XMAC) {
4418 Val64 = pAC->Pnmi.BufPort[NetIndex].RxNoBufCts;
4420 else {
4421 Val64 = pAC->Pnmi.Port[NetIndex].RxNoBufCts;
4425 * by default 32bit values are evaluated
4427 if (!Is64BitReq) {
4428 Val32 = (SK_U32)Val64;
4429 SK_PNMI_STORE_U32(pBuf, Val32);
4430 *pLen = sizeof(SK_U32);
4432 else {
4433 SK_PNMI_STORE_U64(pBuf, Val64);
4434 *pLen = sizeof(SK_U64);
4436 break;
4438 case OID_GEN_TRANSMIT_QUEUE_LENGTH:
4439 Val32 = (SK_U32)pAC->Pnmi.Port[NetIndex].TxSwQueueLen;
4440 SK_PNMI_STORE_U32(pBuf, Val32);
4441 *pLen = sizeof(SK_U32);
4442 break;
4444 default:
4445 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR034,
4446 SK_PNMI_ERR034MSG);
4448 *pLen = 0;
4449 return (SK_PNMI_ERR_GENERAL);
4452 if (Id == OID_SKGE_RX_HW_ERROR_CTS ||
4453 Id == OID_SKGE_TX_HW_ERROR_CTS ||
4454 Id == OID_SKGE_IN_ERRORS_CTS ||
4455 Id == OID_SKGE_OUT_ERROR_CTS ||
4456 Id == OID_GEN_XMIT_ERROR ||
4457 Id == OID_GEN_RCV_ERROR) {
4459 pAC->Pnmi.MacUpdatedFlag --;
4462 return (SK_PNMI_ERR_OK);
4465 /*****************************************************************************
4467 * Rlmt - OID handler function of OID_SKGE_RLMT_XXX single instance.
4469 * Description:
4470 * Get/Presets/Sets the RLMT OIDs.
4472 * Returns:
4473 * SK_PNMI_ERR_OK The request was successfully performed.
4474 * SK_PNMI_ERR_GENERAL A general severe internal error occured.
4475 * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
4476 * the correct data (e.g. a 32bit value is
4477 * needed, but a 16 bit value was passed).
4478 * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
4479 * value range.
4480 * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set.
4481 * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
4482 * exist (e.g. port instance 3 on a two port
4483 * adapter.
4485 PNMI_STATIC int Rlmt(
4486 SK_AC *pAC, /* Pointer to adapter context */
4487 SK_IOC IoC, /* IO context handle */
4488 int Action, /* GET/PRESET/SET action */
4489 SK_U32 Id, /* Object ID that is to be processed */
4490 char *pBuf, /* Buffer used for the management data transfer */
4491 unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
4492 SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
4493 unsigned int TableIndex, /* Index to the Id table */
4494 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
4496 int Ret;
4497 unsigned int PhysPortIndex;
4498 unsigned int PhysPortMax;
4499 SK_EVPARA EventParam;
4500 SK_U32 Val32;
4501 SK_U64 Val64;
4505 * Check instance. Only single instance OIDs are allowed here.
4507 if (Instance != (SK_U32)(-1) && Instance != 1) {
4509 *pLen = 0;
4510 return (SK_PNMI_ERR_UNKNOWN_INST);
4514 * Perform the requested action.
4516 if (Action == SK_PNMI_GET) {
4519 * Check if the buffer length is large enough.
4522 switch (Id) {
4524 case OID_SKGE_RLMT_MODE:
4525 case OID_SKGE_RLMT_PORT_ACTIVE:
4526 case OID_SKGE_RLMT_PORT_PREFERRED:
4527 if (*pLen < sizeof(SK_U8)) {
4529 *pLen = sizeof(SK_U8);
4530 return (SK_PNMI_ERR_TOO_SHORT);
4532 break;
4534 case OID_SKGE_RLMT_PORT_NUMBER:
4535 if (*pLen < sizeof(SK_U32)) {
4537 *pLen = sizeof(SK_U32);
4538 return (SK_PNMI_ERR_TOO_SHORT);
4540 break;
4542 case OID_SKGE_RLMT_CHANGE_CTS:
4543 case OID_SKGE_RLMT_CHANGE_TIME:
4544 case OID_SKGE_RLMT_CHANGE_ESTIM:
4545 case OID_SKGE_RLMT_CHANGE_THRES:
4546 if (*pLen < sizeof(SK_U64)) {
4548 *pLen = sizeof(SK_U64);
4549 return (SK_PNMI_ERR_TOO_SHORT);
4551 break;
4553 default:
4554 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR035,
4555 SK_PNMI_ERR035MSG);
4557 *pLen = 0;
4558 return (SK_PNMI_ERR_GENERAL);
4562 * Update RLMT statistic and increment semaphores to indicate
4563 * that an update was already done. Maybe RLMT will hold its
4564 * statistic always up to date some time. Then we can
4565 * remove this type of call.
4567 if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) {
4569 *pLen = 0;
4570 return (Ret);
4572 pAC->Pnmi.RlmtUpdatedFlag ++;
4575 * Retrieve Value
4577 switch (Id) {
4579 case OID_SKGE_RLMT_MODE:
4580 *pBuf = (char)pAC->Rlmt.Net[0].RlmtMode;
4581 *pLen = sizeof(char);
4582 break;
4584 case OID_SKGE_RLMT_PORT_NUMBER:
4585 Val32 = (SK_U32)pAC->GIni.GIMacsFound;
4586 SK_PNMI_STORE_U32(pBuf, Val32);
4587 *pLen = sizeof(SK_U32);
4588 break;
4590 case OID_SKGE_RLMT_PORT_ACTIVE:
4591 *pBuf = 0;
4593 * If multiple ports may become active this OID
4594 * doesn't make sense any more. A new variable in
4595 * the port structure should be created. However,
4596 * for this variable the first active port is
4597 * returned.
4599 PhysPortMax = pAC->GIni.GIMacsFound;
4601 for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax;
4602 PhysPortIndex ++) {
4604 if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
4606 *pBuf = (char)SK_PNMI_PORT_PHYS2LOG(PhysPortIndex);
4607 break;
4610 *pLen = sizeof(char);
4611 break;
4613 case OID_SKGE_RLMT_PORT_PREFERRED:
4614 *pBuf = (char)SK_PNMI_PORT_PHYS2LOG(pAC->Rlmt.Net[NetIndex].Preference);
4615 *pLen = sizeof(char);
4616 break;
4618 case OID_SKGE_RLMT_CHANGE_CTS:
4619 Val64 = pAC->Pnmi.RlmtChangeCts;
4620 SK_PNMI_STORE_U64(pBuf, Val64);
4621 *pLen = sizeof(SK_U64);
4622 break;
4624 case OID_SKGE_RLMT_CHANGE_TIME:
4625 Val64 = pAC->Pnmi.RlmtChangeTime;
4626 SK_PNMI_STORE_U64(pBuf, Val64);
4627 *pLen = sizeof(SK_U64);
4628 break;
4630 case OID_SKGE_RLMT_CHANGE_ESTIM:
4631 Val64 = pAC->Pnmi.RlmtChangeEstimate.Estimate;
4632 SK_PNMI_STORE_U64(pBuf, Val64);
4633 *pLen = sizeof(SK_U64);
4634 break;
4636 case OID_SKGE_RLMT_CHANGE_THRES:
4637 Val64 = pAC->Pnmi.RlmtChangeThreshold;
4638 SK_PNMI_STORE_U64(pBuf, Val64);
4639 *pLen = sizeof(SK_U64);
4640 break;
4642 default:
4643 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR,
4644 ("Rlmt: Unknown OID should be handled before"));
4646 pAC->Pnmi.RlmtUpdatedFlag --;
4647 *pLen = 0;
4648 return (SK_PNMI_ERR_GENERAL);
4651 pAC->Pnmi.RlmtUpdatedFlag --;
4653 else {
4654 /* Perform a preset or set */
4655 switch (Id) {
4657 case OID_SKGE_RLMT_MODE:
4658 /* Check if the buffer length is plausible */
4659 if (*pLen < sizeof(char)) {
4661 *pLen = sizeof(char);
4662 return (SK_PNMI_ERR_TOO_SHORT);
4664 /* Check if the value range is correct */
4665 if (*pLen != sizeof(char) ||
4666 (*pBuf & SK_PNMI_RLMT_MODE_CHK_LINK) == 0 ||
4667 *(SK_U8 *)pBuf > 15) {
4669 *pLen = 0;
4670 return (SK_PNMI_ERR_BAD_VALUE);
4672 /* The preset ends here */
4673 if (Action == SK_PNMI_PRESET) {
4675 *pLen = 0;
4676 return (SK_PNMI_ERR_OK);
4678 /* Send an event to RLMT to change the mode */
4679 SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
4680 EventParam.Para32[0] |= (SK_U32)(*pBuf);
4681 EventParam.Para32[1] = 0;
4682 if (SkRlmtEvent(pAC, IoC, SK_RLMT_MODE_CHANGE,
4683 EventParam) > 0) {
4685 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR037,
4686 SK_PNMI_ERR037MSG);
4688 *pLen = 0;
4689 return (SK_PNMI_ERR_GENERAL);
4691 break;
4693 case OID_SKGE_RLMT_PORT_PREFERRED:
4694 /* Check if the buffer length is plausible */
4695 if (*pLen < sizeof(char)) {
4697 *pLen = sizeof(char);
4698 return (SK_PNMI_ERR_TOO_SHORT);
4700 /* Check if the value range is correct */
4701 if (*pLen != sizeof(char) || *(SK_U8 *)pBuf >
4702 (SK_U8)pAC->GIni.GIMacsFound) {
4704 *pLen = 0;
4705 return (SK_PNMI_ERR_BAD_VALUE);
4707 /* The preset ends here */
4708 if (Action == SK_PNMI_PRESET) {
4710 *pLen = 0;
4711 return (SK_PNMI_ERR_OK);
4715 * Send an event to RLMT change the preferred port.
4716 * A param of -1 means automatic mode. RLMT will
4717 * make the decision which is the preferred port.
4719 SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
4720 EventParam.Para32[0] = (SK_U32)(*pBuf) - 1;
4721 EventParam.Para32[1] = NetIndex;
4722 if (SkRlmtEvent(pAC, IoC, SK_RLMT_PREFPORT_CHANGE,
4723 EventParam) > 0) {
4725 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR038,
4726 SK_PNMI_ERR038MSG);
4728 *pLen = 0;
4729 return (SK_PNMI_ERR_GENERAL);
4731 break;
4733 case OID_SKGE_RLMT_CHANGE_THRES:
4734 /* Check if the buffer length is plausible */
4735 if (*pLen < sizeof(SK_U64)) {
4737 *pLen = sizeof(SK_U64);
4738 return (SK_PNMI_ERR_TOO_SHORT);
4741 * There are not many restrictions to the
4742 * value range.
4744 if (*pLen != sizeof(SK_U64)) {
4746 *pLen = 0;
4747 return (SK_PNMI_ERR_BAD_VALUE);
4749 /* A preset ends here */
4750 if (Action == SK_PNMI_PRESET) {
4752 *pLen = 0;
4753 return (SK_PNMI_ERR_OK);
4756 * Store the new threshold, which will be taken
4757 * on the next timer event.
4759 SK_PNMI_READ_U64(pBuf, Val64);
4760 pAC->Pnmi.RlmtChangeThreshold = Val64;
4761 break;
4763 default:
4764 /* The other OIDs are not be able for set */
4765 *pLen = 0;
4766 return (SK_PNMI_ERR_READ_ONLY);
4770 return (SK_PNMI_ERR_OK);
4773 /*****************************************************************************
4775 * RlmtStat - OID handler function of OID_SKGE_RLMT_XXX multiple instance.
4777 * Description:
4778 * Performs get requests on multiple instance variables.
4780 * Returns:
4781 * SK_PNMI_ERR_OK The request was successfully performed.
4782 * SK_PNMI_ERR_GENERAL A general severe internal error occured.
4783 * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
4784 * the correct data (e.g. a 32bit value is
4785 * needed, but a 16 bit value was passed).
4786 * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
4787 * exist (e.g. port instance 3 on a two port
4788 * adapter.
4790 PNMI_STATIC int RlmtStat(
4791 SK_AC *pAC, /* Pointer to adapter context */
4792 SK_IOC IoC, /* IO context handle */
4793 int Action, /* GET/PRESET/SET action */
4794 SK_U32 Id, /* Object ID that is to be processed */
4795 char *pBuf, /* Buffer used for the management data transfer */
4796 unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
4797 SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
4798 unsigned int TableIndex, /* Index to the Id table */
4799 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
4801 unsigned int PhysPortMax;
4802 unsigned int PhysPortIndex;
4803 unsigned int Limit;
4804 unsigned int Offset;
4805 int Ret;
4806 SK_U32 Val32;
4807 SK_U64 Val64;
4810 * Calculate the port indexes from the instance.
4812 PhysPortMax = pAC->GIni.GIMacsFound;
4814 if ((Instance != (SK_U32)(-1))) {
4815 /* Check instance range */
4816 if ((Instance < 1) || (Instance > PhysPortMax)) {
4818 *pLen = 0;
4819 return (SK_PNMI_ERR_UNKNOWN_INST);
4822 /* Single net mode */
4823 PhysPortIndex = Instance - 1;
4825 /* Dual net mode */
4826 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
4827 PhysPortIndex = NetIndex;
4830 /* Both net modes */
4831 Limit = PhysPortIndex + 1;
4833 else {
4834 /* Single net mode */
4835 PhysPortIndex = 0;
4836 Limit = PhysPortMax;
4838 /* Dual net mode */
4839 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
4840 PhysPortIndex = NetIndex;
4841 Limit = PhysPortIndex + 1;
4846 * Currently only get requests are allowed.
4848 if (Action != SK_PNMI_GET) {
4850 *pLen = 0;
4851 return (SK_PNMI_ERR_READ_ONLY);
4855 * Check if the buffer length is large enough.
4857 switch (Id) {
4859 case OID_SKGE_RLMT_PORT_INDEX:
4860 case OID_SKGE_RLMT_STATUS:
4861 if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U32)) {
4863 *pLen = (Limit - PhysPortIndex) * sizeof(SK_U32);
4864 return (SK_PNMI_ERR_TOO_SHORT);
4866 break;
4868 case OID_SKGE_RLMT_TX_HELLO_CTS:
4869 case OID_SKGE_RLMT_RX_HELLO_CTS:
4870 case OID_SKGE_RLMT_TX_SP_REQ_CTS:
4871 case OID_SKGE_RLMT_RX_SP_CTS:
4872 if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U64)) {
4874 *pLen = (Limit - PhysPortIndex) * sizeof(SK_U64);
4875 return (SK_PNMI_ERR_TOO_SHORT);
4877 break;
4879 default:
4880 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR039,
4881 SK_PNMI_ERR039MSG);
4883 *pLen = 0;
4884 return (SK_PNMI_ERR_GENERAL);
4889 * Update statistic and increment semaphores to indicate that
4890 * an update was already done.
4892 if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) {
4894 *pLen = 0;
4895 return (Ret);
4897 pAC->Pnmi.RlmtUpdatedFlag ++;
4900 * Get value
4902 Offset = 0;
4903 for (; PhysPortIndex < Limit; PhysPortIndex ++) {
4905 switch (Id) {
4907 case OID_SKGE_RLMT_PORT_INDEX:
4908 Val32 = PhysPortIndex;
4909 SK_PNMI_STORE_U32(pBuf + Offset, Val32);
4910 Offset += sizeof(SK_U32);
4911 break;
4913 case OID_SKGE_RLMT_STATUS:
4914 if (pAC->Rlmt.Port[PhysPortIndex].PortState ==
4915 SK_RLMT_PS_INIT ||
4916 pAC->Rlmt.Port[PhysPortIndex].PortState ==
4917 SK_RLMT_PS_DOWN) {
4919 Val32 = SK_PNMI_RLMT_STATUS_ERROR;
4921 else if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
4923 Val32 = SK_PNMI_RLMT_STATUS_ACTIVE;
4925 else {
4926 Val32 = SK_PNMI_RLMT_STATUS_STANDBY;
4928 SK_PNMI_STORE_U32(pBuf + Offset, Val32);
4929 Offset += sizeof(SK_U32);
4930 break;
4932 case OID_SKGE_RLMT_TX_HELLO_CTS:
4933 Val64 = pAC->Rlmt.Port[PhysPortIndex].TxHelloCts;
4934 SK_PNMI_STORE_U64(pBuf + Offset, Val64);
4935 Offset += sizeof(SK_U64);
4936 break;
4938 case OID_SKGE_RLMT_RX_HELLO_CTS:
4939 Val64 = pAC->Rlmt.Port[PhysPortIndex].RxHelloCts;
4940 SK_PNMI_STORE_U64(pBuf + Offset, Val64);
4941 Offset += sizeof(SK_U64);
4942 break;
4944 case OID_SKGE_RLMT_TX_SP_REQ_CTS:
4945 Val64 = pAC->Rlmt.Port[PhysPortIndex].TxSpHelloReqCts;
4946 SK_PNMI_STORE_U64(pBuf + Offset, Val64);
4947 Offset += sizeof(SK_U64);
4948 break;
4950 case OID_SKGE_RLMT_RX_SP_CTS:
4951 Val64 = pAC->Rlmt.Port[PhysPortIndex].RxSpHelloCts;
4952 SK_PNMI_STORE_U64(pBuf + Offset, Val64);
4953 Offset += sizeof(SK_U64);
4954 break;
4956 default:
4957 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR,
4958 ("RlmtStat: Unknown OID should be errored before"));
4960 pAC->Pnmi.RlmtUpdatedFlag --;
4961 *pLen = 0;
4962 return (SK_PNMI_ERR_GENERAL);
4965 *pLen = Offset;
4967 pAC->Pnmi.RlmtUpdatedFlag --;
4969 return (SK_PNMI_ERR_OK);
4972 /*****************************************************************************
4974 * MacPrivateConf - OID handler function of OIDs concerning the configuration
4976 * Description:
4977 * Get/Presets/Sets the OIDs concerning the configuration.
4979 * Returns:
4980 * SK_PNMI_ERR_OK The request was successfully performed.
4981 * SK_PNMI_ERR_GENERAL A general severe internal error occured.
4982 * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
4983 * the correct data (e.g. a 32bit value is
4984 * needed, but a 16 bit value was passed).
4985 * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
4986 * value range.
4987 * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set.
4988 * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
4989 * exist (e.g. port instance 3 on a two port
4990 * adapter.
4992 PNMI_STATIC int MacPrivateConf(
4993 SK_AC *pAC, /* Pointer to adapter context */
4994 SK_IOC IoC, /* IO context handle */
4995 int Action, /* GET/PRESET/SET action */
4996 SK_U32 Id, /* Object ID that is to be processed */
4997 char *pBuf, /* Buffer used for the management data transfer */
4998 unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
4999 SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
5000 unsigned int TableIndex, /* Index to the Id table */
5001 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
5003 unsigned int PhysPortMax;
5004 unsigned int PhysPortIndex;
5005 unsigned int LogPortMax;
5006 unsigned int LogPortIndex;
5007 unsigned int Limit;
5008 unsigned int Offset;
5009 char Val8;
5010 char *pBufPtr;
5011 int Ret;
5012 SK_EVPARA EventParam;
5013 SK_U32 Val32;
5016 * Calculate instance if wished. MAC index 0 is the virtual MAC.
5018 PhysPortMax = pAC->GIni.GIMacsFound;
5019 LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax);
5021 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */
5022 LogPortMax--;
5025 if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried */
5026 /* Check instance range */
5027 if ((Instance < 1) || (Instance > LogPortMax)) {
5029 *pLen = 0;
5030 return (SK_PNMI_ERR_UNKNOWN_INST);
5032 LogPortIndex = SK_PNMI_PORT_INST2LOG(Instance);
5033 Limit = LogPortIndex + 1;
5036 else { /* Instance == (SK_U32)(-1), get all Instances of that OID */
5038 LogPortIndex = 0;
5039 Limit = LogPortMax;
5043 * Perform action
5045 if (Action == SK_PNMI_GET) {
5047 /* Check length */
5048 switch (Id) {
5050 case OID_SKGE_PMD:
5051 case OID_SKGE_CONNECTOR:
5052 case OID_SKGE_LINK_CAP:
5053 case OID_SKGE_LINK_MODE:
5054 case OID_SKGE_LINK_MODE_STATUS:
5055 case OID_SKGE_LINK_STATUS:
5056 case OID_SKGE_FLOWCTRL_CAP:
5057 case OID_SKGE_FLOWCTRL_MODE:
5058 case OID_SKGE_FLOWCTRL_STATUS:
5059 case OID_SKGE_PHY_OPERATION_CAP:
5060 case OID_SKGE_PHY_OPERATION_MODE:
5061 case OID_SKGE_PHY_OPERATION_STATUS:
5062 case OID_SKGE_SPEED_CAP:
5063 case OID_SKGE_SPEED_MODE:
5064 case OID_SKGE_SPEED_STATUS:
5065 #ifdef SK_PHY_LP_MODE
5066 case OID_SKGE_PHY_LP_MODE:
5067 #endif
5068 if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U8)) {
5070 *pLen = (Limit - LogPortIndex) * sizeof(SK_U8);
5071 return (SK_PNMI_ERR_TOO_SHORT);
5073 break;
5075 case OID_SKGE_MTU:
5076 case OID_SKGE_PHY_TYPE:
5077 if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U32)) {
5079 *pLen = (Limit - LogPortIndex) * sizeof(SK_U32);
5080 return (SK_PNMI_ERR_TOO_SHORT);
5082 break;
5084 default:
5085 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR041,
5086 SK_PNMI_ERR041MSG);
5087 *pLen = 0;
5088 return (SK_PNMI_ERR_GENERAL);
5092 * Update statistic and increment semaphore to indicate
5093 * that an update was already done.
5095 if ((Ret = SirqUpdate(pAC, IoC)) != SK_PNMI_ERR_OK) {
5097 *pLen = 0;
5098 return (Ret);
5100 pAC->Pnmi.SirqUpdatedFlag ++;
5103 * Get value
5105 Offset = 0;
5106 for (; LogPortIndex < Limit; LogPortIndex ++) {
5108 pBufPtr = pBuf + Offset;
5110 switch (Id) {
5112 case OID_SKGE_PMD:
5113 *pBufPtr = pAC->Pnmi.PMD;
5114 Offset += sizeof(char);
5115 break;
5117 case OID_SKGE_CONNECTOR:
5118 *pBufPtr = pAC->Pnmi.Connector;
5119 Offset += sizeof(char);
5120 break;
5122 case OID_SKGE_PHY_TYPE:
5123 if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
5124 if (LogPortIndex == 0) {
5125 continue;
5127 else {
5128 /* Get value for physical ports */
5129 PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
5130 pAC, LogPortIndex);
5131 Val32 = pAC->GIni.GP[PhysPortIndex].PhyType;
5132 SK_PNMI_STORE_U32(pBufPtr, Val32);
5135 else { /* DualNetMode */
5137 Val32 = pAC->GIni.GP[NetIndex].PhyType;
5138 SK_PNMI_STORE_U32(pBufPtr, Val32);
5140 Offset += sizeof(SK_U32);
5141 break;
5143 #ifdef SK_PHY_LP_MODE
5144 case OID_SKGE_PHY_LP_MODE:
5145 if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
5146 if (LogPortIndex == 0) {
5147 continue;
5149 else {
5150 /* Get value for physical ports */
5151 PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex);
5152 Val8 = (SK_U8) pAC->GIni.GP[PhysPortIndex].PPhyPowerState;
5153 *pBufPtr = Val8;
5156 else { /* DualNetMode */
5158 Val8 = (SK_U8) pAC->GIni.GP[PhysPortIndex].PPhyPowerState;
5159 *pBufPtr = Val8;
5161 Offset += sizeof(SK_U8);
5162 break;
5163 #endif
5165 case OID_SKGE_LINK_CAP:
5166 if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
5167 if (LogPortIndex == 0) {
5168 /* Get value for virtual port */
5169 VirtualConf(pAC, IoC, Id, pBufPtr);
5171 else {
5172 /* Get value for physical ports */
5173 PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
5174 pAC, LogPortIndex);
5176 *pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkCap;
5179 else { /* DualNetMode */
5181 *pBufPtr = pAC->GIni.GP[NetIndex].PLinkCap;
5183 Offset += sizeof(char);
5184 break;
5186 case OID_SKGE_LINK_MODE:
5187 if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
5188 if (LogPortIndex == 0) {
5189 /* Get value for virtual port */
5190 VirtualConf(pAC, IoC, Id, pBufPtr);
5192 else {
5193 /* Get value for physical ports */
5194 PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
5195 pAC, LogPortIndex);
5197 *pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkModeConf;
5200 else { /* DualNetMode */
5202 *pBufPtr = pAC->GIni.GP[NetIndex].PLinkModeConf;
5204 Offset += sizeof(char);
5205 break;
5207 case OID_SKGE_LINK_MODE_STATUS:
5208 if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
5209 if (LogPortIndex == 0) {
5210 /* Get value for virtual port */
5211 VirtualConf(pAC, IoC, Id, pBufPtr);
5213 else {
5214 /* Get value for physical port */
5215 PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
5216 pAC, LogPortIndex);
5218 *pBufPtr =
5219 CalculateLinkModeStatus(pAC, IoC, PhysPortIndex);
5222 else { /* DualNetMode */
5224 *pBufPtr = CalculateLinkModeStatus(pAC, IoC, NetIndex);
5226 Offset += sizeof(char);
5227 break;
5229 case OID_SKGE_LINK_STATUS:
5230 if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
5231 if (LogPortIndex == 0) {
5232 /* Get value for virtual port */
5233 VirtualConf(pAC, IoC, Id, pBufPtr);
5235 else {
5236 /* Get value for physical ports */
5237 PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
5238 pAC, LogPortIndex);
5240 *pBufPtr = CalculateLinkStatus(pAC, IoC, PhysPortIndex);
5243 else { /* DualNetMode */
5245 *pBufPtr = CalculateLinkStatus(pAC, IoC, NetIndex);
5247 Offset += sizeof(char);
5248 break;
5250 case OID_SKGE_FLOWCTRL_CAP:
5251 if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
5252 if (LogPortIndex == 0) {
5253 /* Get value for virtual port */
5254 VirtualConf(pAC, IoC, Id, pBufPtr);
5256 else {
5257 /* Get value for physical ports */
5258 PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
5259 pAC, LogPortIndex);
5261 *pBufPtr = pAC->GIni.GP[PhysPortIndex].PFlowCtrlCap;
5264 else { /* DualNetMode */
5266 *pBufPtr = pAC->GIni.GP[NetIndex].PFlowCtrlCap;
5268 Offset += sizeof(char);
5269 break;
5271 case OID_SKGE_FLOWCTRL_MODE:
5272 if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
5273 if (LogPortIndex == 0) {
5274 /* Get value for virtual port */
5275 VirtualConf(pAC, IoC, Id, pBufPtr);
5277 else {
5278 /* Get value for physical port */
5279 PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
5280 pAC, LogPortIndex);
5282 *pBufPtr = pAC->GIni.GP[PhysPortIndex].PFlowCtrlMode;
5285 else { /* DualNetMode */
5287 *pBufPtr = pAC->GIni.GP[NetIndex].PFlowCtrlMode;
5289 Offset += sizeof(char);
5290 break;
5292 case OID_SKGE_FLOWCTRL_STATUS:
5293 if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
5294 if (LogPortIndex == 0) {
5295 /* Get value for virtual port */
5296 VirtualConf(pAC, IoC, Id, pBufPtr);
5298 else {
5299 /* Get value for physical port */
5300 PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
5301 pAC, LogPortIndex);
5303 *pBufPtr = pAC->GIni.GP[PhysPortIndex].PFlowCtrlStatus;
5306 else { /* DualNetMode */
5308 *pBufPtr = pAC->GIni.GP[NetIndex].PFlowCtrlStatus;
5310 Offset += sizeof(char);
5311 break;
5313 case OID_SKGE_PHY_OPERATION_CAP:
5314 if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
5315 if (LogPortIndex == 0) {
5316 /* Get value for virtual port */
5317 VirtualConf(pAC, IoC, Id, pBufPtr);
5319 else {
5320 /* Get value for physical ports */
5321 PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
5322 pAC, LogPortIndex);
5324 *pBufPtr = pAC->GIni.GP[PhysPortIndex].PMSCap;
5327 else { /* DualNetMode */
5329 *pBufPtr = pAC->GIni.GP[NetIndex].PMSCap;
5331 Offset += sizeof(char);
5332 break;
5334 case OID_SKGE_PHY_OPERATION_MODE:
5335 if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
5336 if (LogPortIndex == 0) {
5337 /* Get value for virtual port */
5338 VirtualConf(pAC, IoC, Id, pBufPtr);
5340 else {
5341 /* Get value for physical port */
5342 PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
5343 pAC, LogPortIndex);
5345 *pBufPtr = pAC->GIni.GP[PhysPortIndex].PMSMode;
5348 else { /* DualNetMode */
5350 *pBufPtr = pAC->GIni.GP[NetIndex].PMSMode;
5352 Offset += sizeof(char);
5353 break;
5355 case OID_SKGE_PHY_OPERATION_STATUS:
5356 if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
5357 if (LogPortIndex == 0) {
5358 /* Get value for virtual port */
5359 VirtualConf(pAC, IoC, Id, pBufPtr);
5361 else {
5362 /* Get value for physical port */
5363 PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
5364 pAC, LogPortIndex);
5366 *pBufPtr = pAC->GIni.GP[PhysPortIndex].PMSStatus;
5369 else {
5371 *pBufPtr = pAC->GIni.GP[NetIndex].PMSStatus;
5373 Offset += sizeof(char);
5374 break;
5376 case OID_SKGE_SPEED_CAP:
5377 if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
5378 if (LogPortIndex == 0) {
5379 /* Get value for virtual port */
5380 VirtualConf(pAC, IoC, Id, pBufPtr);
5382 else {
5383 /* Get value for physical ports */
5384 PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
5385 pAC, LogPortIndex);
5387 *pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkSpeedCap;
5390 else { /* DualNetMode */
5392 *pBufPtr = pAC->GIni.GP[NetIndex].PLinkSpeedCap;
5394 Offset += sizeof(char);
5395 break;
5397 case OID_SKGE_SPEED_MODE:
5398 if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
5399 if (LogPortIndex == 0) {
5400 /* Get value for virtual port */
5401 VirtualConf(pAC, IoC, Id, pBufPtr);
5403 else {
5404 /* Get value for physical port */
5405 PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
5406 pAC, LogPortIndex);
5408 *pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkSpeed;
5411 else { /* DualNetMode */
5413 *pBufPtr = pAC->GIni.GP[NetIndex].PLinkSpeed;
5415 Offset += sizeof(char);
5416 break;
5418 case OID_SKGE_SPEED_STATUS:
5419 if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
5420 if (LogPortIndex == 0) {
5421 /* Get value for virtual port */
5422 VirtualConf(pAC, IoC, Id, pBufPtr);
5424 else {
5425 /* Get value for physical port */
5426 PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
5427 pAC, LogPortIndex);
5429 *pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkSpeedUsed;
5432 else { /* DualNetMode */
5434 *pBufPtr = pAC->GIni.GP[NetIndex].PLinkSpeedUsed;
5436 Offset += sizeof(char);
5437 break;
5439 case OID_SKGE_MTU:
5440 Val32 = SK_DRIVER_GET_MTU(pAC, IoC, NetIndex);
5441 SK_PNMI_STORE_U32(pBufPtr, Val32);
5442 Offset += sizeof(SK_U32);
5443 break;
5445 default:
5446 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR,
5447 ("MacPrivateConf: Unknown OID should be handled before"));
5449 pAC->Pnmi.SirqUpdatedFlag --;
5450 return (SK_PNMI_ERR_GENERAL);
5453 *pLen = Offset;
5454 pAC->Pnmi.SirqUpdatedFlag --;
5456 return (SK_PNMI_ERR_OK);
5460 * From here SET or PRESET action. Check if the passed
5461 * buffer length is plausible.
5463 switch (Id) {
5465 case OID_SKGE_LINK_MODE:
5466 case OID_SKGE_FLOWCTRL_MODE:
5467 case OID_SKGE_PHY_OPERATION_MODE:
5468 case OID_SKGE_SPEED_MODE:
5469 if (*pLen < Limit - LogPortIndex) {
5471 *pLen = Limit - LogPortIndex;
5472 return (SK_PNMI_ERR_TOO_SHORT);
5474 if (*pLen != Limit - LogPortIndex) {
5476 *pLen = 0;
5477 return (SK_PNMI_ERR_BAD_VALUE);
5479 break;
5481 #ifdef SK_PHY_LP_MODE
5482 case OID_SKGE_PHY_LP_MODE:
5483 if (*pLen < Limit - LogPortIndex) {
5485 *pLen = Limit - LogPortIndex;
5486 return (SK_PNMI_ERR_TOO_SHORT);
5488 break;
5489 #endif
5491 case OID_SKGE_MTU:
5492 if (*pLen < sizeof(SK_U32)) {
5494 *pLen = sizeof(SK_U32);
5495 return (SK_PNMI_ERR_TOO_SHORT);
5497 if (*pLen != sizeof(SK_U32)) {
5499 *pLen = 0;
5500 return (SK_PNMI_ERR_BAD_VALUE);
5502 break;
5504 default:
5505 *pLen = 0;
5506 return (SK_PNMI_ERR_READ_ONLY);
5510 * Perform preset or set
5512 Offset = 0;
5513 for (; LogPortIndex < Limit; LogPortIndex ++) {
5515 switch (Id) {
5517 case OID_SKGE_LINK_MODE:
5518 /* Check the value range */
5519 Val8 = *(pBuf + Offset);
5520 if (Val8 == 0) {
5522 Offset += sizeof(char);
5523 break;
5525 if (Val8 < SK_LMODE_HALF ||
5526 (LogPortIndex != 0 && Val8 > SK_LMODE_AUTOSENSE) ||
5527 (LogPortIndex == 0 && Val8 > SK_LMODE_INDETERMINATED)) {
5529 *pLen = 0;
5530 return (SK_PNMI_ERR_BAD_VALUE);
5533 /* The preset ends here */
5534 if (Action == SK_PNMI_PRESET) {
5536 return (SK_PNMI_ERR_OK);
5539 if (LogPortIndex == 0) {
5542 * The virtual port consists of all currently
5543 * active ports. Find them and send an event
5544 * with the new link mode to SIRQ.
5546 for (PhysPortIndex = 0;
5547 PhysPortIndex < PhysPortMax;
5548 PhysPortIndex ++) {
5550 if (!pAC->Pnmi.Port[PhysPortIndex].
5551 ActiveFlag) {
5553 continue;
5556 EventParam.Para32[0] = PhysPortIndex;
5557 EventParam.Para32[1] = (SK_U32)Val8;
5558 if (SkGeSirqEvent(pAC, IoC,
5559 SK_HWEV_SET_LMODE,
5560 EventParam) > 0) {
5562 SK_ERR_LOG(pAC, SK_ERRCL_SW,
5563 SK_PNMI_ERR043,
5564 SK_PNMI_ERR043MSG);
5566 *pLen = 0;
5567 return (SK_PNMI_ERR_GENERAL);
5571 else {
5573 * Send an event with the new link mode to
5574 * the SIRQ module.
5576 EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS(
5577 pAC, LogPortIndex);
5578 EventParam.Para32[1] = (SK_U32)Val8;
5579 if (SkGeSirqEvent(pAC, IoC, SK_HWEV_SET_LMODE,
5580 EventParam) > 0) {
5582 SK_ERR_LOG(pAC, SK_ERRCL_SW,
5583 SK_PNMI_ERR043,
5584 SK_PNMI_ERR043MSG);
5586 *pLen = 0;
5587 return (SK_PNMI_ERR_GENERAL);
5590 Offset += sizeof(char);
5591 break;
5593 case OID_SKGE_FLOWCTRL_MODE:
5594 /* Check the value range */
5595 Val8 = *(pBuf + Offset);
5596 if (Val8 == 0) {
5598 Offset += sizeof(char);
5599 break;
5601 if (Val8 < SK_FLOW_MODE_NONE ||
5602 (LogPortIndex != 0 && Val8 > SK_FLOW_MODE_SYM_OR_REM) ||
5603 (LogPortIndex == 0 && Val8 > SK_FLOW_MODE_INDETERMINATED)) {
5605 *pLen = 0;
5606 return (SK_PNMI_ERR_BAD_VALUE);
5609 /* The preset ends here */
5610 if (Action == SK_PNMI_PRESET) {
5612 return (SK_PNMI_ERR_OK);
5615 if (LogPortIndex == 0) {
5618 * The virtual port consists of all currently
5619 * active ports. Find them and send an event
5620 * with the new flow control mode to SIRQ.
5622 for (PhysPortIndex = 0;
5623 PhysPortIndex < PhysPortMax;
5624 PhysPortIndex ++) {
5626 if (!pAC->Pnmi.Port[PhysPortIndex].
5627 ActiveFlag) {
5629 continue;
5632 EventParam.Para32[0] = PhysPortIndex;
5633 EventParam.Para32[1] = (SK_U32)Val8;
5634 if (SkGeSirqEvent(pAC, IoC,
5635 SK_HWEV_SET_FLOWMODE,
5636 EventParam) > 0) {
5638 SK_ERR_LOG(pAC, SK_ERRCL_SW,
5639 SK_PNMI_ERR044,
5640 SK_PNMI_ERR044MSG);
5642 *pLen = 0;
5643 return (SK_PNMI_ERR_GENERAL);
5647 else {
5649 * Send an event with the new flow control
5650 * mode to the SIRQ module.
5652 EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS(
5653 pAC, LogPortIndex);
5654 EventParam.Para32[1] = (SK_U32)Val8;
5655 if (SkGeSirqEvent(pAC, IoC,
5656 SK_HWEV_SET_FLOWMODE, EventParam)
5657 > 0) {
5659 SK_ERR_LOG(pAC, SK_ERRCL_SW,
5660 SK_PNMI_ERR044,
5661 SK_PNMI_ERR044MSG);
5663 *pLen = 0;
5664 return (SK_PNMI_ERR_GENERAL);
5667 Offset += sizeof(char);
5668 break;
5670 case OID_SKGE_PHY_OPERATION_MODE :
5671 /* Check the value range */
5672 Val8 = *(pBuf + Offset);
5673 if (Val8 == 0) {
5674 /* mode of this port remains unchanged */
5675 Offset += sizeof(char);
5676 break;
5678 if (Val8 < SK_MS_MODE_AUTO ||
5679 (LogPortIndex != 0 && Val8 > SK_MS_MODE_SLAVE) ||
5680 (LogPortIndex == 0 && Val8 > SK_MS_MODE_INDETERMINATED)) {
5682 *pLen = 0;
5683 return (SK_PNMI_ERR_BAD_VALUE);
5686 /* The preset ends here */
5687 if (Action == SK_PNMI_PRESET) {
5689 return (SK_PNMI_ERR_OK);
5692 if (LogPortIndex == 0) {
5695 * The virtual port consists of all currently
5696 * active ports. Find them and send an event
5697 * with new master/slave (role) mode to SIRQ.
5699 for (PhysPortIndex = 0;
5700 PhysPortIndex < PhysPortMax;
5701 PhysPortIndex ++) {
5703 if (!pAC->Pnmi.Port[PhysPortIndex].
5704 ActiveFlag) {
5706 continue;
5709 EventParam.Para32[0] = PhysPortIndex;
5710 EventParam.Para32[1] = (SK_U32)Val8;
5711 if (SkGeSirqEvent(pAC, IoC,
5712 SK_HWEV_SET_ROLE,
5713 EventParam) > 0) {
5715 SK_ERR_LOG(pAC, SK_ERRCL_SW,
5716 SK_PNMI_ERR042,
5717 SK_PNMI_ERR042MSG);
5719 *pLen = 0;
5720 return (SK_PNMI_ERR_GENERAL);
5724 else {
5726 * Send an event with the new master/slave
5727 * (role) mode to the SIRQ module.
5729 EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS(
5730 pAC, LogPortIndex);
5731 EventParam.Para32[1] = (SK_U32)Val8;
5732 if (SkGeSirqEvent(pAC, IoC,
5733 SK_HWEV_SET_ROLE, EventParam) > 0) {
5735 SK_ERR_LOG(pAC, SK_ERRCL_SW,
5736 SK_PNMI_ERR042,
5737 SK_PNMI_ERR042MSG);
5739 *pLen = 0;
5740 return (SK_PNMI_ERR_GENERAL);
5744 Offset += sizeof(char);
5745 break;
5747 case OID_SKGE_SPEED_MODE:
5748 /* Check the value range */
5749 Val8 = *(pBuf + Offset);
5750 if (Val8 == 0) {
5752 Offset += sizeof(char);
5753 break;
5755 if (Val8 < (SK_LSPEED_AUTO) ||
5756 (LogPortIndex != 0 && Val8 > (SK_LSPEED_1000MBPS)) ||
5757 (LogPortIndex == 0 && Val8 > (SK_LSPEED_INDETERMINATED))) {
5759 *pLen = 0;
5760 return (SK_PNMI_ERR_BAD_VALUE);
5763 /* The preset ends here */
5764 if (Action == SK_PNMI_PRESET) {
5766 return (SK_PNMI_ERR_OK);
5769 if (LogPortIndex == 0) {
5772 * The virtual port consists of all currently
5773 * active ports. Find them and send an event
5774 * with the new flow control mode to SIRQ.
5776 for (PhysPortIndex = 0;
5777 PhysPortIndex < PhysPortMax;
5778 PhysPortIndex ++) {
5780 if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
5782 continue;
5785 EventParam.Para32[0] = PhysPortIndex;
5786 EventParam.Para32[1] = (SK_U32)Val8;
5787 if (SkGeSirqEvent(pAC, IoC,
5788 SK_HWEV_SET_SPEED,
5789 EventParam) > 0) {
5791 SK_ERR_LOG(pAC, SK_ERRCL_SW,
5792 SK_PNMI_ERR045,
5793 SK_PNMI_ERR045MSG);
5795 *pLen = 0;
5796 return (SK_PNMI_ERR_GENERAL);
5800 else {
5802 * Send an event with the new flow control
5803 * mode to the SIRQ module.
5805 EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS(
5806 pAC, LogPortIndex);
5807 EventParam.Para32[1] = (SK_U32)Val8;
5808 if (SkGeSirqEvent(pAC, IoC,
5809 SK_HWEV_SET_SPEED,
5810 EventParam) > 0) {
5812 SK_ERR_LOG(pAC, SK_ERRCL_SW,
5813 SK_PNMI_ERR045,
5814 SK_PNMI_ERR045MSG);
5816 *pLen = 0;
5817 return (SK_PNMI_ERR_GENERAL);
5820 Offset += sizeof(char);
5821 break;
5823 case OID_SKGE_MTU :
5824 /* Check the value range */
5825 Val32 = *(SK_U32*)(pBuf + Offset);
5826 if (Val32 == 0) {
5827 /* mtu of this port remains unchanged */
5828 Offset += sizeof(SK_U32);
5829 break;
5831 if (SK_DRIVER_PRESET_MTU(pAC, IoC, NetIndex, Val32) != 0) {
5832 *pLen = 0;
5833 return (SK_PNMI_ERR_BAD_VALUE);
5836 /* The preset ends here */
5837 if (Action == SK_PNMI_PRESET) {
5838 return (SK_PNMI_ERR_OK);
5841 if (SK_DRIVER_SET_MTU(pAC, IoC, NetIndex, Val32) != 0) {
5842 return (SK_PNMI_ERR_GENERAL);
5845 Offset += sizeof(SK_U32);
5846 break;
5848 #ifdef SK_PHY_LP_MODE
5849 case OID_SKGE_PHY_LP_MODE:
5850 /* The preset ends here */
5851 if (Action == SK_PNMI_PRESET) {
5853 return (SK_PNMI_ERR_OK);
5856 if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
5857 if (LogPortIndex == 0) {
5858 Offset = 0;
5859 continue;
5861 else {
5862 /* Set value for physical ports */
5863 PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex);
5865 switch (*(pBuf + Offset)) {
5866 case 0:
5867 /* If LowPowerMode is active, we can leave it. */
5868 if (pAC->GIni.GP[PhysPortIndex].PPhyPowerState) {
5870 Val32 = SkGmLeaveLowPowerMode(pAC, IoC, PhysPortIndex);
5872 if (pAC->GIni.GP[PhysPortIndex].PPhyPowerState < 3) {
5874 SkDrvInitAdapter(pAC);
5876 break;
5878 else {
5879 *pLen = 0;
5880 return (SK_PNMI_ERR_GENERAL);
5882 case 1:
5883 case 2:
5884 case 3:
5885 case 4:
5886 /* If no LowPowerMode is active, we can enter it. */
5887 if (!pAC->GIni.GP[PhysPortIndex].PPhyPowerState) {
5889 if ((*(pBuf + Offset)) < 3) {
5891 SkDrvDeInitAdapter(pAC);
5894 Val32 = SkGmEnterLowPowerMode(pAC, IoC, PhysPortIndex, *pBuf);
5895 break;
5897 else {
5898 *pLen = 0;
5899 return (SK_PNMI_ERR_GENERAL);
5901 default:
5902 *pLen = 0;
5903 return (SK_PNMI_ERR_BAD_VALUE);
5907 else { /* DualNetMode */
5909 switch (*(pBuf + Offset)) {
5910 case 0:
5911 /* If we are in a LowPowerMode, we can leave it. */
5912 if (pAC->GIni.GP[PhysPortIndex].PPhyPowerState) {
5914 Val32 = SkGmLeaveLowPowerMode(pAC, IoC, PhysPortIndex);
5916 if (pAC->GIni.GP[PhysPortIndex].PPhyPowerState < 3) {
5918 SkDrvInitAdapter(pAC);
5920 break;
5922 else {
5923 *pLen = 0;
5924 return (SK_PNMI_ERR_GENERAL);
5927 case 1:
5928 case 2:
5929 case 3:
5930 case 4:
5931 /* If we are not already in LowPowerMode, we can enter it. */
5932 if (!pAC->GIni.GP[PhysPortIndex].PPhyPowerState) {
5934 if ((*(pBuf + Offset)) < 3) {
5936 SkDrvDeInitAdapter(pAC);
5938 else {
5940 Val32 = SkGmEnterLowPowerMode(pAC, IoC, PhysPortIndex, *pBuf);
5942 break;
5944 else {
5945 *pLen = 0;
5946 return (SK_PNMI_ERR_GENERAL);
5949 default:
5950 *pLen = 0;
5951 return (SK_PNMI_ERR_BAD_VALUE);
5954 Offset += sizeof(SK_U8);
5955 break;
5956 #endif
5958 default:
5959 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR,
5960 ("MacPrivateConf: Unknown OID should be handled before set"));
5962 *pLen = 0;
5963 return (SK_PNMI_ERR_GENERAL);
5967 return (SK_PNMI_ERR_OK);
5970 /*****************************************************************************
5972 * Monitor - OID handler function for RLMT_MONITOR_XXX
5974 * Description:
5975 * Because RLMT currently does not support the monitoring of
5976 * remote adapter cards, we return always an empty table.
5978 * Returns:
5979 * SK_PNMI_ERR_OK The request was successfully performed.
5980 * SK_PNMI_ERR_GENERAL A general severe internal error occured.
5981 * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
5982 * the correct data (e.g. a 32bit value is
5983 * needed, but a 16 bit value was passed).
5984 * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
5985 * value range.
5986 * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set.
5987 * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
5988 * exist (e.g. port instance 3 on a two port
5989 * adapter.
5991 PNMI_STATIC int Monitor(
5992 SK_AC *pAC, /* Pointer to adapter context */
5993 SK_IOC IoC, /* IO context handle */
5994 int Action, /* GET/PRESET/SET action */
5995 SK_U32 Id, /* Object ID that is to be processed */
5996 char *pBuf, /* Buffer used for the management data transfer */
5997 unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
5998 SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
5999 unsigned int TableIndex, /* Index to the Id table */
6000 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
6002 unsigned int Index;
6003 unsigned int Limit;
6004 unsigned int Offset;
6005 unsigned int Entries;
6009 * Calculate instance if wished.
6011 /* XXX Not yet implemented. Return always an empty table. */
6012 Entries = 0;
6014 if ((Instance != (SK_U32)(-1))) {
6016 if ((Instance < 1) || (Instance > Entries)) {
6018 *pLen = 0;
6019 return (SK_PNMI_ERR_UNKNOWN_INST);
6022 Index = (unsigned int)Instance - 1;
6023 Limit = (unsigned int)Instance;
6025 else {
6026 Index = 0;
6027 Limit = Entries;
6031 * Get/Set value
6033 if (Action == SK_PNMI_GET) {
6035 for (Offset=0; Index < Limit; Index ++) {
6037 switch (Id) {
6039 case OID_SKGE_RLMT_MONITOR_INDEX:
6040 case OID_SKGE_RLMT_MONITOR_ADDR:
6041 case OID_SKGE_RLMT_MONITOR_ERRS:
6042 case OID_SKGE_RLMT_MONITOR_TIMESTAMP:
6043 case OID_SKGE_RLMT_MONITOR_ADMIN:
6044 break;
6046 default:
6047 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR046,
6048 SK_PNMI_ERR046MSG);
6050 *pLen = 0;
6051 return (SK_PNMI_ERR_GENERAL);
6054 *pLen = Offset;
6056 else {
6057 /* Only MONITOR_ADMIN can be set */
6058 if (Id != OID_SKGE_RLMT_MONITOR_ADMIN) {
6060 *pLen = 0;
6061 return (SK_PNMI_ERR_READ_ONLY);
6064 /* Check if the length is plausible */
6065 if (*pLen < (Limit - Index)) {
6067 return (SK_PNMI_ERR_TOO_SHORT);
6069 /* Okay, we have a wide value range */
6070 if (*pLen != (Limit - Index)) {
6072 *pLen = 0;
6073 return (SK_PNMI_ERR_BAD_VALUE);
6076 for (Offset=0; Index < Limit; Index ++) {
6080 * XXX Not yet implemented. Return always BAD_VALUE, because the table
6081 * is empty.
6083 *pLen = 0;
6084 return (SK_PNMI_ERR_BAD_VALUE);
6087 return (SK_PNMI_ERR_OK);
6090 /*****************************************************************************
6092 * VirtualConf - Calculates the values of configuration OIDs for virtual port
6094 * Description:
6095 * We handle here the get of the configuration group OIDs, which are
6096 * a little bit complicated. The virtual port consists of all currently
6097 * active physical ports. If multiple ports are active and configured
6098 * differently we get in some trouble to return a single value. So we
6099 * get the value of the first active port and compare it with that of
6100 * the other active ports. If they are not the same, we return a value
6101 * that indicates that the state is indeterminated.
6103 * Returns:
6104 * Nothing
6106 PNMI_STATIC void VirtualConf(
6107 SK_AC *pAC, /* Pointer to adapter context */
6108 SK_IOC IoC, /* IO context handle */
6109 SK_U32 Id, /* Object ID that is to be processed */
6110 char *pBuf) /* Buffer used for the management data transfer */
6112 unsigned int PhysPortMax;
6113 unsigned int PhysPortIndex;
6114 SK_U8 Val8;
6115 SK_U32 Val32;
6116 SK_BOOL PortActiveFlag;
6117 SK_GEPORT *pPrt;
6119 *pBuf = 0;
6120 PortActiveFlag = SK_FALSE;
6121 PhysPortMax = pAC->GIni.GIMacsFound;
6123 for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax;
6124 PhysPortIndex ++) {
6126 pPrt = &pAC->GIni.GP[PhysPortIndex];
6128 /* Check if the physical port is active */
6129 if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
6131 continue;
6134 PortActiveFlag = SK_TRUE;
6136 switch (Id) {
6138 case OID_SKGE_PHY_TYPE:
6139 /* Check if it is the first active port */
6140 if (*pBuf == 0) {
6141 Val32 = pPrt->PhyType;
6142 SK_PNMI_STORE_U32(pBuf, Val32);
6143 continue;
6146 case OID_SKGE_LINK_CAP:
6149 * Different capabilities should not happen, but
6150 * in the case of the cases OR them all together.
6151 * From a curious point of view the virtual port
6152 * is capable of all found capabilities.
6154 *pBuf |= pPrt->PLinkCap;
6155 break;
6157 case OID_SKGE_LINK_MODE:
6158 /* Check if it is the first active port */
6159 if (*pBuf == 0) {
6161 *pBuf = pPrt->PLinkModeConf;
6162 continue;
6166 * If we find an active port with a different link
6167 * mode than the first one we return a value that
6168 * indicates that the link mode is indeterminated.
6170 if (*pBuf != pPrt->PLinkModeConf) {
6172 *pBuf = SK_LMODE_INDETERMINATED;
6174 break;
6176 case OID_SKGE_LINK_MODE_STATUS:
6177 /* Get the link mode of the physical port */
6178 Val8 = CalculateLinkModeStatus(pAC, IoC, PhysPortIndex);
6180 /* Check if it is the first active port */
6181 if (*pBuf == 0) {
6183 *pBuf = Val8;
6184 continue;
6188 * If we find an active port with a different link
6189 * mode status than the first one we return a value
6190 * that indicates that the link mode status is
6191 * indeterminated.
6193 if (*pBuf != Val8) {
6195 *pBuf = SK_LMODE_STAT_INDETERMINATED;
6197 break;
6199 case OID_SKGE_LINK_STATUS:
6200 /* Get the link status of the physical port */
6201 Val8 = CalculateLinkStatus(pAC, IoC, PhysPortIndex);
6203 /* Check if it is the first active port */
6204 if (*pBuf == 0) {
6206 *pBuf = Val8;
6207 continue;
6211 * If we find an active port with a different link
6212 * status than the first one, we return a value
6213 * that indicates that the link status is
6214 * indeterminated.
6216 if (*pBuf != Val8) {
6218 *pBuf = SK_PNMI_RLMT_LSTAT_INDETERMINATED;
6220 break;
6222 case OID_SKGE_FLOWCTRL_CAP:
6223 /* Check if it is the first active port */
6224 if (*pBuf == 0) {
6226 *pBuf = pPrt->PFlowCtrlCap;
6227 continue;
6231 * From a curious point of view the virtual port
6232 * is capable of all found capabilities.
6234 *pBuf |= pPrt->PFlowCtrlCap;
6235 break;
6237 case OID_SKGE_FLOWCTRL_MODE:
6238 /* Check if it is the first active port */
6239 if (*pBuf == 0) {
6241 *pBuf = pPrt->PFlowCtrlMode;
6242 continue;
6246 * If we find an active port with a different flow
6247 * control mode than the first one, we return a value
6248 * that indicates that the mode is indeterminated.
6250 if (*pBuf != pPrt->PFlowCtrlMode) {
6252 *pBuf = SK_FLOW_MODE_INDETERMINATED;
6254 break;
6256 case OID_SKGE_FLOWCTRL_STATUS:
6257 /* Check if it is the first active port */
6258 if (*pBuf == 0) {
6260 *pBuf = pPrt->PFlowCtrlStatus;
6261 continue;
6265 * If we find an active port with a different flow
6266 * control status than the first one, we return a
6267 * value that indicates that the status is
6268 * indeterminated.
6270 if (*pBuf != pPrt->PFlowCtrlStatus) {
6272 *pBuf = SK_FLOW_STAT_INDETERMINATED;
6274 break;
6276 case OID_SKGE_PHY_OPERATION_CAP:
6277 /* Check if it is the first active port */
6278 if (*pBuf == 0) {
6280 *pBuf = pPrt->PMSCap;
6281 continue;
6285 * From a curious point of view the virtual port
6286 * is capable of all found capabilities.
6288 *pBuf |= pPrt->PMSCap;
6289 break;
6291 case OID_SKGE_PHY_OPERATION_MODE:
6292 /* Check if it is the first active port */
6293 if (*pBuf == 0) {
6295 *pBuf = pPrt->PMSMode;
6296 continue;
6300 * If we find an active port with a different master/
6301 * slave mode than the first one, we return a value
6302 * that indicates that the mode is indeterminated.
6304 if (*pBuf != pPrt->PMSMode) {
6306 *pBuf = SK_MS_MODE_INDETERMINATED;
6308 break;
6310 case OID_SKGE_PHY_OPERATION_STATUS:
6311 /* Check if it is the first active port */
6312 if (*pBuf == 0) {
6314 *pBuf = pPrt->PMSStatus;
6315 continue;
6319 * If we find an active port with a different master/
6320 * slave status than the first one, we return a
6321 * value that indicates that the status is
6322 * indeterminated.
6324 if (*pBuf != pPrt->PMSStatus) {
6326 *pBuf = SK_MS_STAT_INDETERMINATED;
6328 break;
6330 case OID_SKGE_SPEED_MODE:
6331 /* Check if it is the first active port */
6332 if (*pBuf == 0) {
6334 *pBuf = pPrt->PLinkSpeed;
6335 continue;
6339 * If we find an active port with a different flow
6340 * control mode than the first one, we return a value
6341 * that indicates that the mode is indeterminated.
6343 if (*pBuf != pPrt->PLinkSpeed) {
6345 *pBuf = SK_LSPEED_INDETERMINATED;
6347 break;
6349 case OID_SKGE_SPEED_STATUS:
6350 /* Check if it is the first active port */
6351 if (*pBuf == 0) {
6353 *pBuf = pPrt->PLinkSpeedUsed;
6354 continue;
6358 * If we find an active port with a different flow
6359 * control status than the first one, we return a
6360 * value that indicates that the status is
6361 * indeterminated.
6363 if (*pBuf != pPrt->PLinkSpeedUsed) {
6365 *pBuf = SK_LSPEED_STAT_INDETERMINATED;
6367 break;
6372 * If no port is active return an indeterminated answer
6374 if (!PortActiveFlag) {
6376 switch (Id) {
6378 case OID_SKGE_LINK_CAP:
6379 *pBuf = SK_LMODE_CAP_INDETERMINATED;
6380 break;
6382 case OID_SKGE_LINK_MODE:
6383 *pBuf = SK_LMODE_INDETERMINATED;
6384 break;
6386 case OID_SKGE_LINK_MODE_STATUS:
6387 *pBuf = SK_LMODE_STAT_INDETERMINATED;
6388 break;
6390 case OID_SKGE_LINK_STATUS:
6391 *pBuf = SK_PNMI_RLMT_LSTAT_INDETERMINATED;
6392 break;
6394 case OID_SKGE_FLOWCTRL_CAP:
6395 case OID_SKGE_FLOWCTRL_MODE:
6396 *pBuf = SK_FLOW_MODE_INDETERMINATED;
6397 break;
6399 case OID_SKGE_FLOWCTRL_STATUS:
6400 *pBuf = SK_FLOW_STAT_INDETERMINATED;
6401 break;
6403 case OID_SKGE_PHY_OPERATION_CAP:
6404 *pBuf = SK_MS_CAP_INDETERMINATED;
6405 break;
6407 case OID_SKGE_PHY_OPERATION_MODE:
6408 *pBuf = SK_MS_MODE_INDETERMINATED;
6409 break;
6411 case OID_SKGE_PHY_OPERATION_STATUS:
6412 *pBuf = SK_MS_STAT_INDETERMINATED;
6413 break;
6414 case OID_SKGE_SPEED_CAP:
6415 *pBuf = SK_LSPEED_CAP_INDETERMINATED;
6416 break;
6418 case OID_SKGE_SPEED_MODE:
6419 *pBuf = SK_LSPEED_INDETERMINATED;
6420 break;
6422 case OID_SKGE_SPEED_STATUS:
6423 *pBuf = SK_LSPEED_STAT_INDETERMINATED;
6424 break;
6429 /*****************************************************************************
6431 * CalculateLinkStatus - Determins the link status of a physical port
6433 * Description:
6434 * Determins the link status the following way:
6435 * LSTAT_PHY_DOWN: Link is down
6436 * LSTAT_AUTONEG: Auto-negotiation failed
6437 * LSTAT_LOG_DOWN: Link is up but RLMT did not yet put the port
6438 * logically up.
6439 * LSTAT_LOG_UP: RLMT marked the port as up
6441 * Returns:
6442 * Link status of physical port
6444 PNMI_STATIC SK_U8 CalculateLinkStatus(
6445 SK_AC *pAC, /* Pointer to adapter context */
6446 SK_IOC IoC, /* IO context handle */
6447 unsigned int PhysPortIndex) /* Physical port index */
6449 SK_U8 Result;
6451 if (!pAC->GIni.GP[PhysPortIndex].PHWLinkUp) {
6453 Result = SK_PNMI_RLMT_LSTAT_PHY_DOWN;
6455 else if (pAC->GIni.GP[PhysPortIndex].PAutoNegFail > 0) {
6457 Result = SK_PNMI_RLMT_LSTAT_AUTONEG;
6459 else if (!pAC->Rlmt.Port[PhysPortIndex].PortDown) {
6461 Result = SK_PNMI_RLMT_LSTAT_LOG_UP;
6463 else {
6464 Result = SK_PNMI_RLMT_LSTAT_LOG_DOWN;
6467 return (Result);
6470 /*****************************************************************************
6472 * CalculateLinkModeStatus - Determins the link mode status of a phys. port
6474 * Description:
6475 * The COMMON module only tells us if the mode is half or full duplex.
6476 * But in the decade of auto sensing it is usefull for the user to
6477 * know if the mode was negotiated or forced. Therefore we have a
6478 * look to the mode, which was last used by the negotiation process.
6480 * Returns:
6481 * The link mode status
6483 PNMI_STATIC SK_U8 CalculateLinkModeStatus(
6484 SK_AC *pAC, /* Pointer to adapter context */
6485 SK_IOC IoC, /* IO context handle */
6486 unsigned int PhysPortIndex) /* Physical port index */
6488 SK_U8 Result;
6490 /* Get the current mode, which can be full or half duplex */
6491 Result = pAC->GIni.GP[PhysPortIndex].PLinkModeStatus;
6493 /* Check if no valid mode could be found (link is down) */
6494 if (Result < SK_LMODE_STAT_HALF) {
6496 Result = SK_LMODE_STAT_UNKNOWN;
6498 else if (pAC->GIni.GP[PhysPortIndex].PLinkMode >= SK_LMODE_AUTOHALF) {
6501 * Auto-negotiation was used to bring up the link. Change
6502 * the already found duplex status that it indicates
6503 * auto-negotiation was involved.
6505 if (Result == SK_LMODE_STAT_HALF) {
6507 Result = SK_LMODE_STAT_AUTOHALF;
6509 else if (Result == SK_LMODE_STAT_FULL) {
6511 Result = SK_LMODE_STAT_AUTOFULL;
6515 return (Result);
6518 /*****************************************************************************
6520 * GetVpdKeyArr - Obtain an array of VPD keys
6522 * Description:
6523 * Read the VPD keys and build an array of VPD keys, which are
6524 * easy to access.
6526 * Returns:
6527 * SK_PNMI_ERR_OK Task successfully performed.
6528 * SK_PNMI_ERR_GENERAL Something went wrong.
6530 PNMI_STATIC int GetVpdKeyArr(
6531 SK_AC *pAC, /* Pointer to adapter context */
6532 SK_IOC IoC, /* IO context handle */
6533 char *pKeyArr, /* Ptr KeyArray */
6534 unsigned int KeyArrLen, /* Length of array in bytes */
6535 unsigned int *pKeyNo) /* Number of keys */
6537 unsigned int BufKeysLen = SK_PNMI_VPD_BUFSIZE;
6538 char BufKeys[SK_PNMI_VPD_BUFSIZE];
6539 unsigned int StartOffset;
6540 unsigned int Offset;
6541 int Index;
6542 int Ret;
6545 SK_MEMSET(pKeyArr, 0, KeyArrLen);
6548 * Get VPD key list
6550 Ret = VpdKeys(pAC, IoC, (char *)&BufKeys, (int *)&BufKeysLen,
6551 (int *)pKeyNo);
6552 if (Ret > 0) {
6554 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR014,
6555 SK_PNMI_ERR014MSG);
6557 return (SK_PNMI_ERR_GENERAL);
6559 /* If no keys are available return now */
6560 if (*pKeyNo == 0 || BufKeysLen == 0) {
6562 return (SK_PNMI_ERR_OK);
6565 * If the key list is too long for us trunc it and give a
6566 * errorlog notification. This case should not happen because
6567 * the maximum number of keys is limited due to RAM limitations
6569 if (*pKeyNo > SK_PNMI_VPD_ENTRIES) {
6571 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR015,
6572 SK_PNMI_ERR015MSG);
6574 *pKeyNo = SK_PNMI_VPD_ENTRIES;
6578 * Now build an array of fixed string length size and copy
6579 * the keys together.
6581 for (Index = 0, StartOffset = 0, Offset = 0; Offset < BufKeysLen;
6582 Offset ++) {
6584 if (BufKeys[Offset] != 0) {
6586 continue;
6589 if (Offset - StartOffset > SK_PNMI_VPD_KEY_SIZE) {
6591 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR016,
6592 SK_PNMI_ERR016MSG);
6593 return (SK_PNMI_ERR_GENERAL);
6596 SK_STRNCPY(pKeyArr + Index * SK_PNMI_VPD_KEY_SIZE,
6597 &BufKeys[StartOffset], SK_PNMI_VPD_KEY_SIZE);
6599 Index ++;
6600 StartOffset = Offset + 1;
6603 /* Last key not zero terminated? Get it anyway */
6604 if (StartOffset < Offset) {
6606 SK_STRNCPY(pKeyArr + Index * SK_PNMI_VPD_KEY_SIZE,
6607 &BufKeys[StartOffset], SK_PNMI_VPD_KEY_SIZE);
6610 return (SK_PNMI_ERR_OK);
6613 /*****************************************************************************
6615 * SirqUpdate - Let the SIRQ update its internal values
6617 * Description:
6618 * Just to be sure that the SIRQ module holds its internal data
6619 * structures up to date, we send an update event before we make
6620 * any access.
6622 * Returns:
6623 * SK_PNMI_ERR_OK Task successfully performed.
6624 * SK_PNMI_ERR_GENERAL Something went wrong.
6626 PNMI_STATIC int SirqUpdate(
6627 SK_AC *pAC, /* Pointer to adapter context */
6628 SK_IOC IoC) /* IO context handle */
6630 SK_EVPARA EventParam;
6633 /* Was the module already updated during the current PNMI call? */
6634 if (pAC->Pnmi.SirqUpdatedFlag > 0) {
6636 return (SK_PNMI_ERR_OK);
6639 /* Send an synchronuous update event to the module */
6640 SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
6641 if (SkGeSirqEvent(pAC, IoC, SK_HWEV_UPDATE_STAT, EventParam) > 0) {
6643 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR047,
6644 SK_PNMI_ERR047MSG);
6646 return (SK_PNMI_ERR_GENERAL);
6649 return (SK_PNMI_ERR_OK);
6652 /*****************************************************************************
6654 * RlmtUpdate - Let the RLMT update its internal values
6656 * Description:
6657 * Just to be sure that the RLMT module holds its internal data
6658 * structures up to date, we send an update event before we make
6659 * any access.
6661 * Returns:
6662 * SK_PNMI_ERR_OK Task successfully performed.
6663 * SK_PNMI_ERR_GENERAL Something went wrong.
6665 PNMI_STATIC int RlmtUpdate(
6666 SK_AC *pAC, /* Pointer to adapter context */
6667 SK_IOC IoC, /* IO context handle */
6668 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */
6670 SK_EVPARA EventParam;
6673 /* Was the module already updated during the current PNMI call? */
6674 if (pAC->Pnmi.RlmtUpdatedFlag > 0) {
6676 return (SK_PNMI_ERR_OK);
6679 /* Send an synchronuous update event to the module */
6680 SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
6681 EventParam.Para32[0] = NetIndex;
6682 EventParam.Para32[1] = (SK_U32)-1;
6683 if (SkRlmtEvent(pAC, IoC, SK_RLMT_STATS_UPDATE, EventParam) > 0) {
6685 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR048,
6686 SK_PNMI_ERR048MSG);
6688 return (SK_PNMI_ERR_GENERAL);
6691 return (SK_PNMI_ERR_OK);
6694 /*****************************************************************************
6696 * MacUpdate - Force the XMAC to output the current statistic
6698 * Description:
6699 * The XMAC holds its statistic internally. To obtain the current
6700 * values we must send a command so that the statistic data will
6701 * be written to a predefined memory area on the adapter.
6703 * Returns:
6704 * SK_PNMI_ERR_OK Task successfully performed.
6705 * SK_PNMI_ERR_GENERAL Something went wrong.
6707 PNMI_STATIC int MacUpdate(
6708 SK_AC *pAC, /* Pointer to adapter context */
6709 SK_IOC IoC, /* IO context handle */
6710 unsigned int FirstMac, /* Index of the first Mac to be updated */
6711 unsigned int LastMac) /* Index of the last Mac to be updated */
6713 unsigned int MacIndex;
6716 * Were the statistics already updated during the
6717 * current PNMI call?
6719 if (pAC->Pnmi.MacUpdatedFlag > 0) {
6721 return (SK_PNMI_ERR_OK);
6724 /* Send an update command to all MACs specified */
6725 for (MacIndex = FirstMac; MacIndex <= LastMac; MacIndex ++) {
6728 * 2002-09-13 pweber: Freeze the current SW counters.
6729 * (That should be done as close as
6730 * possible to the update of the
6731 * HW counters)
6733 if (pAC->GIni.GIMacType == SK_MAC_XMAC) {
6734 pAC->Pnmi.BufPort[MacIndex] = pAC->Pnmi.Port[MacIndex];
6737 /* 2002-09-13 pweber: Update the HW counter */
6738 if (pAC->GIni.GIFunc.pFnMacUpdateStats(pAC, IoC, MacIndex) != 0) {
6740 return (SK_PNMI_ERR_GENERAL);
6744 return (SK_PNMI_ERR_OK);
6747 /*****************************************************************************
6749 * GetStatVal - Retrieve an XMAC statistic counter
6751 * Description:
6752 * Retrieves the statistic counter of a virtual or physical port. The
6753 * virtual port is identified by the index 0. It consists of all
6754 * currently active ports. To obtain the counter value for this port
6755 * we must add the statistic counter of all active ports. To grant
6756 * continuous counter values for the virtual port even when port
6757 * switches occur we must additionally add a delta value, which was
6758 * calculated during a SK_PNMI_EVT_RLMT_ACTIVE_UP event.
6760 * Returns:
6761 * Requested statistic value
6763 PNMI_STATIC SK_U64 GetStatVal(
6764 SK_AC *pAC, /* Pointer to adapter context */
6765 SK_IOC IoC, /* IO context handle */
6766 unsigned int LogPortIndex, /* Index of the logical Port to be processed */
6767 unsigned int StatIndex, /* Index to statistic value */
6768 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */
6770 unsigned int PhysPortIndex;
6771 unsigned int PhysPortMax;
6772 SK_U64 Val = 0;
6775 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */
6777 PhysPortIndex = NetIndex;
6779 Val = GetPhysStatVal(pAC, IoC, PhysPortIndex, StatIndex);
6781 else { /* Single Net mode */
6783 if (LogPortIndex == 0) {
6785 PhysPortMax = pAC->GIni.GIMacsFound;
6787 /* Add counter of all active ports */
6788 for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax;
6789 PhysPortIndex ++) {
6791 if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
6793 Val += GetPhysStatVal(pAC, IoC, PhysPortIndex, StatIndex);
6797 /* Correct value because of port switches */
6798 Val += pAC->Pnmi.VirtualCounterOffset[StatIndex];
6800 else {
6801 /* Get counter value of physical port */
6802 PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex);
6804 Val = GetPhysStatVal(pAC, IoC, PhysPortIndex, StatIndex);
6807 return (Val);
6810 /*****************************************************************************
6812 * GetPhysStatVal - Get counter value for physical port
6814 * Description:
6815 * Builds a 64bit counter value. Except for the octet counters
6816 * the lower 32bit are counted in hardware and the upper 32bit
6817 * in software by monitoring counter overflow interrupts in the
6818 * event handler. To grant continous counter values during XMAC
6819 * resets (caused by a workaround) we must add a delta value.
6820 * The delta was calculated in the event handler when a
6821 * SK_PNMI_EVT_XMAC_RESET was received.
6823 * Returns:
6824 * Counter value
6826 PNMI_STATIC SK_U64 GetPhysStatVal(
6827 SK_AC *pAC, /* Pointer to adapter context */
6828 SK_IOC IoC, /* IO context handle */
6829 unsigned int PhysPortIndex, /* Index of the logical Port to be processed */
6830 unsigned int StatIndex) /* Index to statistic value */
6832 SK_U64 Val = 0;
6833 SK_U32 LowVal = 0;
6834 SK_U32 HighVal = 0;
6835 SK_U16 Word;
6836 int MacType;
6837 unsigned int HelpIndex;
6838 SK_GEPORT *pPrt;
6840 SK_PNMI_PORT *pPnmiPrt;
6841 SK_GEMACFUNC *pFnMac;
6843 pPrt = &pAC->GIni.GP[PhysPortIndex];
6845 MacType = pAC->GIni.GIMacType;
6847 /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
6848 if (MacType == SK_MAC_XMAC) {
6849 pPnmiPrt = &pAC->Pnmi.BufPort[PhysPortIndex];
6851 else {
6852 pPnmiPrt = &pAC->Pnmi.Port[PhysPortIndex];
6855 pFnMac = &pAC->GIni.GIFunc;
6857 switch (StatIndex) {
6858 case SK_PNMI_HTX:
6859 if (MacType == SK_MAC_GMAC) {
6860 (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
6861 StatAddr[SK_PNMI_HTX_BROADCAST][MacType].Reg,
6862 &LowVal);
6863 (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
6864 StatAddr[SK_PNMI_HTX_MULTICAST][MacType].Reg,
6865 &HighVal);
6866 LowVal += HighVal;
6867 (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
6868 StatAddr[SK_PNMI_HTX_UNICAST][MacType].Reg,
6869 &HighVal);
6870 LowVal += HighVal;
6872 else {
6873 (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
6874 StatAddr[StatIndex][MacType].Reg,
6875 &LowVal);
6877 HighVal = pPnmiPrt->CounterHigh[StatIndex];
6878 break;
6880 case SK_PNMI_HRX:
6881 if (MacType == SK_MAC_GMAC) {
6882 (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
6883 StatAddr[SK_PNMI_HRX_BROADCAST][MacType].Reg,
6884 &LowVal);
6885 (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
6886 StatAddr[SK_PNMI_HRX_MULTICAST][MacType].Reg,
6887 &HighVal);
6888 LowVal += HighVal;
6889 (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
6890 StatAddr[SK_PNMI_HRX_UNICAST][MacType].Reg,
6891 &HighVal);
6892 LowVal += HighVal;
6894 else {
6895 (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
6896 StatAddr[StatIndex][MacType].Reg,
6897 &LowVal);
6899 HighVal = pPnmiPrt->CounterHigh[StatIndex];
6900 break;
6902 case SK_PNMI_HTX_OCTET:
6903 case SK_PNMI_HRX_OCTET:
6904 (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
6905 StatAddr[StatIndex][MacType].Reg,
6906 &HighVal);
6907 (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
6908 StatAddr[StatIndex + 1][MacType].Reg,
6909 &LowVal);
6910 break;
6912 case SK_PNMI_HTX_BURST:
6913 case SK_PNMI_HTX_EXCESS_DEF:
6914 case SK_PNMI_HTX_CARRIER:
6915 /* Not supported by GMAC */
6916 if (MacType == SK_MAC_GMAC) {
6917 return (Val);
6920 (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
6921 StatAddr[StatIndex][MacType].Reg,
6922 &LowVal);
6923 HighVal = pPnmiPrt->CounterHigh[StatIndex];
6924 break;
6926 case SK_PNMI_HTX_MACC:
6927 /* GMAC only supports PAUSE MAC control frames */
6928 if (MacType == SK_MAC_GMAC) {
6929 HelpIndex = SK_PNMI_HTX_PMACC;
6931 else {
6932 HelpIndex = StatIndex;
6935 (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
6936 StatAddr[HelpIndex][MacType].Reg,
6937 &LowVal);
6939 HighVal = pPnmiPrt->CounterHigh[StatIndex];
6940 break;
6942 case SK_PNMI_HTX_COL:
6943 case SK_PNMI_HRX_UNDERSIZE:
6944 /* Not supported by XMAC */
6945 if (MacType == SK_MAC_XMAC) {
6946 return (Val);
6949 (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
6950 StatAddr[StatIndex][MacType].Reg,
6951 &LowVal);
6952 HighVal = pPnmiPrt->CounterHigh[StatIndex];
6953 break;
6955 case SK_PNMI_HTX_DEFFERAL:
6956 /* Not supported by GMAC */
6957 if (MacType == SK_MAC_GMAC) {
6958 return (Val);
6962 * XMAC counts frames with deferred transmission
6963 * even in full-duplex mode.
6965 * In full-duplex mode the counter remains constant!
6967 if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL) ||
6968 (pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL)) {
6970 LowVal = 0;
6971 HighVal = 0;
6973 else {
6974 /* Otherwise get contents of hardware register */
6975 (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
6976 StatAddr[StatIndex][MacType].Reg,
6977 &LowVal);
6978 HighVal = pPnmiPrt->CounterHigh[StatIndex];
6980 break;
6982 case SK_PNMI_HRX_BADOCTET:
6983 /* Not supported by XMAC */
6984 if (MacType == SK_MAC_XMAC) {
6985 return (Val);
6988 (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
6989 StatAddr[StatIndex][MacType].Reg,
6990 &HighVal);
6991 (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
6992 StatAddr[StatIndex + 1][MacType].Reg,
6993 &LowVal);
6994 break;
6996 case SK_PNMI_HTX_OCTETLOW:
6997 case SK_PNMI_HRX_OCTETLOW:
6998 case SK_PNMI_HRX_BADOCTETLOW:
6999 return (Val);
7001 case SK_PNMI_HRX_LONGFRAMES:
7002 /* For XMAC the SW counter is managed by PNMI */
7003 if (MacType == SK_MAC_XMAC) {
7004 return (pPnmiPrt->StatRxLongFrameCts);
7007 (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
7008 StatAddr[StatIndex][MacType].Reg,
7009 &LowVal);
7010 HighVal = pPnmiPrt->CounterHigh[StatIndex];
7011 break;
7013 case SK_PNMI_HRX_TOO_LONG:
7014 (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
7015 StatAddr[StatIndex][MacType].Reg,
7016 &LowVal);
7017 HighVal = pPnmiPrt->CounterHigh[StatIndex];
7019 Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal);
7021 if (MacType == SK_MAC_GMAC) {
7022 /* For GMAC the SW counter is additionally managed by PNMI */
7023 Val += pPnmiPrt->StatRxFrameTooLongCts;
7025 else {
7027 * Frames longer than IEEE 802.3 frame max size are counted
7028 * by XMAC in frame_too_long counter even reception of long
7029 * frames was enabled and the frame was correct.
7030 * So correct the value by subtracting RxLongFrame counter.
7032 Val -= pPnmiPrt->StatRxLongFrameCts;
7035 LowVal = (SK_U32)Val;
7036 HighVal = (SK_U32)(Val >> 32);
7037 break;
7039 case SK_PNMI_HRX_SHORTS:
7040 /* Not supported by GMAC */
7041 if (MacType == SK_MAC_GMAC) {
7042 /* GM_RXE_FRAG?? */
7043 return (Val);
7047 * XMAC counts short frame errors even if link down (#10620)
7049 * If link-down the counter remains constant
7051 if (pPrt->PLinkModeStatus != SK_LMODE_STAT_UNKNOWN) {
7053 /* Otherwise get incremental difference */
7054 (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
7055 StatAddr[StatIndex][MacType].Reg,
7056 &LowVal);
7057 HighVal = pPnmiPrt->CounterHigh[StatIndex];
7059 Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal);
7060 Val -= pPnmiPrt->RxShortZeroMark;
7062 LowVal = (SK_U32)Val;
7063 HighVal = (SK_U32)(Val >> 32);
7065 break;
7067 case SK_PNMI_HRX_MACC:
7068 case SK_PNMI_HRX_MACC_UNKWN:
7069 case SK_PNMI_HRX_BURST:
7070 case SK_PNMI_HRX_MISSED:
7071 case SK_PNMI_HRX_FRAMING:
7072 case SK_PNMI_HRX_CARRIER:
7073 case SK_PNMI_HRX_IRLENGTH:
7074 case SK_PNMI_HRX_SYMBOL:
7075 case SK_PNMI_HRX_CEXT:
7076 /* Not supported by GMAC */
7077 if (MacType == SK_MAC_GMAC) {
7078 return (Val);
7081 (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
7082 StatAddr[StatIndex][MacType].Reg,
7083 &LowVal);
7084 HighVal = pPnmiPrt->CounterHigh[StatIndex];
7085 break;
7087 case SK_PNMI_HRX_PMACC_ERR:
7088 /* For GMAC the SW counter is managed by PNMI */
7089 if (MacType == SK_MAC_GMAC) {
7090 return (pPnmiPrt->StatRxPMaccErr);
7093 (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
7094 StatAddr[StatIndex][MacType].Reg,
7095 &LowVal);
7096 HighVal = pPnmiPrt->CounterHigh[StatIndex];
7097 break;
7099 /* SW counter managed by PNMI */
7100 case SK_PNMI_HTX_SYNC:
7101 LowVal = (SK_U32)pPnmiPrt->StatSyncCts;
7102 HighVal = (SK_U32)(pPnmiPrt->StatSyncCts >> 32);
7103 break;
7105 /* SW counter managed by PNMI */
7106 case SK_PNMI_HTX_SYNC_OCTET:
7107 LowVal = (SK_U32)pPnmiPrt->StatSyncOctetsCts;
7108 HighVal = (SK_U32)(pPnmiPrt->StatSyncOctetsCts >> 32);
7109 break;
7111 case SK_PNMI_HRX_FCS:
7113 * Broadcom filters FCS errors and counts it in
7114 * Receive Error Counter register
7116 if (pPrt->PhyType == SK_PHY_BCOM) {
7117 /* do not read while not initialized (PHY_READ hangs!)*/
7118 if (pPrt->PState != SK_PRT_RESET) {
7119 SkXmPhyRead(pAC, IoC, PhysPortIndex, PHY_BCOM_RE_CTR, &Word);
7121 LowVal = Word;
7123 HighVal = pPnmiPrt->CounterHigh[StatIndex];
7125 else {
7126 (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
7127 StatAddr[StatIndex][MacType].Reg,
7128 &LowVal);
7129 HighVal = pPnmiPrt->CounterHigh[StatIndex];
7131 break;
7133 default:
7134 (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
7135 StatAddr[StatIndex][MacType].Reg,
7136 &LowVal);
7137 HighVal = pPnmiPrt->CounterHigh[StatIndex];
7138 break;
7141 Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal);
7143 /* Correct value because of possible XMAC reset. XMAC Errata #2 */
7144 Val += pPnmiPrt->CounterOffset[StatIndex];
7146 return (Val);
7149 /*****************************************************************************
7151 * ResetCounter - Set all counters and timestamps to zero
7153 * Description:
7154 * Notifies other common modules which store statistic data to
7155 * reset their counters and finally reset our own counters.
7157 * Returns:
7158 * Nothing
7160 PNMI_STATIC void ResetCounter(
7161 SK_AC *pAC, /* Pointer to adapter context */
7162 SK_IOC IoC, /* IO context handle */
7163 SK_U32 NetIndex)
7165 unsigned int PhysPortIndex;
7166 SK_EVPARA EventParam;
7169 SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
7171 /* Notify sensor module */
7172 SkEventQueue(pAC, SKGE_I2C, SK_I2CEV_CLEAR, EventParam);
7174 /* Notify RLMT module */
7175 EventParam.Para32[0] = NetIndex;
7176 EventParam.Para32[1] = (SK_U32)-1;
7177 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STATS_CLEAR, EventParam);
7178 EventParam.Para32[1] = 0;
7180 /* Notify SIRQ module */
7181 SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_CLEAR_STAT, EventParam);
7183 /* Notify CSUM module */
7184 #ifdef SK_USE_CSUM
7185 EventParam.Para32[0] = NetIndex;
7186 EventParam.Para32[1] = (SK_U32)-1;
7187 SkEventQueue(pAC, SKGE_CSUM, SK_CSUM_EVENT_CLEAR_PROTO_STATS,
7188 EventParam);
7189 #endif /* SK_USE_CSUM */
7191 /* Clear XMAC statistic */
7192 for (PhysPortIndex = 0; PhysPortIndex <
7193 (unsigned int)pAC->GIni.GIMacsFound; PhysPortIndex ++) {
7195 (void)pAC->GIni.GIFunc.pFnMacResetCounter(pAC, IoC, PhysPortIndex);
7197 SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].CounterHigh,
7198 0, sizeof(pAC->Pnmi.Port[PhysPortIndex].CounterHigh));
7199 SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].
7200 CounterOffset, 0, sizeof(pAC->Pnmi.Port[
7201 PhysPortIndex].CounterOffset));
7202 SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].StatSyncCts,
7203 0, sizeof(pAC->Pnmi.Port[PhysPortIndex].StatSyncCts));
7204 SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].
7205 StatSyncOctetsCts, 0, sizeof(pAC->Pnmi.Port[
7206 PhysPortIndex].StatSyncOctetsCts));
7207 SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].
7208 StatRxLongFrameCts, 0, sizeof(pAC->Pnmi.Port[
7209 PhysPortIndex].StatRxLongFrameCts));
7210 SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].
7211 StatRxFrameTooLongCts, 0, sizeof(pAC->Pnmi.Port[
7212 PhysPortIndex].StatRxFrameTooLongCts));
7213 SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].
7214 StatRxPMaccErr, 0, sizeof(pAC->Pnmi.Port[
7215 PhysPortIndex].StatRxPMaccErr));
7219 * Clear local statistics
7221 SK_MEMSET((char *)&pAC->Pnmi.VirtualCounterOffset, 0,
7222 sizeof(pAC->Pnmi.VirtualCounterOffset));
7223 pAC->Pnmi.RlmtChangeCts = 0;
7224 pAC->Pnmi.RlmtChangeTime = 0;
7225 SK_MEMSET((char *)&pAC->Pnmi.RlmtChangeEstimate.EstValue[0], 0,
7226 sizeof(pAC->Pnmi.RlmtChangeEstimate.EstValue));
7227 pAC->Pnmi.RlmtChangeEstimate.EstValueIndex = 0;
7228 pAC->Pnmi.RlmtChangeEstimate.Estimate = 0;
7229 pAC->Pnmi.Port[NetIndex].TxSwQueueMax = 0;
7230 pAC->Pnmi.Port[NetIndex].TxRetryCts = 0;
7231 pAC->Pnmi.Port[NetIndex].RxIntrCts = 0;
7232 pAC->Pnmi.Port[NetIndex].TxIntrCts = 0;
7233 pAC->Pnmi.Port[NetIndex].RxNoBufCts = 0;
7234 pAC->Pnmi.Port[NetIndex].TxNoBufCts = 0;
7235 pAC->Pnmi.Port[NetIndex].TxUsedDescrNo = 0;
7236 pAC->Pnmi.Port[NetIndex].RxDeliveredCts = 0;
7237 pAC->Pnmi.Port[NetIndex].RxOctetsDeliveredCts = 0;
7238 pAC->Pnmi.Port[NetIndex].ErrRecoveryCts = 0;
7241 /*****************************************************************************
7243 * GetTrapEntry - Get an entry in the trap buffer
7245 * Description:
7246 * The trap buffer stores various events. A user application somehow
7247 * gets notified that an event occured and retrieves the trap buffer
7248 * contens (or simply polls the buffer). The buffer is organized as
7249 * a ring which stores the newest traps at the beginning. The oldest
7250 * traps are overwritten by the newest ones. Each trap entry has a
7251 * unique number, so that applications may detect new trap entries.
7253 * Returns:
7254 * A pointer to the trap entry
7256 PNMI_STATIC char* GetTrapEntry(
7257 SK_AC *pAC, /* Pointer to adapter context */
7258 SK_U32 TrapId, /* SNMP ID of the trap */
7259 unsigned int Size) /* Space needed for trap entry */
7261 unsigned int BufPad = pAC->Pnmi.TrapBufPad;
7262 unsigned int BufFree = pAC->Pnmi.TrapBufFree;
7263 unsigned int Beg = pAC->Pnmi.TrapQueueBeg;
7264 unsigned int End = pAC->Pnmi.TrapQueueEnd;
7265 char *pBuf = &pAC->Pnmi.TrapBuf[0];
7266 int Wrap;
7267 unsigned int NeededSpace;
7268 unsigned int EntrySize;
7269 SK_U32 Val32;
7270 SK_U64 Val64;
7273 /* Last byte of entry will get a copy of the entry length */
7274 Size ++;
7277 * Calculate needed buffer space */
7278 if (Beg >= Size) {
7280 NeededSpace = Size;
7281 Wrap = SK_FALSE;
7283 else {
7284 NeededSpace = Beg + Size;
7285 Wrap = SK_TRUE;
7289 * Check if enough buffer space is provided. Otherwise
7290 * free some entries. Leave one byte space between begin
7291 * and end of buffer to make it possible to detect whether
7292 * the buffer is full or empty
7294 while (BufFree < NeededSpace + 1) {
7296 if (End == 0) {
7298 End = SK_PNMI_TRAP_QUEUE_LEN;
7301 EntrySize = (unsigned int)*((unsigned char *)pBuf + End - 1);
7302 BufFree += EntrySize;
7303 End -= EntrySize;
7304 #ifdef DEBUG
7305 SK_MEMSET(pBuf + End, (char)(-1), EntrySize);
7306 #endif /* DEBUG */
7307 if (End == BufPad) {
7308 #ifdef DEBUG
7309 SK_MEMSET(pBuf, (char)(-1), End);
7310 #endif /* DEBUG */
7311 BufFree += End;
7312 End = 0;
7313 BufPad = 0;
7318 * Insert new entry as first entry. Newest entries are
7319 * stored at the beginning of the queue.
7321 if (Wrap) {
7323 BufPad = Beg;
7324 Beg = SK_PNMI_TRAP_QUEUE_LEN - Size;
7326 else {
7327 Beg = Beg - Size;
7329 BufFree -= NeededSpace;
7331 /* Save the current offsets */
7332 pAC->Pnmi.TrapQueueBeg = Beg;
7333 pAC->Pnmi.TrapQueueEnd = End;
7334 pAC->Pnmi.TrapBufPad = BufPad;
7335 pAC->Pnmi.TrapBufFree = BufFree;
7337 /* Initialize the trap entry */
7338 *(pBuf + Beg + Size - 1) = (char)Size;
7339 *(pBuf + Beg) = (char)Size;
7340 Val32 = (pAC->Pnmi.TrapUnique) ++;
7341 SK_PNMI_STORE_U32(pBuf + Beg + 1, Val32);
7342 SK_PNMI_STORE_U32(pBuf + Beg + 1 + sizeof(SK_U32), TrapId);
7343 Val64 = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC));
7344 SK_PNMI_STORE_U64(pBuf + Beg + 1 + 2 * sizeof(SK_U32), Val64);
7346 return (pBuf + Beg);
7349 /*****************************************************************************
7351 * CopyTrapQueue - Copies the trap buffer for the TRAP OID
7353 * Description:
7354 * On a query of the TRAP OID the trap buffer contents will be
7355 * copied continuously to the request buffer, which must be large
7356 * enough. No length check is performed.
7358 * Returns:
7359 * Nothing
7361 PNMI_STATIC void CopyTrapQueue(
7362 SK_AC *pAC, /* Pointer to adapter context */
7363 char *pDstBuf) /* Buffer to which the queued traps will be copied */
7365 unsigned int BufPad = pAC->Pnmi.TrapBufPad;
7366 unsigned int Trap = pAC->Pnmi.TrapQueueBeg;
7367 unsigned int End = pAC->Pnmi.TrapQueueEnd;
7368 char *pBuf = &pAC->Pnmi.TrapBuf[0];
7369 unsigned int Len;
7370 unsigned int DstOff = 0;
7373 while (Trap != End) {
7375 Len = (unsigned int)*(pBuf + Trap);
7378 * Last byte containing a copy of the length will
7379 * not be copied.
7381 *(pDstBuf + DstOff) = (char)(Len - 1);
7382 SK_MEMCPY(pDstBuf + DstOff + 1, pBuf + Trap + 1, Len - 2);
7383 DstOff += Len - 1;
7385 Trap += Len;
7386 if (Trap == SK_PNMI_TRAP_QUEUE_LEN) {
7388 Trap = BufPad;
7393 /*****************************************************************************
7395 * GetTrapQueueLen - Get the length of the trap buffer
7397 * Description:
7398 * Evaluates the number of currently stored traps and the needed
7399 * buffer size to retrieve them.
7401 * Returns:
7402 * Nothing
7404 PNMI_STATIC void GetTrapQueueLen(
7405 SK_AC *pAC, /* Pointer to adapter context */
7406 unsigned int *pLen, /* Length in Bytes of all queued traps */
7407 unsigned int *pEntries) /* Returns number of trapes stored in queue */
7409 unsigned int BufPad = pAC->Pnmi.TrapBufPad;
7410 unsigned int Trap = pAC->Pnmi.TrapQueueBeg;
7411 unsigned int End = pAC->Pnmi.TrapQueueEnd;
7412 char *pBuf = &pAC->Pnmi.TrapBuf[0];
7413 unsigned int Len;
7414 unsigned int Entries = 0;
7415 unsigned int TotalLen = 0;
7418 while (Trap != End) {
7420 Len = (unsigned int)*(pBuf + Trap);
7421 TotalLen += Len - 1;
7422 Entries ++;
7424 Trap += Len;
7425 if (Trap == SK_PNMI_TRAP_QUEUE_LEN) {
7427 Trap = BufPad;
7431 *pEntries = Entries;
7432 *pLen = TotalLen;
7435 /*****************************************************************************
7437 * QueueSimpleTrap - Store a simple trap to the trap buffer
7439 * Description:
7440 * A simple trap is a trap with now additional data. It consists
7441 * simply of a trap code.
7443 * Returns:
7444 * Nothing
7446 PNMI_STATIC void QueueSimpleTrap(
7447 SK_AC *pAC, /* Pointer to adapter context */
7448 SK_U32 TrapId) /* Type of sensor trap */
7450 GetTrapEntry(pAC, TrapId, SK_PNMI_TRAP_SIMPLE_LEN);
7453 /*****************************************************************************
7455 * QueueSensorTrap - Stores a sensor trap in the trap buffer
7457 * Description:
7458 * Gets an entry in the trap buffer and fills it with sensor related
7459 * data.
7461 * Returns:
7462 * Nothing
7464 PNMI_STATIC void QueueSensorTrap(
7465 SK_AC *pAC, /* Pointer to adapter context */
7466 SK_U32 TrapId, /* Type of sensor trap */
7467 unsigned int SensorIndex) /* Index of sensor which caused the trap */
7469 char *pBuf;
7470 unsigned int Offset;
7471 unsigned int DescrLen;
7472 SK_U32 Val32;
7475 /* Get trap buffer entry */
7476 DescrLen = SK_STRLEN(pAC->I2c.SenTable[SensorIndex].SenDesc);
7477 pBuf = GetTrapEntry(pAC, TrapId,
7478 SK_PNMI_TRAP_SENSOR_LEN_BASE + DescrLen);
7479 Offset = SK_PNMI_TRAP_SIMPLE_LEN;
7481 /* Store additionally sensor trap related data */
7482 Val32 = OID_SKGE_SENSOR_INDEX;
7483 SK_PNMI_STORE_U32(pBuf + Offset, Val32);
7484 *(pBuf + Offset + 4) = 4;
7485 Val32 = (SK_U32)SensorIndex;
7486 SK_PNMI_STORE_U32(pBuf + Offset + 5, Val32);
7487 Offset += 9;
7489 Val32 = (SK_U32)OID_SKGE_SENSOR_DESCR;
7490 SK_PNMI_STORE_U32(pBuf + Offset, Val32);
7491 *(pBuf + Offset + 4) = (char)DescrLen;
7492 SK_MEMCPY(pBuf + Offset + 5, pAC->I2c.SenTable[SensorIndex].SenDesc,
7493 DescrLen);
7494 Offset += DescrLen + 5;
7496 Val32 = OID_SKGE_SENSOR_TYPE;
7497 SK_PNMI_STORE_U32(pBuf + Offset, Val32);
7498 *(pBuf + Offset + 4) = 1;
7499 *(pBuf + Offset + 5) = (char)pAC->I2c.SenTable[SensorIndex].SenType;
7500 Offset += 6;
7502 Val32 = OID_SKGE_SENSOR_VALUE;
7503 SK_PNMI_STORE_U32(pBuf + Offset, Val32);
7504 *(pBuf + Offset + 4) = 4;
7505 Val32 = (SK_U32)pAC->I2c.SenTable[SensorIndex].SenValue;
7506 SK_PNMI_STORE_U32(pBuf + Offset + 5, Val32);
7509 /*****************************************************************************
7511 * QueueRlmtNewMacTrap - Store a port switch trap in the trap buffer
7513 * Description:
7514 * Nothing further to explain.
7516 * Returns:
7517 * Nothing
7519 PNMI_STATIC void QueueRlmtNewMacTrap(
7520 SK_AC *pAC, /* Pointer to adapter context */
7521 unsigned int ActiveMac) /* Index (0..n) of the currently active port */
7523 char *pBuf;
7524 SK_U32 Val32;
7527 pBuf = GetTrapEntry(pAC, OID_SKGE_TRAP_RLMT_CHANGE_PORT,
7528 SK_PNMI_TRAP_RLMT_CHANGE_LEN);
7530 Val32 = OID_SKGE_RLMT_PORT_ACTIVE;
7531 SK_PNMI_STORE_U32(pBuf + SK_PNMI_TRAP_SIMPLE_LEN, Val32);
7532 *(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 4) = 1;
7533 *(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 5) = (char)ActiveMac;
7536 /*****************************************************************************
7538 * QueueRlmtPortTrap - Store port related RLMT trap to trap buffer
7540 * Description:
7541 * Nothing further to explain.
7543 * Returns:
7544 * Nothing
7546 PNMI_STATIC void QueueRlmtPortTrap(
7547 SK_AC *pAC, /* Pointer to adapter context */
7548 SK_U32 TrapId, /* Type of RLMT port trap */
7549 unsigned int PortIndex) /* Index of the port, which changed its state */
7551 char *pBuf;
7552 SK_U32 Val32;
7555 pBuf = GetTrapEntry(pAC, TrapId, SK_PNMI_TRAP_RLMT_PORT_LEN);
7557 Val32 = OID_SKGE_RLMT_PORT_INDEX;
7558 SK_PNMI_STORE_U32(pBuf + SK_PNMI_TRAP_SIMPLE_LEN, Val32);
7559 *(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 4) = 1;
7560 *(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 5) = (char)PortIndex;
7563 /*****************************************************************************
7565 * CopyMac - Copies a MAC address
7567 * Description:
7568 * Nothing further to explain.
7570 * Returns:
7571 * Nothing
7573 PNMI_STATIC void CopyMac(
7574 char *pDst, /* Pointer to destination buffer */
7575 SK_MAC_ADDR *pMac) /* Pointer of Source */
7577 int i;
7580 for (i = 0; i < sizeof(SK_MAC_ADDR); i ++) {
7582 *(pDst + i) = pMac->a[i];
7586 #ifdef SK_POWER_MGMT
7587 /*****************************************************************************
7589 * PowerManagement - OID handler function of PowerManagement OIDs
7591 * Description:
7592 * The code is simple. No description necessary.
7594 * Returns:
7595 * SK_PNMI_ERR_OK The request was successfully performed.
7596 * SK_PNMI_ERR_GENERAL A general severe internal error occured.
7597 * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
7598 * the correct data (e.g. a 32bit value is
7599 * needed, but a 16 bit value was passed).
7600 * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
7601 * exist (e.g. port instance 3 on a two port
7602 * adapter.
7605 PNMI_STATIC int PowerManagement(
7606 SK_AC *pAC, /* Pointer to adapter context */
7607 SK_IOC IoC, /* IO context handle */
7608 int Action, /* Get/PreSet/Set action */
7609 SK_U32 Id, /* Object ID that is to be processed */
7610 char *pBuf, /* Buffer to which to mgmt data will be retrieved */
7611 unsigned int *pLen, /* On call: buffer length. On return: used buffer */
7612 SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
7613 unsigned int TableIndex, /* Index to the Id table */
7614 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */
7617 SK_U32 RetCode = SK_PNMI_ERR_GENERAL;
7620 * Check instance. We only handle single instance variables
7622 if (Instance != (SK_U32)(-1) && Instance != 1) {
7624 *pLen = 0;
7625 return (SK_PNMI_ERR_UNKNOWN_INST);
7629 /* Check length */
7630 switch (Id) {
7632 case OID_PNP_CAPABILITIES:
7633 if (*pLen < sizeof(SK_PNP_CAPABILITIES)) {
7635 *pLen = sizeof(SK_PNP_CAPABILITIES);
7636 return (SK_PNMI_ERR_TOO_SHORT);
7638 break;
7640 case OID_PNP_SET_POWER:
7641 case OID_PNP_QUERY_POWER:
7642 if (*pLen < sizeof(SK_DEVICE_POWER_STATE))
7644 *pLen = sizeof(SK_DEVICE_POWER_STATE);
7645 return (SK_PNMI_ERR_TOO_SHORT);
7647 break;
7649 case OID_PNP_ADD_WAKE_UP_PATTERN:
7650 case OID_PNP_REMOVE_WAKE_UP_PATTERN:
7651 if (*pLen < sizeof(SK_PM_PACKET_PATTERN)) {
7653 *pLen = sizeof(SK_PM_PACKET_PATTERN);
7654 return (SK_PNMI_ERR_TOO_SHORT);
7656 break;
7658 case OID_PNP_ENABLE_WAKE_UP:
7659 if (*pLen < sizeof(SK_U32)) {
7661 *pLen = sizeof(SK_U32);
7662 return (SK_PNMI_ERR_TOO_SHORT);
7664 break;
7668 * Perform action
7670 if (Action == SK_PNMI_GET) {
7673 * Get value
7675 switch (Id) {
7677 case OID_PNP_CAPABILITIES:
7678 RetCode = SkPowerQueryPnPCapabilities(pAC, IoC, pBuf, pLen);
7679 break;
7681 case OID_PNP_QUERY_POWER:
7682 /* The Windows DDK describes: An OID_PNP_QUERY_POWER requests
7683 the miniport to indicate whether it can transition its NIC
7684 to the low-power state.
7685 A miniport driver must always return NDIS_STATUS_SUCCESS
7686 to a query of OID_PNP_QUERY_POWER. */
7687 *pLen = sizeof(SK_DEVICE_POWER_STATE);
7688 RetCode = SK_PNMI_ERR_OK;
7689 break;
7691 /* NDIS handles these OIDs as write-only.
7692 * So in case of get action the buffer with written length = 0
7693 * is returned
7695 case OID_PNP_SET_POWER:
7696 case OID_PNP_ADD_WAKE_UP_PATTERN:
7697 case OID_PNP_REMOVE_WAKE_UP_PATTERN:
7698 *pLen = 0;
7699 RetCode = SK_PNMI_ERR_NOT_SUPPORTED;
7700 break;
7702 case OID_PNP_ENABLE_WAKE_UP:
7703 RetCode = SkPowerGetEnableWakeUp(pAC, IoC, pBuf, pLen);
7704 break;
7706 default:
7707 RetCode = SK_PNMI_ERR_GENERAL;
7708 break;
7711 return (RetCode);
7716 * Perform preset or set
7719 /* POWER module does not support PRESET action */
7720 if (Action == SK_PNMI_PRESET) {
7721 return (SK_PNMI_ERR_OK);
7724 switch (Id) {
7725 case OID_PNP_SET_POWER:
7726 RetCode = SkPowerSetPower(pAC, IoC, pBuf, pLen);
7727 break;
7729 case OID_PNP_ADD_WAKE_UP_PATTERN:
7730 RetCode = SkPowerAddWakeUpPattern(pAC, IoC, pBuf, pLen);
7731 break;
7733 case OID_PNP_REMOVE_WAKE_UP_PATTERN:
7734 RetCode = SkPowerRemoveWakeUpPattern(pAC, IoC, pBuf, pLen);
7735 break;
7737 case OID_PNP_ENABLE_WAKE_UP:
7738 RetCode = SkPowerSetEnableWakeUp(pAC, IoC, pBuf, pLen);
7739 break;
7741 default:
7742 RetCode = SK_PNMI_ERR_READ_ONLY;
7745 return (RetCode);
7747 #endif /* SK_POWER_MGMT */
7749 #ifdef SK_DIAG_SUPPORT
7750 /*****************************************************************************
7752 * DiagActions - OID handler function of Diagnostic driver
7754 * Description:
7755 * The code is simple. No description necessary.
7757 * Returns:
7758 * SK_PNMI_ERR_OK The request was successfully performed.
7759 * SK_PNMI_ERR_GENERAL A general severe internal error occured.
7760 * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
7761 * the correct data (e.g. a 32bit value is
7762 * needed, but a 16 bit value was passed).
7763 * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
7764 * exist (e.g. port instance 3 on a two port
7765 * adapter.
7768 PNMI_STATIC int DiagActions(
7769 SK_AC *pAC, /* Pointer to adapter context */
7770 SK_IOC IoC, /* IO context handle */
7771 int Action, /* GET/PRESET/SET action */
7772 SK_U32 Id, /* Object ID that is to be processed */
7773 char *pBuf, /* Buffer used for the management data transfer */
7774 unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
7775 SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
7776 unsigned int TableIndex, /* Index to the Id table */
7777 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
7780 SK_U32 DiagStatus;
7781 SK_U32 RetCode = SK_PNMI_ERR_GENERAL;
7784 * Check instance. We only handle single instance variables.
7786 if (Instance != (SK_U32)(-1) && Instance != 1) {
7788 *pLen = 0;
7789 return (SK_PNMI_ERR_UNKNOWN_INST);
7793 * Check length.
7795 switch (Id) {
7797 case OID_SKGE_DIAG_MODE:
7798 if (*pLen < sizeof(SK_U32)) {
7800 *pLen = sizeof(SK_U32);
7801 return (SK_PNMI_ERR_TOO_SHORT);
7803 break;
7805 default:
7806 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR040, SK_PNMI_ERR040MSG);
7807 *pLen = 0;
7808 return (SK_PNMI_ERR_GENERAL);
7811 /* Perform action. */
7813 /* GET value. */
7814 if (Action == SK_PNMI_GET) {
7816 switch (Id) {
7818 case OID_SKGE_DIAG_MODE:
7819 DiagStatus = pAC->Pnmi.DiagAttached;
7820 SK_PNMI_STORE_U32(pBuf, DiagStatus);
7821 *pLen = sizeof(SK_U32);
7822 RetCode = SK_PNMI_ERR_OK;
7823 break;
7825 default:
7826 *pLen = 0;
7827 RetCode = SK_PNMI_ERR_GENERAL;
7828 break;
7830 return (RetCode);
7833 /* From here SET or PRESET value. */
7835 /* PRESET value is not supported. */
7836 if (Action == SK_PNMI_PRESET) {
7837 return (SK_PNMI_ERR_OK);
7840 /* SET value. */
7841 switch (Id) {
7842 case OID_SKGE_DIAG_MODE:
7844 /* Handle the SET. */
7845 switch (*pBuf) {
7847 /* Attach the DIAG to this adapter. */
7848 case SK_DIAG_ATTACHED:
7849 /* Check if we come from running */
7850 if (pAC->Pnmi.DiagAttached == SK_DIAG_RUNNING) {
7852 RetCode = SkDrvLeaveDiagMode(pAC);
7855 else if (pAC->Pnmi.DiagAttached == SK_DIAG_IDLE) {
7857 RetCode = SK_PNMI_ERR_OK;
7860 else {
7862 RetCode = SK_PNMI_ERR_GENERAL;
7866 if (RetCode == SK_PNMI_ERR_OK) {
7868 pAC->Pnmi.DiagAttached = SK_DIAG_ATTACHED;
7870 break;
7872 /* Enter the DIAG mode in the driver. */
7873 case SK_DIAG_RUNNING:
7874 RetCode = SK_PNMI_ERR_OK;
7877 * If DiagAttached is set, we can tell the driver
7878 * to enter the DIAG mode.
7880 if (pAC->Pnmi.DiagAttached == SK_DIAG_ATTACHED) {
7881 /* If DiagMode is not active, we can enter it. */
7882 if (!pAC->DiagModeActive) {
7884 RetCode = SkDrvEnterDiagMode(pAC);
7886 else {
7888 RetCode = SK_PNMI_ERR_GENERAL;
7891 else {
7893 RetCode = SK_PNMI_ERR_GENERAL;
7896 if (RetCode == SK_PNMI_ERR_OK) {
7898 pAC->Pnmi.DiagAttached = SK_DIAG_RUNNING;
7900 break;
7902 case SK_DIAG_IDLE:
7903 /* Check if we come from running */
7904 if (pAC->Pnmi.DiagAttached == SK_DIAG_RUNNING) {
7906 RetCode = SkDrvLeaveDiagMode(pAC);
7909 else if (pAC->Pnmi.DiagAttached == SK_DIAG_ATTACHED) {
7911 RetCode = SK_PNMI_ERR_OK;
7914 else {
7916 RetCode = SK_PNMI_ERR_GENERAL;
7920 if (RetCode == SK_PNMI_ERR_OK) {
7922 pAC->Pnmi.DiagAttached = SK_DIAG_IDLE;
7924 break;
7926 default:
7927 RetCode = SK_PNMI_ERR_BAD_VALUE;
7928 break;
7930 break;
7932 default:
7933 RetCode = SK_PNMI_ERR_GENERAL;
7936 if (RetCode == SK_PNMI_ERR_OK) {
7937 *pLen = sizeof(SK_U32);
7939 else {
7941 *pLen = 0;
7943 return (RetCode);
7945 #endif /* SK_DIAG_SUPPORT */
7947 /*****************************************************************************
7949 * Vct - OID handler function of OIDs
7951 * Description:
7952 * The code is simple. No description necessary.
7954 * Returns:
7955 * SK_PNMI_ERR_OK The request was performed successfully.
7956 * SK_PNMI_ERR_GENERAL A general severe internal error occured.
7957 * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
7958 * the correct data (e.g. a 32bit value is
7959 * needed, but a 16 bit value was passed).
7960 * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
7961 * exist (e.g. port instance 3 on a two port
7962 * adapter).
7963 * SK_PNMI_ERR_READ_ONLY Only the Get action is allowed.
7967 PNMI_STATIC int Vct(
7968 SK_AC *pAC, /* Pointer to adapter context */
7969 SK_IOC IoC, /* IO context handle */
7970 int Action, /* GET/PRESET/SET action */
7971 SK_U32 Id, /* Object ID that is to be processed */
7972 char *pBuf, /* Buffer used for the management data transfer */
7973 unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
7974 SK_U32 Instance, /* Instance (-1,2..n) that is to be queried */
7975 unsigned int TableIndex, /* Index to the Id table */
7976 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
7978 SK_GEPORT *pPrt;
7979 SK_PNMI_VCT *pVctBackupData;
7980 SK_U32 LogPortMax;
7981 SK_U32 PhysPortMax;
7982 SK_U32 PhysPortIndex;
7983 SK_U32 Limit;
7984 SK_U32 Offset;
7985 SK_BOOL Link;
7986 SK_U32 RetCode = SK_PNMI_ERR_GENERAL;
7987 int i;
7988 SK_EVPARA Para;
7989 SK_U32 CableLength;
7992 * Calculate the port indexes from the instance.
7994 PhysPortMax = pAC->GIni.GIMacsFound;
7995 LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax);
7997 /* Dual net mode? */
7998 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
7999 LogPortMax--;
8002 if ((Instance != (SK_U32) (-1))) {
8003 /* Check instance range. */
8004 if ((Instance < 2) || (Instance > LogPortMax)) {
8005 *pLen = 0;
8006 return (SK_PNMI_ERR_UNKNOWN_INST);
8009 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
8010 PhysPortIndex = NetIndex;
8012 else {
8013 PhysPortIndex = Instance - 2;
8015 Limit = PhysPortIndex + 1;
8017 else {
8019 * Instance == (SK_U32) (-1), get all Instances of that OID.
8021 * Not implemented yet. May be used in future releases.
8023 PhysPortIndex = 0;
8024 Limit = PhysPortMax;
8027 pPrt = &pAC->GIni.GP[PhysPortIndex];
8028 if (pPrt->PHWLinkUp) {
8029 Link = SK_TRUE;
8031 else {
8032 Link = SK_FALSE;
8035 /* Check MAC type */
8036 if (pPrt->PhyType != SK_PHY_MARV_COPPER) {
8037 *pLen = 0;
8038 return (SK_PNMI_ERR_GENERAL);
8041 /* Initialize backup data pointer. */
8042 pVctBackupData = &pAC->Pnmi.VctBackup[PhysPortIndex];
8044 /* Check action type */
8045 if (Action == SK_PNMI_GET) {
8046 /* Check length */
8047 switch (Id) {
8049 case OID_SKGE_VCT_GET:
8050 if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_PNMI_VCT)) {
8051 *pLen = (Limit - PhysPortIndex) * sizeof(SK_PNMI_VCT);
8052 return (SK_PNMI_ERR_TOO_SHORT);
8054 break;
8056 case OID_SKGE_VCT_STATUS:
8057 if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U8)) {
8058 *pLen = (Limit - PhysPortIndex) * sizeof(SK_U8);
8059 return (SK_PNMI_ERR_TOO_SHORT);
8061 break;
8063 default:
8064 *pLen = 0;
8065 return (SK_PNMI_ERR_GENERAL);
8068 /* Get value */
8069 Offset = 0;
8070 for (; PhysPortIndex < Limit; PhysPortIndex++) {
8071 switch (Id) {
8073 case OID_SKGE_VCT_GET:
8074 if ((Link == SK_FALSE) &&
8075 (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING)) {
8076 RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_FALSE);
8077 if (RetCode == 0) {
8078 pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_PENDING;
8079 pAC->Pnmi.VctStatus[PhysPortIndex] |=
8080 (SK_PNMI_VCT_NEW_VCT_DATA | SK_PNMI_VCT_TEST_DONE);
8082 /* Copy results for later use to PNMI struct. */
8083 for (i = 0; i < 4; i++) {
8084 if (pPrt->PMdiPairSts[i] == SK_PNMI_VCT_NORMAL_CABLE) {
8085 if ((pPrt->PMdiPairLen[i] > 35) && (pPrt->PMdiPairLen[i] < 0xff)) {
8086 pPrt->PMdiPairSts[i] = SK_PNMI_VCT_IMPEDANCE_MISMATCH;
8089 if ((pPrt->PMdiPairLen[i] > 35) && (pPrt->PMdiPairLen[i] != 0xff)) {
8090 CableLength = 1000 * (((175 * pPrt->PMdiPairLen[i]) / 210) - 28);
8092 else {
8093 CableLength = 0;
8095 pVctBackupData->PMdiPairLen[i] = CableLength;
8096 pVctBackupData->PMdiPairSts[i] = pPrt->PMdiPairSts[i];
8099 Para.Para32[0] = PhysPortIndex;
8100 Para.Para32[1] = -1;
8101 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para);
8102 SkEventDispatcher(pAC, IoC);
8104 else {
8105 ; /* VCT test is running. */
8109 /* Get all results. */
8110 CheckVctStatus(pAC, IoC, pBuf, Offset, PhysPortIndex);
8111 Offset += sizeof(SK_U8);
8112 *(pBuf + Offset) = pPrt->PCableLen;
8113 Offset += sizeof(SK_U8);
8114 for (i = 0; i < 4; i++) {
8115 SK_PNMI_STORE_U32((pBuf + Offset), pVctBackupData->PMdiPairLen[i]);
8116 Offset += sizeof(SK_U32);
8118 for (i = 0; i < 4; i++) {
8119 *(pBuf + Offset) = pVctBackupData->PMdiPairSts[i];
8120 Offset += sizeof(SK_U8);
8123 RetCode = SK_PNMI_ERR_OK;
8124 break;
8126 case OID_SKGE_VCT_STATUS:
8127 CheckVctStatus(pAC, IoC, pBuf, Offset, PhysPortIndex);
8128 Offset += sizeof(SK_U8);
8129 RetCode = SK_PNMI_ERR_OK;
8130 break;
8132 default:
8133 *pLen = 0;
8134 return (SK_PNMI_ERR_GENERAL);
8136 } /* for */
8137 *pLen = Offset;
8138 return (RetCode);
8140 } /* if SK_PNMI_GET */
8143 * From here SET or PRESET action. Check if the passed
8144 * buffer length is plausible.
8147 /* Check length */
8148 switch (Id) {
8149 case OID_SKGE_VCT_SET:
8150 if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U32)) {
8151 *pLen = (Limit - PhysPortIndex) * sizeof(SK_U32);
8152 return (SK_PNMI_ERR_TOO_SHORT);
8154 break;
8156 default:
8157 *pLen = 0;
8158 return (SK_PNMI_ERR_GENERAL);
8162 * Perform preset or set.
8165 /* VCT does not support PRESET action. */
8166 if (Action == SK_PNMI_PRESET) {
8167 return (SK_PNMI_ERR_OK);
8170 Offset = 0;
8171 for (; PhysPortIndex < Limit; PhysPortIndex++) {
8172 switch (Id) {
8173 case OID_SKGE_VCT_SET: /* Start VCT test. */
8174 if (Link == SK_FALSE) {
8175 SkGeStopPort(pAC, IoC, PhysPortIndex, SK_STOP_ALL, SK_SOFT_RST);
8177 RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_TRUE);
8178 if (RetCode == 0) { /* RetCode: 0 => Start! */
8179 pAC->Pnmi.VctStatus[PhysPortIndex] |= SK_PNMI_VCT_PENDING;
8180 pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_NEW_VCT_DATA;
8181 pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_LINK;
8184 * Start VCT timer counter.
8186 SK_MEMSET((char *) &Para, 0, sizeof(Para));
8187 Para.Para32[0] = PhysPortIndex;
8188 Para.Para32[1] = -1;
8189 SkTimerStart(pAC, IoC, &pAC->Pnmi.VctTimeout[PhysPortIndex].VctTimer,
8190 4000000, SKGE_PNMI, SK_PNMI_EVT_VCT_RESET, Para);
8191 SK_PNMI_STORE_U32((pBuf + Offset), RetCode);
8192 RetCode = SK_PNMI_ERR_OK;
8194 else { /* RetCode: 2 => Running! */
8195 SK_PNMI_STORE_U32((pBuf + Offset), RetCode);
8196 RetCode = SK_PNMI_ERR_OK;
8199 else { /* RetCode: 4 => Link! */
8200 RetCode = 4;
8201 SK_PNMI_STORE_U32((pBuf + Offset), RetCode);
8202 RetCode = SK_PNMI_ERR_OK;
8204 Offset += sizeof(SK_U32);
8205 break;
8207 default:
8208 *pLen = 0;
8209 return (SK_PNMI_ERR_GENERAL);
8211 } /* for */
8212 *pLen = Offset;
8213 return (RetCode);
8215 } /* Vct */
8218 PNMI_STATIC void CheckVctStatus(
8219 SK_AC *pAC,
8220 SK_IOC IoC,
8221 char *pBuf,
8222 SK_U32 Offset,
8223 SK_U32 PhysPortIndex)
8225 SK_GEPORT *pPrt;
8226 SK_PNMI_VCT *pVctData;
8227 SK_U32 RetCode;
8229 pPrt = &pAC->GIni.GP[PhysPortIndex];
8231 pVctData = (SK_PNMI_VCT *) (pBuf + Offset);
8232 pVctData->VctStatus = SK_PNMI_VCT_NONE;
8234 if (!pPrt->PHWLinkUp) {
8236 /* Was a VCT test ever made before? */
8237 if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_TEST_DONE) {
8238 if ((pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_LINK)) {
8239 pVctData->VctStatus |= SK_PNMI_VCT_OLD_VCT_DATA;
8241 else {
8242 pVctData->VctStatus |= SK_PNMI_VCT_NEW_VCT_DATA;
8246 /* Check VCT test status. */
8247 RetCode = SkGmCableDiagStatus(pAC,IoC, PhysPortIndex, SK_FALSE);
8248 if (RetCode == 2) { /* VCT test is running. */
8249 pVctData->VctStatus |= SK_PNMI_VCT_RUNNING;
8251 else { /* VCT data was copied to pAC here. Check PENDING state. */
8252 if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING) {
8253 pVctData->VctStatus |= SK_PNMI_VCT_NEW_VCT_DATA;
8257 if (pPrt->PCableLen != 0xff) { /* Old DSP value. */
8258 pVctData->VctStatus |= SK_PNMI_VCT_OLD_DSP_DATA;
8261 else {
8263 /* Was a VCT test ever made before? */
8264 if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_TEST_DONE) {
8265 pVctData->VctStatus &= ~SK_PNMI_VCT_NEW_VCT_DATA;
8266 pVctData->VctStatus |= SK_PNMI_VCT_OLD_VCT_DATA;
8269 /* DSP only valid in 100/1000 modes. */
8270 if (pAC->GIni.GP[PhysPortIndex].PLinkSpeedUsed !=
8271 SK_LSPEED_STAT_10MBPS) {
8272 pVctData->VctStatus |= SK_PNMI_VCT_NEW_DSP_DATA;
8275 } /* CheckVctStatus */
8278 /*****************************************************************************
8280 * SkPnmiGenIoctl - Handles new generic PNMI IOCTL, calls the needed
8281 * PNMI function depending on the subcommand and
8282 * returns all data belonging to the complete database
8283 * or OID request.
8285 * Description:
8286 * Looks up the requested subcommand, calls the corresponding handler
8287 * function and passes all required parameters to it.
8288 * The function is called by the driver. It is needed to handle the new
8289 * generic PNMI IOCTL. This IOCTL is given to the driver and contains both
8290 * the OID and a subcommand to decide what kind of request has to be done.
8292 * Returns:
8293 * SK_PNMI_ERR_OK The request was successfully performed
8294 * SK_PNMI_ERR_GENERAL A general severe internal error occured
8295 * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to take
8296 * the data.
8297 * SK_PNMI_ERR_UNKNOWN_OID The requested OID is unknown
8298 * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
8299 * exist (e.g. port instance 3 on a two port
8300 * adapter.
8302 int SkPnmiGenIoctl(
8303 SK_AC *pAC, /* Pointer to adapter context struct */
8304 SK_IOC IoC, /* I/O context */
8305 void *pBuf, /* Buffer used for the management data transfer */
8306 unsigned int *pLen, /* Length of buffer */
8307 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
8309 SK_I32 Mode; /* Store value of subcommand. */
8310 SK_U32 Oid; /* Store value of OID. */
8311 int ReturnCode; /* Store return value to show status of PNMI action. */
8312 int HeaderLength; /* Length of desired action plus OID. */
8314 ReturnCode = SK_PNMI_ERR_GENERAL;
8316 SK_MEMCPY(&Mode, pBuf, sizeof(SK_I32));
8317 SK_MEMCPY(&Oid, (char *) pBuf + sizeof(SK_I32), sizeof(SK_U32));
8318 HeaderLength = sizeof(SK_I32) + sizeof(SK_U32);
8319 *pLen = *pLen - HeaderLength;
8320 SK_MEMCPY((char *) pBuf + sizeof(SK_I32), (char *) pBuf + HeaderLength, *pLen);
8322 switch(Mode) {
8323 case SK_GET_SINGLE_VAR:
8324 ReturnCode = SkPnmiGetVar(pAC, IoC, Oid,
8325 (char *) pBuf + sizeof(SK_I32), pLen,
8326 ((SK_U32) (-1)), NetIndex);
8327 SK_PNMI_STORE_U32(pBuf, ReturnCode);
8328 *pLen = *pLen + sizeof(SK_I32);
8329 break;
8330 case SK_PRESET_SINGLE_VAR:
8331 ReturnCode = SkPnmiPreSetVar(pAC, IoC, Oid,
8332 (char *) pBuf + sizeof(SK_I32), pLen,
8333 ((SK_U32) (-1)), NetIndex);
8334 SK_PNMI_STORE_U32(pBuf, ReturnCode);
8335 *pLen = *pLen + sizeof(SK_I32);
8336 break;
8337 case SK_SET_SINGLE_VAR:
8338 ReturnCode = SkPnmiSetVar(pAC, IoC, Oid,
8339 (char *) pBuf + sizeof(SK_I32), pLen,
8340 ((SK_U32) (-1)), NetIndex);
8341 SK_PNMI_STORE_U32(pBuf, ReturnCode);
8342 *pLen = *pLen + sizeof(SK_I32);
8343 break;
8344 case SK_GET_FULL_MIB:
8345 ReturnCode = SkPnmiGetStruct(pAC, IoC, pBuf, pLen, NetIndex);
8346 break;
8347 case SK_PRESET_FULL_MIB:
8348 ReturnCode = SkPnmiPreSetStruct(pAC, IoC, pBuf, pLen, NetIndex);
8349 break;
8350 case SK_SET_FULL_MIB:
8351 ReturnCode = SkPnmiSetStruct(pAC, IoC, pBuf, pLen, NetIndex);
8352 break;
8353 default:
8354 break;
8357 return (ReturnCode);
8359 } /* SkGeIocGen */