Committer: Michael Beasley <mike@snafu.setup>
[mikesnafu-overlay.git] / drivers / net / sk98lin / skgepnmi.c
blob876bb2158fa6e2d7c43f2637a9ed3dd81e4cf5ef
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 SkPnmiSetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, void *pBuf,
60 unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex);
61 int SkPnmiGetStruct(SK_AC *pAC, SK_IOC IoC, void *pBuf,
62 unsigned int *pLen, SK_U32 NetIndex);
63 int SkPnmiPreSetStruct(SK_AC *pAC, SK_IOC IoC, void *pBuf,
64 unsigned int *pLen, SK_U32 NetIndex);
65 int SkPnmiSetStruct(SK_AC *pAC, SK_IOC IoC, void *pBuf,
66 unsigned int *pLen, SK_U32 NetIndex);
67 int SkPnmiEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event, SK_EVPARA Param);
68 int SkPnmiGenIoctl(SK_AC *pAC, SK_IOC IoC, void * pBuf,
69 unsigned int * pLen, SK_U32 NetIndex);
73 * Private Function prototypes
76 PNMI_STATIC SK_U8 CalculateLinkModeStatus(SK_AC *pAC, SK_IOC IoC, unsigned int
77 PhysPortIndex);
78 PNMI_STATIC SK_U8 CalculateLinkStatus(SK_AC *pAC, SK_IOC IoC, unsigned int
79 PhysPortIndex);
80 PNMI_STATIC void CopyMac(char *pDst, SK_MAC_ADDR *pMac);
81 PNMI_STATIC void CopyTrapQueue(SK_AC *pAC, char *pDstBuf);
82 PNMI_STATIC SK_U64 GetPhysStatVal(SK_AC *pAC, SK_IOC IoC,
83 unsigned int PhysPortIndex, unsigned int StatIndex);
84 PNMI_STATIC SK_U64 GetStatVal(SK_AC *pAC, SK_IOC IoC, unsigned int LogPortIndex,
85 unsigned int StatIndex, SK_U32 NetIndex);
86 PNMI_STATIC char* GetTrapEntry(SK_AC *pAC, SK_U32 TrapId, unsigned int Size);
87 PNMI_STATIC void GetTrapQueueLen(SK_AC *pAC, unsigned int *pLen,
88 unsigned int *pEntries);
89 PNMI_STATIC int GetVpdKeyArr(SK_AC *pAC, SK_IOC IoC, char *pKeyArr,
90 unsigned int KeyArrLen, unsigned int *pKeyNo);
91 PNMI_STATIC int LookupId(SK_U32 Id);
92 PNMI_STATIC int MacUpdate(SK_AC *pAC, SK_IOC IoC, unsigned int FirstMac,
93 unsigned int LastMac);
94 PNMI_STATIC int PnmiStruct(SK_AC *pAC, SK_IOC IoC, int Action, char *pBuf,
95 unsigned int *pLen, SK_U32 NetIndex);
96 PNMI_STATIC int PnmiVar(SK_AC *pAC, SK_IOC IoC, int Action, SK_U32 Id,
97 char *pBuf, unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex);
98 PNMI_STATIC void QueueRlmtNewMacTrap(SK_AC *pAC, unsigned int ActiveMac);
99 PNMI_STATIC void QueueRlmtPortTrap(SK_AC *pAC, SK_U32 TrapId,
100 unsigned int PortIndex);
101 PNMI_STATIC void QueueSensorTrap(SK_AC *pAC, SK_U32 TrapId,
102 unsigned int SensorIndex);
103 PNMI_STATIC void QueueSimpleTrap(SK_AC *pAC, SK_U32 TrapId);
104 PNMI_STATIC void ResetCounter(SK_AC *pAC, SK_IOC IoC, SK_U32 NetIndex);
105 PNMI_STATIC int RlmtUpdate(SK_AC *pAC, SK_IOC IoC, SK_U32 NetIndex);
106 PNMI_STATIC int SirqUpdate(SK_AC *pAC, SK_IOC IoC);
107 PNMI_STATIC void VirtualConf(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, char *pBuf);
108 PNMI_STATIC int Vct(SK_AC *pAC, SK_IOC IoC, int Action, SK_U32 Id, char *pBuf,
109 unsigned int *pLen, SK_U32 Instance, unsigned int TableIndex, SK_U32 NetIndex);
110 PNMI_STATIC void CheckVctStatus(SK_AC *, SK_IOC, char *, SK_U32, SK_U32);
113 * Table to correlate OID with handler function and index to
114 * hardware register stored in StatAddress if applicable.
116 #include "skgemib.c"
118 /* global variables **********************************************************/
121 * Overflow status register bit table and corresponding counter
122 * dependent on MAC type - the number relates to the size of overflow
123 * mask returned by the pFnMacOverflow function
125 PNMI_STATIC const SK_U16 StatOvrflwBit[][SK_PNMI_MAC_TYPES] = {
126 /* Bit0 */ { SK_PNMI_HTX, SK_PNMI_HTX_UNICAST},
127 /* Bit1 */ { SK_PNMI_HTX_OCTETHIGH, SK_PNMI_HTX_BROADCAST},
128 /* Bit2 */ { SK_PNMI_HTX_OCTETLOW, SK_PNMI_HTX_PMACC},
129 /* Bit3 */ { SK_PNMI_HTX_BROADCAST, SK_PNMI_HTX_MULTICAST},
130 /* Bit4 */ { SK_PNMI_HTX_MULTICAST, SK_PNMI_HTX_OCTETLOW},
131 /* Bit5 */ { SK_PNMI_HTX_UNICAST, SK_PNMI_HTX_OCTETHIGH},
132 /* Bit6 */ { SK_PNMI_HTX_LONGFRAMES, SK_PNMI_HTX_64},
133 /* Bit7 */ { SK_PNMI_HTX_BURST, SK_PNMI_HTX_127},
134 /* Bit8 */ { SK_PNMI_HTX_PMACC, SK_PNMI_HTX_255},
135 /* Bit9 */ { SK_PNMI_HTX_MACC, SK_PNMI_HTX_511},
136 /* Bit10 */ { SK_PNMI_HTX_SINGLE_COL, SK_PNMI_HTX_1023},
137 /* Bit11 */ { SK_PNMI_HTX_MULTI_COL, SK_PNMI_HTX_MAX},
138 /* Bit12 */ { SK_PNMI_HTX_EXCESS_COL, SK_PNMI_HTX_LONGFRAMES},
139 /* Bit13 */ { SK_PNMI_HTX_LATE_COL, SK_PNMI_HTX_RESERVED},
140 /* Bit14 */ { SK_PNMI_HTX_DEFFERAL, SK_PNMI_HTX_COL},
141 /* Bit15 */ { SK_PNMI_HTX_EXCESS_DEF, SK_PNMI_HTX_LATE_COL},
142 /* Bit16 */ { SK_PNMI_HTX_UNDERRUN, SK_PNMI_HTX_EXCESS_COL},
143 /* Bit17 */ { SK_PNMI_HTX_CARRIER, SK_PNMI_HTX_MULTI_COL},
144 /* Bit18 */ { SK_PNMI_HTX_UTILUNDER, SK_PNMI_HTX_SINGLE_COL},
145 /* Bit19 */ { SK_PNMI_HTX_UTILOVER, SK_PNMI_HTX_UNDERRUN},
146 /* Bit20 */ { SK_PNMI_HTX_64, SK_PNMI_HTX_RESERVED},
147 /* Bit21 */ { SK_PNMI_HTX_127, SK_PNMI_HTX_RESERVED},
148 /* Bit22 */ { SK_PNMI_HTX_255, SK_PNMI_HTX_RESERVED},
149 /* Bit23 */ { SK_PNMI_HTX_511, SK_PNMI_HTX_RESERVED},
150 /* Bit24 */ { SK_PNMI_HTX_1023, SK_PNMI_HTX_RESERVED},
151 /* Bit25 */ { SK_PNMI_HTX_MAX, SK_PNMI_HTX_RESERVED},
152 /* Bit26 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED},
153 /* Bit27 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED},
154 /* Bit28 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED},
155 /* Bit29 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED},
156 /* Bit30 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED},
157 /* Bit31 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED},
158 /* Bit32 */ { SK_PNMI_HRX, SK_PNMI_HRX_UNICAST},
159 /* Bit33 */ { SK_PNMI_HRX_OCTETHIGH, SK_PNMI_HRX_BROADCAST},
160 /* Bit34 */ { SK_PNMI_HRX_OCTETLOW, SK_PNMI_HRX_PMACC},
161 /* Bit35 */ { SK_PNMI_HRX_BROADCAST, SK_PNMI_HRX_MULTICAST},
162 /* Bit36 */ { SK_PNMI_HRX_MULTICAST, SK_PNMI_HRX_FCS},
163 /* Bit37 */ { SK_PNMI_HRX_UNICAST, SK_PNMI_HRX_RESERVED},
164 /* Bit38 */ { SK_PNMI_HRX_PMACC, SK_PNMI_HRX_OCTETLOW},
165 /* Bit39 */ { SK_PNMI_HRX_MACC, SK_PNMI_HRX_OCTETHIGH},
166 /* Bit40 */ { SK_PNMI_HRX_PMACC_ERR, SK_PNMI_HRX_BADOCTETLOW},
167 /* Bit41 */ { SK_PNMI_HRX_MACC_UNKWN, SK_PNMI_HRX_BADOCTETHIGH},
168 /* Bit42 */ { SK_PNMI_HRX_BURST, SK_PNMI_HRX_UNDERSIZE},
169 /* Bit43 */ { SK_PNMI_HRX_MISSED, SK_PNMI_HRX_RUNT},
170 /* Bit44 */ { SK_PNMI_HRX_FRAMING, SK_PNMI_HRX_64},
171 /* Bit45 */ { SK_PNMI_HRX_OVERFLOW, SK_PNMI_HRX_127},
172 /* Bit46 */ { SK_PNMI_HRX_JABBER, SK_PNMI_HRX_255},
173 /* Bit47 */ { SK_PNMI_HRX_CARRIER, SK_PNMI_HRX_511},
174 /* Bit48 */ { SK_PNMI_HRX_IRLENGTH, SK_PNMI_HRX_1023},
175 /* Bit49 */ { SK_PNMI_HRX_SYMBOL, SK_PNMI_HRX_MAX},
176 /* Bit50 */ { SK_PNMI_HRX_SHORTS, SK_PNMI_HRX_LONGFRAMES},
177 /* Bit51 */ { SK_PNMI_HRX_RUNT, SK_PNMI_HRX_TOO_LONG},
178 /* Bit52 */ { SK_PNMI_HRX_TOO_LONG, SK_PNMI_HRX_JABBER},
179 /* Bit53 */ { SK_PNMI_HRX_FCS, SK_PNMI_HRX_RESERVED},
180 /* Bit54 */ { SK_PNMI_HRX_RESERVED, SK_PNMI_HRX_OVERFLOW},
181 /* Bit55 */ { SK_PNMI_HRX_CEXT, SK_PNMI_HRX_RESERVED},
182 /* Bit56 */ { SK_PNMI_HRX_UTILUNDER, SK_PNMI_HRX_RESERVED},
183 /* Bit57 */ { SK_PNMI_HRX_UTILOVER, SK_PNMI_HRX_RESERVED},
184 /* Bit58 */ { SK_PNMI_HRX_64, SK_PNMI_HRX_RESERVED},
185 /* Bit59 */ { SK_PNMI_HRX_127, SK_PNMI_HRX_RESERVED},
186 /* Bit60 */ { SK_PNMI_HRX_255, SK_PNMI_HRX_RESERVED},
187 /* Bit61 */ { SK_PNMI_HRX_511, SK_PNMI_HRX_RESERVED},
188 /* Bit62 */ { SK_PNMI_HRX_1023, SK_PNMI_HRX_RESERVED},
189 /* Bit63 */ { SK_PNMI_HRX_MAX, SK_PNMI_HRX_RESERVED}
193 * Table for hardware register saving on resets and port switches
195 PNMI_STATIC const SK_PNMI_STATADDR StatAddr[SK_PNMI_MAX_IDX][SK_PNMI_MAC_TYPES] = {
196 /* SK_PNMI_HTX */
197 {{XM_TXF_OK, SK_TRUE}, {0, SK_FALSE}},
198 /* SK_PNMI_HTX_OCTETHIGH */
199 {{XM_TXO_OK_HI, SK_TRUE}, {GM_TXO_OK_HI, SK_TRUE}},
200 /* SK_PNMI_HTX_OCTETLOW */
201 {{XM_TXO_OK_LO, SK_FALSE}, {GM_TXO_OK_LO, SK_FALSE}},
202 /* SK_PNMI_HTX_BROADCAST */
203 {{XM_TXF_BC_OK, SK_TRUE}, {GM_TXF_BC_OK, SK_TRUE}},
204 /* SK_PNMI_HTX_MULTICAST */
205 {{XM_TXF_MC_OK, SK_TRUE}, {GM_TXF_MC_OK, SK_TRUE}},
206 /* SK_PNMI_HTX_UNICAST */
207 {{XM_TXF_UC_OK, SK_TRUE}, {GM_TXF_UC_OK, SK_TRUE}},
208 /* SK_PNMI_HTX_BURST */
209 {{XM_TXE_BURST, SK_TRUE}, {0, SK_FALSE}},
210 /* SK_PNMI_HTX_PMACC */
211 {{XM_TXF_MPAUSE, SK_TRUE}, {GM_TXF_MPAUSE, SK_TRUE}},
212 /* SK_PNMI_HTX_MACC */
213 {{XM_TXF_MCTRL, SK_TRUE}, {0, SK_FALSE}},
214 /* SK_PNMI_HTX_COL */
215 {{0, SK_FALSE}, {GM_TXF_COL, SK_TRUE}},
216 /* SK_PNMI_HTX_SINGLE_COL */
217 {{XM_TXF_SNG_COL, SK_TRUE}, {GM_TXF_SNG_COL, SK_TRUE}},
218 /* SK_PNMI_HTX_MULTI_COL */
219 {{XM_TXF_MUL_COL, SK_TRUE}, {GM_TXF_MUL_COL, SK_TRUE}},
220 /* SK_PNMI_HTX_EXCESS_COL */
221 {{XM_TXF_ABO_COL, SK_TRUE}, {GM_TXF_ABO_COL, SK_TRUE}},
222 /* SK_PNMI_HTX_LATE_COL */
223 {{XM_TXF_LAT_COL, SK_TRUE}, {GM_TXF_LAT_COL, SK_TRUE}},
224 /* SK_PNMI_HTX_DEFFERAL */
225 {{XM_TXF_DEF, SK_TRUE}, {0, SK_FALSE}},
226 /* SK_PNMI_HTX_EXCESS_DEF */
227 {{XM_TXF_EX_DEF, SK_TRUE}, {0, SK_FALSE}},
228 /* SK_PNMI_HTX_UNDERRUN */
229 {{XM_TXE_FIFO_UR, SK_TRUE}, {GM_TXE_FIFO_UR, SK_TRUE}},
230 /* SK_PNMI_HTX_CARRIER */
231 {{XM_TXE_CS_ERR, SK_TRUE}, {0, SK_FALSE}},
232 /* SK_PNMI_HTX_UTILUNDER */
233 {{0, SK_FALSE}, {0, SK_FALSE}},
234 /* SK_PNMI_HTX_UTILOVER */
235 {{0, SK_FALSE}, {0, SK_FALSE}},
236 /* SK_PNMI_HTX_64 */
237 {{XM_TXF_64B, SK_TRUE}, {GM_TXF_64B, SK_TRUE}},
238 /* SK_PNMI_HTX_127 */
239 {{XM_TXF_127B, SK_TRUE}, {GM_TXF_127B, SK_TRUE}},
240 /* SK_PNMI_HTX_255 */
241 {{XM_TXF_255B, SK_TRUE}, {GM_TXF_255B, SK_TRUE}},
242 /* SK_PNMI_HTX_511 */
243 {{XM_TXF_511B, SK_TRUE}, {GM_TXF_511B, SK_TRUE}},
244 /* SK_PNMI_HTX_1023 */
245 {{XM_TXF_1023B, SK_TRUE}, {GM_TXF_1023B, SK_TRUE}},
246 /* SK_PNMI_HTX_MAX */
247 {{XM_TXF_MAX_SZ, SK_TRUE}, {GM_TXF_1518B, SK_TRUE}},
248 /* SK_PNMI_HTX_LONGFRAMES */
249 {{XM_TXF_LONG, SK_TRUE}, {GM_TXF_MAX_SZ, SK_TRUE}},
250 /* SK_PNMI_HTX_SYNC */
251 {{0, SK_FALSE}, {0, SK_FALSE}},
252 /* SK_PNMI_HTX_SYNC_OCTET */
253 {{0, SK_FALSE}, {0, SK_FALSE}},
254 /* SK_PNMI_HTX_RESERVED */
255 {{0, SK_FALSE}, {0, SK_FALSE}},
256 /* SK_PNMI_HRX */
257 {{XM_RXF_OK, SK_TRUE}, {0, SK_FALSE}},
258 /* SK_PNMI_HRX_OCTETHIGH */
259 {{XM_RXO_OK_HI, SK_TRUE}, {GM_RXO_OK_HI, SK_TRUE}},
260 /* SK_PNMI_HRX_OCTETLOW */
261 {{XM_RXO_OK_LO, SK_FALSE}, {GM_RXO_OK_LO, SK_FALSE}},
262 /* SK_PNMI_HRX_BADOCTETHIGH */
263 {{0, SK_FALSE}, {GM_RXO_ERR_HI, SK_TRUE}},
264 /* SK_PNMI_HRX_BADOCTETLOW */
265 {{0, SK_FALSE}, {GM_RXO_ERR_LO, SK_TRUE}},
266 /* SK_PNMI_HRX_BROADCAST */
267 {{XM_RXF_BC_OK, SK_TRUE}, {GM_RXF_BC_OK, SK_TRUE}},
268 /* SK_PNMI_HRX_MULTICAST */
269 {{XM_RXF_MC_OK, SK_TRUE}, {GM_RXF_MC_OK, SK_TRUE}},
270 /* SK_PNMI_HRX_UNICAST */
271 {{XM_RXF_UC_OK, SK_TRUE}, {GM_RXF_UC_OK, SK_TRUE}},
272 /* SK_PNMI_HRX_PMACC */
273 {{XM_RXF_MPAUSE, SK_TRUE}, {GM_RXF_MPAUSE, SK_TRUE}},
274 /* SK_PNMI_HRX_MACC */
275 {{XM_RXF_MCTRL, SK_TRUE}, {0, SK_FALSE}},
276 /* SK_PNMI_HRX_PMACC_ERR */
277 {{XM_RXF_INV_MP, SK_TRUE}, {0, SK_FALSE}},
278 /* SK_PNMI_HRX_MACC_UNKWN */
279 {{XM_RXF_INV_MOC, SK_TRUE}, {0, SK_FALSE}},
280 /* SK_PNMI_HRX_BURST */
281 {{XM_RXE_BURST, SK_TRUE}, {0, SK_FALSE}},
282 /* SK_PNMI_HRX_MISSED */
283 {{XM_RXE_FMISS, SK_TRUE}, {0, SK_FALSE}},
284 /* SK_PNMI_HRX_FRAMING */
285 {{XM_RXF_FRA_ERR, SK_TRUE}, {0, SK_FALSE}},
286 /* SK_PNMI_HRX_UNDERSIZE */
287 {{0, SK_FALSE}, {GM_RXF_SHT, SK_TRUE}},
288 /* SK_PNMI_HRX_OVERFLOW */
289 {{XM_RXE_FIFO_OV, SK_TRUE}, {GM_RXE_FIFO_OV, SK_TRUE}},
290 /* SK_PNMI_HRX_JABBER */
291 {{XM_RXF_JAB_PKT, SK_TRUE}, {GM_RXF_JAB_PKT, SK_TRUE}},
292 /* SK_PNMI_HRX_CARRIER */
293 {{XM_RXE_CAR_ERR, SK_TRUE}, {0, SK_FALSE}},
294 /* SK_PNMI_HRX_IRLENGTH */
295 {{XM_RXF_LEN_ERR, SK_TRUE}, {0, SK_FALSE}},
296 /* SK_PNMI_HRX_SYMBOL */
297 {{XM_RXE_SYM_ERR, SK_TRUE}, {0, SK_FALSE}},
298 /* SK_PNMI_HRX_SHORTS */
299 {{XM_RXE_SHT_ERR, SK_TRUE}, {0, SK_FALSE}},
300 /* SK_PNMI_HRX_RUNT */
301 {{XM_RXE_RUNT, SK_TRUE}, {GM_RXE_FRAG, SK_TRUE}},
302 /* SK_PNMI_HRX_TOO_LONG */
303 {{XM_RXF_LNG_ERR, SK_TRUE}, {GM_RXF_LNG_ERR, SK_TRUE}},
304 /* SK_PNMI_HRX_FCS */
305 {{XM_RXF_FCS_ERR, SK_TRUE}, {GM_RXF_FCS_ERR, SK_TRUE}},
306 /* SK_PNMI_HRX_CEXT */
307 {{XM_RXF_CEX_ERR, SK_TRUE}, {0, SK_FALSE}},
308 /* SK_PNMI_HRX_UTILUNDER */
309 {{0, SK_FALSE}, {0, SK_FALSE}},
310 /* SK_PNMI_HRX_UTILOVER */
311 {{0, SK_FALSE}, {0, SK_FALSE}},
312 /* SK_PNMI_HRX_64 */
313 {{XM_RXF_64B, SK_TRUE}, {GM_RXF_64B, SK_TRUE}},
314 /* SK_PNMI_HRX_127 */
315 {{XM_RXF_127B, SK_TRUE}, {GM_RXF_127B, SK_TRUE}},
316 /* SK_PNMI_HRX_255 */
317 {{XM_RXF_255B, SK_TRUE}, {GM_RXF_255B, SK_TRUE}},
318 /* SK_PNMI_HRX_511 */
319 {{XM_RXF_511B, SK_TRUE}, {GM_RXF_511B, SK_TRUE}},
320 /* SK_PNMI_HRX_1023 */
321 {{XM_RXF_1023B, SK_TRUE}, {GM_RXF_1023B, SK_TRUE}},
322 /* SK_PNMI_HRX_MAX */
323 {{XM_RXF_MAX_SZ, SK_TRUE}, {GM_RXF_1518B, SK_TRUE}},
324 /* SK_PNMI_HRX_LONGFRAMES */
325 {{0, SK_FALSE}, {GM_RXF_MAX_SZ, SK_TRUE}},
326 /* SK_PNMI_HRX_RESERVED */
327 {{0, SK_FALSE}, {0, SK_FALSE}}
331 /*****************************************************************************
333 * Public functions
337 /*****************************************************************************
339 * SkPnmiInit - Init function of PNMI
341 * Description:
342 * SK_INIT_DATA: Initialises the data structures
343 * SK_INIT_IO: Resets the XMAC statistics, determines the device and
344 * connector type.
345 * SK_INIT_RUN: Starts a timer event for port switch per hour
346 * calculation.
348 * Returns:
349 * Always 0
351 int SkPnmiInit(
352 SK_AC *pAC, /* Pointer to adapter context */
353 SK_IOC IoC, /* IO context handle */
354 int Level) /* Initialization level */
356 unsigned int PortMax; /* Number of ports */
357 unsigned int PortIndex; /* Current port index in loop */
358 SK_U16 Val16; /* Multiple purpose 16 bit variable */
359 SK_U8 Val8; /* Mulitple purpose 8 bit variable */
360 SK_EVPARA EventParam; /* Event struct for timer event */
361 SK_PNMI_VCT *pVctBackupData;
364 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
365 ("PNMI: SkPnmiInit: Called, level=%d\n", Level));
367 switch (Level) {
369 case SK_INIT_DATA:
370 SK_MEMSET((char *)&pAC->Pnmi, 0, sizeof(pAC->Pnmi));
371 pAC->Pnmi.TrapBufFree = SK_PNMI_TRAP_QUEUE_LEN;
372 pAC->Pnmi.StartUpTime = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC));
373 pAC->Pnmi.RlmtChangeThreshold = SK_PNMI_DEF_RLMT_CHG_THRES;
374 for (PortIndex = 0; PortIndex < SK_MAX_MACS; PortIndex ++) {
376 pAC->Pnmi.Port[PortIndex].ActiveFlag = SK_FALSE;
377 pAC->Pnmi.DualNetActiveFlag = SK_FALSE;
380 #ifdef SK_PNMI_CHECK
381 if (SK_PNMI_MAX_IDX != SK_PNMI_CNT_NO) {
383 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR049, SK_PNMI_ERR049MSG);
385 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_INIT | SK_DBGCAT_FATAL,
386 ("CounterOffset struct size (%d) differs from "
387 "SK_PNMI_MAX_IDX (%d)\n",
388 SK_PNMI_CNT_NO, SK_PNMI_MAX_IDX));
391 #endif /* SK_PNMI_CHECK */
392 break;
394 case SK_INIT_IO:
396 * Reset MAC counters
398 PortMax = pAC->GIni.GIMacsFound;
400 for (PortIndex = 0; PortIndex < PortMax; PortIndex ++) {
402 pAC->GIni.GIFunc.pFnMacResetCounter(pAC, IoC, PortIndex);
405 /* Initialize DSP variables for Vct() to 0xff => Never written! */
406 for (PortIndex = 0; PortIndex < PortMax; PortIndex ++) {
407 pAC->GIni.GP[PortIndex].PCableLen = 0xff;
408 pVctBackupData = &pAC->Pnmi.VctBackup[PortIndex];
409 pVctBackupData->PCableLen = 0xff;
413 * Get pci bus speed
415 SK_IN16(IoC, B0_CTST, &Val16);
416 if ((Val16 & CS_BUS_CLOCK) == 0) {
418 pAC->Pnmi.PciBusSpeed = 33;
420 else {
421 pAC->Pnmi.PciBusSpeed = 66;
425 * Get pci bus width
427 SK_IN16(IoC, B0_CTST, &Val16);
428 if ((Val16 & CS_BUS_SLOT_SZ) == 0) {
430 pAC->Pnmi.PciBusWidth = 32;
432 else {
433 pAC->Pnmi.PciBusWidth = 64;
437 * Get chipset
439 switch (pAC->GIni.GIChipId) {
440 case CHIP_ID_GENESIS:
441 pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_XMAC;
442 break;
444 case CHIP_ID_YUKON:
445 pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_YUKON;
446 break;
448 default:
449 break;
453 * Get PMD and DeviceType
455 SK_IN8(IoC, B2_PMD_TYP, &Val8);
456 switch (Val8) {
457 case 'S':
458 pAC->Pnmi.PMD = 3;
459 if (pAC->GIni.GIMacsFound > 1) {
461 pAC->Pnmi.DeviceType = 0x00020002;
463 else {
464 pAC->Pnmi.DeviceType = 0x00020001;
466 break;
468 case 'L':
469 pAC->Pnmi.PMD = 2;
470 if (pAC->GIni.GIMacsFound > 1) {
472 pAC->Pnmi.DeviceType = 0x00020004;
474 else {
475 pAC->Pnmi.DeviceType = 0x00020003;
477 break;
479 case 'C':
480 pAC->Pnmi.PMD = 4;
481 if (pAC->GIni.GIMacsFound > 1) {
483 pAC->Pnmi.DeviceType = 0x00020006;
485 else {
486 pAC->Pnmi.DeviceType = 0x00020005;
488 break;
490 case 'T':
491 pAC->Pnmi.PMD = 5;
492 if (pAC->GIni.GIMacsFound > 1) {
494 pAC->Pnmi.DeviceType = 0x00020008;
496 else {
497 pAC->Pnmi.DeviceType = 0x00020007;
499 break;
501 default :
502 pAC->Pnmi.PMD = 1;
503 pAC->Pnmi.DeviceType = 0;
504 break;
508 * Get connector
510 SK_IN8(IoC, B2_CONN_TYP, &Val8);
511 switch (Val8) {
512 case 'C':
513 pAC->Pnmi.Connector = 2;
514 break;
516 case 'D':
517 pAC->Pnmi.Connector = 3;
518 break;
520 case 'F':
521 pAC->Pnmi.Connector = 4;
522 break;
524 case 'J':
525 pAC->Pnmi.Connector = 5;
526 break;
528 case 'V':
529 pAC->Pnmi.Connector = 6;
530 break;
532 default:
533 pAC->Pnmi.Connector = 1;
534 break;
536 break;
538 case SK_INIT_RUN:
540 * Start timer for RLMT change counter
542 SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
543 SkTimerStart(pAC, IoC, &pAC->Pnmi.RlmtChangeEstimate.EstTimer,
544 28125000, SKGE_PNMI, SK_PNMI_EVT_CHG_EST_TIMER,
545 EventParam);
546 break;
548 default:
549 break; /* Nothing todo */
552 return (0);
555 /*****************************************************************************
557 * SkPnmiGetVar - Retrieves the value of a single OID
559 * Description:
560 * Calls a general sub-function for all this stuff. If the instance
561 * -1 is passed, the values of all instances are returned in an
562 * array of values.
564 * Returns:
565 * SK_PNMI_ERR_OK The request was successfully performed
566 * SK_PNMI_ERR_GENERAL A general severe internal error occured
567 * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to take
568 * the data.
569 * SK_PNMI_ERR_UNKNOWN_OID The requested OID is unknown
570 * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
571 * exist (e.g. port instance 3 on a two port
572 * adapter.
574 static int SkPnmiGetVar(
575 SK_AC *pAC, /* Pointer to adapter context */
576 SK_IOC IoC, /* IO context handle */
577 SK_U32 Id, /* Object ID that is to be processed */
578 void *pBuf, /* Buffer to which the management data will be copied */
579 unsigned int *pLen, /* On call: buffer length. On return: used buffer */
580 SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
581 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
583 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
584 ("PNMI: SkPnmiGetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n",
585 Id, *pLen, Instance, NetIndex));
587 return (PnmiVar(pAC, IoC, SK_PNMI_GET, Id, (char *)pBuf, pLen,
588 Instance, NetIndex));
591 /*****************************************************************************
593 * SkPnmiPreSetVar - Presets the value of a single OID
595 * Description:
596 * Calls a general sub-function for all this stuff. The preset does
597 * the same as a set, but returns just before finally setting the
598 * new value. This is useful to check if a set might be successfull.
599 * If the instance -1 is passed, an array of values is supposed and
600 * all instances of the OID will be set.
602 * Returns:
603 * SK_PNMI_ERR_OK The request was successfully performed.
604 * SK_PNMI_ERR_GENERAL A general severe internal error occured.
605 * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
606 * the correct data (e.g. a 32bit value is
607 * needed, but a 16 bit value was passed).
608 * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
609 * value range.
610 * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set.
611 * SK_PNMI_ERR_UNKNOWN_OID The requested OID is unknown.
612 * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
613 * exist (e.g. port instance 3 on a two port
614 * adapter.
616 static int SkPnmiPreSetVar(
617 SK_AC *pAC, /* Pointer to adapter context */
618 SK_IOC IoC, /* IO context handle */
619 SK_U32 Id, /* Object ID that is to be processed */
620 void *pBuf, /* Buffer to which the management data will be copied */
621 unsigned int *pLen, /* Total length of management data */
622 SK_U32 Instance, /* Instance (1..n) that is to be set or -1 */
623 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
625 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
626 ("PNMI: SkPnmiPreSetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n",
627 Id, *pLen, Instance, NetIndex));
630 return (PnmiVar(pAC, IoC, SK_PNMI_PRESET, Id, (char *)pBuf, pLen,
631 Instance, NetIndex));
634 /*****************************************************************************
636 * SkPnmiSetVar - Sets the value of a single OID
638 * Description:
639 * Calls a general sub-function for all this stuff. The preset does
640 * the same as a set, but returns just before finally setting the
641 * new value. This is useful to check if a set might be successfull.
642 * If the instance -1 is passed, an array of values is supposed and
643 * all instances of the OID will be set.
645 * Returns:
646 * SK_PNMI_ERR_OK The request was successfully performed.
647 * SK_PNMI_ERR_GENERAL A general severe internal error occured.
648 * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
649 * the correct data (e.g. a 32bit value is
650 * needed, but a 16 bit value was passed).
651 * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
652 * value range.
653 * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set.
654 * SK_PNMI_ERR_UNKNOWN_OID The requested OID is unknown.
655 * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
656 * exist (e.g. port instance 3 on a two port
657 * adapter.
659 int SkPnmiSetVar(
660 SK_AC *pAC, /* Pointer to adapter context */
661 SK_IOC IoC, /* IO context handle */
662 SK_U32 Id, /* Object ID that is to be processed */
663 void *pBuf, /* Buffer to which the management data will be copied */
664 unsigned int *pLen, /* Total length of management data */
665 SK_U32 Instance, /* Instance (1..n) that is to be set or -1 */
666 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
668 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
669 ("PNMI: SkPnmiSetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n",
670 Id, *pLen, Instance, NetIndex));
672 return (PnmiVar(pAC, IoC, SK_PNMI_SET, Id, (char *)pBuf, pLen,
673 Instance, NetIndex));
676 /*****************************************************************************
678 * SkPnmiGetStruct - Retrieves the management database in SK_PNMI_STRUCT_DATA
680 * Description:
681 * Runs through the IdTable, queries the single OIDs and stores the
682 * returned data into the management database structure
683 * SK_PNMI_STRUCT_DATA. The offset of the OID in the structure
684 * is stored in the IdTable. The return value of the function will also
685 * be stored in SK_PNMI_STRUCT_DATA if the passed buffer has the
686 * minimum size of SK_PNMI_MIN_STRUCT_SIZE.
688 * Returns:
689 * SK_PNMI_ERR_OK The request was successfully performed
690 * SK_PNMI_ERR_GENERAL A general severe internal error occured
691 * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to take
692 * the data.
693 * SK_PNMI_ERR_UNKNOWN_NET The requested NetIndex doesn't exist
695 int SkPnmiGetStruct(
696 SK_AC *pAC, /* Pointer to adapter context */
697 SK_IOC IoC, /* IO context handle */
698 void *pBuf, /* Buffer to which the management data will be copied. */
699 unsigned int *pLen, /* Length of buffer */
700 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
702 int Ret;
703 unsigned int TableIndex;
704 unsigned int DstOffset;
705 unsigned int InstanceNo;
706 unsigned int InstanceCnt;
707 SK_U32 Instance;
708 unsigned int TmpLen;
709 char KeyArr[SK_PNMI_VPD_ENTRIES][SK_PNMI_VPD_KEY_SIZE];
712 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
713 ("PNMI: SkPnmiGetStruct: Called, BufLen=%d, NetIndex=%d\n",
714 *pLen, NetIndex));
716 if (*pLen < SK_PNMI_STRUCT_SIZE) {
718 if (*pLen >= SK_PNMI_MIN_STRUCT_SIZE) {
720 SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_TOO_SHORT,
721 (SK_U32)(-1));
724 *pLen = SK_PNMI_STRUCT_SIZE;
725 return (SK_PNMI_ERR_TOO_SHORT);
729 * Check NetIndex
731 if (NetIndex >= pAC->Rlmt.NumNets) {
732 return (SK_PNMI_ERR_UNKNOWN_NET);
735 /* Update statistic */
736 SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On call");
738 if ((Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1)) !=
739 SK_PNMI_ERR_OK) {
741 SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
742 *pLen = SK_PNMI_MIN_STRUCT_SIZE;
743 return (Ret);
746 if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) {
748 SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
749 *pLen = SK_PNMI_MIN_STRUCT_SIZE;
750 return (Ret);
753 if ((Ret = SirqUpdate(pAC, IoC)) != SK_PNMI_ERR_OK) {
755 SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
756 *pLen = SK_PNMI_MIN_STRUCT_SIZE;
757 return (Ret);
761 * Increment semaphores to indicate that an update was
762 * already done
764 pAC->Pnmi.MacUpdatedFlag ++;
765 pAC->Pnmi.RlmtUpdatedFlag ++;
766 pAC->Pnmi.SirqUpdatedFlag ++;
768 /* Get vpd keys for instance calculation */
769 Ret = GetVpdKeyArr(pAC, IoC, &KeyArr[0][0], sizeof(KeyArr), &TmpLen);
770 if (Ret != SK_PNMI_ERR_OK) {
772 pAC->Pnmi.MacUpdatedFlag --;
773 pAC->Pnmi.RlmtUpdatedFlag --;
774 pAC->Pnmi.SirqUpdatedFlag --;
776 SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return");
777 SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
778 *pLen = SK_PNMI_MIN_STRUCT_SIZE;
779 return (SK_PNMI_ERR_GENERAL);
782 /* Retrieve values */
783 SK_MEMSET((char *)pBuf, 0, SK_PNMI_STRUCT_SIZE);
784 for (TableIndex = 0; TableIndex < ID_TABLE_SIZE; TableIndex ++) {
786 InstanceNo = IdTable[TableIndex].InstanceNo;
787 for (InstanceCnt = 1; InstanceCnt <= InstanceNo;
788 InstanceCnt ++) {
790 DstOffset = IdTable[TableIndex].Offset +
791 (InstanceCnt - 1) *
792 IdTable[TableIndex].StructSize;
795 * For the VPD the instance is not an index number
796 * but the key itself. Determin with the instance
797 * counter the VPD key to be used.
799 if (IdTable[TableIndex].Id == OID_SKGE_VPD_KEY ||
800 IdTable[TableIndex].Id == OID_SKGE_VPD_VALUE ||
801 IdTable[TableIndex].Id == OID_SKGE_VPD_ACCESS ||
802 IdTable[TableIndex].Id == OID_SKGE_VPD_ACTION) {
804 SK_STRNCPY((char *)&Instance, KeyArr[InstanceCnt - 1], 4);
806 else {
807 Instance = (SK_U32)InstanceCnt;
810 TmpLen = *pLen - DstOffset;
811 Ret = IdTable[TableIndex].Func(pAC, IoC, SK_PNMI_GET,
812 IdTable[TableIndex].Id, (char *)pBuf +
813 DstOffset, &TmpLen, Instance, TableIndex, NetIndex);
816 * An unknown instance error means that we reached
817 * the last instance of that variable. Proceed with
818 * the next OID in the table and ignore the return
819 * code.
821 if (Ret == SK_PNMI_ERR_UNKNOWN_INST) {
823 break;
826 if (Ret != SK_PNMI_ERR_OK) {
828 pAC->Pnmi.MacUpdatedFlag --;
829 pAC->Pnmi.RlmtUpdatedFlag --;
830 pAC->Pnmi.SirqUpdatedFlag --;
832 SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return");
833 SK_PNMI_SET_STAT(pBuf, Ret, DstOffset);
834 *pLen = SK_PNMI_MIN_STRUCT_SIZE;
835 return (Ret);
840 pAC->Pnmi.MacUpdatedFlag --;
841 pAC->Pnmi.RlmtUpdatedFlag --;
842 pAC->Pnmi.SirqUpdatedFlag --;
844 *pLen = SK_PNMI_STRUCT_SIZE;
845 SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return");
846 SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_OK, (SK_U32)(-1));
847 return (SK_PNMI_ERR_OK);
850 /*****************************************************************************
852 * SkPnmiPreSetStruct - Presets the management database in SK_PNMI_STRUCT_DATA
854 * Description:
855 * Calls a general sub-function for all this set stuff. The preset does
856 * the same as a set, but returns just before finally setting the
857 * new value. This is useful to check if a set might be successfull.
858 * The sub-function runs through the IdTable, checks which OIDs are able
859 * to set, and calls the handler function of the OID to perform the
860 * preset. The return value of the function will also be stored in
861 * SK_PNMI_STRUCT_DATA if the passed buffer has the minimum size of
862 * SK_PNMI_MIN_STRUCT_SIZE.
864 * Returns:
865 * SK_PNMI_ERR_OK The request was successfully performed.
866 * SK_PNMI_ERR_GENERAL A general severe internal error occured.
867 * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
868 * the correct data (e.g. a 32bit value is
869 * needed, but a 16 bit value was passed).
870 * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
871 * value range.
873 int SkPnmiPreSetStruct(
874 SK_AC *pAC, /* Pointer to adapter context */
875 SK_IOC IoC, /* IO context handle */
876 void *pBuf, /* Buffer which contains the data to be set */
877 unsigned int *pLen, /* Length of buffer */
878 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
880 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
881 ("PNMI: SkPnmiPreSetStruct: Called, BufLen=%d, NetIndex=%d\n",
882 *pLen, NetIndex));
884 return (PnmiStruct(pAC, IoC, SK_PNMI_PRESET, (char *)pBuf,
885 pLen, NetIndex));
888 /*****************************************************************************
890 * SkPnmiSetStruct - Sets the management database in SK_PNMI_STRUCT_DATA
892 * Description:
893 * Calls a general sub-function for all this set stuff. The return value
894 * of the function will also be stored in SK_PNMI_STRUCT_DATA if the
895 * passed buffer has the minimum size of SK_PNMI_MIN_STRUCT_SIZE.
896 * The sub-function runs through the IdTable, checks which OIDs are able
897 * to set, and calls the handler function of the OID to perform the
898 * set. The return value of the function will also be stored in
899 * SK_PNMI_STRUCT_DATA if the passed buffer has the minimum size of
900 * SK_PNMI_MIN_STRUCT_SIZE.
902 * Returns:
903 * SK_PNMI_ERR_OK The request was successfully performed.
904 * SK_PNMI_ERR_GENERAL A general severe internal error occured.
905 * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
906 * the correct data (e.g. a 32bit value is
907 * needed, but a 16 bit value was passed).
908 * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
909 * value range.
911 int SkPnmiSetStruct(
912 SK_AC *pAC, /* Pointer to adapter context */
913 SK_IOC IoC, /* IO context handle */
914 void *pBuf, /* Buffer which contains the data to be set */
915 unsigned int *pLen, /* Length of buffer */
916 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
918 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
919 ("PNMI: SkPnmiSetStruct: Called, BufLen=%d, NetIndex=%d\n",
920 *pLen, NetIndex));
922 return (PnmiStruct(pAC, IoC, SK_PNMI_SET, (char *)pBuf,
923 pLen, NetIndex));
926 /*****************************************************************************
928 * SkPnmiEvent - Event handler
930 * Description:
931 * Handles the following events:
932 * SK_PNMI_EVT_SIRQ_OVERFLOW When a hardware counter overflows an
933 * interrupt will be generated which is
934 * first handled by SIRQ which generates a
935 * this event. The event increments the
936 * upper 32 bit of the 64 bit counter.
937 * SK_PNMI_EVT_SEN_XXX The event is generated by the I2C module
938 * when a sensor reports a warning or
939 * error. The event will store a trap
940 * message in the trap buffer.
941 * SK_PNMI_EVT_CHG_EST_TIMER The timer event was initiated by this
942 * module and is used to calculate the
943 * port switches per hour.
944 * SK_PNMI_EVT_CLEAR_COUNTER The event clears all counters and
945 * timestamps.
946 * SK_PNMI_EVT_XMAC_RESET The event is generated by the driver
947 * before a hard reset of the XMAC is
948 * performed. All counters will be saved
949 * and added to the hardware counter
950 * values after reset to grant continuous
951 * counter values.
952 * SK_PNMI_EVT_RLMT_PORT_UP Generated by RLMT to notify that a port
953 * went logically up. A trap message will
954 * be stored to the trap buffer.
955 * SK_PNMI_EVT_RLMT_PORT_DOWN Generated by RLMT to notify that a port
956 * went logically down. A trap message will
957 * be stored to the trap buffer.
958 * SK_PNMI_EVT_RLMT_SEGMENTATION Generated by RLMT to notify that two
959 * spanning tree root bridges were
960 * detected. A trap message will be stored
961 * to the trap buffer.
962 * SK_PNMI_EVT_RLMT_ACTIVE_DOWN Notifies PNMI that an active port went
963 * down. PNMI will not further add the
964 * statistic values to the virtual port.
965 * SK_PNMI_EVT_RLMT_ACTIVE_UP Notifies PNMI that a port went up and
966 * is now an active port. PNMI will now
967 * add the statistic data of this port to
968 * the virtual port.
969 * SK_PNMI_EVT_RLMT_SET_NETS Notifies PNMI about the net mode. The first parameter
970 * contains the number of nets. 1 means single net, 2 means
971 * dual net. The second parameter is -1
973 * Returns:
974 * Always 0
976 int SkPnmiEvent(
977 SK_AC *pAC, /* Pointer to adapter context */
978 SK_IOC IoC, /* IO context handle */
979 SK_U32 Event, /* Event-Id */
980 SK_EVPARA Param) /* Event dependent parameter */
982 unsigned int PhysPortIndex;
983 unsigned int MaxNetNumber;
984 int CounterIndex;
985 int Ret;
986 SK_U16 MacStatus;
987 SK_U64 OverflowStatus;
988 SK_U64 Mask;
989 int MacType;
990 SK_U64 Value;
991 SK_U32 Val32;
992 SK_U16 Register;
993 SK_EVPARA EventParam;
994 SK_U64 NewestValue;
995 SK_U64 OldestValue;
996 SK_U64 Delta;
997 SK_PNMI_ESTIMATE *pEst;
998 SK_U32 NetIndex;
999 SK_GEPORT *pPrt;
1000 SK_PNMI_VCT *pVctBackupData;
1001 SK_U32 RetCode;
1002 int i;
1003 SK_U32 CableLength;
1006 #ifdef DEBUG
1007 if (Event != SK_PNMI_EVT_XMAC_RESET) {
1009 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
1010 ("PNMI: SkPnmiEvent: Called, Event=0x%x, Param=0x%x\n",
1011 (unsigned int)Event, (unsigned int)Param.Para64));
1013 #endif /* DEBUG */
1014 SK_PNMI_CHECKFLAGS("SkPnmiEvent: On call");
1016 MacType = pAC->GIni.GIMacType;
1018 switch (Event) {
1020 case SK_PNMI_EVT_SIRQ_OVERFLOW:
1021 PhysPortIndex = (int)Param.Para32[0];
1022 MacStatus = (SK_U16)Param.Para32[1];
1023 #ifdef DEBUG
1024 if (PhysPortIndex >= SK_MAX_MACS) {
1026 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
1027 ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SIRQ_OVERFLOW parameter"
1028 " wrong, PhysPortIndex=0x%x\n",
1029 PhysPortIndex));
1030 return (0);
1032 #endif /* DEBUG */
1033 OverflowStatus = 0;
1036 * Check which source caused an overflow interrupt.
1038 if ((pAC->GIni.GIFunc.pFnMacOverflow(pAC, IoC, PhysPortIndex,
1039 MacStatus, &OverflowStatus) != 0) ||
1040 (OverflowStatus == 0)) {
1042 SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
1043 return (0);
1047 * Check the overflow status register and increment
1048 * the upper dword of corresponding counter.
1050 for (CounterIndex = 0; CounterIndex < sizeof(Mask) * 8;
1051 CounterIndex ++) {
1053 Mask = (SK_U64)1 << CounterIndex;
1054 if ((OverflowStatus & Mask) == 0) {
1056 continue;
1059 switch (StatOvrflwBit[CounterIndex][MacType]) {
1061 case SK_PNMI_HTX_UTILUNDER:
1062 case SK_PNMI_HTX_UTILOVER:
1063 if (MacType == SK_MAC_XMAC) {
1064 XM_IN16(IoC, PhysPortIndex, XM_TX_CMD, &Register);
1065 Register |= XM_TX_SAM_LINE;
1066 XM_OUT16(IoC, PhysPortIndex, XM_TX_CMD, Register);
1068 break;
1070 case SK_PNMI_HRX_UTILUNDER:
1071 case SK_PNMI_HRX_UTILOVER:
1072 if (MacType == SK_MAC_XMAC) {
1073 XM_IN16(IoC, PhysPortIndex, XM_RX_CMD, &Register);
1074 Register |= XM_RX_SAM_LINE;
1075 XM_OUT16(IoC, PhysPortIndex, XM_RX_CMD, Register);
1077 break;
1079 case SK_PNMI_HTX_OCTETHIGH:
1080 case SK_PNMI_HTX_OCTETLOW:
1081 case SK_PNMI_HTX_RESERVED:
1082 case SK_PNMI_HRX_OCTETHIGH:
1083 case SK_PNMI_HRX_OCTETLOW:
1084 case SK_PNMI_HRX_IRLENGTH:
1085 case SK_PNMI_HRX_RESERVED:
1088 * the following counters aren't be handled (id > 63)
1090 case SK_PNMI_HTX_SYNC:
1091 case SK_PNMI_HTX_SYNC_OCTET:
1092 break;
1094 case SK_PNMI_HRX_LONGFRAMES:
1095 if (MacType == SK_MAC_GMAC) {
1096 pAC->Pnmi.Port[PhysPortIndex].
1097 CounterHigh[CounterIndex] ++;
1099 break;
1101 default:
1102 pAC->Pnmi.Port[PhysPortIndex].
1103 CounterHigh[CounterIndex] ++;
1106 break;
1108 case SK_PNMI_EVT_SEN_WAR_LOW:
1109 #ifdef DEBUG
1110 if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) {
1112 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
1113 ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_WAR_LOW parameter wrong, SensorIndex=%d\n",
1114 (unsigned int)Param.Para64));
1115 return (0);
1117 #endif /* DEBUG */
1120 * Store a trap message in the trap buffer and generate
1121 * an event for user space applications with the
1122 * SK_DRIVER_SENDEVENT macro.
1124 QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_WAR_LOW,
1125 (unsigned int)Param.Para64);
1126 (void)SK_DRIVER_SENDEVENT(pAC, IoC);
1127 break;
1129 case SK_PNMI_EVT_SEN_WAR_UPP:
1130 #ifdef DEBUG
1131 if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) {
1133 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
1134 ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_WAR_UPP parameter wrong, SensorIndex=%d\n",
1135 (unsigned int)Param.Para64));
1136 return (0);
1138 #endif /* DEBUG */
1141 * Store a trap message in the trap buffer and generate
1142 * an event for user space applications with the
1143 * SK_DRIVER_SENDEVENT macro.
1145 QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_WAR_UPP,
1146 (unsigned int)Param.Para64);
1147 (void)SK_DRIVER_SENDEVENT(pAC, IoC);
1148 break;
1150 case SK_PNMI_EVT_SEN_ERR_LOW:
1151 #ifdef DEBUG
1152 if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) {
1154 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
1155 ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_ERR_LOW parameter wrong, SensorIndex=%d\n",
1156 (unsigned int)Param.Para64));
1157 return (0);
1159 #endif /* DEBUG */
1162 * Store a trap message in the trap buffer and generate
1163 * an event for user space applications with the
1164 * SK_DRIVER_SENDEVENT macro.
1166 QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_ERR_LOW,
1167 (unsigned int)Param.Para64);
1168 (void)SK_DRIVER_SENDEVENT(pAC, IoC);
1169 break;
1171 case SK_PNMI_EVT_SEN_ERR_UPP:
1172 #ifdef DEBUG
1173 if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) {
1175 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
1176 ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_ERR_UPP parameter wrong, SensorIndex=%d\n",
1177 (unsigned int)Param.Para64));
1178 return (0);
1180 #endif /* DEBUG */
1183 * Store a trap message in the trap buffer and generate
1184 * an event for user space applications with the
1185 * SK_DRIVER_SENDEVENT macro.
1187 QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_ERR_UPP,
1188 (unsigned int)Param.Para64);
1189 (void)SK_DRIVER_SENDEVENT(pAC, IoC);
1190 break;
1192 case SK_PNMI_EVT_CHG_EST_TIMER:
1194 * Calculate port switch average on a per hour basis
1195 * Time interval for check : 28125 ms
1196 * Number of values for average : 8
1198 * Be careful in changing these values, on change check
1199 * - typedef of SK_PNMI_ESTIMATE (Size of EstValue
1200 * array one less than value number)
1201 * - Timer initialization SkTimerStart() in SkPnmiInit
1202 * - Delta value below must be multiplicated with
1203 * power of 2
1206 pEst = &pAC->Pnmi.RlmtChangeEstimate;
1207 CounterIndex = pEst->EstValueIndex + 1;
1208 if (CounterIndex == 7) {
1210 CounterIndex = 0;
1212 pEst->EstValueIndex = CounterIndex;
1214 NewestValue = pAC->Pnmi.RlmtChangeCts;
1215 OldestValue = pEst->EstValue[CounterIndex];
1216 pEst->EstValue[CounterIndex] = NewestValue;
1219 * Calculate average. Delta stores the number of
1220 * port switches per 28125 * 8 = 225000 ms
1222 if (NewestValue >= OldestValue) {
1224 Delta = NewestValue - OldestValue;
1226 else {
1227 /* Overflow situation */
1228 Delta = (SK_U64)(0 - OldestValue) + NewestValue;
1232 * Extrapolate delta to port switches per hour.
1233 * Estimate = Delta * (3600000 / 225000)
1234 * = Delta * 16
1235 * = Delta << 4
1237 pAC->Pnmi.RlmtChangeEstimate.Estimate = Delta << 4;
1240 * Check if threshold is exceeded. If the threshold is
1241 * permanently exceeded every 28125 ms an event will be
1242 * generated to remind the user of this condition.
1244 if ((pAC->Pnmi.RlmtChangeThreshold != 0) &&
1245 (pAC->Pnmi.RlmtChangeEstimate.Estimate >=
1246 pAC->Pnmi.RlmtChangeThreshold)) {
1248 QueueSimpleTrap(pAC, OID_SKGE_TRAP_RLMT_CHANGE_THRES);
1249 (void)SK_DRIVER_SENDEVENT(pAC, IoC);
1252 SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
1253 SkTimerStart(pAC, IoC, &pAC->Pnmi.RlmtChangeEstimate.EstTimer,
1254 28125000, SKGE_PNMI, SK_PNMI_EVT_CHG_EST_TIMER,
1255 EventParam);
1256 break;
1258 case SK_PNMI_EVT_CLEAR_COUNTER:
1260 * Param.Para32[0] contains the NetIndex (0 ..1).
1261 * Param.Para32[1] is reserved, contains -1.
1263 NetIndex = (SK_U32)Param.Para32[0];
1265 #ifdef DEBUG
1266 if (NetIndex >= pAC->Rlmt.NumNets) {
1268 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
1269 ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_CLEAR_COUNTER parameter wrong, NetIndex=%d\n",
1270 NetIndex));
1272 return (0);
1274 #endif /* DEBUG */
1277 * Set all counters and timestamps to zero.
1278 * The according NetIndex is required as a
1279 * parameter of the event.
1281 ResetCounter(pAC, IoC, NetIndex);
1282 break;
1284 case SK_PNMI_EVT_XMAC_RESET:
1286 * To grant continuous counter values store the current
1287 * XMAC statistic values to the entries 1..n of the
1288 * CounterOffset array. XMAC Errata #2
1290 #ifdef DEBUG
1291 if ((unsigned int)Param.Para64 >= SK_MAX_MACS) {
1293 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
1294 ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_XMAC_RESET parameter wrong, PhysPortIndex=%d\n",
1295 (unsigned int)Param.Para64));
1296 return (0);
1298 #endif
1299 PhysPortIndex = (unsigned int)Param.Para64;
1302 * Update XMAC statistic to get fresh values
1304 Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1);
1305 if (Ret != SK_PNMI_ERR_OK) {
1307 SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
1308 return (0);
1311 * Increment semaphore to indicate that an update was
1312 * already done
1314 pAC->Pnmi.MacUpdatedFlag ++;
1316 for (CounterIndex = 0; CounterIndex < SK_PNMI_MAX_IDX;
1317 CounterIndex ++) {
1319 if (!StatAddr[CounterIndex][MacType].GetOffset) {
1321 continue;
1324 pAC->Pnmi.Port[PhysPortIndex].CounterOffset[CounterIndex] =
1325 GetPhysStatVal(pAC, IoC, PhysPortIndex, CounterIndex);
1327 pAC->Pnmi.Port[PhysPortIndex].CounterHigh[CounterIndex] = 0;
1330 pAC->Pnmi.MacUpdatedFlag --;
1331 break;
1333 case SK_PNMI_EVT_RLMT_PORT_UP:
1334 PhysPortIndex = (unsigned int)Param.Para32[0];
1335 #ifdef DEBUG
1336 if (PhysPortIndex >= SK_MAX_MACS) {
1338 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
1339 ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_PORT_UP parameter"
1340 " wrong, PhysPortIndex=%d\n", PhysPortIndex));
1342 return (0);
1344 #endif /* DEBUG */
1347 * Store a trap message in the trap buffer and generate an event for
1348 * user space applications with the SK_DRIVER_SENDEVENT macro.
1350 QueueRlmtPortTrap(pAC, OID_SKGE_TRAP_RLMT_PORT_UP, PhysPortIndex);
1351 (void)SK_DRIVER_SENDEVENT(pAC, IoC);
1353 /* Bugfix for XMAC errata (#10620)*/
1354 if (MacType == SK_MAC_XMAC) {
1355 /* Add incremental difference to offset (#10620)*/
1356 (void)pAC->GIni.GIFunc.pFnMacStatistic(pAC, IoC, PhysPortIndex,
1357 XM_RXE_SHT_ERR, &Val32);
1359 Value = (((SK_U64)pAC->Pnmi.Port[PhysPortIndex].
1360 CounterHigh[SK_PNMI_HRX_SHORTS] << 32) | (SK_U64)Val32);
1361 pAC->Pnmi.Port[PhysPortIndex].CounterOffset[SK_PNMI_HRX_SHORTS] +=
1362 Value - pAC->Pnmi.Port[PhysPortIndex].RxShortZeroMark;
1365 /* Tell VctStatus() that a link was up meanwhile. */
1366 pAC->Pnmi.VctStatus[PhysPortIndex] |= SK_PNMI_VCT_LINK;
1367 break;
1369 case SK_PNMI_EVT_RLMT_PORT_DOWN:
1370 PhysPortIndex = (unsigned int)Param.Para32[0];
1372 #ifdef DEBUG
1373 if (PhysPortIndex >= SK_MAX_MACS) {
1375 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
1376 ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_PORT_DOWN parameter"
1377 " wrong, PhysPortIndex=%d\n", PhysPortIndex));
1379 return (0);
1381 #endif /* DEBUG */
1384 * Store a trap message in the trap buffer and generate an event for
1385 * user space applications with the SK_DRIVER_SENDEVENT macro.
1387 QueueRlmtPortTrap(pAC, OID_SKGE_TRAP_RLMT_PORT_DOWN, PhysPortIndex);
1388 (void)SK_DRIVER_SENDEVENT(pAC, IoC);
1390 /* Bugfix #10620 - get zero level for incremental difference */
1391 if (MacType == SK_MAC_XMAC) {
1393 (void)pAC->GIni.GIFunc.pFnMacStatistic(pAC, IoC, PhysPortIndex,
1394 XM_RXE_SHT_ERR, &Val32);
1396 pAC->Pnmi.Port[PhysPortIndex].RxShortZeroMark =
1397 (((SK_U64)pAC->Pnmi.Port[PhysPortIndex].
1398 CounterHigh[SK_PNMI_HRX_SHORTS] << 32) | (SK_U64)Val32);
1400 break;
1402 case SK_PNMI_EVT_RLMT_ACTIVE_DOWN:
1403 PhysPortIndex = (unsigned int)Param.Para32[0];
1404 NetIndex = (SK_U32)Param.Para32[1];
1406 #ifdef DEBUG
1407 if (PhysPortIndex >= SK_MAX_MACS) {
1409 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
1410 ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_DOWN parameter too high, PhysPort=%d\n",
1411 PhysPortIndex));
1414 if (NetIndex >= pAC->Rlmt.NumNets) {
1416 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
1417 ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_DOWN parameter too high, NetIndex=%d\n",
1418 NetIndex));
1420 #endif /* DEBUG */
1423 * For now, ignore event if NetIndex != 0.
1425 if (Param.Para32[1] != 0) {
1427 return (0);
1431 * Nothing to do if port is already inactive
1433 if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
1435 return (0);
1439 * Update statistic counters to calculate new offset for the virtual
1440 * port and increment semaphore to indicate that an update was already
1441 * done.
1443 if (MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1) !=
1444 SK_PNMI_ERR_OK) {
1446 SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
1447 return (0);
1449 pAC->Pnmi.MacUpdatedFlag ++;
1452 * Calculate new counter offset for virtual port to grant continous
1453 * counting on port switches. The virtual port consists of all currently
1454 * active ports. The port down event indicates that a port is removed
1455 * from the virtual port. Therefore add the counter value of the removed
1456 * port to the CounterOffset for the virtual port to grant the same
1457 * counter value.
1459 for (CounterIndex = 0; CounterIndex < SK_PNMI_MAX_IDX;
1460 CounterIndex ++) {
1462 if (!StatAddr[CounterIndex][MacType].GetOffset) {
1464 continue;
1467 Value = GetPhysStatVal(pAC, IoC, PhysPortIndex, CounterIndex);
1469 pAC->Pnmi.VirtualCounterOffset[CounterIndex] += Value;
1473 * Set port to inactive
1475 pAC->Pnmi.Port[PhysPortIndex].ActiveFlag = SK_FALSE;
1477 pAC->Pnmi.MacUpdatedFlag --;
1478 break;
1480 case SK_PNMI_EVT_RLMT_ACTIVE_UP:
1481 PhysPortIndex = (unsigned int)Param.Para32[0];
1482 NetIndex = (SK_U32)Param.Para32[1];
1484 #ifdef DEBUG
1485 if (PhysPortIndex >= SK_MAX_MACS) {
1487 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
1488 ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_UP parameter too high, PhysPort=%d\n",
1489 PhysPortIndex));
1492 if (NetIndex >= pAC->Rlmt.NumNets) {
1494 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL,
1495 ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_UP parameter too high, NetIndex=%d\n",
1496 NetIndex));
1498 #endif /* DEBUG */
1501 * For now, ignore event if NetIndex != 0.
1503 if (Param.Para32[1] != 0) {
1505 return (0);
1509 * Nothing to do if port is already active
1511 if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
1513 return (0);
1517 * Statistic maintenance
1519 pAC->Pnmi.RlmtChangeCts ++;
1520 pAC->Pnmi.RlmtChangeTime = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC));
1523 * Store a trap message in the trap buffer and generate an event for
1524 * user space applications with the SK_DRIVER_SENDEVENT macro.
1526 QueueRlmtNewMacTrap(pAC, PhysPortIndex);
1527 (void)SK_DRIVER_SENDEVENT(pAC, IoC);
1530 * Update statistic counters to calculate new offset for the virtual
1531 * port and increment semaphore to indicate that an update was
1532 * already done.
1534 if (MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1) !=
1535 SK_PNMI_ERR_OK) {
1537 SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
1538 return (0);
1540 pAC->Pnmi.MacUpdatedFlag ++;
1543 * Calculate new counter offset for virtual port to grant continous
1544 * counting on port switches. A new port is added to the virtual port.
1545 * Therefore substract the counter value of the new port from the
1546 * CounterOffset for the virtual port to grant the same value.
1548 for (CounterIndex = 0; CounterIndex < SK_PNMI_MAX_IDX;
1549 CounterIndex ++) {
1551 if (!StatAddr[CounterIndex][MacType].GetOffset) {
1553 continue;
1556 Value = GetPhysStatVal(pAC, IoC, PhysPortIndex, CounterIndex);
1558 pAC->Pnmi.VirtualCounterOffset[CounterIndex] -= Value;
1561 /* Set port to active */
1562 pAC->Pnmi.Port[PhysPortIndex].ActiveFlag = SK_TRUE;
1564 pAC->Pnmi.MacUpdatedFlag --;
1565 break;
1567 case SK_PNMI_EVT_RLMT_SEGMENTATION:
1569 * Para.Para32[0] contains the NetIndex.
1573 * Store a trap message in the trap buffer and generate an event for
1574 * user space applications with the SK_DRIVER_SENDEVENT macro.
1576 QueueSimpleTrap(pAC, OID_SKGE_TRAP_RLMT_SEGMENTATION);
1577 (void)SK_DRIVER_SENDEVENT(pAC, IoC);
1578 break;
1580 case SK_PNMI_EVT_RLMT_SET_NETS:
1582 * Param.Para32[0] contains the number of Nets.
1583 * Param.Para32[1] is reserved, contains -1.
1586 * Check number of nets
1588 MaxNetNumber = pAC->GIni.GIMacsFound;
1589 if (((unsigned int)Param.Para32[0] < 1)
1590 || ((unsigned int)Param.Para32[0] > MaxNetNumber)) {
1591 return (SK_PNMI_ERR_UNKNOWN_NET);
1594 if ((unsigned int)Param.Para32[0] == 1) { /* single net mode */
1595 pAC->Pnmi.DualNetActiveFlag = SK_FALSE;
1597 else { /* dual net mode */
1598 pAC->Pnmi.DualNetActiveFlag = SK_TRUE;
1600 break;
1602 case SK_PNMI_EVT_VCT_RESET:
1603 PhysPortIndex = Param.Para32[0];
1604 pPrt = &pAC->GIni.GP[PhysPortIndex];
1605 pVctBackupData = &pAC->Pnmi.VctBackup[PhysPortIndex];
1607 if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING) {
1608 RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_FALSE);
1609 if (RetCode == 2) {
1611 * VCT test is still running.
1612 * Start VCT timer counter again.
1614 SK_MEMSET((char *) &Param, 0, sizeof(Param));
1615 Param.Para32[0] = PhysPortIndex;
1616 Param.Para32[1] = -1;
1617 SkTimerStart(pAC, IoC,
1618 &pAC->Pnmi.VctTimeout[PhysPortIndex].VctTimer,
1619 4000000, SKGE_PNMI, SK_PNMI_EVT_VCT_RESET, Param);
1620 break;
1622 pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_PENDING;
1623 pAC->Pnmi.VctStatus[PhysPortIndex] |=
1624 (SK_PNMI_VCT_NEW_VCT_DATA | SK_PNMI_VCT_TEST_DONE);
1626 /* Copy results for later use to PNMI struct. */
1627 for (i = 0; i < 4; i++) {
1628 if (pPrt->PMdiPairSts[i] == SK_PNMI_VCT_NORMAL_CABLE) {
1629 if ((pPrt->PMdiPairLen[i] > 35) &&
1630 (pPrt->PMdiPairLen[i] < 0xff)) {
1631 pPrt->PMdiPairSts[i] = SK_PNMI_VCT_IMPEDANCE_MISMATCH;
1634 if ((pPrt->PMdiPairLen[i] > 35) &&
1635 (pPrt->PMdiPairLen[i] != 0xff)) {
1636 CableLength = 1000 *
1637 (((175 * pPrt->PMdiPairLen[i]) / 210) - 28);
1639 else {
1640 CableLength = 0;
1642 pVctBackupData->PMdiPairLen[i] = CableLength;
1643 pVctBackupData->PMdiPairSts[i] = pPrt->PMdiPairSts[i];
1646 Param.Para32[0] = PhysPortIndex;
1647 Param.Para32[1] = -1;
1648 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Param);
1649 SkEventDispatcher(pAC, IoC);
1652 break;
1654 default:
1655 break;
1658 SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return");
1659 return (0);
1663 /******************************************************************************
1665 * Private functions
1669 /*****************************************************************************
1671 * PnmiVar - Gets, presets, and sets single OIDs
1673 * Description:
1674 * Looks up the requested OID, calls the corresponding handler
1675 * function, and passes the parameters with the get, preset, or
1676 * set command. The function is called by SkGePnmiGetVar,
1677 * SkGePnmiPreSetVar, or SkGePnmiSetVar.
1679 * Returns:
1680 * SK_PNMI_ERR_XXX. For details have a look at the description of the
1681 * calling functions.
1682 * SK_PNMI_ERR_UNKNOWN_NET The requested NetIndex doesn't exist
1684 PNMI_STATIC int PnmiVar(
1685 SK_AC *pAC, /* Pointer to adapter context */
1686 SK_IOC IoC, /* IO context handle */
1687 int Action, /* GET/PRESET/SET action */
1688 SK_U32 Id, /* Object ID that is to be processed */
1689 char *pBuf, /* Buffer used for the management data transfer */
1690 unsigned int *pLen, /* Total length of pBuf management data */
1691 SK_U32 Instance, /* Instance (1..n) that is to be set or -1 */
1692 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
1694 unsigned int TableIndex;
1695 int Ret;
1698 if ((TableIndex = LookupId(Id)) == (unsigned int)(-1)) {
1700 *pLen = 0;
1701 return (SK_PNMI_ERR_UNKNOWN_OID);
1704 /* Check NetIndex */
1705 if (NetIndex >= pAC->Rlmt.NumNets) {
1706 return (SK_PNMI_ERR_UNKNOWN_NET);
1709 SK_PNMI_CHECKFLAGS("PnmiVar: On call");
1711 Ret = IdTable[TableIndex].Func(pAC, IoC, Action, Id, pBuf, pLen,
1712 Instance, TableIndex, NetIndex);
1714 SK_PNMI_CHECKFLAGS("PnmiVar: On return");
1716 return (Ret);
1719 /*****************************************************************************
1721 * PnmiStruct - Presets and Sets data in structure SK_PNMI_STRUCT_DATA
1723 * Description:
1724 * The return value of the function will also be stored in
1725 * SK_PNMI_STRUCT_DATA if the passed buffer has the minimum size of
1726 * SK_PNMI_MIN_STRUCT_SIZE. The sub-function runs through the IdTable,
1727 * checks which OIDs are able to set, and calls the handler function of
1728 * the OID to perform the set. The return value of the function will
1729 * also be stored in SK_PNMI_STRUCT_DATA if the passed buffer has the
1730 * minimum size of SK_PNMI_MIN_STRUCT_SIZE. The function is called
1731 * by SkGePnmiPreSetStruct and SkGePnmiSetStruct.
1733 * Returns:
1734 * SK_PNMI_ERR_XXX. The codes are described in the calling functions.
1735 * SK_PNMI_ERR_UNKNOWN_NET The requested NetIndex doesn't exist
1737 PNMI_STATIC int PnmiStruct(
1738 SK_AC *pAC, /* Pointer to adapter context */
1739 SK_IOC IoC, /* IO context handle */
1740 int Action, /* PRESET/SET action to be performed */
1741 char *pBuf, /* Buffer used for the management data transfer */
1742 unsigned int *pLen, /* Length of pBuf management data buffer */
1743 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
1745 int Ret;
1746 unsigned int TableIndex;
1747 unsigned int DstOffset;
1748 unsigned int Len;
1749 unsigned int InstanceNo;
1750 unsigned int InstanceCnt;
1751 SK_U32 Instance;
1752 SK_U32 Id;
1755 /* Check if the passed buffer has the right size */
1756 if (*pLen < SK_PNMI_STRUCT_SIZE) {
1758 /* Check if we can return the error within the buffer */
1759 if (*pLen >= SK_PNMI_MIN_STRUCT_SIZE) {
1761 SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_TOO_SHORT,
1762 (SK_U32)(-1));
1765 *pLen = SK_PNMI_STRUCT_SIZE;
1766 return (SK_PNMI_ERR_TOO_SHORT);
1769 /* Check NetIndex */
1770 if (NetIndex >= pAC->Rlmt.NumNets) {
1771 return (SK_PNMI_ERR_UNKNOWN_NET);
1774 SK_PNMI_CHECKFLAGS("PnmiStruct: On call");
1777 * Update the values of RLMT and SIRQ and increment semaphores to
1778 * indicate that an update was already done.
1780 if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) {
1782 SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
1783 *pLen = SK_PNMI_MIN_STRUCT_SIZE;
1784 return (Ret);
1787 if ((Ret = SirqUpdate(pAC, IoC)) != SK_PNMI_ERR_OK) {
1789 SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1));
1790 *pLen = SK_PNMI_MIN_STRUCT_SIZE;
1791 return (Ret);
1794 pAC->Pnmi.RlmtUpdatedFlag ++;
1795 pAC->Pnmi.SirqUpdatedFlag ++;
1797 /* Preset/Set values */
1798 for (TableIndex = 0; TableIndex < ID_TABLE_SIZE; TableIndex ++) {
1800 if ((IdTable[TableIndex].Access != SK_PNMI_RW) &&
1801 (IdTable[TableIndex].Access != SK_PNMI_WO)) {
1803 continue;
1806 InstanceNo = IdTable[TableIndex].InstanceNo;
1807 Id = IdTable[TableIndex].Id;
1809 for (InstanceCnt = 1; InstanceCnt <= InstanceNo;
1810 InstanceCnt ++) {
1812 DstOffset = IdTable[TableIndex].Offset +
1813 (InstanceCnt - 1) *
1814 IdTable[TableIndex].StructSize;
1817 * Because VPD multiple instance variables are
1818 * not setable we do not need to evaluate VPD
1819 * instances. Have a look to VPD instance
1820 * calculation in SkPnmiGetStruct().
1822 Instance = (SK_U32)InstanceCnt;
1825 * Evaluate needed buffer length
1827 Len = 0;
1828 Ret = IdTable[TableIndex].Func(pAC, IoC,
1829 SK_PNMI_GET, IdTable[TableIndex].Id,
1830 NULL, &Len, Instance, TableIndex, NetIndex);
1832 if (Ret == SK_PNMI_ERR_UNKNOWN_INST) {
1834 break;
1836 if (Ret != SK_PNMI_ERR_TOO_SHORT) {
1838 pAC->Pnmi.RlmtUpdatedFlag --;
1839 pAC->Pnmi.SirqUpdatedFlag --;
1841 SK_PNMI_CHECKFLAGS("PnmiStruct: On return");
1842 SK_PNMI_SET_STAT(pBuf,
1843 SK_PNMI_ERR_GENERAL, DstOffset);
1844 *pLen = SK_PNMI_MIN_STRUCT_SIZE;
1845 return (SK_PNMI_ERR_GENERAL);
1847 if (Id == OID_SKGE_VPD_ACTION) {
1849 switch (*(pBuf + DstOffset)) {
1851 case SK_PNMI_VPD_CREATE:
1852 Len = 3 + *(pBuf + DstOffset + 3);
1853 break;
1855 case SK_PNMI_VPD_DELETE:
1856 Len = 3;
1857 break;
1859 default:
1860 Len = 1;
1861 break;
1865 /* Call the OID handler function */
1866 Ret = IdTable[TableIndex].Func(pAC, IoC, Action,
1867 IdTable[TableIndex].Id, pBuf + DstOffset,
1868 &Len, Instance, TableIndex, NetIndex);
1870 if (Ret != SK_PNMI_ERR_OK) {
1872 pAC->Pnmi.RlmtUpdatedFlag --;
1873 pAC->Pnmi.SirqUpdatedFlag --;
1875 SK_PNMI_CHECKFLAGS("PnmiStruct: On return");
1876 SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_BAD_VALUE,
1877 DstOffset);
1878 *pLen = SK_PNMI_MIN_STRUCT_SIZE;
1879 return (SK_PNMI_ERR_BAD_VALUE);
1884 pAC->Pnmi.RlmtUpdatedFlag --;
1885 pAC->Pnmi.SirqUpdatedFlag --;
1887 SK_PNMI_CHECKFLAGS("PnmiStruct: On return");
1888 SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_OK, (SK_U32)(-1));
1889 return (SK_PNMI_ERR_OK);
1892 /*****************************************************************************
1894 * LookupId - Lookup an OID in the IdTable
1896 * Description:
1897 * Scans the IdTable to find the table entry of an OID.
1899 * Returns:
1900 * The table index or -1 if not found.
1902 PNMI_STATIC int LookupId(
1903 SK_U32 Id) /* Object identifier to be searched */
1905 int i;
1907 for (i = 0; i < ID_TABLE_SIZE; i++) {
1909 if (IdTable[i].Id == Id) {
1911 return i;
1915 return (-1);
1918 /*****************************************************************************
1920 * OidStruct - Handler of OID_SKGE_ALL_DATA
1922 * Description:
1923 * This OID performs a Get/Preset/SetStruct call and returns all data
1924 * in a SK_PNMI_STRUCT_DATA structure.
1926 * Returns:
1927 * SK_PNMI_ERR_OK The request was successfully performed.
1928 * SK_PNMI_ERR_GENERAL A general severe internal error occured.
1929 * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
1930 * the correct data (e.g. a 32bit value is
1931 * needed, but a 16 bit value was passed).
1932 * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
1933 * value range.
1934 * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set.
1935 * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
1936 * exist (e.g. port instance 3 on a two port
1937 * adapter.
1939 PNMI_STATIC int OidStruct(
1940 SK_AC *pAC, /* Pointer to adapter context */
1941 SK_IOC IoC, /* IO context handle */
1942 int Action, /* GET/PRESET/SET action */
1943 SK_U32 Id, /* Object ID that is to be processed */
1944 char *pBuf, /* Buffer used for the management data transfer */
1945 unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
1946 SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
1947 unsigned int TableIndex, /* Index to the Id table */
1948 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
1950 if (Id != OID_SKGE_ALL_DATA) {
1952 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR003,
1953 SK_PNMI_ERR003MSG);
1955 *pLen = 0;
1956 return (SK_PNMI_ERR_GENERAL);
1960 * Check instance. We only handle single instance variables
1962 if (Instance != (SK_U32)(-1) && Instance != 1) {
1964 *pLen = 0;
1965 return (SK_PNMI_ERR_UNKNOWN_INST);
1968 switch (Action) {
1970 case SK_PNMI_GET:
1971 return (SkPnmiGetStruct(pAC, IoC, pBuf, pLen, NetIndex));
1973 case SK_PNMI_PRESET:
1974 return (SkPnmiPreSetStruct(pAC, IoC, pBuf, pLen, NetIndex));
1976 case SK_PNMI_SET:
1977 return (SkPnmiSetStruct(pAC, IoC, pBuf, pLen, NetIndex));
1980 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR004, SK_PNMI_ERR004MSG);
1982 *pLen = 0;
1983 return (SK_PNMI_ERR_GENERAL);
1986 /*****************************************************************************
1988 * Perform - OID handler of OID_SKGE_ACTION
1990 * Description:
1991 * None.
1993 * Returns:
1994 * SK_PNMI_ERR_OK The request was successfully performed.
1995 * SK_PNMI_ERR_GENERAL A general severe internal error occured.
1996 * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
1997 * the correct data (e.g. a 32bit value is
1998 * needed, but a 16 bit value was passed).
1999 * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
2000 * value range.
2001 * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set.
2002 * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
2003 * exist (e.g. port instance 3 on a two port
2004 * adapter.
2006 PNMI_STATIC int Perform(
2007 SK_AC *pAC, /* Pointer to adapter context */
2008 SK_IOC IoC, /* IO context handle */
2009 int Action, /* GET/PRESET/SET action */
2010 SK_U32 Id, /* Object ID that is to be processed */
2011 char *pBuf, /* Buffer used for the management data transfer */
2012 unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
2013 SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
2014 unsigned int TableIndex, /* Index to the Id table */
2015 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
2017 int Ret;
2018 SK_U32 ActionOp;
2022 * Check instance. We only handle single instance variables
2024 if (Instance != (SK_U32)(-1) && Instance != 1) {
2026 *pLen = 0;
2027 return (SK_PNMI_ERR_UNKNOWN_INST);
2030 if (*pLen < sizeof(SK_U32)) {
2032 *pLen = sizeof(SK_U32);
2033 return (SK_PNMI_ERR_TOO_SHORT);
2036 /* Check if a get should be performed */
2037 if (Action == SK_PNMI_GET) {
2039 /* A get is easy. We always return the same value */
2040 ActionOp = (SK_U32)SK_PNMI_ACT_IDLE;
2041 SK_PNMI_STORE_U32(pBuf, ActionOp);
2042 *pLen = sizeof(SK_U32);
2044 return (SK_PNMI_ERR_OK);
2047 /* Continue with PRESET/SET action */
2048 if (*pLen > sizeof(SK_U32)) {
2050 return (SK_PNMI_ERR_BAD_VALUE);
2053 /* Check if the command is a known one */
2054 SK_PNMI_READ_U32(pBuf, ActionOp);
2055 if (*pLen > sizeof(SK_U32) ||
2056 (ActionOp != SK_PNMI_ACT_IDLE &&
2057 ActionOp != SK_PNMI_ACT_RESET &&
2058 ActionOp != SK_PNMI_ACT_SELFTEST &&
2059 ActionOp != SK_PNMI_ACT_RESETCNT)) {
2061 *pLen = 0;
2062 return (SK_PNMI_ERR_BAD_VALUE);
2065 /* A preset ends here */
2066 if (Action == SK_PNMI_PRESET) {
2068 return (SK_PNMI_ERR_OK);
2071 switch (ActionOp) {
2073 case SK_PNMI_ACT_IDLE:
2074 /* Nothing to do */
2075 break;
2077 case SK_PNMI_ACT_RESET:
2079 * Perform a driver reset or something that comes near
2080 * to this.
2082 Ret = SK_DRIVER_RESET(pAC, IoC);
2083 if (Ret != 0) {
2085 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR005,
2086 SK_PNMI_ERR005MSG);
2088 return (SK_PNMI_ERR_GENERAL);
2090 break;
2092 case SK_PNMI_ACT_SELFTEST:
2094 * Perform a driver selftest or something similar to this.
2095 * Currently this feature is not used and will probably
2096 * implemented in another way.
2098 Ret = SK_DRIVER_SELFTEST(pAC, IoC);
2099 pAC->Pnmi.TestResult = Ret;
2100 break;
2102 case SK_PNMI_ACT_RESETCNT:
2103 /* Set all counters and timestamps to zero */
2104 ResetCounter(pAC, IoC, NetIndex);
2105 break;
2107 default:
2108 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR006,
2109 SK_PNMI_ERR006MSG);
2111 return (SK_PNMI_ERR_GENERAL);
2114 return (SK_PNMI_ERR_OK);
2117 /*****************************************************************************
2119 * Mac8023Stat - OID handler of OID_GEN_XXX and OID_802_3_XXX
2121 * Description:
2122 * Retrieves the statistic values of the virtual port (logical
2123 * index 0). Only special OIDs of NDIS are handled which consist
2124 * of a 32 bit instead of a 64 bit value. The OIDs are public
2125 * because perhaps some other platform can use them too.
2127 * Returns:
2128 * SK_PNMI_ERR_OK The request was successfully performed.
2129 * SK_PNMI_ERR_GENERAL A general severe internal error occured.
2130 * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
2131 * the correct data (e.g. a 32bit value is
2132 * needed, but a 16 bit value was passed).
2133 * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
2134 * exist (e.g. port instance 3 on a two port
2135 * adapter.
2137 PNMI_STATIC int Mac8023Stat(
2138 SK_AC *pAC, /* Pointer to adapter context */
2139 SK_IOC IoC, /* IO context handle */
2140 int Action, /* GET/PRESET/SET action */
2141 SK_U32 Id, /* Object ID that is to be processed */
2142 char *pBuf, /* Buffer used for the management data transfer */
2143 unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
2144 SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
2145 unsigned int TableIndex, /* Index to the Id table */
2146 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
2148 int Ret;
2149 SK_U64 StatVal;
2150 SK_U32 StatVal32;
2151 SK_BOOL Is64BitReq = SK_FALSE;
2154 * Only the active Mac is returned
2156 if (Instance != (SK_U32)(-1) && Instance != 1) {
2158 *pLen = 0;
2159 return (SK_PNMI_ERR_UNKNOWN_INST);
2163 * Check action type
2165 if (Action != SK_PNMI_GET) {
2167 *pLen = 0;
2168 return (SK_PNMI_ERR_READ_ONLY);
2171 /* Check length */
2172 switch (Id) {
2174 case OID_802_3_PERMANENT_ADDRESS:
2175 case OID_802_3_CURRENT_ADDRESS:
2176 if (*pLen < sizeof(SK_MAC_ADDR)) {
2178 *pLen = sizeof(SK_MAC_ADDR);
2179 return (SK_PNMI_ERR_TOO_SHORT);
2181 break;
2183 default:
2184 #ifndef SK_NDIS_64BIT_CTR
2185 if (*pLen < sizeof(SK_U32)) {
2186 *pLen = sizeof(SK_U32);
2187 return (SK_PNMI_ERR_TOO_SHORT);
2190 #else /* SK_NDIS_64BIT_CTR */
2192 /* for compatibility, at least 32bit are required for OID */
2193 if (*pLen < sizeof(SK_U32)) {
2195 * but indicate handling for 64bit values,
2196 * if insufficient space is provided
2198 *pLen = sizeof(SK_U64);
2199 return (SK_PNMI_ERR_TOO_SHORT);
2202 Is64BitReq = (*pLen < sizeof(SK_U64)) ? SK_FALSE : SK_TRUE;
2203 #endif /* SK_NDIS_64BIT_CTR */
2204 break;
2208 * Update all statistics, because we retrieve virtual MAC, which
2209 * consists of multiple physical statistics and increment semaphore
2210 * to indicate that an update was already done.
2212 Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1);
2213 if ( Ret != SK_PNMI_ERR_OK) {
2215 *pLen = 0;
2216 return (Ret);
2218 pAC->Pnmi.MacUpdatedFlag ++;
2221 * Get value (MAC Index 0 identifies the virtual MAC)
2223 switch (Id) {
2225 case OID_802_3_PERMANENT_ADDRESS:
2226 CopyMac(pBuf, &pAC->Addr.Net[NetIndex].PermanentMacAddress);
2227 *pLen = sizeof(SK_MAC_ADDR);
2228 break;
2230 case OID_802_3_CURRENT_ADDRESS:
2231 CopyMac(pBuf, &pAC->Addr.Net[NetIndex].CurrentMacAddress);
2232 *pLen = sizeof(SK_MAC_ADDR);
2233 break;
2235 default:
2236 StatVal = GetStatVal(pAC, IoC, 0, IdTable[TableIndex].Param, NetIndex);
2238 /* by default 32bit values are evaluated */
2239 if (!Is64BitReq) {
2240 StatVal32 = (SK_U32)StatVal;
2241 SK_PNMI_STORE_U32(pBuf, StatVal32);
2242 *pLen = sizeof(SK_U32);
2244 else {
2245 SK_PNMI_STORE_U64(pBuf, StatVal);
2246 *pLen = sizeof(SK_U64);
2248 break;
2251 pAC->Pnmi.MacUpdatedFlag --;
2253 return (SK_PNMI_ERR_OK);
2256 /*****************************************************************************
2258 * MacPrivateStat - OID handler function of OID_SKGE_STAT_XXX
2260 * Description:
2261 * Retrieves the MAC statistic data.
2263 * Returns:
2264 * SK_PNMI_ERR_OK The request was successfully performed.
2265 * SK_PNMI_ERR_GENERAL A general severe internal error occured.
2266 * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
2267 * the correct data (e.g. a 32bit value is
2268 * needed, but a 16 bit value was passed).
2269 * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
2270 * exist (e.g. port instance 3 on a two port
2271 * adapter.
2273 PNMI_STATIC int MacPrivateStat(
2274 SK_AC *pAC, /* Pointer to adapter context */
2275 SK_IOC IoC, /* IO context handle */
2276 int Action, /* GET/PRESET/SET action */
2277 SK_U32 Id, /* Object ID that is to be processed */
2278 char *pBuf, /* Buffer used for the management data transfer */
2279 unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
2280 SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
2281 unsigned int TableIndex, /* Index to the Id table */
2282 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
2284 unsigned int LogPortMax;
2285 unsigned int LogPortIndex;
2286 unsigned int PhysPortMax;
2287 unsigned int Limit;
2288 unsigned int Offset;
2289 int MacType;
2290 int Ret;
2291 SK_U64 StatVal;
2295 /* Calculate instance if wished. MAC index 0 is the virtual MAC */
2296 PhysPortMax = pAC->GIni.GIMacsFound;
2297 LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax);
2299 MacType = pAC->GIni.GIMacType;
2301 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */
2302 LogPortMax--;
2305 if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried */
2306 /* Check instance range */
2307 if ((Instance < 1) || (Instance > LogPortMax)) {
2309 *pLen = 0;
2310 return (SK_PNMI_ERR_UNKNOWN_INST);
2312 LogPortIndex = SK_PNMI_PORT_INST2LOG(Instance);
2313 Limit = LogPortIndex + 1;
2316 else { /* Instance == (SK_U32)(-1), get all Instances of that OID */
2318 LogPortIndex = 0;
2319 Limit = LogPortMax;
2322 /* Check action */
2323 if (Action != SK_PNMI_GET) {
2325 *pLen = 0;
2326 return (SK_PNMI_ERR_READ_ONLY);
2329 /* Check length */
2330 if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U64)) {
2332 *pLen = (Limit - LogPortIndex) * sizeof(SK_U64);
2333 return (SK_PNMI_ERR_TOO_SHORT);
2337 * Update MAC statistic and increment semaphore to indicate that
2338 * an update was already done.
2340 Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1);
2341 if (Ret != SK_PNMI_ERR_OK) {
2343 *pLen = 0;
2344 return (Ret);
2346 pAC->Pnmi.MacUpdatedFlag ++;
2348 /* Get value */
2349 Offset = 0;
2350 for (; LogPortIndex < Limit; LogPortIndex ++) {
2352 switch (Id) {
2354 /* XXX not yet implemented due to XMAC problems
2355 case OID_SKGE_STAT_TX_UTIL:
2356 return (SK_PNMI_ERR_GENERAL);
2358 /* XXX not yet implemented due to XMAC problems
2359 case OID_SKGE_STAT_RX_UTIL:
2360 return (SK_PNMI_ERR_GENERAL);
2362 case OID_SKGE_STAT_RX:
2363 if (MacType == SK_MAC_GMAC) {
2364 StatVal =
2365 GetStatVal(pAC, IoC, LogPortIndex,
2366 SK_PNMI_HRX_BROADCAST, NetIndex) +
2367 GetStatVal(pAC, IoC, LogPortIndex,
2368 SK_PNMI_HRX_MULTICAST, NetIndex) +
2369 GetStatVal(pAC, IoC, LogPortIndex,
2370 SK_PNMI_HRX_UNICAST, NetIndex) +
2371 GetStatVal(pAC, IoC, LogPortIndex,
2372 SK_PNMI_HRX_UNDERSIZE, NetIndex);
2374 else {
2375 StatVal = GetStatVal(pAC, IoC, LogPortIndex,
2376 IdTable[TableIndex].Param, NetIndex);
2378 break;
2380 case OID_SKGE_STAT_TX:
2381 if (MacType == SK_MAC_GMAC) {
2382 StatVal =
2383 GetStatVal(pAC, IoC, LogPortIndex,
2384 SK_PNMI_HTX_BROADCAST, NetIndex) +
2385 GetStatVal(pAC, IoC, LogPortIndex,
2386 SK_PNMI_HTX_MULTICAST, NetIndex) +
2387 GetStatVal(pAC, IoC, LogPortIndex,
2388 SK_PNMI_HTX_UNICAST, NetIndex);
2390 else {
2391 StatVal = GetStatVal(pAC, IoC, LogPortIndex,
2392 IdTable[TableIndex].Param, NetIndex);
2394 break;
2396 default:
2397 StatVal = GetStatVal(pAC, IoC, LogPortIndex,
2398 IdTable[TableIndex].Param, NetIndex);
2400 SK_PNMI_STORE_U64(pBuf + Offset, StatVal);
2402 Offset += sizeof(SK_U64);
2404 *pLen = Offset;
2406 pAC->Pnmi.MacUpdatedFlag --;
2408 return (SK_PNMI_ERR_OK);
2411 /*****************************************************************************
2413 * Addr - OID handler function of OID_SKGE_PHYS_CUR_ADDR and _FAC_ADDR
2415 * Description:
2416 * Get/Presets/Sets the current and factory MAC address. The MAC
2417 * address of the virtual port, which is reported to the OS, may
2418 * not be changed, but the physical ones. A set to the virtual port
2419 * will be ignored. No error should be reported because otherwise
2420 * a multiple instance set (-1) would always fail.
2422 * Returns:
2423 * SK_PNMI_ERR_OK The request was successfully performed.
2424 * SK_PNMI_ERR_GENERAL A general severe internal error occured.
2425 * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
2426 * the correct data (e.g. a 32bit value is
2427 * needed, but a 16 bit value was passed).
2428 * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
2429 * value range.
2430 * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set.
2431 * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
2432 * exist (e.g. port instance 3 on a two port
2433 * adapter.
2435 PNMI_STATIC int Addr(
2436 SK_AC *pAC, /* Pointer to adapter context */
2437 SK_IOC IoC, /* IO context handle */
2438 int Action, /* GET/PRESET/SET action */
2439 SK_U32 Id, /* Object ID that is to be processed */
2440 char *pBuf, /* Buffer used for the management data transfer */
2441 unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
2442 SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
2443 unsigned int TableIndex, /* Index to the Id table */
2444 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
2446 int Ret;
2447 unsigned int LogPortMax;
2448 unsigned int PhysPortMax;
2449 unsigned int LogPortIndex;
2450 unsigned int PhysPortIndex;
2451 unsigned int Limit;
2452 unsigned int Offset = 0;
2455 * Calculate instance if wished. MAC index 0 is the virtual
2456 * MAC.
2458 PhysPortMax = pAC->GIni.GIMacsFound;
2459 LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax);
2461 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */
2462 LogPortMax--;
2465 if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried */
2466 /* Check instance range */
2467 if ((Instance < 1) || (Instance > LogPortMax)) {
2469 *pLen = 0;
2470 return (SK_PNMI_ERR_UNKNOWN_INST);
2472 LogPortIndex = SK_PNMI_PORT_INST2LOG(Instance);
2473 Limit = LogPortIndex + 1;
2475 else { /* Instance == (SK_U32)(-1), get all Instances of that OID */
2477 LogPortIndex = 0;
2478 Limit = LogPortMax;
2482 * Perform Action
2484 if (Action == SK_PNMI_GET) {
2486 /* Check length */
2487 if (*pLen < (Limit - LogPortIndex) * 6) {
2489 *pLen = (Limit - LogPortIndex) * 6;
2490 return (SK_PNMI_ERR_TOO_SHORT);
2494 * Get value
2496 for (; LogPortIndex < Limit; LogPortIndex ++) {
2498 switch (Id) {
2500 case OID_SKGE_PHYS_CUR_ADDR:
2501 if (LogPortIndex == 0) {
2502 CopyMac(pBuf + Offset, &pAC->Addr.Net[NetIndex].CurrentMacAddress);
2504 else {
2505 PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex);
2507 CopyMac(pBuf + Offset,
2508 &pAC->Addr.Port[PhysPortIndex].CurrentMacAddress);
2510 Offset += 6;
2511 break;
2513 case OID_SKGE_PHYS_FAC_ADDR:
2514 if (LogPortIndex == 0) {
2515 CopyMac(pBuf + Offset,
2516 &pAC->Addr.Net[NetIndex].PermanentMacAddress);
2518 else {
2519 PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
2520 pAC, LogPortIndex);
2522 CopyMac(pBuf + Offset,
2523 &pAC->Addr.Port[PhysPortIndex].PermanentMacAddress);
2525 Offset += 6;
2526 break;
2528 default:
2529 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR008,
2530 SK_PNMI_ERR008MSG);
2532 *pLen = 0;
2533 return (SK_PNMI_ERR_GENERAL);
2537 *pLen = Offset;
2539 else {
2541 * The logical MAC address may not be changed only
2542 * the physical ones
2544 if (Id == OID_SKGE_PHYS_FAC_ADDR) {
2546 *pLen = 0;
2547 return (SK_PNMI_ERR_READ_ONLY);
2551 * Only the current address may be changed
2553 if (Id != OID_SKGE_PHYS_CUR_ADDR) {
2555 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR009,
2556 SK_PNMI_ERR009MSG);
2558 *pLen = 0;
2559 return (SK_PNMI_ERR_GENERAL);
2562 /* Check length */
2563 if (*pLen < (Limit - LogPortIndex) * 6) {
2565 *pLen = (Limit - LogPortIndex) * 6;
2566 return (SK_PNMI_ERR_TOO_SHORT);
2568 if (*pLen > (Limit - LogPortIndex) * 6) {
2570 *pLen = 0;
2571 return (SK_PNMI_ERR_BAD_VALUE);
2575 * Check Action
2577 if (Action == SK_PNMI_PRESET) {
2579 *pLen = 0;
2580 return (SK_PNMI_ERR_OK);
2584 * Set OID_SKGE_MAC_CUR_ADDR
2586 for (; LogPortIndex < Limit; LogPortIndex ++, Offset += 6) {
2589 * A set to virtual port and set of broadcast
2590 * address will be ignored
2592 if (LogPortIndex == 0 || SK_MEMCMP(pBuf + Offset,
2593 "\xff\xff\xff\xff\xff\xff", 6) == 0) {
2595 continue;
2598 PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC,
2599 LogPortIndex);
2601 Ret = SkAddrOverride(pAC, IoC, PhysPortIndex,
2602 (SK_MAC_ADDR *)(pBuf + Offset),
2603 (LogPortIndex == 0 ? SK_ADDR_VIRTUAL_ADDRESS :
2604 SK_ADDR_PHYSICAL_ADDRESS));
2605 if (Ret != SK_ADDR_OVERRIDE_SUCCESS) {
2607 return (SK_PNMI_ERR_GENERAL);
2610 *pLen = Offset;
2613 return (SK_PNMI_ERR_OK);
2616 /*****************************************************************************
2618 * CsumStat - OID handler function of OID_SKGE_CHKSM_XXX
2620 * Description:
2621 * Retrieves the statistic values of the CSUM module. The CSUM data
2622 * structure must be available in the SK_AC even if the CSUM module
2623 * is not included, because PNMI reads the statistic data from the
2624 * CSUM part of SK_AC directly.
2626 * Returns:
2627 * SK_PNMI_ERR_OK The request was successfully performed.
2628 * SK_PNMI_ERR_GENERAL A general severe internal error occured.
2629 * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
2630 * the correct data (e.g. a 32bit value is
2631 * needed, but a 16 bit value was passed).
2632 * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
2633 * exist (e.g. port instance 3 on a two port
2634 * adapter.
2636 PNMI_STATIC int CsumStat(
2637 SK_AC *pAC, /* Pointer to adapter context */
2638 SK_IOC IoC, /* IO context handle */
2639 int Action, /* GET/PRESET/SET action */
2640 SK_U32 Id, /* Object ID that is to be processed */
2641 char *pBuf, /* Buffer used for the management data transfer */
2642 unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
2643 SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
2644 unsigned int TableIndex, /* Index to the Id table */
2645 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
2647 unsigned int Index;
2648 unsigned int Limit;
2649 unsigned int Offset = 0;
2650 SK_U64 StatVal;
2654 * Calculate instance if wished
2656 if (Instance != (SK_U32)(-1)) {
2658 if ((Instance < 1) || (Instance > SKCS_NUM_PROTOCOLS)) {
2660 *pLen = 0;
2661 return (SK_PNMI_ERR_UNKNOWN_INST);
2663 Index = (unsigned int)Instance - 1;
2664 Limit = Index + 1;
2666 else {
2667 Index = 0;
2668 Limit = SKCS_NUM_PROTOCOLS;
2672 * Check action
2674 if (Action != SK_PNMI_GET) {
2676 *pLen = 0;
2677 return (SK_PNMI_ERR_READ_ONLY);
2680 /* Check length */
2681 if (*pLen < (Limit - Index) * sizeof(SK_U64)) {
2683 *pLen = (Limit - Index) * sizeof(SK_U64);
2684 return (SK_PNMI_ERR_TOO_SHORT);
2688 * Get value
2690 for (; Index < Limit; Index ++) {
2692 switch (Id) {
2694 case OID_SKGE_CHKSM_RX_OK_CTS:
2695 StatVal = pAC->Csum.ProtoStats[NetIndex][Index].RxOkCts;
2696 break;
2698 case OID_SKGE_CHKSM_RX_UNABLE_CTS:
2699 StatVal = pAC->Csum.ProtoStats[NetIndex][Index].RxUnableCts;
2700 break;
2702 case OID_SKGE_CHKSM_RX_ERR_CTS:
2703 StatVal = pAC->Csum.ProtoStats[NetIndex][Index].RxErrCts;
2704 break;
2706 case OID_SKGE_CHKSM_TX_OK_CTS:
2707 StatVal = pAC->Csum.ProtoStats[NetIndex][Index].TxOkCts;
2708 break;
2710 case OID_SKGE_CHKSM_TX_UNABLE_CTS:
2711 StatVal = pAC->Csum.ProtoStats[NetIndex][Index].TxUnableCts;
2712 break;
2714 default:
2715 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR010,
2716 SK_PNMI_ERR010MSG);
2718 *pLen = 0;
2719 return (SK_PNMI_ERR_GENERAL);
2722 SK_PNMI_STORE_U64(pBuf + Offset, StatVal);
2723 Offset += sizeof(SK_U64);
2727 * Store used buffer space
2729 *pLen = Offset;
2731 return (SK_PNMI_ERR_OK);
2734 /*****************************************************************************
2736 * SensorStat - OID handler function of OID_SKGE_SENSOR_XXX
2738 * Description:
2739 * Retrieves the statistic values of the I2C module, which handles
2740 * the temperature and voltage sensors.
2742 * Returns:
2743 * SK_PNMI_ERR_OK The request was successfully performed.
2744 * SK_PNMI_ERR_GENERAL A general severe internal error occured.
2745 * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
2746 * the correct data (e.g. a 32bit value is
2747 * needed, but a 16 bit value was passed).
2748 * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
2749 * exist (e.g. port instance 3 on a two port
2750 * adapter.
2752 PNMI_STATIC int SensorStat(
2753 SK_AC *pAC, /* Pointer to adapter context */
2754 SK_IOC IoC, /* IO context handle */
2755 int Action, /* GET/PRESET/SET action */
2756 SK_U32 Id, /* Object ID that is to be processed */
2757 char *pBuf, /* Buffer used for the management data transfer */
2758 unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
2759 SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
2760 unsigned int TableIndex, /* Index to the Id table */
2761 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
2763 unsigned int i;
2764 unsigned int Index;
2765 unsigned int Limit;
2766 unsigned int Offset;
2767 unsigned int Len;
2768 SK_U32 Val32;
2769 SK_U64 Val64;
2773 * Calculate instance if wished
2775 if ((Instance != (SK_U32)(-1))) {
2777 if ((Instance < 1) || (Instance > (SK_U32)pAC->I2c.MaxSens)) {
2779 *pLen = 0;
2780 return (SK_PNMI_ERR_UNKNOWN_INST);
2783 Index = (unsigned int)Instance -1;
2784 Limit = (unsigned int)Instance;
2786 else {
2787 Index = 0;
2788 Limit = (unsigned int) pAC->I2c.MaxSens;
2792 * Check action
2794 if (Action != SK_PNMI_GET) {
2796 *pLen = 0;
2797 return (SK_PNMI_ERR_READ_ONLY);
2800 /* Check length */
2801 switch (Id) {
2803 case OID_SKGE_SENSOR_VALUE:
2804 case OID_SKGE_SENSOR_WAR_THRES_LOW:
2805 case OID_SKGE_SENSOR_WAR_THRES_UPP:
2806 case OID_SKGE_SENSOR_ERR_THRES_LOW:
2807 case OID_SKGE_SENSOR_ERR_THRES_UPP:
2808 if (*pLen < (Limit - Index) * sizeof(SK_U32)) {
2810 *pLen = (Limit - Index) * sizeof(SK_U32);
2811 return (SK_PNMI_ERR_TOO_SHORT);
2813 break;
2815 case OID_SKGE_SENSOR_DESCR:
2816 for (Offset = 0, i = Index; i < Limit; i ++) {
2818 Len = (unsigned int)
2819 SK_STRLEN(pAC->I2c.SenTable[i].SenDesc) + 1;
2820 if (Len >= SK_PNMI_STRINGLEN2) {
2822 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR011,
2823 SK_PNMI_ERR011MSG);
2825 *pLen = 0;
2826 return (SK_PNMI_ERR_GENERAL);
2828 Offset += Len;
2830 if (*pLen < Offset) {
2832 *pLen = Offset;
2833 return (SK_PNMI_ERR_TOO_SHORT);
2835 break;
2837 case OID_SKGE_SENSOR_INDEX:
2838 case OID_SKGE_SENSOR_TYPE:
2839 case OID_SKGE_SENSOR_STATUS:
2840 if (*pLen < Limit - Index) {
2842 *pLen = Limit - Index;
2843 return (SK_PNMI_ERR_TOO_SHORT);
2845 break;
2847 case OID_SKGE_SENSOR_WAR_CTS:
2848 case OID_SKGE_SENSOR_WAR_TIME:
2849 case OID_SKGE_SENSOR_ERR_CTS:
2850 case OID_SKGE_SENSOR_ERR_TIME:
2851 if (*pLen < (Limit - Index) * sizeof(SK_U64)) {
2853 *pLen = (Limit - Index) * sizeof(SK_U64);
2854 return (SK_PNMI_ERR_TOO_SHORT);
2856 break;
2858 default:
2859 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR012,
2860 SK_PNMI_ERR012MSG);
2862 *pLen = 0;
2863 return (SK_PNMI_ERR_GENERAL);
2868 * Get value
2870 for (Offset = 0; Index < Limit; Index ++) {
2872 switch (Id) {
2874 case OID_SKGE_SENSOR_INDEX:
2875 *(pBuf + Offset) = (char)Index;
2876 Offset += sizeof(char);
2877 break;
2879 case OID_SKGE_SENSOR_DESCR:
2880 Len = SK_STRLEN(pAC->I2c.SenTable[Index].SenDesc);
2881 SK_MEMCPY(pBuf + Offset + 1,
2882 pAC->I2c.SenTable[Index].SenDesc, Len);
2883 *(pBuf + Offset) = (char)Len;
2884 Offset += Len + 1;
2885 break;
2887 case OID_SKGE_SENSOR_TYPE:
2888 *(pBuf + Offset) =
2889 (char)pAC->I2c.SenTable[Index].SenType;
2890 Offset += sizeof(char);
2891 break;
2893 case OID_SKGE_SENSOR_VALUE:
2894 Val32 = (SK_U32)pAC->I2c.SenTable[Index].SenValue;
2895 SK_PNMI_STORE_U32(pBuf + Offset, Val32);
2896 Offset += sizeof(SK_U32);
2897 break;
2899 case OID_SKGE_SENSOR_WAR_THRES_LOW:
2900 Val32 = (SK_U32)pAC->I2c.SenTable[Index].
2901 SenThreWarnLow;
2902 SK_PNMI_STORE_U32(pBuf + Offset, Val32);
2903 Offset += sizeof(SK_U32);
2904 break;
2906 case OID_SKGE_SENSOR_WAR_THRES_UPP:
2907 Val32 = (SK_U32)pAC->I2c.SenTable[Index].
2908 SenThreWarnHigh;
2909 SK_PNMI_STORE_U32(pBuf + Offset, Val32);
2910 Offset += sizeof(SK_U32);
2911 break;
2913 case OID_SKGE_SENSOR_ERR_THRES_LOW:
2914 Val32 = (SK_U32)pAC->I2c.SenTable[Index].
2915 SenThreErrLow;
2916 SK_PNMI_STORE_U32(pBuf + Offset, Val32);
2917 Offset += sizeof(SK_U32);
2918 break;
2920 case OID_SKGE_SENSOR_ERR_THRES_UPP:
2921 Val32 = pAC->I2c.SenTable[Index].SenThreErrHigh;
2922 SK_PNMI_STORE_U32(pBuf + Offset, Val32);
2923 Offset += sizeof(SK_U32);
2924 break;
2926 case OID_SKGE_SENSOR_STATUS:
2927 *(pBuf + Offset) =
2928 (char)pAC->I2c.SenTable[Index].SenErrFlag;
2929 Offset += sizeof(char);
2930 break;
2932 case OID_SKGE_SENSOR_WAR_CTS:
2933 Val64 = pAC->I2c.SenTable[Index].SenWarnCts;
2934 SK_PNMI_STORE_U64(pBuf + Offset, Val64);
2935 Offset += sizeof(SK_U64);
2936 break;
2938 case OID_SKGE_SENSOR_ERR_CTS:
2939 Val64 = pAC->I2c.SenTable[Index].SenErrCts;
2940 SK_PNMI_STORE_U64(pBuf + Offset, Val64);
2941 Offset += sizeof(SK_U64);
2942 break;
2944 case OID_SKGE_SENSOR_WAR_TIME:
2945 Val64 = SK_PNMI_HUNDREDS_SEC(pAC->I2c.SenTable[Index].
2946 SenBegWarnTS);
2947 SK_PNMI_STORE_U64(pBuf + Offset, Val64);
2948 Offset += sizeof(SK_U64);
2949 break;
2951 case OID_SKGE_SENSOR_ERR_TIME:
2952 Val64 = SK_PNMI_HUNDREDS_SEC(pAC->I2c.SenTable[Index].
2953 SenBegErrTS);
2954 SK_PNMI_STORE_U64(pBuf + Offset, Val64);
2955 Offset += sizeof(SK_U64);
2956 break;
2958 default:
2959 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR,
2960 ("SensorStat: Unknown OID should be handled before"));
2962 return (SK_PNMI_ERR_GENERAL);
2967 * Store used buffer space
2969 *pLen = Offset;
2971 return (SK_PNMI_ERR_OK);
2974 /*****************************************************************************
2976 * Vpd - OID handler function of OID_SKGE_VPD_XXX
2978 * Description:
2979 * Get/preset/set of VPD data. As instance the name of a VPD key
2980 * can be passed. The Instance parameter is a SK_U32 and can be
2981 * used as a string buffer for the VPD key, because their maximum
2982 * length is 4 byte.
2984 * Returns:
2985 * SK_PNMI_ERR_OK The request was successfully performed.
2986 * SK_PNMI_ERR_GENERAL A general severe internal error occured.
2987 * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
2988 * the correct data (e.g. a 32bit value is
2989 * needed, but a 16 bit value was passed).
2990 * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
2991 * value range.
2992 * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set.
2993 * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
2994 * exist (e.g. port instance 3 on a two port
2995 * adapter.
2997 PNMI_STATIC int Vpd(
2998 SK_AC *pAC, /* Pointer to adapter context */
2999 SK_IOC IoC, /* IO context handle */
3000 int Action, /* GET/PRESET/SET action */
3001 SK_U32 Id, /* Object ID that is to be processed */
3002 char *pBuf, /* Buffer used for the management data transfer */
3003 unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
3004 SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
3005 unsigned int TableIndex, /* Index to the Id table */
3006 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
3008 SK_VPD_STATUS *pVpdStatus;
3009 unsigned int BufLen;
3010 char Buf[256];
3011 char KeyArr[SK_PNMI_VPD_ENTRIES][SK_PNMI_VPD_KEY_SIZE];
3012 char KeyStr[SK_PNMI_VPD_KEY_SIZE];
3013 unsigned int KeyNo;
3014 unsigned int Offset;
3015 unsigned int Index;
3016 unsigned int FirstIndex;
3017 unsigned int LastIndex;
3018 unsigned int Len;
3019 int Ret;
3020 SK_U32 Val32;
3023 * Get array of all currently stored VPD keys
3025 Ret = GetVpdKeyArr(pAC, IoC, &KeyArr[0][0], sizeof(KeyArr), &KeyNo);
3026 if (Ret != SK_PNMI_ERR_OK) {
3027 *pLen = 0;
3028 return (Ret);
3032 * If instance is not -1, try to find the requested VPD key for
3033 * the multiple instance variables. The other OIDs as for example
3034 * OID VPD_ACTION are single instance variables and must be
3035 * handled separatly.
3037 FirstIndex = 0;
3038 LastIndex = KeyNo;
3040 if ((Instance != (SK_U32)(-1))) {
3042 if (Id == OID_SKGE_VPD_KEY || Id == OID_SKGE_VPD_VALUE ||
3043 Id == OID_SKGE_VPD_ACCESS) {
3045 SK_STRNCPY(KeyStr, (char *)&Instance, 4);
3046 KeyStr[4] = 0;
3048 for (Index = 0; Index < KeyNo; Index ++) {
3050 if (SK_STRCMP(KeyStr, KeyArr[Index]) == 0) {
3051 FirstIndex = Index;
3052 LastIndex = Index+1;
3053 break;
3056 if (Index == KeyNo) {
3058 *pLen = 0;
3059 return (SK_PNMI_ERR_UNKNOWN_INST);
3062 else if (Instance != 1) {
3064 *pLen = 0;
3065 return (SK_PNMI_ERR_UNKNOWN_INST);
3070 * Get value, if a query should be performed
3072 if (Action == SK_PNMI_GET) {
3074 switch (Id) {
3076 case OID_SKGE_VPD_FREE_BYTES:
3077 /* Check length of buffer */
3078 if (*pLen < sizeof(SK_U32)) {
3080 *pLen = sizeof(SK_U32);
3081 return (SK_PNMI_ERR_TOO_SHORT);
3083 /* Get number of free bytes */
3084 pVpdStatus = VpdStat(pAC, IoC);
3085 if (pVpdStatus == NULL) {
3087 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR017,
3088 SK_PNMI_ERR017MSG);
3090 *pLen = 0;
3091 return (SK_PNMI_ERR_GENERAL);
3093 if ((pVpdStatus->vpd_status & VPD_VALID) == 0) {
3095 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR018,
3096 SK_PNMI_ERR018MSG);
3098 *pLen = 0;
3099 return (SK_PNMI_ERR_GENERAL);
3102 Val32 = (SK_U32)pVpdStatus->vpd_free_rw;
3103 SK_PNMI_STORE_U32(pBuf, Val32);
3104 *pLen = sizeof(SK_U32);
3105 break;
3107 case OID_SKGE_VPD_ENTRIES_LIST:
3108 /* Check length */
3109 for (Len = 0, Index = 0; Index < KeyNo; Index ++) {
3111 Len += SK_STRLEN(KeyArr[Index]) + 1;
3113 if (*pLen < Len) {
3115 *pLen = Len;
3116 return (SK_PNMI_ERR_TOO_SHORT);
3119 /* Get value */
3120 *(pBuf) = (char)Len - 1;
3121 for (Offset = 1, Index = 0; Index < KeyNo; Index ++) {
3123 Len = SK_STRLEN(KeyArr[Index]);
3124 SK_MEMCPY(pBuf + Offset, KeyArr[Index], Len);
3126 Offset += Len;
3128 if (Index < KeyNo - 1) {
3130 *(pBuf + Offset) = ' ';
3131 Offset ++;
3134 *pLen = Offset;
3135 break;
3137 case OID_SKGE_VPD_ENTRIES_NUMBER:
3138 /* Check length */
3139 if (*pLen < sizeof(SK_U32)) {
3141 *pLen = sizeof(SK_U32);
3142 return (SK_PNMI_ERR_TOO_SHORT);
3145 Val32 = (SK_U32)KeyNo;
3146 SK_PNMI_STORE_U32(pBuf, Val32);
3147 *pLen = sizeof(SK_U32);
3148 break;
3150 case OID_SKGE_VPD_KEY:
3151 /* Check buffer length, if it is large enough */
3152 for (Len = 0, Index = FirstIndex;
3153 Index < LastIndex; Index ++) {
3155 Len += SK_STRLEN(KeyArr[Index]) + 1;
3157 if (*pLen < Len) {
3159 *pLen = Len;
3160 return (SK_PNMI_ERR_TOO_SHORT);
3164 * Get the key to an intermediate buffer, because
3165 * we have to prepend a length byte.
3167 for (Offset = 0, Index = FirstIndex;
3168 Index < LastIndex; Index ++) {
3170 Len = SK_STRLEN(KeyArr[Index]);
3172 *(pBuf + Offset) = (char)Len;
3173 SK_MEMCPY(pBuf + Offset + 1, KeyArr[Index],
3174 Len);
3175 Offset += Len + 1;
3177 *pLen = Offset;
3178 break;
3180 case OID_SKGE_VPD_VALUE:
3181 /* Check the buffer length if it is large enough */
3182 for (Offset = 0, Index = FirstIndex;
3183 Index < LastIndex; Index ++) {
3185 BufLen = 256;
3186 if (VpdRead(pAC, IoC, KeyArr[Index], Buf,
3187 (int *)&BufLen) > 0 ||
3188 BufLen >= SK_PNMI_VPD_DATALEN) {
3190 SK_ERR_LOG(pAC, SK_ERRCL_SW,
3191 SK_PNMI_ERR021,
3192 SK_PNMI_ERR021MSG);
3194 return (SK_PNMI_ERR_GENERAL);
3196 Offset += BufLen + 1;
3198 if (*pLen < Offset) {
3200 *pLen = Offset;
3201 return (SK_PNMI_ERR_TOO_SHORT);
3205 * Get the value to an intermediate buffer, because
3206 * we have to prepend a length byte.
3208 for (Offset = 0, Index = FirstIndex;
3209 Index < LastIndex; Index ++) {
3211 BufLen = 256;
3212 if (VpdRead(pAC, IoC, KeyArr[Index], Buf,
3213 (int *)&BufLen) > 0 ||
3214 BufLen >= SK_PNMI_VPD_DATALEN) {
3216 SK_ERR_LOG(pAC, SK_ERRCL_SW,
3217 SK_PNMI_ERR022,
3218 SK_PNMI_ERR022MSG);
3220 *pLen = 0;
3221 return (SK_PNMI_ERR_GENERAL);
3224 *(pBuf + Offset) = (char)BufLen;
3225 SK_MEMCPY(pBuf + Offset + 1, Buf, BufLen);
3226 Offset += BufLen + 1;
3228 *pLen = Offset;
3229 break;
3231 case OID_SKGE_VPD_ACCESS:
3232 if (*pLen < LastIndex - FirstIndex) {
3234 *pLen = LastIndex - FirstIndex;
3235 return (SK_PNMI_ERR_TOO_SHORT);
3238 for (Offset = 0, Index = FirstIndex;
3239 Index < LastIndex; Index ++) {
3241 if (VpdMayWrite(KeyArr[Index])) {
3243 *(pBuf + Offset) = SK_PNMI_VPD_RW;
3245 else {
3246 *(pBuf + Offset) = SK_PNMI_VPD_RO;
3248 Offset ++;
3250 *pLen = Offset;
3251 break;
3253 case OID_SKGE_VPD_ACTION:
3254 Offset = LastIndex - FirstIndex;
3255 if (*pLen < Offset) {
3257 *pLen = Offset;
3258 return (SK_PNMI_ERR_TOO_SHORT);
3260 SK_MEMSET(pBuf, 0, Offset);
3261 *pLen = Offset;
3262 break;
3264 default:
3265 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR023,
3266 SK_PNMI_ERR023MSG);
3268 *pLen = 0;
3269 return (SK_PNMI_ERR_GENERAL);
3272 else {
3273 /* The only OID which can be set is VPD_ACTION */
3274 if (Id != OID_SKGE_VPD_ACTION) {
3276 if (Id == OID_SKGE_VPD_FREE_BYTES ||
3277 Id == OID_SKGE_VPD_ENTRIES_LIST ||
3278 Id == OID_SKGE_VPD_ENTRIES_NUMBER ||
3279 Id == OID_SKGE_VPD_KEY ||
3280 Id == OID_SKGE_VPD_VALUE ||
3281 Id == OID_SKGE_VPD_ACCESS) {
3283 *pLen = 0;
3284 return (SK_PNMI_ERR_READ_ONLY);
3287 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR024,
3288 SK_PNMI_ERR024MSG);
3290 *pLen = 0;
3291 return (SK_PNMI_ERR_GENERAL);
3295 * From this point we handle VPD_ACTION. Check the buffer
3296 * length. It should at least have the size of one byte.
3298 if (*pLen < 1) {
3300 *pLen = 1;
3301 return (SK_PNMI_ERR_TOO_SHORT);
3305 * The first byte contains the VPD action type we should
3306 * perform.
3308 switch (*pBuf) {
3310 case SK_PNMI_VPD_IGNORE:
3311 /* Nothing to do */
3312 break;
3314 case SK_PNMI_VPD_CREATE:
3316 * We have to create a new VPD entry or we modify
3317 * an existing one. Check first the buffer length.
3319 if (*pLen < 4) {
3321 *pLen = 4;
3322 return (SK_PNMI_ERR_TOO_SHORT);
3324 KeyStr[0] = pBuf[1];
3325 KeyStr[1] = pBuf[2];
3326 KeyStr[2] = 0;
3329 * Is the entry writable or does it belong to the
3330 * read-only area?
3332 if (!VpdMayWrite(KeyStr)) {
3334 *pLen = 0;
3335 return (SK_PNMI_ERR_BAD_VALUE);
3338 Offset = (int)pBuf[3] & 0xFF;
3340 SK_MEMCPY(Buf, pBuf + 4, Offset);
3341 Buf[Offset] = 0;
3343 /* A preset ends here */
3344 if (Action == SK_PNMI_PRESET) {
3346 return (SK_PNMI_ERR_OK);
3349 /* Write the new entry or modify an existing one */
3350 Ret = VpdWrite(pAC, IoC, KeyStr, Buf);
3351 if (Ret == SK_PNMI_VPD_NOWRITE ) {
3353 *pLen = 0;
3354 return (SK_PNMI_ERR_BAD_VALUE);
3356 else if (Ret != SK_PNMI_VPD_OK) {
3358 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR025,
3359 SK_PNMI_ERR025MSG);
3361 *pLen = 0;
3362 return (SK_PNMI_ERR_GENERAL);
3366 * Perform an update of the VPD data. This is
3367 * not mandantory, but just to be sure.
3369 Ret = VpdUpdate(pAC, IoC);
3370 if (Ret != SK_PNMI_VPD_OK) {
3372 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR026,
3373 SK_PNMI_ERR026MSG);
3375 *pLen = 0;
3376 return (SK_PNMI_ERR_GENERAL);
3378 break;
3380 case SK_PNMI_VPD_DELETE:
3381 /* Check if the buffer size is plausible */
3382 if (*pLen < 3) {
3384 *pLen = 3;
3385 return (SK_PNMI_ERR_TOO_SHORT);
3387 if (*pLen > 3) {
3389 *pLen = 0;
3390 return (SK_PNMI_ERR_BAD_VALUE);
3392 KeyStr[0] = pBuf[1];
3393 KeyStr[1] = pBuf[2];
3394 KeyStr[2] = 0;
3396 /* Find the passed key in the array */
3397 for (Index = 0; Index < KeyNo; Index ++) {
3399 if (SK_STRCMP(KeyStr, KeyArr[Index]) == 0) {
3401 break;
3405 * If we cannot find the key it is wrong, so we
3406 * return an appropriate error value.
3408 if (Index == KeyNo) {
3410 *pLen = 0;
3411 return (SK_PNMI_ERR_BAD_VALUE);
3414 if (Action == SK_PNMI_PRESET) {
3416 return (SK_PNMI_ERR_OK);
3419 /* Ok, you wanted it and you will get it */
3420 Ret = VpdDelete(pAC, IoC, KeyStr);
3421 if (Ret != SK_PNMI_VPD_OK) {
3423 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR027,
3424 SK_PNMI_ERR027MSG);
3426 *pLen = 0;
3427 return (SK_PNMI_ERR_GENERAL);
3431 * Perform an update of the VPD data. This is
3432 * not mandantory, but just to be sure.
3434 Ret = VpdUpdate(pAC, IoC);
3435 if (Ret != SK_PNMI_VPD_OK) {
3437 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR028,
3438 SK_PNMI_ERR028MSG);
3440 *pLen = 0;
3441 return (SK_PNMI_ERR_GENERAL);
3443 break;
3445 default:
3446 *pLen = 0;
3447 return (SK_PNMI_ERR_BAD_VALUE);
3451 return (SK_PNMI_ERR_OK);
3454 /*****************************************************************************
3456 * General - OID handler function of various single instance OIDs
3458 * Description:
3459 * The code is simple. No description necessary.
3461 * Returns:
3462 * SK_PNMI_ERR_OK The request was successfully performed.
3463 * SK_PNMI_ERR_GENERAL A general severe internal error occured.
3464 * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
3465 * the correct data (e.g. a 32bit value is
3466 * needed, but a 16 bit value was passed).
3467 * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
3468 * exist (e.g. port instance 3 on a two port
3469 * adapter.
3471 PNMI_STATIC int General(
3472 SK_AC *pAC, /* Pointer to adapter context */
3473 SK_IOC IoC, /* IO context handle */
3474 int Action, /* GET/PRESET/SET action */
3475 SK_U32 Id, /* Object ID that is to be processed */
3476 char *pBuf, /* Buffer used for the management data transfer */
3477 unsigned int *pLen, /* On call: buffer length. On return: used buffer */
3478 SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
3479 unsigned int TableIndex, /* Index to the Id table */
3480 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
3482 int Ret;
3483 unsigned int Index;
3484 unsigned int Len;
3485 unsigned int Offset;
3486 unsigned int Val;
3487 SK_U8 Val8;
3488 SK_U16 Val16;
3489 SK_U32 Val32;
3490 SK_U64 Val64;
3491 SK_U64 Val64RxHwErrs = 0;
3492 SK_U64 Val64TxHwErrs = 0;
3493 SK_BOOL Is64BitReq = SK_FALSE;
3494 char Buf[256];
3495 int MacType;
3498 * Check instance. We only handle single instance variables.
3500 if (Instance != (SK_U32)(-1) && Instance != 1) {
3502 *pLen = 0;
3503 return (SK_PNMI_ERR_UNKNOWN_INST);
3507 * Check action. We only allow get requests.
3509 if (Action != SK_PNMI_GET) {
3511 *pLen = 0;
3512 return (SK_PNMI_ERR_READ_ONLY);
3515 MacType = pAC->GIni.GIMacType;
3518 * Check length for the various supported OIDs
3520 switch (Id) {
3522 case OID_GEN_XMIT_ERROR:
3523 case OID_GEN_RCV_ERROR:
3524 case OID_GEN_RCV_NO_BUFFER:
3525 #ifndef SK_NDIS_64BIT_CTR
3526 if (*pLen < sizeof(SK_U32)) {
3527 *pLen = sizeof(SK_U32);
3528 return (SK_PNMI_ERR_TOO_SHORT);
3531 #else /* SK_NDIS_64BIT_CTR */
3534 * for compatibility, at least 32bit are required for oid
3536 if (*pLen < sizeof(SK_U32)) {
3538 * but indicate handling for 64bit values,
3539 * if insufficient space is provided
3541 *pLen = sizeof(SK_U64);
3542 return (SK_PNMI_ERR_TOO_SHORT);
3545 Is64BitReq = (*pLen < sizeof(SK_U64)) ? SK_FALSE : SK_TRUE;
3546 #endif /* SK_NDIS_64BIT_CTR */
3547 break;
3549 case OID_SKGE_PORT_NUMBER:
3550 case OID_SKGE_DEVICE_TYPE:
3551 case OID_SKGE_RESULT:
3552 case OID_SKGE_RLMT_MONITOR_NUMBER:
3553 case OID_GEN_TRANSMIT_QUEUE_LENGTH:
3554 case OID_SKGE_TRAP_NUMBER:
3555 case OID_SKGE_MDB_VERSION:
3556 case OID_SKGE_BOARDLEVEL:
3557 case OID_SKGE_CHIPID:
3558 case OID_SKGE_RAMSIZE:
3559 if (*pLen < sizeof(SK_U32)) {
3561 *pLen = sizeof(SK_U32);
3562 return (SK_PNMI_ERR_TOO_SHORT);
3564 break;
3566 case OID_SKGE_CHIPSET:
3567 if (*pLen < sizeof(SK_U16)) {
3569 *pLen = sizeof(SK_U16);
3570 return (SK_PNMI_ERR_TOO_SHORT);
3572 break;
3574 case OID_SKGE_BUS_TYPE:
3575 case OID_SKGE_BUS_SPEED:
3576 case OID_SKGE_BUS_WIDTH:
3577 case OID_SKGE_SENSOR_NUMBER:
3578 case OID_SKGE_CHKSM_NUMBER:
3579 case OID_SKGE_VAUXAVAIL:
3580 if (*pLen < sizeof(SK_U8)) {
3582 *pLen = sizeof(SK_U8);
3583 return (SK_PNMI_ERR_TOO_SHORT);
3585 break;
3587 case OID_SKGE_TX_SW_QUEUE_LEN:
3588 case OID_SKGE_TX_SW_QUEUE_MAX:
3589 case OID_SKGE_TX_RETRY:
3590 case OID_SKGE_RX_INTR_CTS:
3591 case OID_SKGE_TX_INTR_CTS:
3592 case OID_SKGE_RX_NO_BUF_CTS:
3593 case OID_SKGE_TX_NO_BUF_CTS:
3594 case OID_SKGE_TX_USED_DESCR_NO:
3595 case OID_SKGE_RX_DELIVERED_CTS:
3596 case OID_SKGE_RX_OCTETS_DELIV_CTS:
3597 case OID_SKGE_RX_HW_ERROR_CTS:
3598 case OID_SKGE_TX_HW_ERROR_CTS:
3599 case OID_SKGE_IN_ERRORS_CTS:
3600 case OID_SKGE_OUT_ERROR_CTS:
3601 case OID_SKGE_ERR_RECOVERY_CTS:
3602 case OID_SKGE_SYSUPTIME:
3603 if (*pLen < sizeof(SK_U64)) {
3605 *pLen = sizeof(SK_U64);
3606 return (SK_PNMI_ERR_TOO_SHORT);
3608 break;
3610 default:
3611 /* Checked later */
3612 break;
3615 /* Update statistic */
3616 if (Id == OID_SKGE_RX_HW_ERROR_CTS ||
3617 Id == OID_SKGE_TX_HW_ERROR_CTS ||
3618 Id == OID_SKGE_IN_ERRORS_CTS ||
3619 Id == OID_SKGE_OUT_ERROR_CTS ||
3620 Id == OID_GEN_XMIT_ERROR ||
3621 Id == OID_GEN_RCV_ERROR) {
3623 /* Force the XMAC to update its statistic counters and
3624 * Increment semaphore to indicate that an update was
3625 * already done.
3627 Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1);
3628 if (Ret != SK_PNMI_ERR_OK) {
3630 *pLen = 0;
3631 return (Ret);
3633 pAC->Pnmi.MacUpdatedFlag ++;
3636 * Some OIDs consist of multiple hardware counters. Those
3637 * values which are contained in all of them will be added
3638 * now.
3640 switch (Id) {
3642 case OID_SKGE_RX_HW_ERROR_CTS:
3643 case OID_SKGE_IN_ERRORS_CTS:
3644 case OID_GEN_RCV_ERROR:
3645 Val64RxHwErrs =
3646 GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_MISSED, NetIndex) +
3647 GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_FRAMING, NetIndex) +
3648 GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_OVERFLOW, NetIndex) +
3649 GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_JABBER, NetIndex) +
3650 GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_CARRIER, NetIndex) +
3651 GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_IRLENGTH, NetIndex) +
3652 GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_SYMBOL, NetIndex) +
3653 GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_SHORTS, NetIndex) +
3654 GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_RUNT, NetIndex) +
3655 GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_TOO_LONG, NetIndex) +
3656 GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_FCS, NetIndex) +
3657 GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_CEXT, NetIndex);
3658 break;
3660 case OID_SKGE_TX_HW_ERROR_CTS:
3661 case OID_SKGE_OUT_ERROR_CTS:
3662 case OID_GEN_XMIT_ERROR:
3663 Val64TxHwErrs =
3664 GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_EXCESS_COL, NetIndex) +
3665 GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_LATE_COL, NetIndex) +
3666 GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_UNDERRUN, NetIndex) +
3667 GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_CARRIER, NetIndex);
3668 break;
3673 * Retrieve value
3675 switch (Id) {
3677 case OID_SKGE_SUPPORTED_LIST:
3678 Len = ID_TABLE_SIZE * sizeof(SK_U32);
3679 if (*pLen < Len) {
3681 *pLen = Len;
3682 return (SK_PNMI_ERR_TOO_SHORT);
3684 for (Offset = 0, Index = 0; Offset < Len;
3685 Offset += sizeof(SK_U32), Index ++) {
3687 Val32 = (SK_U32)IdTable[Index].Id;
3688 SK_PNMI_STORE_U32(pBuf + Offset, Val32);
3690 *pLen = Len;
3691 break;
3693 case OID_SKGE_BOARDLEVEL:
3694 Val32 = (SK_U32)pAC->GIni.GILevel;
3695 SK_PNMI_STORE_U32(pBuf, Val32);
3696 *pLen = sizeof(SK_U32);
3697 break;
3699 case OID_SKGE_PORT_NUMBER:
3700 Val32 = (SK_U32)pAC->GIni.GIMacsFound;
3701 SK_PNMI_STORE_U32(pBuf, Val32);
3702 *pLen = sizeof(SK_U32);
3703 break;
3705 case OID_SKGE_DEVICE_TYPE:
3706 Val32 = (SK_U32)pAC->Pnmi.DeviceType;
3707 SK_PNMI_STORE_U32(pBuf, Val32);
3708 *pLen = sizeof(SK_U32);
3709 break;
3711 case OID_SKGE_DRIVER_DESCR:
3712 if (pAC->Pnmi.pDriverDescription == NULL) {
3714 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR007,
3715 SK_PNMI_ERR007MSG);
3717 *pLen = 0;
3718 return (SK_PNMI_ERR_GENERAL);
3721 Len = SK_STRLEN(pAC->Pnmi.pDriverDescription) + 1;
3722 if (Len > SK_PNMI_STRINGLEN1) {
3724 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR029,
3725 SK_PNMI_ERR029MSG);
3727 *pLen = 0;
3728 return (SK_PNMI_ERR_GENERAL);
3731 if (*pLen < Len) {
3733 *pLen = Len;
3734 return (SK_PNMI_ERR_TOO_SHORT);
3736 *pBuf = (char)(Len - 1);
3737 SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverDescription, Len - 1);
3738 *pLen = Len;
3739 break;
3741 case OID_SKGE_DRIVER_VERSION:
3742 if (pAC->Pnmi.pDriverVersion == NULL) {
3744 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR030,
3745 SK_PNMI_ERR030MSG);
3747 *pLen = 0;
3748 return (SK_PNMI_ERR_GENERAL);
3751 Len = SK_STRLEN(pAC->Pnmi.pDriverVersion) + 1;
3752 if (Len > SK_PNMI_STRINGLEN1) {
3754 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR031,
3755 SK_PNMI_ERR031MSG);
3757 *pLen = 0;
3758 return (SK_PNMI_ERR_GENERAL);
3761 if (*pLen < Len) {
3763 *pLen = Len;
3764 return (SK_PNMI_ERR_TOO_SHORT);
3766 *pBuf = (char)(Len - 1);
3767 SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverVersion, Len - 1);
3768 *pLen = Len;
3769 break;
3771 case OID_SKGE_DRIVER_RELDATE:
3772 if (pAC->Pnmi.pDriverReleaseDate == NULL) {
3774 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR030,
3775 SK_PNMI_ERR053MSG);
3777 *pLen = 0;
3778 return (SK_PNMI_ERR_GENERAL);
3781 Len = SK_STRLEN(pAC->Pnmi.pDriverReleaseDate) + 1;
3782 if (Len > SK_PNMI_STRINGLEN1) {
3784 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR031,
3785 SK_PNMI_ERR054MSG);
3787 *pLen = 0;
3788 return (SK_PNMI_ERR_GENERAL);
3791 if (*pLen < Len) {
3793 *pLen = Len;
3794 return (SK_PNMI_ERR_TOO_SHORT);
3796 *pBuf = (char)(Len - 1);
3797 SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverReleaseDate, Len - 1);
3798 *pLen = Len;
3799 break;
3801 case OID_SKGE_DRIVER_FILENAME:
3802 if (pAC->Pnmi.pDriverFileName == NULL) {
3804 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR030,
3805 SK_PNMI_ERR055MSG);
3807 *pLen = 0;
3808 return (SK_PNMI_ERR_GENERAL);
3811 Len = SK_STRLEN(pAC->Pnmi.pDriverFileName) + 1;
3812 if (Len > SK_PNMI_STRINGLEN1) {
3814 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR031,
3815 SK_PNMI_ERR056MSG);
3817 *pLen = 0;
3818 return (SK_PNMI_ERR_GENERAL);
3821 if (*pLen < Len) {
3823 *pLen = Len;
3824 return (SK_PNMI_ERR_TOO_SHORT);
3826 *pBuf = (char)(Len - 1);
3827 SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverFileName, Len - 1);
3828 *pLen = Len;
3829 break;
3831 case OID_SKGE_HW_DESCR:
3833 * The hardware description is located in the VPD. This
3834 * query may move to the initialisation routine. But
3835 * the VPD data is cached and therefore a call here
3836 * will not make much difference.
3838 Len = 256;
3839 if (VpdRead(pAC, IoC, VPD_NAME, Buf, (int *)&Len) > 0) {
3841 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR032,
3842 SK_PNMI_ERR032MSG);
3844 *pLen = 0;
3845 return (SK_PNMI_ERR_GENERAL);
3847 Len ++;
3848 if (Len > SK_PNMI_STRINGLEN1) {
3850 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR033,
3851 SK_PNMI_ERR033MSG);
3853 *pLen = 0;
3854 return (SK_PNMI_ERR_GENERAL);
3856 if (*pLen < Len) {
3858 *pLen = Len;
3859 return (SK_PNMI_ERR_TOO_SHORT);
3861 *pBuf = (char)(Len - 1);
3862 SK_MEMCPY(pBuf + 1, Buf, Len - 1);
3863 *pLen = Len;
3864 break;
3866 case OID_SKGE_HW_VERSION:
3867 /* Oh, I love to do some string manipulation */
3868 if (*pLen < 5) {
3870 *pLen = 5;
3871 return (SK_PNMI_ERR_TOO_SHORT);
3873 Val8 = (SK_U8)pAC->GIni.GIPciHwRev;
3874 pBuf[0] = 4;
3875 pBuf[1] = 'v';
3876 pBuf[2] = (char)(0x30 | ((Val8 >> 4) & 0x0F));
3877 pBuf[3] = '.';
3878 pBuf[4] = (char)(0x30 | (Val8 & 0x0F));
3879 *pLen = 5;
3880 break;
3882 case OID_SKGE_CHIPSET:
3883 Val16 = pAC->Pnmi.Chipset;
3884 SK_PNMI_STORE_U16(pBuf, Val16);
3885 *pLen = sizeof(SK_U16);
3886 break;
3888 case OID_SKGE_CHIPID:
3889 Val32 = pAC->GIni.GIChipId;
3890 SK_PNMI_STORE_U32(pBuf, Val32);
3891 *pLen = sizeof(SK_U32);
3892 break;
3894 case OID_SKGE_RAMSIZE:
3895 Val32 = pAC->GIni.GIRamSize;
3896 SK_PNMI_STORE_U32(pBuf, Val32);
3897 *pLen = sizeof(SK_U32);
3898 break;
3900 case OID_SKGE_VAUXAVAIL:
3901 *pBuf = (char) pAC->GIni.GIVauxAvail;
3902 *pLen = sizeof(char);
3903 break;
3905 case OID_SKGE_BUS_TYPE:
3906 *pBuf = (char) SK_PNMI_BUS_PCI;
3907 *pLen = sizeof(char);
3908 break;
3910 case OID_SKGE_BUS_SPEED:
3911 *pBuf = pAC->Pnmi.PciBusSpeed;
3912 *pLen = sizeof(char);
3913 break;
3915 case OID_SKGE_BUS_WIDTH:
3916 *pBuf = pAC->Pnmi.PciBusWidth;
3917 *pLen = sizeof(char);
3918 break;
3920 case OID_SKGE_RESULT:
3921 Val32 = pAC->Pnmi.TestResult;
3922 SK_PNMI_STORE_U32(pBuf, Val32);
3923 *pLen = sizeof(SK_U32);
3924 break;
3926 case OID_SKGE_SENSOR_NUMBER:
3927 *pBuf = (char)pAC->I2c.MaxSens;
3928 *pLen = sizeof(char);
3929 break;
3931 case OID_SKGE_CHKSM_NUMBER:
3932 *pBuf = SKCS_NUM_PROTOCOLS;
3933 *pLen = sizeof(char);
3934 break;
3936 case OID_SKGE_TRAP_NUMBER:
3937 GetTrapQueueLen(pAC, &Len, &Val);
3938 Val32 = (SK_U32)Val;
3939 SK_PNMI_STORE_U32(pBuf, Val32);
3940 *pLen = sizeof(SK_U32);
3941 break;
3943 case OID_SKGE_TRAP:
3944 GetTrapQueueLen(pAC, &Len, &Val);
3945 if (*pLen < Len) {
3947 *pLen = Len;
3948 return (SK_PNMI_ERR_TOO_SHORT);
3950 CopyTrapQueue(pAC, pBuf);
3951 *pLen = Len;
3952 break;
3954 case OID_SKGE_RLMT_MONITOR_NUMBER:
3955 /* XXX Not yet implemented by RLMT therefore we return zero elements */
3956 Val32 = 0;
3957 SK_PNMI_STORE_U32(pBuf, Val32);
3958 *pLen = sizeof(SK_U32);
3959 break;
3961 case OID_SKGE_TX_SW_QUEUE_LEN:
3962 /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
3963 if (MacType == SK_MAC_XMAC) {
3964 /* Dual net mode */
3965 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
3966 Val64 = pAC->Pnmi.BufPort[NetIndex].TxSwQueueLen;
3968 /* Single net mode */
3969 else {
3970 Val64 = pAC->Pnmi.BufPort[0].TxSwQueueLen +
3971 pAC->Pnmi.BufPort[1].TxSwQueueLen;
3974 else {
3975 /* Dual net mode */
3976 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
3977 Val64 = pAC->Pnmi.Port[NetIndex].TxSwQueueLen;
3979 /* Single net mode */
3980 else {
3981 Val64 = pAC->Pnmi.Port[0].TxSwQueueLen +
3982 pAC->Pnmi.Port[1].TxSwQueueLen;
3985 SK_PNMI_STORE_U64(pBuf, Val64);
3986 *pLen = sizeof(SK_U64);
3987 break;
3990 case OID_SKGE_TX_SW_QUEUE_MAX:
3991 /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
3992 if (MacType == SK_MAC_XMAC) {
3993 /* Dual net mode */
3994 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
3995 Val64 = pAC->Pnmi.BufPort[NetIndex].TxSwQueueMax;
3997 /* Single net mode */
3998 else {
3999 Val64 = pAC->Pnmi.BufPort[0].TxSwQueueMax +
4000 pAC->Pnmi.BufPort[1].TxSwQueueMax;
4003 else {
4004 /* Dual net mode */
4005 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
4006 Val64 = pAC->Pnmi.Port[NetIndex].TxSwQueueMax;
4008 /* Single net mode */
4009 else {
4010 Val64 = pAC->Pnmi.Port[0].TxSwQueueMax +
4011 pAC->Pnmi.Port[1].TxSwQueueMax;
4014 SK_PNMI_STORE_U64(pBuf, Val64);
4015 *pLen = sizeof(SK_U64);
4016 break;
4018 case OID_SKGE_TX_RETRY:
4019 /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
4020 if (MacType == SK_MAC_XMAC) {
4021 /* Dual net mode */
4022 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
4023 Val64 = pAC->Pnmi.BufPort[NetIndex].TxRetryCts;
4025 /* Single net mode */
4026 else {
4027 Val64 = pAC->Pnmi.BufPort[0].TxRetryCts +
4028 pAC->Pnmi.BufPort[1].TxRetryCts;
4031 else {
4032 /* Dual net mode */
4033 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
4034 Val64 = pAC->Pnmi.Port[NetIndex].TxRetryCts;
4036 /* Single net mode */
4037 else {
4038 Val64 = pAC->Pnmi.Port[0].TxRetryCts +
4039 pAC->Pnmi.Port[1].TxRetryCts;
4042 SK_PNMI_STORE_U64(pBuf, Val64);
4043 *pLen = sizeof(SK_U64);
4044 break;
4046 case OID_SKGE_RX_INTR_CTS:
4047 /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
4048 if (MacType == SK_MAC_XMAC) {
4049 /* Dual net mode */
4050 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
4051 Val64 = pAC->Pnmi.BufPort[NetIndex].RxIntrCts;
4053 /* Single net mode */
4054 else {
4055 Val64 = pAC->Pnmi.BufPort[0].RxIntrCts +
4056 pAC->Pnmi.BufPort[1].RxIntrCts;
4059 else {
4060 /* Dual net mode */
4061 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
4062 Val64 = pAC->Pnmi.Port[NetIndex].RxIntrCts;
4064 /* Single net mode */
4065 else {
4066 Val64 = pAC->Pnmi.Port[0].RxIntrCts +
4067 pAC->Pnmi.Port[1].RxIntrCts;
4070 SK_PNMI_STORE_U64(pBuf, Val64);
4071 *pLen = sizeof(SK_U64);
4072 break;
4074 case OID_SKGE_TX_INTR_CTS:
4075 /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
4076 if (MacType == SK_MAC_XMAC) {
4077 /* Dual net mode */
4078 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
4079 Val64 = pAC->Pnmi.BufPort[NetIndex].TxIntrCts;
4081 /* Single net mode */
4082 else {
4083 Val64 = pAC->Pnmi.BufPort[0].TxIntrCts +
4084 pAC->Pnmi.BufPort[1].TxIntrCts;
4087 else {
4088 /* Dual net mode */
4089 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
4090 Val64 = pAC->Pnmi.Port[NetIndex].TxIntrCts;
4092 /* Single net mode */
4093 else {
4094 Val64 = pAC->Pnmi.Port[0].TxIntrCts +
4095 pAC->Pnmi.Port[1].TxIntrCts;
4098 SK_PNMI_STORE_U64(pBuf, Val64);
4099 *pLen = sizeof(SK_U64);
4100 break;
4102 case OID_SKGE_RX_NO_BUF_CTS:
4103 /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
4104 if (MacType == SK_MAC_XMAC) {
4105 /* Dual net mode */
4106 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
4107 Val64 = pAC->Pnmi.BufPort[NetIndex].RxNoBufCts;
4109 /* Single net mode */
4110 else {
4111 Val64 = pAC->Pnmi.BufPort[0].RxNoBufCts +
4112 pAC->Pnmi.BufPort[1].RxNoBufCts;
4115 else {
4116 /* Dual net mode */
4117 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
4118 Val64 = pAC->Pnmi.Port[NetIndex].RxNoBufCts;
4120 /* Single net mode */
4121 else {
4122 Val64 = pAC->Pnmi.Port[0].RxNoBufCts +
4123 pAC->Pnmi.Port[1].RxNoBufCts;
4126 SK_PNMI_STORE_U64(pBuf, Val64);
4127 *pLen = sizeof(SK_U64);
4128 break;
4130 case OID_SKGE_TX_NO_BUF_CTS:
4131 /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
4132 if (MacType == SK_MAC_XMAC) {
4133 /* Dual net mode */
4134 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
4135 Val64 = pAC->Pnmi.BufPort[NetIndex].TxNoBufCts;
4137 /* Single net mode */
4138 else {
4139 Val64 = pAC->Pnmi.BufPort[0].TxNoBufCts +
4140 pAC->Pnmi.BufPort[1].TxNoBufCts;
4143 else {
4144 /* Dual net mode */
4145 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
4146 Val64 = pAC->Pnmi.Port[NetIndex].TxNoBufCts;
4148 /* Single net mode */
4149 else {
4150 Val64 = pAC->Pnmi.Port[0].TxNoBufCts +
4151 pAC->Pnmi.Port[1].TxNoBufCts;
4154 SK_PNMI_STORE_U64(pBuf, Val64);
4155 *pLen = sizeof(SK_U64);
4156 break;
4158 case OID_SKGE_TX_USED_DESCR_NO:
4159 /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
4160 if (MacType == SK_MAC_XMAC) {
4161 /* Dual net mode */
4162 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
4163 Val64 = pAC->Pnmi.BufPort[NetIndex].TxUsedDescrNo;
4165 /* Single net mode */
4166 else {
4167 Val64 = pAC->Pnmi.BufPort[0].TxUsedDescrNo +
4168 pAC->Pnmi.BufPort[1].TxUsedDescrNo;
4171 else {
4172 /* Dual net mode */
4173 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
4174 Val64 = pAC->Pnmi.Port[NetIndex].TxUsedDescrNo;
4176 /* Single net mode */
4177 else {
4178 Val64 = pAC->Pnmi.Port[0].TxUsedDescrNo +
4179 pAC->Pnmi.Port[1].TxUsedDescrNo;
4182 SK_PNMI_STORE_U64(pBuf, Val64);
4183 *pLen = sizeof(SK_U64);
4184 break;
4186 case OID_SKGE_RX_DELIVERED_CTS:
4187 /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
4188 if (MacType == SK_MAC_XMAC) {
4189 /* Dual net mode */
4190 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
4191 Val64 = pAC->Pnmi.BufPort[NetIndex].RxDeliveredCts;
4193 /* Single net mode */
4194 else {
4195 Val64 = pAC->Pnmi.BufPort[0].RxDeliveredCts +
4196 pAC->Pnmi.BufPort[1].RxDeliveredCts;
4199 else {
4200 /* Dual net mode */
4201 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
4202 Val64 = pAC->Pnmi.Port[NetIndex].RxDeliveredCts;
4204 /* Single net mode */
4205 else {
4206 Val64 = pAC->Pnmi.Port[0].RxDeliveredCts +
4207 pAC->Pnmi.Port[1].RxDeliveredCts;
4210 SK_PNMI_STORE_U64(pBuf, Val64);
4211 *pLen = sizeof(SK_U64);
4212 break;
4214 case OID_SKGE_RX_OCTETS_DELIV_CTS:
4215 /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
4216 if (MacType == SK_MAC_XMAC) {
4217 /* Dual net mode */
4218 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
4219 Val64 = pAC->Pnmi.BufPort[NetIndex].RxOctetsDeliveredCts;
4221 /* Single net mode */
4222 else {
4223 Val64 = pAC->Pnmi.BufPort[0].RxOctetsDeliveredCts +
4224 pAC->Pnmi.BufPort[1].RxOctetsDeliveredCts;
4227 else {
4228 /* Dual net mode */
4229 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
4230 Val64 = pAC->Pnmi.Port[NetIndex].RxOctetsDeliveredCts;
4232 /* Single net mode */
4233 else {
4234 Val64 = pAC->Pnmi.Port[0].RxOctetsDeliveredCts +
4235 pAC->Pnmi.Port[1].RxOctetsDeliveredCts;
4238 SK_PNMI_STORE_U64(pBuf, Val64);
4239 *pLen = sizeof(SK_U64);
4240 break;
4242 case OID_SKGE_RX_HW_ERROR_CTS:
4243 SK_PNMI_STORE_U64(pBuf, Val64RxHwErrs);
4244 *pLen = sizeof(SK_U64);
4245 break;
4247 case OID_SKGE_TX_HW_ERROR_CTS:
4248 SK_PNMI_STORE_U64(pBuf, Val64TxHwErrs);
4249 *pLen = sizeof(SK_U64);
4250 break;
4252 case OID_SKGE_IN_ERRORS_CTS:
4253 /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
4254 if (MacType == SK_MAC_XMAC) {
4255 /* Dual net mode */
4256 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
4257 Val64 = Val64RxHwErrs + pAC->Pnmi.BufPort[NetIndex].RxNoBufCts;
4259 /* Single net mode */
4260 else {
4261 Val64 = Val64RxHwErrs +
4262 pAC->Pnmi.BufPort[0].RxNoBufCts +
4263 pAC->Pnmi.BufPort[1].RxNoBufCts;
4266 else {
4267 /* Dual net mode */
4268 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
4269 Val64 = Val64RxHwErrs + pAC->Pnmi.Port[NetIndex].RxNoBufCts;
4271 /* Single net mode */
4272 else {
4273 Val64 = Val64RxHwErrs +
4274 pAC->Pnmi.Port[0].RxNoBufCts +
4275 pAC->Pnmi.Port[1].RxNoBufCts;
4278 SK_PNMI_STORE_U64(pBuf, Val64);
4279 *pLen = sizeof(SK_U64);
4280 break;
4282 case OID_SKGE_OUT_ERROR_CTS:
4283 /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
4284 if (MacType == SK_MAC_XMAC) {
4285 /* Dual net mode */
4286 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
4287 Val64 = Val64TxHwErrs + pAC->Pnmi.BufPort[NetIndex].TxNoBufCts;
4289 /* Single net mode */
4290 else {
4291 Val64 = Val64TxHwErrs +
4292 pAC->Pnmi.BufPort[0].TxNoBufCts +
4293 pAC->Pnmi.BufPort[1].TxNoBufCts;
4296 else {
4297 /* Dual net mode */
4298 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
4299 Val64 = Val64TxHwErrs + pAC->Pnmi.Port[NetIndex].TxNoBufCts;
4301 /* Single net mode */
4302 else {
4303 Val64 = Val64TxHwErrs +
4304 pAC->Pnmi.Port[0].TxNoBufCts +
4305 pAC->Pnmi.Port[1].TxNoBufCts;
4308 SK_PNMI_STORE_U64(pBuf, Val64);
4309 *pLen = sizeof(SK_U64);
4310 break;
4312 case OID_SKGE_ERR_RECOVERY_CTS:
4313 /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
4314 if (MacType == SK_MAC_XMAC) {
4315 /* Dual net mode */
4316 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
4317 Val64 = pAC->Pnmi.BufPort[NetIndex].ErrRecoveryCts;
4319 /* Single net mode */
4320 else {
4321 Val64 = pAC->Pnmi.BufPort[0].ErrRecoveryCts +
4322 pAC->Pnmi.BufPort[1].ErrRecoveryCts;
4325 else {
4326 /* Dual net mode */
4327 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
4328 Val64 = pAC->Pnmi.Port[NetIndex].ErrRecoveryCts;
4330 /* Single net mode */
4331 else {
4332 Val64 = pAC->Pnmi.Port[0].ErrRecoveryCts +
4333 pAC->Pnmi.Port[1].ErrRecoveryCts;
4336 SK_PNMI_STORE_U64(pBuf, Val64);
4337 *pLen = sizeof(SK_U64);
4338 break;
4340 case OID_SKGE_SYSUPTIME:
4341 Val64 = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC));
4342 Val64 -= pAC->Pnmi.StartUpTime;
4343 SK_PNMI_STORE_U64(pBuf, Val64);
4344 *pLen = sizeof(SK_U64);
4345 break;
4347 case OID_SKGE_MDB_VERSION:
4348 Val32 = SK_PNMI_MDB_VERSION;
4349 SK_PNMI_STORE_U32(pBuf, Val32);
4350 *pLen = sizeof(SK_U32);
4351 break;
4353 case OID_GEN_RCV_ERROR:
4354 /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
4355 if (MacType == SK_MAC_XMAC) {
4356 Val64 = Val64RxHwErrs + pAC->Pnmi.BufPort[NetIndex].RxNoBufCts;
4358 else {
4359 Val64 = Val64RxHwErrs + pAC->Pnmi.Port[NetIndex].RxNoBufCts;
4363 * by default 32bit values are evaluated
4365 if (!Is64BitReq) {
4366 Val32 = (SK_U32)Val64;
4367 SK_PNMI_STORE_U32(pBuf, Val32);
4368 *pLen = sizeof(SK_U32);
4370 else {
4371 SK_PNMI_STORE_U64(pBuf, Val64);
4372 *pLen = sizeof(SK_U64);
4374 break;
4376 case OID_GEN_XMIT_ERROR:
4377 /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
4378 if (MacType == SK_MAC_XMAC) {
4379 Val64 = Val64TxHwErrs + pAC->Pnmi.BufPort[NetIndex].TxNoBufCts;
4381 else {
4382 Val64 = Val64TxHwErrs + pAC->Pnmi.Port[NetIndex].TxNoBufCts;
4386 * by default 32bit values are evaluated
4388 if (!Is64BitReq) {
4389 Val32 = (SK_U32)Val64;
4390 SK_PNMI_STORE_U32(pBuf, Val32);
4391 *pLen = sizeof(SK_U32);
4393 else {
4394 SK_PNMI_STORE_U64(pBuf, Val64);
4395 *pLen = sizeof(SK_U64);
4397 break;
4399 case OID_GEN_RCV_NO_BUFFER:
4400 /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
4401 if (MacType == SK_MAC_XMAC) {
4402 Val64 = pAC->Pnmi.BufPort[NetIndex].RxNoBufCts;
4404 else {
4405 Val64 = pAC->Pnmi.Port[NetIndex].RxNoBufCts;
4409 * by default 32bit values are evaluated
4411 if (!Is64BitReq) {
4412 Val32 = (SK_U32)Val64;
4413 SK_PNMI_STORE_U32(pBuf, Val32);
4414 *pLen = sizeof(SK_U32);
4416 else {
4417 SK_PNMI_STORE_U64(pBuf, Val64);
4418 *pLen = sizeof(SK_U64);
4420 break;
4422 case OID_GEN_TRANSMIT_QUEUE_LENGTH:
4423 Val32 = (SK_U32)pAC->Pnmi.Port[NetIndex].TxSwQueueLen;
4424 SK_PNMI_STORE_U32(pBuf, Val32);
4425 *pLen = sizeof(SK_U32);
4426 break;
4428 default:
4429 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR034,
4430 SK_PNMI_ERR034MSG);
4432 *pLen = 0;
4433 return (SK_PNMI_ERR_GENERAL);
4436 if (Id == OID_SKGE_RX_HW_ERROR_CTS ||
4437 Id == OID_SKGE_TX_HW_ERROR_CTS ||
4438 Id == OID_SKGE_IN_ERRORS_CTS ||
4439 Id == OID_SKGE_OUT_ERROR_CTS ||
4440 Id == OID_GEN_XMIT_ERROR ||
4441 Id == OID_GEN_RCV_ERROR) {
4443 pAC->Pnmi.MacUpdatedFlag --;
4446 return (SK_PNMI_ERR_OK);
4449 /*****************************************************************************
4451 * Rlmt - OID handler function of OID_SKGE_RLMT_XXX single instance.
4453 * Description:
4454 * Get/Presets/Sets the RLMT OIDs.
4456 * Returns:
4457 * SK_PNMI_ERR_OK The request was successfully performed.
4458 * SK_PNMI_ERR_GENERAL A general severe internal error occured.
4459 * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
4460 * the correct data (e.g. a 32bit value is
4461 * needed, but a 16 bit value was passed).
4462 * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
4463 * value range.
4464 * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set.
4465 * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
4466 * exist (e.g. port instance 3 on a two port
4467 * adapter.
4469 PNMI_STATIC int Rlmt(
4470 SK_AC *pAC, /* Pointer to adapter context */
4471 SK_IOC IoC, /* IO context handle */
4472 int Action, /* GET/PRESET/SET action */
4473 SK_U32 Id, /* Object ID that is to be processed */
4474 char *pBuf, /* Buffer used for the management data transfer */
4475 unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
4476 SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
4477 unsigned int TableIndex, /* Index to the Id table */
4478 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
4480 int Ret;
4481 unsigned int PhysPortIndex;
4482 unsigned int PhysPortMax;
4483 SK_EVPARA EventParam;
4484 SK_U32 Val32;
4485 SK_U64 Val64;
4489 * Check instance. Only single instance OIDs are allowed here.
4491 if (Instance != (SK_U32)(-1) && Instance != 1) {
4493 *pLen = 0;
4494 return (SK_PNMI_ERR_UNKNOWN_INST);
4498 * Perform the requested action.
4500 if (Action == SK_PNMI_GET) {
4503 * Check if the buffer length is large enough.
4506 switch (Id) {
4508 case OID_SKGE_RLMT_MODE:
4509 case OID_SKGE_RLMT_PORT_ACTIVE:
4510 case OID_SKGE_RLMT_PORT_PREFERRED:
4511 if (*pLen < sizeof(SK_U8)) {
4513 *pLen = sizeof(SK_U8);
4514 return (SK_PNMI_ERR_TOO_SHORT);
4516 break;
4518 case OID_SKGE_RLMT_PORT_NUMBER:
4519 if (*pLen < sizeof(SK_U32)) {
4521 *pLen = sizeof(SK_U32);
4522 return (SK_PNMI_ERR_TOO_SHORT);
4524 break;
4526 case OID_SKGE_RLMT_CHANGE_CTS:
4527 case OID_SKGE_RLMT_CHANGE_TIME:
4528 case OID_SKGE_RLMT_CHANGE_ESTIM:
4529 case OID_SKGE_RLMT_CHANGE_THRES:
4530 if (*pLen < sizeof(SK_U64)) {
4532 *pLen = sizeof(SK_U64);
4533 return (SK_PNMI_ERR_TOO_SHORT);
4535 break;
4537 default:
4538 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR035,
4539 SK_PNMI_ERR035MSG);
4541 *pLen = 0;
4542 return (SK_PNMI_ERR_GENERAL);
4546 * Update RLMT statistic and increment semaphores to indicate
4547 * that an update was already done. Maybe RLMT will hold its
4548 * statistic always up to date some time. Then we can
4549 * remove this type of call.
4551 if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) {
4553 *pLen = 0;
4554 return (Ret);
4556 pAC->Pnmi.RlmtUpdatedFlag ++;
4559 * Retrieve Value
4561 switch (Id) {
4563 case OID_SKGE_RLMT_MODE:
4564 *pBuf = (char)pAC->Rlmt.Net[0].RlmtMode;
4565 *pLen = sizeof(char);
4566 break;
4568 case OID_SKGE_RLMT_PORT_NUMBER:
4569 Val32 = (SK_U32)pAC->GIni.GIMacsFound;
4570 SK_PNMI_STORE_U32(pBuf, Val32);
4571 *pLen = sizeof(SK_U32);
4572 break;
4574 case OID_SKGE_RLMT_PORT_ACTIVE:
4575 *pBuf = 0;
4577 * If multiple ports may become active this OID
4578 * doesn't make sense any more. A new variable in
4579 * the port structure should be created. However,
4580 * for this variable the first active port is
4581 * returned.
4583 PhysPortMax = pAC->GIni.GIMacsFound;
4585 for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax;
4586 PhysPortIndex ++) {
4588 if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
4590 *pBuf = (char)SK_PNMI_PORT_PHYS2LOG(PhysPortIndex);
4591 break;
4594 *pLen = sizeof(char);
4595 break;
4597 case OID_SKGE_RLMT_PORT_PREFERRED:
4598 *pBuf = (char)SK_PNMI_PORT_PHYS2LOG(pAC->Rlmt.Net[NetIndex].Preference);
4599 *pLen = sizeof(char);
4600 break;
4602 case OID_SKGE_RLMT_CHANGE_CTS:
4603 Val64 = pAC->Pnmi.RlmtChangeCts;
4604 SK_PNMI_STORE_U64(pBuf, Val64);
4605 *pLen = sizeof(SK_U64);
4606 break;
4608 case OID_SKGE_RLMT_CHANGE_TIME:
4609 Val64 = pAC->Pnmi.RlmtChangeTime;
4610 SK_PNMI_STORE_U64(pBuf, Val64);
4611 *pLen = sizeof(SK_U64);
4612 break;
4614 case OID_SKGE_RLMT_CHANGE_ESTIM:
4615 Val64 = pAC->Pnmi.RlmtChangeEstimate.Estimate;
4616 SK_PNMI_STORE_U64(pBuf, Val64);
4617 *pLen = sizeof(SK_U64);
4618 break;
4620 case OID_SKGE_RLMT_CHANGE_THRES:
4621 Val64 = pAC->Pnmi.RlmtChangeThreshold;
4622 SK_PNMI_STORE_U64(pBuf, Val64);
4623 *pLen = sizeof(SK_U64);
4624 break;
4626 default:
4627 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR,
4628 ("Rlmt: Unknown OID should be handled before"));
4630 pAC->Pnmi.RlmtUpdatedFlag --;
4631 *pLen = 0;
4632 return (SK_PNMI_ERR_GENERAL);
4635 pAC->Pnmi.RlmtUpdatedFlag --;
4637 else {
4638 /* Perform a preset or set */
4639 switch (Id) {
4641 case OID_SKGE_RLMT_MODE:
4642 /* Check if the buffer length is plausible */
4643 if (*pLen < sizeof(char)) {
4645 *pLen = sizeof(char);
4646 return (SK_PNMI_ERR_TOO_SHORT);
4648 /* Check if the value range is correct */
4649 if (*pLen != sizeof(char) ||
4650 (*pBuf & SK_PNMI_RLMT_MODE_CHK_LINK) == 0 ||
4651 *(SK_U8 *)pBuf > 15) {
4653 *pLen = 0;
4654 return (SK_PNMI_ERR_BAD_VALUE);
4656 /* The preset ends here */
4657 if (Action == SK_PNMI_PRESET) {
4659 *pLen = 0;
4660 return (SK_PNMI_ERR_OK);
4662 /* Send an event to RLMT to change the mode */
4663 SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
4664 EventParam.Para32[0] |= (SK_U32)(*pBuf);
4665 EventParam.Para32[1] = 0;
4666 if (SkRlmtEvent(pAC, IoC, SK_RLMT_MODE_CHANGE,
4667 EventParam) > 0) {
4669 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR037,
4670 SK_PNMI_ERR037MSG);
4672 *pLen = 0;
4673 return (SK_PNMI_ERR_GENERAL);
4675 break;
4677 case OID_SKGE_RLMT_PORT_PREFERRED:
4678 /* Check if the buffer length is plausible */
4679 if (*pLen < sizeof(char)) {
4681 *pLen = sizeof(char);
4682 return (SK_PNMI_ERR_TOO_SHORT);
4684 /* Check if the value range is correct */
4685 if (*pLen != sizeof(char) || *(SK_U8 *)pBuf >
4686 (SK_U8)pAC->GIni.GIMacsFound) {
4688 *pLen = 0;
4689 return (SK_PNMI_ERR_BAD_VALUE);
4691 /* The preset ends here */
4692 if (Action == SK_PNMI_PRESET) {
4694 *pLen = 0;
4695 return (SK_PNMI_ERR_OK);
4699 * Send an event to RLMT change the preferred port.
4700 * A param of -1 means automatic mode. RLMT will
4701 * make the decision which is the preferred port.
4703 SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
4704 EventParam.Para32[0] = (SK_U32)(*pBuf) - 1;
4705 EventParam.Para32[1] = NetIndex;
4706 if (SkRlmtEvent(pAC, IoC, SK_RLMT_PREFPORT_CHANGE,
4707 EventParam) > 0) {
4709 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR038,
4710 SK_PNMI_ERR038MSG);
4712 *pLen = 0;
4713 return (SK_PNMI_ERR_GENERAL);
4715 break;
4717 case OID_SKGE_RLMT_CHANGE_THRES:
4718 /* Check if the buffer length is plausible */
4719 if (*pLen < sizeof(SK_U64)) {
4721 *pLen = sizeof(SK_U64);
4722 return (SK_PNMI_ERR_TOO_SHORT);
4725 * There are not many restrictions to the
4726 * value range.
4728 if (*pLen != sizeof(SK_U64)) {
4730 *pLen = 0;
4731 return (SK_PNMI_ERR_BAD_VALUE);
4733 /* A preset ends here */
4734 if (Action == SK_PNMI_PRESET) {
4736 *pLen = 0;
4737 return (SK_PNMI_ERR_OK);
4740 * Store the new threshold, which will be taken
4741 * on the next timer event.
4743 SK_PNMI_READ_U64(pBuf, Val64);
4744 pAC->Pnmi.RlmtChangeThreshold = Val64;
4745 break;
4747 default:
4748 /* The other OIDs are not be able for set */
4749 *pLen = 0;
4750 return (SK_PNMI_ERR_READ_ONLY);
4754 return (SK_PNMI_ERR_OK);
4757 /*****************************************************************************
4759 * RlmtStat - OID handler function of OID_SKGE_RLMT_XXX multiple instance.
4761 * Description:
4762 * Performs get requests on multiple instance variables.
4764 * Returns:
4765 * SK_PNMI_ERR_OK The request was successfully performed.
4766 * SK_PNMI_ERR_GENERAL A general severe internal error occured.
4767 * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
4768 * the correct data (e.g. a 32bit value is
4769 * needed, but a 16 bit value was passed).
4770 * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
4771 * exist (e.g. port instance 3 on a two port
4772 * adapter.
4774 PNMI_STATIC int RlmtStat(
4775 SK_AC *pAC, /* Pointer to adapter context */
4776 SK_IOC IoC, /* IO context handle */
4777 int Action, /* GET/PRESET/SET action */
4778 SK_U32 Id, /* Object ID that is to be processed */
4779 char *pBuf, /* Buffer used for the management data transfer */
4780 unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
4781 SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
4782 unsigned int TableIndex, /* Index to the Id table */
4783 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
4785 unsigned int PhysPortMax;
4786 unsigned int PhysPortIndex;
4787 unsigned int Limit;
4788 unsigned int Offset;
4789 int Ret;
4790 SK_U32 Val32;
4791 SK_U64 Val64;
4794 * Calculate the port indexes from the instance.
4796 PhysPortMax = pAC->GIni.GIMacsFound;
4798 if ((Instance != (SK_U32)(-1))) {
4799 /* Check instance range */
4800 if ((Instance < 1) || (Instance > PhysPortMax)) {
4802 *pLen = 0;
4803 return (SK_PNMI_ERR_UNKNOWN_INST);
4806 /* Single net mode */
4807 PhysPortIndex = Instance - 1;
4809 /* Dual net mode */
4810 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
4811 PhysPortIndex = NetIndex;
4814 /* Both net modes */
4815 Limit = PhysPortIndex + 1;
4817 else {
4818 /* Single net mode */
4819 PhysPortIndex = 0;
4820 Limit = PhysPortMax;
4822 /* Dual net mode */
4823 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
4824 PhysPortIndex = NetIndex;
4825 Limit = PhysPortIndex + 1;
4830 * Currently only get requests are allowed.
4832 if (Action != SK_PNMI_GET) {
4834 *pLen = 0;
4835 return (SK_PNMI_ERR_READ_ONLY);
4839 * Check if the buffer length is large enough.
4841 switch (Id) {
4843 case OID_SKGE_RLMT_PORT_INDEX:
4844 case OID_SKGE_RLMT_STATUS:
4845 if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U32)) {
4847 *pLen = (Limit - PhysPortIndex) * sizeof(SK_U32);
4848 return (SK_PNMI_ERR_TOO_SHORT);
4850 break;
4852 case OID_SKGE_RLMT_TX_HELLO_CTS:
4853 case OID_SKGE_RLMT_RX_HELLO_CTS:
4854 case OID_SKGE_RLMT_TX_SP_REQ_CTS:
4855 case OID_SKGE_RLMT_RX_SP_CTS:
4856 if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U64)) {
4858 *pLen = (Limit - PhysPortIndex) * sizeof(SK_U64);
4859 return (SK_PNMI_ERR_TOO_SHORT);
4861 break;
4863 default:
4864 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR039,
4865 SK_PNMI_ERR039MSG);
4867 *pLen = 0;
4868 return (SK_PNMI_ERR_GENERAL);
4873 * Update statistic and increment semaphores to indicate that
4874 * an update was already done.
4876 if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) {
4878 *pLen = 0;
4879 return (Ret);
4881 pAC->Pnmi.RlmtUpdatedFlag ++;
4884 * Get value
4886 Offset = 0;
4887 for (; PhysPortIndex < Limit; PhysPortIndex ++) {
4889 switch (Id) {
4891 case OID_SKGE_RLMT_PORT_INDEX:
4892 Val32 = PhysPortIndex;
4893 SK_PNMI_STORE_U32(pBuf + Offset, Val32);
4894 Offset += sizeof(SK_U32);
4895 break;
4897 case OID_SKGE_RLMT_STATUS:
4898 if (pAC->Rlmt.Port[PhysPortIndex].PortState ==
4899 SK_RLMT_PS_INIT ||
4900 pAC->Rlmt.Port[PhysPortIndex].PortState ==
4901 SK_RLMT_PS_DOWN) {
4903 Val32 = SK_PNMI_RLMT_STATUS_ERROR;
4905 else if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
4907 Val32 = SK_PNMI_RLMT_STATUS_ACTIVE;
4909 else {
4910 Val32 = SK_PNMI_RLMT_STATUS_STANDBY;
4912 SK_PNMI_STORE_U32(pBuf + Offset, Val32);
4913 Offset += sizeof(SK_U32);
4914 break;
4916 case OID_SKGE_RLMT_TX_HELLO_CTS:
4917 Val64 = pAC->Rlmt.Port[PhysPortIndex].TxHelloCts;
4918 SK_PNMI_STORE_U64(pBuf + Offset, Val64);
4919 Offset += sizeof(SK_U64);
4920 break;
4922 case OID_SKGE_RLMT_RX_HELLO_CTS:
4923 Val64 = pAC->Rlmt.Port[PhysPortIndex].RxHelloCts;
4924 SK_PNMI_STORE_U64(pBuf + Offset, Val64);
4925 Offset += sizeof(SK_U64);
4926 break;
4928 case OID_SKGE_RLMT_TX_SP_REQ_CTS:
4929 Val64 = pAC->Rlmt.Port[PhysPortIndex].TxSpHelloReqCts;
4930 SK_PNMI_STORE_U64(pBuf + Offset, Val64);
4931 Offset += sizeof(SK_U64);
4932 break;
4934 case OID_SKGE_RLMT_RX_SP_CTS:
4935 Val64 = pAC->Rlmt.Port[PhysPortIndex].RxSpHelloCts;
4936 SK_PNMI_STORE_U64(pBuf + Offset, Val64);
4937 Offset += sizeof(SK_U64);
4938 break;
4940 default:
4941 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR,
4942 ("RlmtStat: Unknown OID should be errored before"));
4944 pAC->Pnmi.RlmtUpdatedFlag --;
4945 *pLen = 0;
4946 return (SK_PNMI_ERR_GENERAL);
4949 *pLen = Offset;
4951 pAC->Pnmi.RlmtUpdatedFlag --;
4953 return (SK_PNMI_ERR_OK);
4956 /*****************************************************************************
4958 * MacPrivateConf - OID handler function of OIDs concerning the configuration
4960 * Description:
4961 * Get/Presets/Sets the OIDs concerning the configuration.
4963 * Returns:
4964 * SK_PNMI_ERR_OK The request was successfully performed.
4965 * SK_PNMI_ERR_GENERAL A general severe internal error occured.
4966 * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
4967 * the correct data (e.g. a 32bit value is
4968 * needed, but a 16 bit value was passed).
4969 * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
4970 * value range.
4971 * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set.
4972 * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
4973 * exist (e.g. port instance 3 on a two port
4974 * adapter.
4976 PNMI_STATIC int MacPrivateConf(
4977 SK_AC *pAC, /* Pointer to adapter context */
4978 SK_IOC IoC, /* IO context handle */
4979 int Action, /* GET/PRESET/SET action */
4980 SK_U32 Id, /* Object ID that is to be processed */
4981 char *pBuf, /* Buffer used for the management data transfer */
4982 unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
4983 SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
4984 unsigned int TableIndex, /* Index to the Id table */
4985 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
4987 unsigned int PhysPortMax;
4988 unsigned int PhysPortIndex;
4989 unsigned int LogPortMax;
4990 unsigned int LogPortIndex;
4991 unsigned int Limit;
4992 unsigned int Offset;
4993 char Val8;
4994 char *pBufPtr;
4995 int Ret;
4996 SK_EVPARA EventParam;
4997 SK_U32 Val32;
5000 * Calculate instance if wished. MAC index 0 is the virtual MAC.
5002 PhysPortMax = pAC->GIni.GIMacsFound;
5003 LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax);
5005 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */
5006 LogPortMax--;
5009 if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried */
5010 /* Check instance range */
5011 if ((Instance < 1) || (Instance > LogPortMax)) {
5013 *pLen = 0;
5014 return (SK_PNMI_ERR_UNKNOWN_INST);
5016 LogPortIndex = SK_PNMI_PORT_INST2LOG(Instance);
5017 Limit = LogPortIndex + 1;
5020 else { /* Instance == (SK_U32)(-1), get all Instances of that OID */
5022 LogPortIndex = 0;
5023 Limit = LogPortMax;
5027 * Perform action
5029 if (Action == SK_PNMI_GET) {
5031 /* Check length */
5032 switch (Id) {
5034 case OID_SKGE_PMD:
5035 case OID_SKGE_CONNECTOR:
5036 case OID_SKGE_LINK_CAP:
5037 case OID_SKGE_LINK_MODE:
5038 case OID_SKGE_LINK_MODE_STATUS:
5039 case OID_SKGE_LINK_STATUS:
5040 case OID_SKGE_FLOWCTRL_CAP:
5041 case OID_SKGE_FLOWCTRL_MODE:
5042 case OID_SKGE_FLOWCTRL_STATUS:
5043 case OID_SKGE_PHY_OPERATION_CAP:
5044 case OID_SKGE_PHY_OPERATION_MODE:
5045 case OID_SKGE_PHY_OPERATION_STATUS:
5046 case OID_SKGE_SPEED_CAP:
5047 case OID_SKGE_SPEED_MODE:
5048 case OID_SKGE_SPEED_STATUS:
5049 if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U8)) {
5051 *pLen = (Limit - LogPortIndex) * sizeof(SK_U8);
5052 return (SK_PNMI_ERR_TOO_SHORT);
5054 break;
5056 case OID_SKGE_MTU:
5057 case OID_SKGE_PHY_TYPE:
5058 if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U32)) {
5060 *pLen = (Limit - LogPortIndex) * sizeof(SK_U32);
5061 return (SK_PNMI_ERR_TOO_SHORT);
5063 break;
5065 default:
5066 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR041,
5067 SK_PNMI_ERR041MSG);
5068 *pLen = 0;
5069 return (SK_PNMI_ERR_GENERAL);
5073 * Update statistic and increment semaphore to indicate
5074 * that an update was already done.
5076 if ((Ret = SirqUpdate(pAC, IoC)) != SK_PNMI_ERR_OK) {
5078 *pLen = 0;
5079 return (Ret);
5081 pAC->Pnmi.SirqUpdatedFlag ++;
5084 * Get value
5086 Offset = 0;
5087 for (; LogPortIndex < Limit; LogPortIndex ++) {
5089 pBufPtr = pBuf + Offset;
5091 switch (Id) {
5093 case OID_SKGE_PMD:
5094 *pBufPtr = pAC->Pnmi.PMD;
5095 Offset += sizeof(char);
5096 break;
5098 case OID_SKGE_CONNECTOR:
5099 *pBufPtr = pAC->Pnmi.Connector;
5100 Offset += sizeof(char);
5101 break;
5103 case OID_SKGE_PHY_TYPE:
5104 if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
5105 if (LogPortIndex == 0) {
5106 continue;
5108 else {
5109 /* Get value for physical ports */
5110 PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
5111 pAC, LogPortIndex);
5112 Val32 = pAC->GIni.GP[PhysPortIndex].PhyType;
5113 SK_PNMI_STORE_U32(pBufPtr, Val32);
5116 else { /* DualNetMode */
5118 Val32 = pAC->GIni.GP[NetIndex].PhyType;
5119 SK_PNMI_STORE_U32(pBufPtr, Val32);
5121 Offset += sizeof(SK_U32);
5122 break;
5124 case OID_SKGE_LINK_CAP:
5125 if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
5126 if (LogPortIndex == 0) {
5127 /* Get value for virtual port */
5128 VirtualConf(pAC, IoC, Id, pBufPtr);
5130 else {
5131 /* Get value for physical ports */
5132 PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
5133 pAC, LogPortIndex);
5135 *pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkCap;
5138 else { /* DualNetMode */
5140 *pBufPtr = pAC->GIni.GP[NetIndex].PLinkCap;
5142 Offset += sizeof(char);
5143 break;
5145 case OID_SKGE_LINK_MODE:
5146 if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
5147 if (LogPortIndex == 0) {
5148 /* Get value for virtual port */
5149 VirtualConf(pAC, IoC, Id, pBufPtr);
5151 else {
5152 /* Get value for physical ports */
5153 PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
5154 pAC, LogPortIndex);
5156 *pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkModeConf;
5159 else { /* DualNetMode */
5161 *pBufPtr = pAC->GIni.GP[NetIndex].PLinkModeConf;
5163 Offset += sizeof(char);
5164 break;
5166 case OID_SKGE_LINK_MODE_STATUS:
5167 if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
5168 if (LogPortIndex == 0) {
5169 /* Get value for virtual port */
5170 VirtualConf(pAC, IoC, Id, pBufPtr);
5172 else {
5173 /* Get value for physical port */
5174 PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
5175 pAC, LogPortIndex);
5177 *pBufPtr =
5178 CalculateLinkModeStatus(pAC, IoC, PhysPortIndex);
5181 else { /* DualNetMode */
5183 *pBufPtr = CalculateLinkModeStatus(pAC, IoC, NetIndex);
5185 Offset += sizeof(char);
5186 break;
5188 case OID_SKGE_LINK_STATUS:
5189 if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
5190 if (LogPortIndex == 0) {
5191 /* Get value for virtual port */
5192 VirtualConf(pAC, IoC, Id, pBufPtr);
5194 else {
5195 /* Get value for physical ports */
5196 PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
5197 pAC, LogPortIndex);
5199 *pBufPtr = CalculateLinkStatus(pAC, IoC, PhysPortIndex);
5202 else { /* DualNetMode */
5204 *pBufPtr = CalculateLinkStatus(pAC, IoC, NetIndex);
5206 Offset += sizeof(char);
5207 break;
5209 case OID_SKGE_FLOWCTRL_CAP:
5210 if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
5211 if (LogPortIndex == 0) {
5212 /* Get value for virtual port */
5213 VirtualConf(pAC, IoC, Id, pBufPtr);
5215 else {
5216 /* Get value for physical ports */
5217 PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
5218 pAC, LogPortIndex);
5220 *pBufPtr = pAC->GIni.GP[PhysPortIndex].PFlowCtrlCap;
5223 else { /* DualNetMode */
5225 *pBufPtr = pAC->GIni.GP[NetIndex].PFlowCtrlCap;
5227 Offset += sizeof(char);
5228 break;
5230 case OID_SKGE_FLOWCTRL_MODE:
5231 if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
5232 if (LogPortIndex == 0) {
5233 /* Get value for virtual port */
5234 VirtualConf(pAC, IoC, Id, pBufPtr);
5236 else {
5237 /* Get value for physical port */
5238 PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
5239 pAC, LogPortIndex);
5241 *pBufPtr = pAC->GIni.GP[PhysPortIndex].PFlowCtrlMode;
5244 else { /* DualNetMode */
5246 *pBufPtr = pAC->GIni.GP[NetIndex].PFlowCtrlMode;
5248 Offset += sizeof(char);
5249 break;
5251 case OID_SKGE_FLOWCTRL_STATUS:
5252 if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
5253 if (LogPortIndex == 0) {
5254 /* Get value for virtual port */
5255 VirtualConf(pAC, IoC, Id, pBufPtr);
5257 else {
5258 /* Get value for physical port */
5259 PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
5260 pAC, LogPortIndex);
5262 *pBufPtr = pAC->GIni.GP[PhysPortIndex].PFlowCtrlStatus;
5265 else { /* DualNetMode */
5267 *pBufPtr = pAC->GIni.GP[NetIndex].PFlowCtrlStatus;
5269 Offset += sizeof(char);
5270 break;
5272 case OID_SKGE_PHY_OPERATION_CAP:
5273 if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
5274 if (LogPortIndex == 0) {
5275 /* Get value for virtual port */
5276 VirtualConf(pAC, IoC, Id, pBufPtr);
5278 else {
5279 /* Get value for physical ports */
5280 PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
5281 pAC, LogPortIndex);
5283 *pBufPtr = pAC->GIni.GP[PhysPortIndex].PMSCap;
5286 else { /* DualNetMode */
5288 *pBufPtr = pAC->GIni.GP[NetIndex].PMSCap;
5290 Offset += sizeof(char);
5291 break;
5293 case OID_SKGE_PHY_OPERATION_MODE:
5294 if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
5295 if (LogPortIndex == 0) {
5296 /* Get value for virtual port */
5297 VirtualConf(pAC, IoC, Id, pBufPtr);
5299 else {
5300 /* Get value for physical port */
5301 PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
5302 pAC, LogPortIndex);
5304 *pBufPtr = pAC->GIni.GP[PhysPortIndex].PMSMode;
5307 else { /* DualNetMode */
5309 *pBufPtr = pAC->GIni.GP[NetIndex].PMSMode;
5311 Offset += sizeof(char);
5312 break;
5314 case OID_SKGE_PHY_OPERATION_STATUS:
5315 if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
5316 if (LogPortIndex == 0) {
5317 /* Get value for virtual port */
5318 VirtualConf(pAC, IoC, Id, pBufPtr);
5320 else {
5321 /* Get value for physical port */
5322 PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
5323 pAC, LogPortIndex);
5325 *pBufPtr = pAC->GIni.GP[PhysPortIndex].PMSStatus;
5328 else {
5330 *pBufPtr = pAC->GIni.GP[NetIndex].PMSStatus;
5332 Offset += sizeof(char);
5333 break;
5335 case OID_SKGE_SPEED_CAP:
5336 if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
5337 if (LogPortIndex == 0) {
5338 /* Get value for virtual port */
5339 VirtualConf(pAC, IoC, Id, pBufPtr);
5341 else {
5342 /* Get value for physical ports */
5343 PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
5344 pAC, LogPortIndex);
5346 *pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkSpeedCap;
5349 else { /* DualNetMode */
5351 *pBufPtr = pAC->GIni.GP[NetIndex].PLinkSpeedCap;
5353 Offset += sizeof(char);
5354 break;
5356 case OID_SKGE_SPEED_MODE:
5357 if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
5358 if (LogPortIndex == 0) {
5359 /* Get value for virtual port */
5360 VirtualConf(pAC, IoC, Id, pBufPtr);
5362 else {
5363 /* Get value for physical port */
5364 PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
5365 pAC, LogPortIndex);
5367 *pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkSpeed;
5370 else { /* DualNetMode */
5372 *pBufPtr = pAC->GIni.GP[NetIndex].PLinkSpeed;
5374 Offset += sizeof(char);
5375 break;
5377 case OID_SKGE_SPEED_STATUS:
5378 if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */
5379 if (LogPortIndex == 0) {
5380 /* Get value for virtual port */
5381 VirtualConf(pAC, IoC, Id, pBufPtr);
5383 else {
5384 /* Get value for physical port */
5385 PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(
5386 pAC, LogPortIndex);
5388 *pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkSpeedUsed;
5391 else { /* DualNetMode */
5393 *pBufPtr = pAC->GIni.GP[NetIndex].PLinkSpeedUsed;
5395 Offset += sizeof(char);
5396 break;
5398 case OID_SKGE_MTU:
5399 Val32 = SK_DRIVER_GET_MTU(pAC, IoC, NetIndex);
5400 SK_PNMI_STORE_U32(pBufPtr, Val32);
5401 Offset += sizeof(SK_U32);
5402 break;
5404 default:
5405 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR,
5406 ("MacPrivateConf: Unknown OID should be handled before"));
5408 pAC->Pnmi.SirqUpdatedFlag --;
5409 return (SK_PNMI_ERR_GENERAL);
5412 *pLen = Offset;
5413 pAC->Pnmi.SirqUpdatedFlag --;
5415 return (SK_PNMI_ERR_OK);
5419 * From here SET or PRESET action. Check if the passed
5420 * buffer length is plausible.
5422 switch (Id) {
5424 case OID_SKGE_LINK_MODE:
5425 case OID_SKGE_FLOWCTRL_MODE:
5426 case OID_SKGE_PHY_OPERATION_MODE:
5427 case OID_SKGE_SPEED_MODE:
5428 if (*pLen < Limit - LogPortIndex) {
5430 *pLen = Limit - LogPortIndex;
5431 return (SK_PNMI_ERR_TOO_SHORT);
5433 if (*pLen != Limit - LogPortIndex) {
5435 *pLen = 0;
5436 return (SK_PNMI_ERR_BAD_VALUE);
5438 break;
5440 case OID_SKGE_MTU:
5441 if (*pLen < sizeof(SK_U32)) {
5443 *pLen = sizeof(SK_U32);
5444 return (SK_PNMI_ERR_TOO_SHORT);
5446 if (*pLen != sizeof(SK_U32)) {
5448 *pLen = 0;
5449 return (SK_PNMI_ERR_BAD_VALUE);
5451 break;
5453 default:
5454 *pLen = 0;
5455 return (SK_PNMI_ERR_READ_ONLY);
5459 * Perform preset or set
5461 Offset = 0;
5462 for (; LogPortIndex < Limit; LogPortIndex ++) {
5464 switch (Id) {
5466 case OID_SKGE_LINK_MODE:
5467 /* Check the value range */
5468 Val8 = *(pBuf + Offset);
5469 if (Val8 == 0) {
5471 Offset += sizeof(char);
5472 break;
5474 if (Val8 < SK_LMODE_HALF ||
5475 (LogPortIndex != 0 && Val8 > SK_LMODE_AUTOSENSE) ||
5476 (LogPortIndex == 0 && Val8 > SK_LMODE_INDETERMINATED)) {
5478 *pLen = 0;
5479 return (SK_PNMI_ERR_BAD_VALUE);
5482 /* The preset ends here */
5483 if (Action == SK_PNMI_PRESET) {
5485 return (SK_PNMI_ERR_OK);
5488 if (LogPortIndex == 0) {
5491 * The virtual port consists of all currently
5492 * active ports. Find them and send an event
5493 * with the new link mode to SIRQ.
5495 for (PhysPortIndex = 0;
5496 PhysPortIndex < PhysPortMax;
5497 PhysPortIndex ++) {
5499 if (!pAC->Pnmi.Port[PhysPortIndex].
5500 ActiveFlag) {
5502 continue;
5505 EventParam.Para32[0] = PhysPortIndex;
5506 EventParam.Para32[1] = (SK_U32)Val8;
5507 if (SkGeSirqEvent(pAC, IoC,
5508 SK_HWEV_SET_LMODE,
5509 EventParam) > 0) {
5511 SK_ERR_LOG(pAC, SK_ERRCL_SW,
5512 SK_PNMI_ERR043,
5513 SK_PNMI_ERR043MSG);
5515 *pLen = 0;
5516 return (SK_PNMI_ERR_GENERAL);
5520 else {
5522 * Send an event with the new link mode to
5523 * the SIRQ module.
5525 EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS(
5526 pAC, LogPortIndex);
5527 EventParam.Para32[1] = (SK_U32)Val8;
5528 if (SkGeSirqEvent(pAC, IoC, SK_HWEV_SET_LMODE,
5529 EventParam) > 0) {
5531 SK_ERR_LOG(pAC, SK_ERRCL_SW,
5532 SK_PNMI_ERR043,
5533 SK_PNMI_ERR043MSG);
5535 *pLen = 0;
5536 return (SK_PNMI_ERR_GENERAL);
5539 Offset += sizeof(char);
5540 break;
5542 case OID_SKGE_FLOWCTRL_MODE:
5543 /* Check the value range */
5544 Val8 = *(pBuf + Offset);
5545 if (Val8 == 0) {
5547 Offset += sizeof(char);
5548 break;
5550 if (Val8 < SK_FLOW_MODE_NONE ||
5551 (LogPortIndex != 0 && Val8 > SK_FLOW_MODE_SYM_OR_REM) ||
5552 (LogPortIndex == 0 && Val8 > SK_FLOW_MODE_INDETERMINATED)) {
5554 *pLen = 0;
5555 return (SK_PNMI_ERR_BAD_VALUE);
5558 /* The preset ends here */
5559 if (Action == SK_PNMI_PRESET) {
5561 return (SK_PNMI_ERR_OK);
5564 if (LogPortIndex == 0) {
5567 * The virtual port consists of all currently
5568 * active ports. Find them and send an event
5569 * with the new flow control mode to SIRQ.
5571 for (PhysPortIndex = 0;
5572 PhysPortIndex < PhysPortMax;
5573 PhysPortIndex ++) {
5575 if (!pAC->Pnmi.Port[PhysPortIndex].
5576 ActiveFlag) {
5578 continue;
5581 EventParam.Para32[0] = PhysPortIndex;
5582 EventParam.Para32[1] = (SK_U32)Val8;
5583 if (SkGeSirqEvent(pAC, IoC,
5584 SK_HWEV_SET_FLOWMODE,
5585 EventParam) > 0) {
5587 SK_ERR_LOG(pAC, SK_ERRCL_SW,
5588 SK_PNMI_ERR044,
5589 SK_PNMI_ERR044MSG);
5591 *pLen = 0;
5592 return (SK_PNMI_ERR_GENERAL);
5596 else {
5598 * Send an event with the new flow control
5599 * mode to the SIRQ module.
5601 EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS(
5602 pAC, LogPortIndex);
5603 EventParam.Para32[1] = (SK_U32)Val8;
5604 if (SkGeSirqEvent(pAC, IoC,
5605 SK_HWEV_SET_FLOWMODE, EventParam)
5606 > 0) {
5608 SK_ERR_LOG(pAC, SK_ERRCL_SW,
5609 SK_PNMI_ERR044,
5610 SK_PNMI_ERR044MSG);
5612 *pLen = 0;
5613 return (SK_PNMI_ERR_GENERAL);
5616 Offset += sizeof(char);
5617 break;
5619 case OID_SKGE_PHY_OPERATION_MODE :
5620 /* Check the value range */
5621 Val8 = *(pBuf + Offset);
5622 if (Val8 == 0) {
5623 /* mode of this port remains unchanged */
5624 Offset += sizeof(char);
5625 break;
5627 if (Val8 < SK_MS_MODE_AUTO ||
5628 (LogPortIndex != 0 && Val8 > SK_MS_MODE_SLAVE) ||
5629 (LogPortIndex == 0 && Val8 > SK_MS_MODE_INDETERMINATED)) {
5631 *pLen = 0;
5632 return (SK_PNMI_ERR_BAD_VALUE);
5635 /* The preset ends here */
5636 if (Action == SK_PNMI_PRESET) {
5638 return (SK_PNMI_ERR_OK);
5641 if (LogPortIndex == 0) {
5644 * The virtual port consists of all currently
5645 * active ports. Find them and send an event
5646 * with new master/slave (role) mode to SIRQ.
5648 for (PhysPortIndex = 0;
5649 PhysPortIndex < PhysPortMax;
5650 PhysPortIndex ++) {
5652 if (!pAC->Pnmi.Port[PhysPortIndex].
5653 ActiveFlag) {
5655 continue;
5658 EventParam.Para32[0] = PhysPortIndex;
5659 EventParam.Para32[1] = (SK_U32)Val8;
5660 if (SkGeSirqEvent(pAC, IoC,
5661 SK_HWEV_SET_ROLE,
5662 EventParam) > 0) {
5664 SK_ERR_LOG(pAC, SK_ERRCL_SW,
5665 SK_PNMI_ERR042,
5666 SK_PNMI_ERR042MSG);
5668 *pLen = 0;
5669 return (SK_PNMI_ERR_GENERAL);
5673 else {
5675 * Send an event with the new master/slave
5676 * (role) mode to the SIRQ module.
5678 EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS(
5679 pAC, LogPortIndex);
5680 EventParam.Para32[1] = (SK_U32)Val8;
5681 if (SkGeSirqEvent(pAC, IoC,
5682 SK_HWEV_SET_ROLE, EventParam) > 0) {
5684 SK_ERR_LOG(pAC, SK_ERRCL_SW,
5685 SK_PNMI_ERR042,
5686 SK_PNMI_ERR042MSG);
5688 *pLen = 0;
5689 return (SK_PNMI_ERR_GENERAL);
5693 Offset += sizeof(char);
5694 break;
5696 case OID_SKGE_SPEED_MODE:
5697 /* Check the value range */
5698 Val8 = *(pBuf + Offset);
5699 if (Val8 == 0) {
5701 Offset += sizeof(char);
5702 break;
5704 if (Val8 < (SK_LSPEED_AUTO) ||
5705 (LogPortIndex != 0 && Val8 > (SK_LSPEED_1000MBPS)) ||
5706 (LogPortIndex == 0 && Val8 > (SK_LSPEED_INDETERMINATED))) {
5708 *pLen = 0;
5709 return (SK_PNMI_ERR_BAD_VALUE);
5712 /* The preset ends here */
5713 if (Action == SK_PNMI_PRESET) {
5715 return (SK_PNMI_ERR_OK);
5718 if (LogPortIndex == 0) {
5721 * The virtual port consists of all currently
5722 * active ports. Find them and send an event
5723 * with the new flow control mode to SIRQ.
5725 for (PhysPortIndex = 0;
5726 PhysPortIndex < PhysPortMax;
5727 PhysPortIndex ++) {
5729 if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
5731 continue;
5734 EventParam.Para32[0] = PhysPortIndex;
5735 EventParam.Para32[1] = (SK_U32)Val8;
5736 if (SkGeSirqEvent(pAC, IoC,
5737 SK_HWEV_SET_SPEED,
5738 EventParam) > 0) {
5740 SK_ERR_LOG(pAC, SK_ERRCL_SW,
5741 SK_PNMI_ERR045,
5742 SK_PNMI_ERR045MSG);
5744 *pLen = 0;
5745 return (SK_PNMI_ERR_GENERAL);
5749 else {
5751 * Send an event with the new flow control
5752 * mode to the SIRQ module.
5754 EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS(
5755 pAC, LogPortIndex);
5756 EventParam.Para32[1] = (SK_U32)Val8;
5757 if (SkGeSirqEvent(pAC, IoC,
5758 SK_HWEV_SET_SPEED,
5759 EventParam) > 0) {
5761 SK_ERR_LOG(pAC, SK_ERRCL_SW,
5762 SK_PNMI_ERR045,
5763 SK_PNMI_ERR045MSG);
5765 *pLen = 0;
5766 return (SK_PNMI_ERR_GENERAL);
5769 Offset += sizeof(char);
5770 break;
5772 case OID_SKGE_MTU :
5773 /* Check the value range */
5774 Val32 = *(SK_U32*)(pBuf + Offset);
5775 if (Val32 == 0) {
5776 /* mtu of this port remains unchanged */
5777 Offset += sizeof(SK_U32);
5778 break;
5780 if (SK_DRIVER_PRESET_MTU(pAC, IoC, NetIndex, Val32) != 0) {
5781 *pLen = 0;
5782 return (SK_PNMI_ERR_BAD_VALUE);
5785 /* The preset ends here */
5786 if (Action == SK_PNMI_PRESET) {
5787 return (SK_PNMI_ERR_OK);
5790 if (SK_DRIVER_SET_MTU(pAC, IoC, NetIndex, Val32) != 0) {
5791 return (SK_PNMI_ERR_GENERAL);
5794 Offset += sizeof(SK_U32);
5795 break;
5797 default:
5798 SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR,
5799 ("MacPrivateConf: Unknown OID should be handled before set"));
5801 *pLen = 0;
5802 return (SK_PNMI_ERR_GENERAL);
5806 return (SK_PNMI_ERR_OK);
5809 /*****************************************************************************
5811 * Monitor - OID handler function for RLMT_MONITOR_XXX
5813 * Description:
5814 * Because RLMT currently does not support the monitoring of
5815 * remote adapter cards, we return always an empty table.
5817 * Returns:
5818 * SK_PNMI_ERR_OK The request was successfully performed.
5819 * SK_PNMI_ERR_GENERAL A general severe internal error occured.
5820 * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
5821 * the correct data (e.g. a 32bit value is
5822 * needed, but a 16 bit value was passed).
5823 * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid
5824 * value range.
5825 * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set.
5826 * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
5827 * exist (e.g. port instance 3 on a two port
5828 * adapter.
5830 PNMI_STATIC int Monitor(
5831 SK_AC *pAC, /* Pointer to adapter context */
5832 SK_IOC IoC, /* IO context handle */
5833 int Action, /* GET/PRESET/SET action */
5834 SK_U32 Id, /* Object ID that is to be processed */
5835 char *pBuf, /* Buffer used for the management data transfer */
5836 unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
5837 SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
5838 unsigned int TableIndex, /* Index to the Id table */
5839 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
5841 unsigned int Index;
5842 unsigned int Limit;
5843 unsigned int Offset;
5844 unsigned int Entries;
5848 * Calculate instance if wished.
5850 /* XXX Not yet implemented. Return always an empty table. */
5851 Entries = 0;
5853 if ((Instance != (SK_U32)(-1))) {
5855 if ((Instance < 1) || (Instance > Entries)) {
5857 *pLen = 0;
5858 return (SK_PNMI_ERR_UNKNOWN_INST);
5861 Index = (unsigned int)Instance - 1;
5862 Limit = (unsigned int)Instance;
5864 else {
5865 Index = 0;
5866 Limit = Entries;
5870 * Get/Set value
5872 if (Action == SK_PNMI_GET) {
5874 for (Offset=0; Index < Limit; Index ++) {
5876 switch (Id) {
5878 case OID_SKGE_RLMT_MONITOR_INDEX:
5879 case OID_SKGE_RLMT_MONITOR_ADDR:
5880 case OID_SKGE_RLMT_MONITOR_ERRS:
5881 case OID_SKGE_RLMT_MONITOR_TIMESTAMP:
5882 case OID_SKGE_RLMT_MONITOR_ADMIN:
5883 break;
5885 default:
5886 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR046,
5887 SK_PNMI_ERR046MSG);
5889 *pLen = 0;
5890 return (SK_PNMI_ERR_GENERAL);
5893 *pLen = Offset;
5895 else {
5896 /* Only MONITOR_ADMIN can be set */
5897 if (Id != OID_SKGE_RLMT_MONITOR_ADMIN) {
5899 *pLen = 0;
5900 return (SK_PNMI_ERR_READ_ONLY);
5903 /* Check if the length is plausible */
5904 if (*pLen < (Limit - Index)) {
5906 return (SK_PNMI_ERR_TOO_SHORT);
5908 /* Okay, we have a wide value range */
5909 if (*pLen != (Limit - Index)) {
5911 *pLen = 0;
5912 return (SK_PNMI_ERR_BAD_VALUE);
5915 for (Offset=0; Index < Limit; Index ++) {
5919 * XXX Not yet implemented. Return always BAD_VALUE, because the table
5920 * is empty.
5922 *pLen = 0;
5923 return (SK_PNMI_ERR_BAD_VALUE);
5926 return (SK_PNMI_ERR_OK);
5929 /*****************************************************************************
5931 * VirtualConf - Calculates the values of configuration OIDs for virtual port
5933 * Description:
5934 * We handle here the get of the configuration group OIDs, which are
5935 * a little bit complicated. The virtual port consists of all currently
5936 * active physical ports. If multiple ports are active and configured
5937 * differently we get in some trouble to return a single value. So we
5938 * get the value of the first active port and compare it with that of
5939 * the other active ports. If they are not the same, we return a value
5940 * that indicates that the state is indeterminated.
5942 * Returns:
5943 * Nothing
5945 PNMI_STATIC void VirtualConf(
5946 SK_AC *pAC, /* Pointer to adapter context */
5947 SK_IOC IoC, /* IO context handle */
5948 SK_U32 Id, /* Object ID that is to be processed */
5949 char *pBuf) /* Buffer used for the management data transfer */
5951 unsigned int PhysPortMax;
5952 unsigned int PhysPortIndex;
5953 SK_U8 Val8;
5954 SK_U32 Val32;
5955 SK_BOOL PortActiveFlag;
5956 SK_GEPORT *pPrt;
5958 *pBuf = 0;
5959 PortActiveFlag = SK_FALSE;
5960 PhysPortMax = pAC->GIni.GIMacsFound;
5962 for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax;
5963 PhysPortIndex ++) {
5965 pPrt = &pAC->GIni.GP[PhysPortIndex];
5967 /* Check if the physical port is active */
5968 if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
5970 continue;
5973 PortActiveFlag = SK_TRUE;
5975 switch (Id) {
5977 case OID_SKGE_PHY_TYPE:
5978 /* Check if it is the first active port */
5979 if (*pBuf == 0) {
5980 Val32 = pPrt->PhyType;
5981 SK_PNMI_STORE_U32(pBuf, Val32);
5982 continue;
5985 case OID_SKGE_LINK_CAP:
5988 * Different capabilities should not happen, but
5989 * in the case of the cases OR them all together.
5990 * From a curious point of view the virtual port
5991 * is capable of all found capabilities.
5993 *pBuf |= pPrt->PLinkCap;
5994 break;
5996 case OID_SKGE_LINK_MODE:
5997 /* Check if it is the first active port */
5998 if (*pBuf == 0) {
6000 *pBuf = pPrt->PLinkModeConf;
6001 continue;
6005 * If we find an active port with a different link
6006 * mode than the first one we return a value that
6007 * indicates that the link mode is indeterminated.
6009 if (*pBuf != pPrt->PLinkModeConf) {
6011 *pBuf = SK_LMODE_INDETERMINATED;
6013 break;
6015 case OID_SKGE_LINK_MODE_STATUS:
6016 /* Get the link mode of the physical port */
6017 Val8 = CalculateLinkModeStatus(pAC, IoC, PhysPortIndex);
6019 /* Check if it is the first active port */
6020 if (*pBuf == 0) {
6022 *pBuf = Val8;
6023 continue;
6027 * If we find an active port with a different link
6028 * mode status than the first one we return a value
6029 * that indicates that the link mode status is
6030 * indeterminated.
6032 if (*pBuf != Val8) {
6034 *pBuf = SK_LMODE_STAT_INDETERMINATED;
6036 break;
6038 case OID_SKGE_LINK_STATUS:
6039 /* Get the link status of the physical port */
6040 Val8 = CalculateLinkStatus(pAC, IoC, PhysPortIndex);
6042 /* Check if it is the first active port */
6043 if (*pBuf == 0) {
6045 *pBuf = Val8;
6046 continue;
6050 * If we find an active port with a different link
6051 * status than the first one, we return a value
6052 * that indicates that the link status is
6053 * indeterminated.
6055 if (*pBuf != Val8) {
6057 *pBuf = SK_PNMI_RLMT_LSTAT_INDETERMINATED;
6059 break;
6061 case OID_SKGE_FLOWCTRL_CAP:
6062 /* Check if it is the first active port */
6063 if (*pBuf == 0) {
6065 *pBuf = pPrt->PFlowCtrlCap;
6066 continue;
6070 * From a curious point of view the virtual port
6071 * is capable of all found capabilities.
6073 *pBuf |= pPrt->PFlowCtrlCap;
6074 break;
6076 case OID_SKGE_FLOWCTRL_MODE:
6077 /* Check if it is the first active port */
6078 if (*pBuf == 0) {
6080 *pBuf = pPrt->PFlowCtrlMode;
6081 continue;
6085 * If we find an active port with a different flow
6086 * control mode than the first one, we return a value
6087 * that indicates that the mode is indeterminated.
6089 if (*pBuf != pPrt->PFlowCtrlMode) {
6091 *pBuf = SK_FLOW_MODE_INDETERMINATED;
6093 break;
6095 case OID_SKGE_FLOWCTRL_STATUS:
6096 /* Check if it is the first active port */
6097 if (*pBuf == 0) {
6099 *pBuf = pPrt->PFlowCtrlStatus;
6100 continue;
6104 * If we find an active port with a different flow
6105 * control status than the first one, we return a
6106 * value that indicates that the status is
6107 * indeterminated.
6109 if (*pBuf != pPrt->PFlowCtrlStatus) {
6111 *pBuf = SK_FLOW_STAT_INDETERMINATED;
6113 break;
6115 case OID_SKGE_PHY_OPERATION_CAP:
6116 /* Check if it is the first active port */
6117 if (*pBuf == 0) {
6119 *pBuf = pPrt->PMSCap;
6120 continue;
6124 * From a curious point of view the virtual port
6125 * is capable of all found capabilities.
6127 *pBuf |= pPrt->PMSCap;
6128 break;
6130 case OID_SKGE_PHY_OPERATION_MODE:
6131 /* Check if it is the first active port */
6132 if (*pBuf == 0) {
6134 *pBuf = pPrt->PMSMode;
6135 continue;
6139 * If we find an active port with a different master/
6140 * slave mode than the first one, we return a value
6141 * that indicates that the mode is indeterminated.
6143 if (*pBuf != pPrt->PMSMode) {
6145 *pBuf = SK_MS_MODE_INDETERMINATED;
6147 break;
6149 case OID_SKGE_PHY_OPERATION_STATUS:
6150 /* Check if it is the first active port */
6151 if (*pBuf == 0) {
6153 *pBuf = pPrt->PMSStatus;
6154 continue;
6158 * If we find an active port with a different master/
6159 * slave status than the first one, we return a
6160 * value that indicates that the status is
6161 * indeterminated.
6163 if (*pBuf != pPrt->PMSStatus) {
6165 *pBuf = SK_MS_STAT_INDETERMINATED;
6167 break;
6169 case OID_SKGE_SPEED_MODE:
6170 /* Check if it is the first active port */
6171 if (*pBuf == 0) {
6173 *pBuf = pPrt->PLinkSpeed;
6174 continue;
6178 * If we find an active port with a different flow
6179 * control mode than the first one, we return a value
6180 * that indicates that the mode is indeterminated.
6182 if (*pBuf != pPrt->PLinkSpeed) {
6184 *pBuf = SK_LSPEED_INDETERMINATED;
6186 break;
6188 case OID_SKGE_SPEED_STATUS:
6189 /* Check if it is the first active port */
6190 if (*pBuf == 0) {
6192 *pBuf = pPrt->PLinkSpeedUsed;
6193 continue;
6197 * If we find an active port with a different flow
6198 * control status than the first one, we return a
6199 * value that indicates that the status is
6200 * indeterminated.
6202 if (*pBuf != pPrt->PLinkSpeedUsed) {
6204 *pBuf = SK_LSPEED_STAT_INDETERMINATED;
6206 break;
6211 * If no port is active return an indeterminated answer
6213 if (!PortActiveFlag) {
6215 switch (Id) {
6217 case OID_SKGE_LINK_CAP:
6218 *pBuf = SK_LMODE_CAP_INDETERMINATED;
6219 break;
6221 case OID_SKGE_LINK_MODE:
6222 *pBuf = SK_LMODE_INDETERMINATED;
6223 break;
6225 case OID_SKGE_LINK_MODE_STATUS:
6226 *pBuf = SK_LMODE_STAT_INDETERMINATED;
6227 break;
6229 case OID_SKGE_LINK_STATUS:
6230 *pBuf = SK_PNMI_RLMT_LSTAT_INDETERMINATED;
6231 break;
6233 case OID_SKGE_FLOWCTRL_CAP:
6234 case OID_SKGE_FLOWCTRL_MODE:
6235 *pBuf = SK_FLOW_MODE_INDETERMINATED;
6236 break;
6238 case OID_SKGE_FLOWCTRL_STATUS:
6239 *pBuf = SK_FLOW_STAT_INDETERMINATED;
6240 break;
6242 case OID_SKGE_PHY_OPERATION_CAP:
6243 *pBuf = SK_MS_CAP_INDETERMINATED;
6244 break;
6246 case OID_SKGE_PHY_OPERATION_MODE:
6247 *pBuf = SK_MS_MODE_INDETERMINATED;
6248 break;
6250 case OID_SKGE_PHY_OPERATION_STATUS:
6251 *pBuf = SK_MS_STAT_INDETERMINATED;
6252 break;
6253 case OID_SKGE_SPEED_CAP:
6254 *pBuf = SK_LSPEED_CAP_INDETERMINATED;
6255 break;
6257 case OID_SKGE_SPEED_MODE:
6258 *pBuf = SK_LSPEED_INDETERMINATED;
6259 break;
6261 case OID_SKGE_SPEED_STATUS:
6262 *pBuf = SK_LSPEED_STAT_INDETERMINATED;
6263 break;
6268 /*****************************************************************************
6270 * CalculateLinkStatus - Determins the link status of a physical port
6272 * Description:
6273 * Determins the link status the following way:
6274 * LSTAT_PHY_DOWN: Link is down
6275 * LSTAT_AUTONEG: Auto-negotiation failed
6276 * LSTAT_LOG_DOWN: Link is up but RLMT did not yet put the port
6277 * logically up.
6278 * LSTAT_LOG_UP: RLMT marked the port as up
6280 * Returns:
6281 * Link status of physical port
6283 PNMI_STATIC SK_U8 CalculateLinkStatus(
6284 SK_AC *pAC, /* Pointer to adapter context */
6285 SK_IOC IoC, /* IO context handle */
6286 unsigned int PhysPortIndex) /* Physical port index */
6288 SK_U8 Result;
6290 if (!pAC->GIni.GP[PhysPortIndex].PHWLinkUp) {
6292 Result = SK_PNMI_RLMT_LSTAT_PHY_DOWN;
6294 else if (pAC->GIni.GP[PhysPortIndex].PAutoNegFail > 0) {
6296 Result = SK_PNMI_RLMT_LSTAT_AUTONEG;
6298 else if (!pAC->Rlmt.Port[PhysPortIndex].PortDown) {
6300 Result = SK_PNMI_RLMT_LSTAT_LOG_UP;
6302 else {
6303 Result = SK_PNMI_RLMT_LSTAT_LOG_DOWN;
6306 return (Result);
6309 /*****************************************************************************
6311 * CalculateLinkModeStatus - Determins the link mode status of a phys. port
6313 * Description:
6314 * The COMMON module only tells us if the mode is half or full duplex.
6315 * But in the decade of auto sensing it is useful for the user to
6316 * know if the mode was negotiated or forced. Therefore we have a
6317 * look to the mode, which was last used by the negotiation process.
6319 * Returns:
6320 * The link mode status
6322 PNMI_STATIC SK_U8 CalculateLinkModeStatus(
6323 SK_AC *pAC, /* Pointer to adapter context */
6324 SK_IOC IoC, /* IO context handle */
6325 unsigned int PhysPortIndex) /* Physical port index */
6327 SK_U8 Result;
6329 /* Get the current mode, which can be full or half duplex */
6330 Result = pAC->GIni.GP[PhysPortIndex].PLinkModeStatus;
6332 /* Check if no valid mode could be found (link is down) */
6333 if (Result < SK_LMODE_STAT_HALF) {
6335 Result = SK_LMODE_STAT_UNKNOWN;
6337 else if (pAC->GIni.GP[PhysPortIndex].PLinkMode >= SK_LMODE_AUTOHALF) {
6340 * Auto-negotiation was used to bring up the link. Change
6341 * the already found duplex status that it indicates
6342 * auto-negotiation was involved.
6344 if (Result == SK_LMODE_STAT_HALF) {
6346 Result = SK_LMODE_STAT_AUTOHALF;
6348 else if (Result == SK_LMODE_STAT_FULL) {
6350 Result = SK_LMODE_STAT_AUTOFULL;
6354 return (Result);
6357 /*****************************************************************************
6359 * GetVpdKeyArr - Obtain an array of VPD keys
6361 * Description:
6362 * Read the VPD keys and build an array of VPD keys, which are
6363 * easy to access.
6365 * Returns:
6366 * SK_PNMI_ERR_OK Task successfully performed.
6367 * SK_PNMI_ERR_GENERAL Something went wrong.
6369 PNMI_STATIC int GetVpdKeyArr(
6370 SK_AC *pAC, /* Pointer to adapter context */
6371 SK_IOC IoC, /* IO context handle */
6372 char *pKeyArr, /* Ptr KeyArray */
6373 unsigned int KeyArrLen, /* Length of array in bytes */
6374 unsigned int *pKeyNo) /* Number of keys */
6376 unsigned int BufKeysLen = SK_PNMI_VPD_BUFSIZE;
6377 char BufKeys[SK_PNMI_VPD_BUFSIZE];
6378 unsigned int StartOffset;
6379 unsigned int Offset;
6380 int Index;
6381 int Ret;
6384 SK_MEMSET(pKeyArr, 0, KeyArrLen);
6387 * Get VPD key list
6389 Ret = VpdKeys(pAC, IoC, (char *)&BufKeys, (int *)&BufKeysLen,
6390 (int *)pKeyNo);
6391 if (Ret > 0) {
6393 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR014,
6394 SK_PNMI_ERR014MSG);
6396 return (SK_PNMI_ERR_GENERAL);
6398 /* If no keys are available return now */
6399 if (*pKeyNo == 0 || BufKeysLen == 0) {
6401 return (SK_PNMI_ERR_OK);
6404 * If the key list is too long for us trunc it and give a
6405 * errorlog notification. This case should not happen because
6406 * the maximum number of keys is limited due to RAM limitations
6408 if (*pKeyNo > SK_PNMI_VPD_ENTRIES) {
6410 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR015,
6411 SK_PNMI_ERR015MSG);
6413 *pKeyNo = SK_PNMI_VPD_ENTRIES;
6417 * Now build an array of fixed string length size and copy
6418 * the keys together.
6420 for (Index = 0, StartOffset = 0, Offset = 0; Offset < BufKeysLen;
6421 Offset ++) {
6423 if (BufKeys[Offset] != 0) {
6425 continue;
6428 if (Offset - StartOffset > SK_PNMI_VPD_KEY_SIZE) {
6430 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR016,
6431 SK_PNMI_ERR016MSG);
6432 return (SK_PNMI_ERR_GENERAL);
6435 SK_STRNCPY(pKeyArr + Index * SK_PNMI_VPD_KEY_SIZE,
6436 &BufKeys[StartOffset], SK_PNMI_VPD_KEY_SIZE);
6438 Index ++;
6439 StartOffset = Offset + 1;
6442 /* Last key not zero terminated? Get it anyway */
6443 if (StartOffset < Offset) {
6445 SK_STRNCPY(pKeyArr + Index * SK_PNMI_VPD_KEY_SIZE,
6446 &BufKeys[StartOffset], SK_PNMI_VPD_KEY_SIZE);
6449 return (SK_PNMI_ERR_OK);
6452 /*****************************************************************************
6454 * SirqUpdate - Let the SIRQ update its internal values
6456 * Description:
6457 * Just to be sure that the SIRQ module holds its internal data
6458 * structures up to date, we send an update event before we make
6459 * any access.
6461 * Returns:
6462 * SK_PNMI_ERR_OK Task successfully performed.
6463 * SK_PNMI_ERR_GENERAL Something went wrong.
6465 PNMI_STATIC int SirqUpdate(
6466 SK_AC *pAC, /* Pointer to adapter context */
6467 SK_IOC IoC) /* IO context handle */
6469 SK_EVPARA EventParam;
6472 /* Was the module already updated during the current PNMI call? */
6473 if (pAC->Pnmi.SirqUpdatedFlag > 0) {
6475 return (SK_PNMI_ERR_OK);
6478 /* Send an synchronuous update event to the module */
6479 SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
6480 if (SkGeSirqEvent(pAC, IoC, SK_HWEV_UPDATE_STAT, EventParam) > 0) {
6482 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR047,
6483 SK_PNMI_ERR047MSG);
6485 return (SK_PNMI_ERR_GENERAL);
6488 return (SK_PNMI_ERR_OK);
6491 /*****************************************************************************
6493 * RlmtUpdate - Let the RLMT update its internal values
6495 * Description:
6496 * Just to be sure that the RLMT module holds its internal data
6497 * structures up to date, we send an update event before we make
6498 * any access.
6500 * Returns:
6501 * SK_PNMI_ERR_OK Task successfully performed.
6502 * SK_PNMI_ERR_GENERAL Something went wrong.
6504 PNMI_STATIC int RlmtUpdate(
6505 SK_AC *pAC, /* Pointer to adapter context */
6506 SK_IOC IoC, /* IO context handle */
6507 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */
6509 SK_EVPARA EventParam;
6512 /* Was the module already updated during the current PNMI call? */
6513 if (pAC->Pnmi.RlmtUpdatedFlag > 0) {
6515 return (SK_PNMI_ERR_OK);
6518 /* Send an synchronuous update event to the module */
6519 SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
6520 EventParam.Para32[0] = NetIndex;
6521 EventParam.Para32[1] = (SK_U32)-1;
6522 if (SkRlmtEvent(pAC, IoC, SK_RLMT_STATS_UPDATE, EventParam) > 0) {
6524 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR048,
6525 SK_PNMI_ERR048MSG);
6527 return (SK_PNMI_ERR_GENERAL);
6530 return (SK_PNMI_ERR_OK);
6533 /*****************************************************************************
6535 * MacUpdate - Force the XMAC to output the current statistic
6537 * Description:
6538 * The XMAC holds its statistic internally. To obtain the current
6539 * values we must send a command so that the statistic data will
6540 * be written to a predefined memory area on the adapter.
6542 * Returns:
6543 * SK_PNMI_ERR_OK Task successfully performed.
6544 * SK_PNMI_ERR_GENERAL Something went wrong.
6546 PNMI_STATIC int MacUpdate(
6547 SK_AC *pAC, /* Pointer to adapter context */
6548 SK_IOC IoC, /* IO context handle */
6549 unsigned int FirstMac, /* Index of the first Mac to be updated */
6550 unsigned int LastMac) /* Index of the last Mac to be updated */
6552 unsigned int MacIndex;
6555 * Were the statistics already updated during the
6556 * current PNMI call?
6558 if (pAC->Pnmi.MacUpdatedFlag > 0) {
6560 return (SK_PNMI_ERR_OK);
6563 /* Send an update command to all MACs specified */
6564 for (MacIndex = FirstMac; MacIndex <= LastMac; MacIndex ++) {
6567 * 2002-09-13 pweber: Freeze the current SW counters.
6568 * (That should be done as close as
6569 * possible to the update of the
6570 * HW counters)
6572 if (pAC->GIni.GIMacType == SK_MAC_XMAC) {
6573 pAC->Pnmi.BufPort[MacIndex] = pAC->Pnmi.Port[MacIndex];
6576 /* 2002-09-13 pweber: Update the HW counter */
6577 if (pAC->GIni.GIFunc.pFnMacUpdateStats(pAC, IoC, MacIndex) != 0) {
6579 return (SK_PNMI_ERR_GENERAL);
6583 return (SK_PNMI_ERR_OK);
6586 /*****************************************************************************
6588 * GetStatVal - Retrieve an XMAC statistic counter
6590 * Description:
6591 * Retrieves the statistic counter of a virtual or physical port. The
6592 * virtual port is identified by the index 0. It consists of all
6593 * currently active ports. To obtain the counter value for this port
6594 * we must add the statistic counter of all active ports. To grant
6595 * continuous counter values for the virtual port even when port
6596 * switches occur we must additionally add a delta value, which was
6597 * calculated during a SK_PNMI_EVT_RLMT_ACTIVE_UP event.
6599 * Returns:
6600 * Requested statistic value
6602 PNMI_STATIC SK_U64 GetStatVal(
6603 SK_AC *pAC, /* Pointer to adapter context */
6604 SK_IOC IoC, /* IO context handle */
6605 unsigned int LogPortIndex, /* Index of the logical Port to be processed */
6606 unsigned int StatIndex, /* Index to statistic value */
6607 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */
6609 unsigned int PhysPortIndex;
6610 unsigned int PhysPortMax;
6611 SK_U64 Val = 0;
6614 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */
6616 PhysPortIndex = NetIndex;
6618 Val = GetPhysStatVal(pAC, IoC, PhysPortIndex, StatIndex);
6620 else { /* Single Net mode */
6622 if (LogPortIndex == 0) {
6624 PhysPortMax = pAC->GIni.GIMacsFound;
6626 /* Add counter of all active ports */
6627 for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax;
6628 PhysPortIndex ++) {
6630 if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) {
6632 Val += GetPhysStatVal(pAC, IoC, PhysPortIndex, StatIndex);
6636 /* Correct value because of port switches */
6637 Val += pAC->Pnmi.VirtualCounterOffset[StatIndex];
6639 else {
6640 /* Get counter value of physical port */
6641 PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex);
6643 Val = GetPhysStatVal(pAC, IoC, PhysPortIndex, StatIndex);
6646 return (Val);
6649 /*****************************************************************************
6651 * GetPhysStatVal - Get counter value for physical port
6653 * Description:
6654 * Builds a 64bit counter value. Except for the octet counters
6655 * the lower 32bit are counted in hardware and the upper 32bit
6656 * in software by monitoring counter overflow interrupts in the
6657 * event handler. To grant continous counter values during XMAC
6658 * resets (caused by a workaround) we must add a delta value.
6659 * The delta was calculated in the event handler when a
6660 * SK_PNMI_EVT_XMAC_RESET was received.
6662 * Returns:
6663 * Counter value
6665 PNMI_STATIC SK_U64 GetPhysStatVal(
6666 SK_AC *pAC, /* Pointer to adapter context */
6667 SK_IOC IoC, /* IO context handle */
6668 unsigned int PhysPortIndex, /* Index of the logical Port to be processed */
6669 unsigned int StatIndex) /* Index to statistic value */
6671 SK_U64 Val = 0;
6672 SK_U32 LowVal = 0;
6673 SK_U32 HighVal = 0;
6674 SK_U16 Word;
6675 int MacType;
6676 unsigned int HelpIndex;
6677 SK_GEPORT *pPrt;
6679 SK_PNMI_PORT *pPnmiPrt;
6680 SK_GEMACFUNC *pFnMac;
6682 pPrt = &pAC->GIni.GP[PhysPortIndex];
6684 MacType = pAC->GIni.GIMacType;
6686 /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */
6687 if (MacType == SK_MAC_XMAC) {
6688 pPnmiPrt = &pAC->Pnmi.BufPort[PhysPortIndex];
6690 else {
6691 pPnmiPrt = &pAC->Pnmi.Port[PhysPortIndex];
6694 pFnMac = &pAC->GIni.GIFunc;
6696 switch (StatIndex) {
6697 case SK_PNMI_HTX:
6698 if (MacType == SK_MAC_GMAC) {
6699 (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
6700 StatAddr[SK_PNMI_HTX_BROADCAST][MacType].Reg,
6701 &LowVal);
6702 (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
6703 StatAddr[SK_PNMI_HTX_MULTICAST][MacType].Reg,
6704 &HighVal);
6705 LowVal += HighVal;
6706 (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
6707 StatAddr[SK_PNMI_HTX_UNICAST][MacType].Reg,
6708 &HighVal);
6709 LowVal += HighVal;
6711 else {
6712 (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
6713 StatAddr[StatIndex][MacType].Reg,
6714 &LowVal);
6716 HighVal = pPnmiPrt->CounterHigh[StatIndex];
6717 break;
6719 case SK_PNMI_HRX:
6720 if (MacType == SK_MAC_GMAC) {
6721 (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
6722 StatAddr[SK_PNMI_HRX_BROADCAST][MacType].Reg,
6723 &LowVal);
6724 (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
6725 StatAddr[SK_PNMI_HRX_MULTICAST][MacType].Reg,
6726 &HighVal);
6727 LowVal += HighVal;
6728 (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
6729 StatAddr[SK_PNMI_HRX_UNICAST][MacType].Reg,
6730 &HighVal);
6731 LowVal += HighVal;
6733 else {
6734 (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
6735 StatAddr[StatIndex][MacType].Reg,
6736 &LowVal);
6738 HighVal = pPnmiPrt->CounterHigh[StatIndex];
6739 break;
6741 case SK_PNMI_HTX_OCTET:
6742 case SK_PNMI_HRX_OCTET:
6743 (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
6744 StatAddr[StatIndex][MacType].Reg,
6745 &HighVal);
6746 (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
6747 StatAddr[StatIndex + 1][MacType].Reg,
6748 &LowVal);
6749 break;
6751 case SK_PNMI_HTX_BURST:
6752 case SK_PNMI_HTX_EXCESS_DEF:
6753 case SK_PNMI_HTX_CARRIER:
6754 /* Not supported by GMAC */
6755 if (MacType == SK_MAC_GMAC) {
6756 return (Val);
6759 (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
6760 StatAddr[StatIndex][MacType].Reg,
6761 &LowVal);
6762 HighVal = pPnmiPrt->CounterHigh[StatIndex];
6763 break;
6765 case SK_PNMI_HTX_MACC:
6766 /* GMAC only supports PAUSE MAC control frames */
6767 if (MacType == SK_MAC_GMAC) {
6768 HelpIndex = SK_PNMI_HTX_PMACC;
6770 else {
6771 HelpIndex = StatIndex;
6774 (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
6775 StatAddr[HelpIndex][MacType].Reg,
6776 &LowVal);
6778 HighVal = pPnmiPrt->CounterHigh[StatIndex];
6779 break;
6781 case SK_PNMI_HTX_COL:
6782 case SK_PNMI_HRX_UNDERSIZE:
6783 /* Not supported by XMAC */
6784 if (MacType == SK_MAC_XMAC) {
6785 return (Val);
6788 (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
6789 StatAddr[StatIndex][MacType].Reg,
6790 &LowVal);
6791 HighVal = pPnmiPrt->CounterHigh[StatIndex];
6792 break;
6794 case SK_PNMI_HTX_DEFFERAL:
6795 /* Not supported by GMAC */
6796 if (MacType == SK_MAC_GMAC) {
6797 return (Val);
6801 * XMAC counts frames with deferred transmission
6802 * even in full-duplex mode.
6804 * In full-duplex mode the counter remains constant!
6806 if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL) ||
6807 (pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL)) {
6809 LowVal = 0;
6810 HighVal = 0;
6812 else {
6813 /* Otherwise get contents of hardware register */
6814 (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
6815 StatAddr[StatIndex][MacType].Reg,
6816 &LowVal);
6817 HighVal = pPnmiPrt->CounterHigh[StatIndex];
6819 break;
6821 case SK_PNMI_HRX_BADOCTET:
6822 /* Not supported by XMAC */
6823 if (MacType == SK_MAC_XMAC) {
6824 return (Val);
6827 (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
6828 StatAddr[StatIndex][MacType].Reg,
6829 &HighVal);
6830 (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
6831 StatAddr[StatIndex + 1][MacType].Reg,
6832 &LowVal);
6833 break;
6835 case SK_PNMI_HTX_OCTETLOW:
6836 case SK_PNMI_HRX_OCTETLOW:
6837 case SK_PNMI_HRX_BADOCTETLOW:
6838 return (Val);
6840 case SK_PNMI_HRX_LONGFRAMES:
6841 /* For XMAC the SW counter is managed by PNMI */
6842 if (MacType == SK_MAC_XMAC) {
6843 return (pPnmiPrt->StatRxLongFrameCts);
6846 (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
6847 StatAddr[StatIndex][MacType].Reg,
6848 &LowVal);
6849 HighVal = pPnmiPrt->CounterHigh[StatIndex];
6850 break;
6852 case SK_PNMI_HRX_TOO_LONG:
6853 (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
6854 StatAddr[StatIndex][MacType].Reg,
6855 &LowVal);
6856 HighVal = pPnmiPrt->CounterHigh[StatIndex];
6858 Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal);
6860 if (MacType == SK_MAC_GMAC) {
6861 /* For GMAC the SW counter is additionally managed by PNMI */
6862 Val += pPnmiPrt->StatRxFrameTooLongCts;
6864 else {
6866 * Frames longer than IEEE 802.3 frame max size are counted
6867 * by XMAC in frame_too_long counter even reception of long
6868 * frames was enabled and the frame was correct.
6869 * So correct the value by subtracting RxLongFrame counter.
6871 Val -= pPnmiPrt->StatRxLongFrameCts;
6874 LowVal = (SK_U32)Val;
6875 HighVal = (SK_U32)(Val >> 32);
6876 break;
6878 case SK_PNMI_HRX_SHORTS:
6879 /* Not supported by GMAC */
6880 if (MacType == SK_MAC_GMAC) {
6881 /* GM_RXE_FRAG?? */
6882 return (Val);
6886 * XMAC counts short frame errors even if link down (#10620)
6888 * If link-down the counter remains constant
6890 if (pPrt->PLinkModeStatus != SK_LMODE_STAT_UNKNOWN) {
6892 /* Otherwise get incremental difference */
6893 (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
6894 StatAddr[StatIndex][MacType].Reg,
6895 &LowVal);
6896 HighVal = pPnmiPrt->CounterHigh[StatIndex];
6898 Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal);
6899 Val -= pPnmiPrt->RxShortZeroMark;
6901 LowVal = (SK_U32)Val;
6902 HighVal = (SK_U32)(Val >> 32);
6904 break;
6906 case SK_PNMI_HRX_MACC:
6907 case SK_PNMI_HRX_MACC_UNKWN:
6908 case SK_PNMI_HRX_BURST:
6909 case SK_PNMI_HRX_MISSED:
6910 case SK_PNMI_HRX_FRAMING:
6911 case SK_PNMI_HRX_CARRIER:
6912 case SK_PNMI_HRX_IRLENGTH:
6913 case SK_PNMI_HRX_SYMBOL:
6914 case SK_PNMI_HRX_CEXT:
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_HRX_PMACC_ERR:
6927 /* For GMAC the SW counter is managed by PNMI */
6928 if (MacType == SK_MAC_GMAC) {
6929 return (pPnmiPrt->StatRxPMaccErr);
6932 (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
6933 StatAddr[StatIndex][MacType].Reg,
6934 &LowVal);
6935 HighVal = pPnmiPrt->CounterHigh[StatIndex];
6936 break;
6938 /* SW counter managed by PNMI */
6939 case SK_PNMI_HTX_SYNC:
6940 LowVal = (SK_U32)pPnmiPrt->StatSyncCts;
6941 HighVal = (SK_U32)(pPnmiPrt->StatSyncCts >> 32);
6942 break;
6944 /* SW counter managed by PNMI */
6945 case SK_PNMI_HTX_SYNC_OCTET:
6946 LowVal = (SK_U32)pPnmiPrt->StatSyncOctetsCts;
6947 HighVal = (SK_U32)(pPnmiPrt->StatSyncOctetsCts >> 32);
6948 break;
6950 case SK_PNMI_HRX_FCS:
6952 * Broadcom filters FCS errors and counts it in
6953 * Receive Error Counter register
6955 if (pPrt->PhyType == SK_PHY_BCOM) {
6956 /* do not read while not initialized (PHY_READ hangs!)*/
6957 if (pPrt->PState != SK_PRT_RESET) {
6958 SkXmPhyRead(pAC, IoC, PhysPortIndex, PHY_BCOM_RE_CTR, &Word);
6960 LowVal = Word;
6962 HighVal = pPnmiPrt->CounterHigh[StatIndex];
6964 else {
6965 (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
6966 StatAddr[StatIndex][MacType].Reg,
6967 &LowVal);
6968 HighVal = pPnmiPrt->CounterHigh[StatIndex];
6970 break;
6972 default:
6973 (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex,
6974 StatAddr[StatIndex][MacType].Reg,
6975 &LowVal);
6976 HighVal = pPnmiPrt->CounterHigh[StatIndex];
6977 break;
6980 Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal);
6982 /* Correct value because of possible XMAC reset. XMAC Errata #2 */
6983 Val += pPnmiPrt->CounterOffset[StatIndex];
6985 return (Val);
6988 /*****************************************************************************
6990 * ResetCounter - Set all counters and timestamps to zero
6992 * Description:
6993 * Notifies other common modules which store statistic data to
6994 * reset their counters and finally reset our own counters.
6996 * Returns:
6997 * Nothing
6999 PNMI_STATIC void ResetCounter(
7000 SK_AC *pAC, /* Pointer to adapter context */
7001 SK_IOC IoC, /* IO context handle */
7002 SK_U32 NetIndex)
7004 unsigned int PhysPortIndex;
7005 SK_EVPARA EventParam;
7008 SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam));
7010 /* Notify sensor module */
7011 SkEventQueue(pAC, SKGE_I2C, SK_I2CEV_CLEAR, EventParam);
7013 /* Notify RLMT module */
7014 EventParam.Para32[0] = NetIndex;
7015 EventParam.Para32[1] = (SK_U32)-1;
7016 SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STATS_CLEAR, EventParam);
7017 EventParam.Para32[1] = 0;
7019 /* Notify SIRQ module */
7020 SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_CLEAR_STAT, EventParam);
7022 /* Notify CSUM module */
7023 #ifdef SK_USE_CSUM
7024 EventParam.Para32[0] = NetIndex;
7025 EventParam.Para32[1] = (SK_U32)-1;
7026 SkEventQueue(pAC, SKGE_CSUM, SK_CSUM_EVENT_CLEAR_PROTO_STATS,
7027 EventParam);
7028 #endif /* SK_USE_CSUM */
7030 /* Clear XMAC statistic */
7031 for (PhysPortIndex = 0; PhysPortIndex <
7032 (unsigned int)pAC->GIni.GIMacsFound; PhysPortIndex ++) {
7034 (void)pAC->GIni.GIFunc.pFnMacResetCounter(pAC, IoC, PhysPortIndex);
7036 SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].CounterHigh,
7037 0, sizeof(pAC->Pnmi.Port[PhysPortIndex].CounterHigh));
7038 SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].
7039 CounterOffset, 0, sizeof(pAC->Pnmi.Port[
7040 PhysPortIndex].CounterOffset));
7041 SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].StatSyncCts,
7042 0, sizeof(pAC->Pnmi.Port[PhysPortIndex].StatSyncCts));
7043 SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].
7044 StatSyncOctetsCts, 0, sizeof(pAC->Pnmi.Port[
7045 PhysPortIndex].StatSyncOctetsCts));
7046 SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].
7047 StatRxLongFrameCts, 0, sizeof(pAC->Pnmi.Port[
7048 PhysPortIndex].StatRxLongFrameCts));
7049 SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].
7050 StatRxFrameTooLongCts, 0, sizeof(pAC->Pnmi.Port[
7051 PhysPortIndex].StatRxFrameTooLongCts));
7052 SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].
7053 StatRxPMaccErr, 0, sizeof(pAC->Pnmi.Port[
7054 PhysPortIndex].StatRxPMaccErr));
7058 * Clear local statistics
7060 SK_MEMSET((char *)&pAC->Pnmi.VirtualCounterOffset, 0,
7061 sizeof(pAC->Pnmi.VirtualCounterOffset));
7062 pAC->Pnmi.RlmtChangeCts = 0;
7063 pAC->Pnmi.RlmtChangeTime = 0;
7064 SK_MEMSET((char *)&pAC->Pnmi.RlmtChangeEstimate.EstValue[0], 0,
7065 sizeof(pAC->Pnmi.RlmtChangeEstimate.EstValue));
7066 pAC->Pnmi.RlmtChangeEstimate.EstValueIndex = 0;
7067 pAC->Pnmi.RlmtChangeEstimate.Estimate = 0;
7068 pAC->Pnmi.Port[NetIndex].TxSwQueueMax = 0;
7069 pAC->Pnmi.Port[NetIndex].TxRetryCts = 0;
7070 pAC->Pnmi.Port[NetIndex].RxIntrCts = 0;
7071 pAC->Pnmi.Port[NetIndex].TxIntrCts = 0;
7072 pAC->Pnmi.Port[NetIndex].RxNoBufCts = 0;
7073 pAC->Pnmi.Port[NetIndex].TxNoBufCts = 0;
7074 pAC->Pnmi.Port[NetIndex].TxUsedDescrNo = 0;
7075 pAC->Pnmi.Port[NetIndex].RxDeliveredCts = 0;
7076 pAC->Pnmi.Port[NetIndex].RxOctetsDeliveredCts = 0;
7077 pAC->Pnmi.Port[NetIndex].ErrRecoveryCts = 0;
7080 /*****************************************************************************
7082 * GetTrapEntry - Get an entry in the trap buffer
7084 * Description:
7085 * The trap buffer stores various events. A user application somehow
7086 * gets notified that an event occured and retrieves the trap buffer
7087 * contens (or simply polls the buffer). The buffer is organized as
7088 * a ring which stores the newest traps at the beginning. The oldest
7089 * traps are overwritten by the newest ones. Each trap entry has a
7090 * unique number, so that applications may detect new trap entries.
7092 * Returns:
7093 * A pointer to the trap entry
7095 PNMI_STATIC char* GetTrapEntry(
7096 SK_AC *pAC, /* Pointer to adapter context */
7097 SK_U32 TrapId, /* SNMP ID of the trap */
7098 unsigned int Size) /* Space needed for trap entry */
7100 unsigned int BufPad = pAC->Pnmi.TrapBufPad;
7101 unsigned int BufFree = pAC->Pnmi.TrapBufFree;
7102 unsigned int Beg = pAC->Pnmi.TrapQueueBeg;
7103 unsigned int End = pAC->Pnmi.TrapQueueEnd;
7104 char *pBuf = &pAC->Pnmi.TrapBuf[0];
7105 int Wrap;
7106 unsigned int NeededSpace;
7107 unsigned int EntrySize;
7108 SK_U32 Val32;
7109 SK_U64 Val64;
7112 /* Last byte of entry will get a copy of the entry length */
7113 Size ++;
7116 * Calculate needed buffer space */
7117 if (Beg >= Size) {
7119 NeededSpace = Size;
7120 Wrap = SK_FALSE;
7122 else {
7123 NeededSpace = Beg + Size;
7124 Wrap = SK_TRUE;
7128 * Check if enough buffer space is provided. Otherwise
7129 * free some entries. Leave one byte space between begin
7130 * and end of buffer to make it possible to detect whether
7131 * the buffer is full or empty
7133 while (BufFree < NeededSpace + 1) {
7135 if (End == 0) {
7137 End = SK_PNMI_TRAP_QUEUE_LEN;
7140 EntrySize = (unsigned int)*((unsigned char *)pBuf + End - 1);
7141 BufFree += EntrySize;
7142 End -= EntrySize;
7143 #ifdef DEBUG
7144 SK_MEMSET(pBuf + End, (char)(-1), EntrySize);
7145 #endif /* DEBUG */
7146 if (End == BufPad) {
7147 #ifdef DEBUG
7148 SK_MEMSET(pBuf, (char)(-1), End);
7149 #endif /* DEBUG */
7150 BufFree += End;
7151 End = 0;
7152 BufPad = 0;
7157 * Insert new entry as first entry. Newest entries are
7158 * stored at the beginning of the queue.
7160 if (Wrap) {
7162 BufPad = Beg;
7163 Beg = SK_PNMI_TRAP_QUEUE_LEN - Size;
7165 else {
7166 Beg = Beg - Size;
7168 BufFree -= NeededSpace;
7170 /* Save the current offsets */
7171 pAC->Pnmi.TrapQueueBeg = Beg;
7172 pAC->Pnmi.TrapQueueEnd = End;
7173 pAC->Pnmi.TrapBufPad = BufPad;
7174 pAC->Pnmi.TrapBufFree = BufFree;
7176 /* Initialize the trap entry */
7177 *(pBuf + Beg + Size - 1) = (char)Size;
7178 *(pBuf + Beg) = (char)Size;
7179 Val32 = (pAC->Pnmi.TrapUnique) ++;
7180 SK_PNMI_STORE_U32(pBuf + Beg + 1, Val32);
7181 SK_PNMI_STORE_U32(pBuf + Beg + 1 + sizeof(SK_U32), TrapId);
7182 Val64 = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC));
7183 SK_PNMI_STORE_U64(pBuf + Beg + 1 + 2 * sizeof(SK_U32), Val64);
7185 return (pBuf + Beg);
7188 /*****************************************************************************
7190 * CopyTrapQueue - Copies the trap buffer for the TRAP OID
7192 * Description:
7193 * On a query of the TRAP OID the trap buffer contents will be
7194 * copied continuously to the request buffer, which must be large
7195 * enough. No length check is performed.
7197 * Returns:
7198 * Nothing
7200 PNMI_STATIC void CopyTrapQueue(
7201 SK_AC *pAC, /* Pointer to adapter context */
7202 char *pDstBuf) /* Buffer to which the queued traps will be copied */
7204 unsigned int BufPad = pAC->Pnmi.TrapBufPad;
7205 unsigned int Trap = pAC->Pnmi.TrapQueueBeg;
7206 unsigned int End = pAC->Pnmi.TrapQueueEnd;
7207 char *pBuf = &pAC->Pnmi.TrapBuf[0];
7208 unsigned int Len;
7209 unsigned int DstOff = 0;
7212 while (Trap != End) {
7214 Len = (unsigned int)*(pBuf + Trap);
7217 * Last byte containing a copy of the length will
7218 * not be copied.
7220 *(pDstBuf + DstOff) = (char)(Len - 1);
7221 SK_MEMCPY(pDstBuf + DstOff + 1, pBuf + Trap + 1, Len - 2);
7222 DstOff += Len - 1;
7224 Trap += Len;
7225 if (Trap == SK_PNMI_TRAP_QUEUE_LEN) {
7227 Trap = BufPad;
7232 /*****************************************************************************
7234 * GetTrapQueueLen - Get the length of the trap buffer
7236 * Description:
7237 * Evaluates the number of currently stored traps and the needed
7238 * buffer size to retrieve them.
7240 * Returns:
7241 * Nothing
7243 PNMI_STATIC void GetTrapQueueLen(
7244 SK_AC *pAC, /* Pointer to adapter context */
7245 unsigned int *pLen, /* Length in Bytes of all queued traps */
7246 unsigned int *pEntries) /* Returns number of trapes stored in queue */
7248 unsigned int BufPad = pAC->Pnmi.TrapBufPad;
7249 unsigned int Trap = pAC->Pnmi.TrapQueueBeg;
7250 unsigned int End = pAC->Pnmi.TrapQueueEnd;
7251 char *pBuf = &pAC->Pnmi.TrapBuf[0];
7252 unsigned int Len;
7253 unsigned int Entries = 0;
7254 unsigned int TotalLen = 0;
7257 while (Trap != End) {
7259 Len = (unsigned int)*(pBuf + Trap);
7260 TotalLen += Len - 1;
7261 Entries ++;
7263 Trap += Len;
7264 if (Trap == SK_PNMI_TRAP_QUEUE_LEN) {
7266 Trap = BufPad;
7270 *pEntries = Entries;
7271 *pLen = TotalLen;
7274 /*****************************************************************************
7276 * QueueSimpleTrap - Store a simple trap to the trap buffer
7278 * Description:
7279 * A simple trap is a trap with now additional data. It consists
7280 * simply of a trap code.
7282 * Returns:
7283 * Nothing
7285 PNMI_STATIC void QueueSimpleTrap(
7286 SK_AC *pAC, /* Pointer to adapter context */
7287 SK_U32 TrapId) /* Type of sensor trap */
7289 GetTrapEntry(pAC, TrapId, SK_PNMI_TRAP_SIMPLE_LEN);
7292 /*****************************************************************************
7294 * QueueSensorTrap - Stores a sensor trap in the trap buffer
7296 * Description:
7297 * Gets an entry in the trap buffer and fills it with sensor related
7298 * data.
7300 * Returns:
7301 * Nothing
7303 PNMI_STATIC void QueueSensorTrap(
7304 SK_AC *pAC, /* Pointer to adapter context */
7305 SK_U32 TrapId, /* Type of sensor trap */
7306 unsigned int SensorIndex) /* Index of sensor which caused the trap */
7308 char *pBuf;
7309 unsigned int Offset;
7310 unsigned int DescrLen;
7311 SK_U32 Val32;
7314 /* Get trap buffer entry */
7315 DescrLen = SK_STRLEN(pAC->I2c.SenTable[SensorIndex].SenDesc);
7316 pBuf = GetTrapEntry(pAC, TrapId,
7317 SK_PNMI_TRAP_SENSOR_LEN_BASE + DescrLen);
7318 Offset = SK_PNMI_TRAP_SIMPLE_LEN;
7320 /* Store additionally sensor trap related data */
7321 Val32 = OID_SKGE_SENSOR_INDEX;
7322 SK_PNMI_STORE_U32(pBuf + Offset, Val32);
7323 *(pBuf + Offset + 4) = 4;
7324 Val32 = (SK_U32)SensorIndex;
7325 SK_PNMI_STORE_U32(pBuf + Offset + 5, Val32);
7326 Offset += 9;
7328 Val32 = (SK_U32)OID_SKGE_SENSOR_DESCR;
7329 SK_PNMI_STORE_U32(pBuf + Offset, Val32);
7330 *(pBuf + Offset + 4) = (char)DescrLen;
7331 SK_MEMCPY(pBuf + Offset + 5, pAC->I2c.SenTable[SensorIndex].SenDesc,
7332 DescrLen);
7333 Offset += DescrLen + 5;
7335 Val32 = OID_SKGE_SENSOR_TYPE;
7336 SK_PNMI_STORE_U32(pBuf + Offset, Val32);
7337 *(pBuf + Offset + 4) = 1;
7338 *(pBuf + Offset + 5) = (char)pAC->I2c.SenTable[SensorIndex].SenType;
7339 Offset += 6;
7341 Val32 = OID_SKGE_SENSOR_VALUE;
7342 SK_PNMI_STORE_U32(pBuf + Offset, Val32);
7343 *(pBuf + Offset + 4) = 4;
7344 Val32 = (SK_U32)pAC->I2c.SenTable[SensorIndex].SenValue;
7345 SK_PNMI_STORE_U32(pBuf + Offset + 5, Val32);
7348 /*****************************************************************************
7350 * QueueRlmtNewMacTrap - Store a port switch trap in the trap buffer
7352 * Description:
7353 * Nothing further to explain.
7355 * Returns:
7356 * Nothing
7358 PNMI_STATIC void QueueRlmtNewMacTrap(
7359 SK_AC *pAC, /* Pointer to adapter context */
7360 unsigned int ActiveMac) /* Index (0..n) of the currently active port */
7362 char *pBuf;
7363 SK_U32 Val32;
7366 pBuf = GetTrapEntry(pAC, OID_SKGE_TRAP_RLMT_CHANGE_PORT,
7367 SK_PNMI_TRAP_RLMT_CHANGE_LEN);
7369 Val32 = OID_SKGE_RLMT_PORT_ACTIVE;
7370 SK_PNMI_STORE_U32(pBuf + SK_PNMI_TRAP_SIMPLE_LEN, Val32);
7371 *(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 4) = 1;
7372 *(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 5) = (char)ActiveMac;
7375 /*****************************************************************************
7377 * QueueRlmtPortTrap - Store port related RLMT trap to trap buffer
7379 * Description:
7380 * Nothing further to explain.
7382 * Returns:
7383 * Nothing
7385 PNMI_STATIC void QueueRlmtPortTrap(
7386 SK_AC *pAC, /* Pointer to adapter context */
7387 SK_U32 TrapId, /* Type of RLMT port trap */
7388 unsigned int PortIndex) /* Index of the port, which changed its state */
7390 char *pBuf;
7391 SK_U32 Val32;
7394 pBuf = GetTrapEntry(pAC, TrapId, SK_PNMI_TRAP_RLMT_PORT_LEN);
7396 Val32 = OID_SKGE_RLMT_PORT_INDEX;
7397 SK_PNMI_STORE_U32(pBuf + SK_PNMI_TRAP_SIMPLE_LEN, Val32);
7398 *(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 4) = 1;
7399 *(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 5) = (char)PortIndex;
7402 /*****************************************************************************
7404 * CopyMac - Copies a MAC address
7406 * Description:
7407 * Nothing further to explain.
7409 * Returns:
7410 * Nothing
7412 PNMI_STATIC void CopyMac(
7413 char *pDst, /* Pointer to destination buffer */
7414 SK_MAC_ADDR *pMac) /* Pointer of Source */
7416 int i;
7419 for (i = 0; i < sizeof(SK_MAC_ADDR); i ++) {
7421 *(pDst + i) = pMac->a[i];
7425 #ifdef SK_POWER_MGMT
7426 /*****************************************************************************
7428 * PowerManagement - OID handler function of PowerManagement OIDs
7430 * Description:
7431 * The code is simple. No description necessary.
7433 * Returns:
7434 * SK_PNMI_ERR_OK The request was successfully performed.
7435 * SK_PNMI_ERR_GENERAL A general severe internal error occured.
7436 * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
7437 * the correct data (e.g. a 32bit value is
7438 * needed, but a 16 bit value was passed).
7439 * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
7440 * exist (e.g. port instance 3 on a two port
7441 * adapter.
7444 PNMI_STATIC int PowerManagement(
7445 SK_AC *pAC, /* Pointer to adapter context */
7446 SK_IOC IoC, /* IO context handle */
7447 int Action, /* Get/PreSet/Set action */
7448 SK_U32 Id, /* Object ID that is to be processed */
7449 char *pBuf, /* Buffer to which to mgmt data will be retrieved */
7450 unsigned int *pLen, /* On call: buffer length. On return: used buffer */
7451 SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
7452 unsigned int TableIndex, /* Index to the Id table */
7453 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */
7456 SK_U32 RetCode = SK_PNMI_ERR_GENERAL;
7459 * Check instance. We only handle single instance variables
7461 if (Instance != (SK_U32)(-1) && Instance != 1) {
7463 *pLen = 0;
7464 return (SK_PNMI_ERR_UNKNOWN_INST);
7468 /* Check length */
7469 switch (Id) {
7471 case OID_PNP_CAPABILITIES:
7472 if (*pLen < sizeof(SK_PNP_CAPABILITIES)) {
7474 *pLen = sizeof(SK_PNP_CAPABILITIES);
7475 return (SK_PNMI_ERR_TOO_SHORT);
7477 break;
7479 case OID_PNP_SET_POWER:
7480 case OID_PNP_QUERY_POWER:
7481 if (*pLen < sizeof(SK_DEVICE_POWER_STATE))
7483 *pLen = sizeof(SK_DEVICE_POWER_STATE);
7484 return (SK_PNMI_ERR_TOO_SHORT);
7486 break;
7488 case OID_PNP_ADD_WAKE_UP_PATTERN:
7489 case OID_PNP_REMOVE_WAKE_UP_PATTERN:
7490 if (*pLen < sizeof(SK_PM_PACKET_PATTERN)) {
7492 *pLen = sizeof(SK_PM_PACKET_PATTERN);
7493 return (SK_PNMI_ERR_TOO_SHORT);
7495 break;
7497 case OID_PNP_ENABLE_WAKE_UP:
7498 if (*pLen < sizeof(SK_U32)) {
7500 *pLen = sizeof(SK_U32);
7501 return (SK_PNMI_ERR_TOO_SHORT);
7503 break;
7507 * Perform action
7509 if (Action == SK_PNMI_GET) {
7512 * Get value
7514 switch (Id) {
7516 case OID_PNP_CAPABILITIES:
7517 RetCode = SkPowerQueryPnPCapabilities(pAC, IoC, pBuf, pLen);
7518 break;
7520 case OID_PNP_QUERY_POWER:
7521 /* The Windows DDK describes: An OID_PNP_QUERY_POWER requests
7522 the miniport to indicate whether it can transition its NIC
7523 to the low-power state.
7524 A miniport driver must always return NDIS_STATUS_SUCCESS
7525 to a query of OID_PNP_QUERY_POWER. */
7526 *pLen = sizeof(SK_DEVICE_POWER_STATE);
7527 RetCode = SK_PNMI_ERR_OK;
7528 break;
7530 /* NDIS handles these OIDs as write-only.
7531 * So in case of get action the buffer with written length = 0
7532 * is returned
7534 case OID_PNP_SET_POWER:
7535 case OID_PNP_ADD_WAKE_UP_PATTERN:
7536 case OID_PNP_REMOVE_WAKE_UP_PATTERN:
7537 *pLen = 0;
7538 RetCode = SK_PNMI_ERR_NOT_SUPPORTED;
7539 break;
7541 case OID_PNP_ENABLE_WAKE_UP:
7542 RetCode = SkPowerGetEnableWakeUp(pAC, IoC, pBuf, pLen);
7543 break;
7545 default:
7546 RetCode = SK_PNMI_ERR_GENERAL;
7547 break;
7550 return (RetCode);
7555 * Perform preset or set
7558 /* POWER module does not support PRESET action */
7559 if (Action == SK_PNMI_PRESET) {
7560 return (SK_PNMI_ERR_OK);
7563 switch (Id) {
7564 case OID_PNP_SET_POWER:
7565 RetCode = SkPowerSetPower(pAC, IoC, pBuf, pLen);
7566 break;
7568 case OID_PNP_ADD_WAKE_UP_PATTERN:
7569 RetCode = SkPowerAddWakeUpPattern(pAC, IoC, pBuf, pLen);
7570 break;
7572 case OID_PNP_REMOVE_WAKE_UP_PATTERN:
7573 RetCode = SkPowerRemoveWakeUpPattern(pAC, IoC, pBuf, pLen);
7574 break;
7576 case OID_PNP_ENABLE_WAKE_UP:
7577 RetCode = SkPowerSetEnableWakeUp(pAC, IoC, pBuf, pLen);
7578 break;
7580 default:
7581 RetCode = SK_PNMI_ERR_READ_ONLY;
7584 return (RetCode);
7586 #endif /* SK_POWER_MGMT */
7588 #ifdef SK_DIAG_SUPPORT
7589 /*****************************************************************************
7591 * DiagActions - OID handler function of Diagnostic driver
7593 * Description:
7594 * The code is simple. No description necessary.
7596 * Returns:
7597 * SK_PNMI_ERR_OK The request was successfully performed.
7598 * SK_PNMI_ERR_GENERAL A general severe internal error occured.
7599 * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
7600 * the correct data (e.g. a 32bit value is
7601 * needed, but a 16 bit value was passed).
7602 * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
7603 * exist (e.g. port instance 3 on a two port
7604 * adapter.
7607 PNMI_STATIC int DiagActions(
7608 SK_AC *pAC, /* Pointer to adapter context */
7609 SK_IOC IoC, /* IO context handle */
7610 int Action, /* GET/PRESET/SET action */
7611 SK_U32 Id, /* Object ID that is to be processed */
7612 char *pBuf, /* Buffer used for the management data transfer */
7613 unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
7614 SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */
7615 unsigned int TableIndex, /* Index to the Id table */
7616 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
7619 SK_U32 DiagStatus;
7620 SK_U32 RetCode = SK_PNMI_ERR_GENERAL;
7623 * Check instance. We only handle single instance variables.
7625 if (Instance != (SK_U32)(-1) && Instance != 1) {
7627 *pLen = 0;
7628 return (SK_PNMI_ERR_UNKNOWN_INST);
7632 * Check length.
7634 switch (Id) {
7636 case OID_SKGE_DIAG_MODE:
7637 if (*pLen < sizeof(SK_U32)) {
7639 *pLen = sizeof(SK_U32);
7640 return (SK_PNMI_ERR_TOO_SHORT);
7642 break;
7644 default:
7645 SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR040, SK_PNMI_ERR040MSG);
7646 *pLen = 0;
7647 return (SK_PNMI_ERR_GENERAL);
7650 /* Perform action. */
7652 /* GET value. */
7653 if (Action == SK_PNMI_GET) {
7655 switch (Id) {
7657 case OID_SKGE_DIAG_MODE:
7658 DiagStatus = pAC->Pnmi.DiagAttached;
7659 SK_PNMI_STORE_U32(pBuf, DiagStatus);
7660 *pLen = sizeof(SK_U32);
7661 RetCode = SK_PNMI_ERR_OK;
7662 break;
7664 default:
7665 *pLen = 0;
7666 RetCode = SK_PNMI_ERR_GENERAL;
7667 break;
7669 return (RetCode);
7672 /* From here SET or PRESET value. */
7674 /* PRESET value is not supported. */
7675 if (Action == SK_PNMI_PRESET) {
7676 return (SK_PNMI_ERR_OK);
7679 /* SET value. */
7680 switch (Id) {
7681 case OID_SKGE_DIAG_MODE:
7683 /* Handle the SET. */
7684 switch (*pBuf) {
7686 /* Attach the DIAG to this adapter. */
7687 case SK_DIAG_ATTACHED:
7688 /* Check if we come from running */
7689 if (pAC->Pnmi.DiagAttached == SK_DIAG_RUNNING) {
7691 RetCode = SkDrvLeaveDiagMode(pAC);
7694 else if (pAC->Pnmi.DiagAttached == SK_DIAG_IDLE) {
7696 RetCode = SK_PNMI_ERR_OK;
7699 else {
7701 RetCode = SK_PNMI_ERR_GENERAL;
7705 if (RetCode == SK_PNMI_ERR_OK) {
7707 pAC->Pnmi.DiagAttached = SK_DIAG_ATTACHED;
7709 break;
7711 /* Enter the DIAG mode in the driver. */
7712 case SK_DIAG_RUNNING:
7713 RetCode = SK_PNMI_ERR_OK;
7716 * If DiagAttached is set, we can tell the driver
7717 * to enter the DIAG mode.
7719 if (pAC->Pnmi.DiagAttached == SK_DIAG_ATTACHED) {
7720 /* If DiagMode is not active, we can enter it. */
7721 if (!pAC->DiagModeActive) {
7723 RetCode = SkDrvEnterDiagMode(pAC);
7725 else {
7727 RetCode = SK_PNMI_ERR_GENERAL;
7730 else {
7732 RetCode = SK_PNMI_ERR_GENERAL;
7735 if (RetCode == SK_PNMI_ERR_OK) {
7737 pAC->Pnmi.DiagAttached = SK_DIAG_RUNNING;
7739 break;
7741 case SK_DIAG_IDLE:
7742 /* Check if we come from running */
7743 if (pAC->Pnmi.DiagAttached == SK_DIAG_RUNNING) {
7745 RetCode = SkDrvLeaveDiagMode(pAC);
7748 else if (pAC->Pnmi.DiagAttached == SK_DIAG_ATTACHED) {
7750 RetCode = SK_PNMI_ERR_OK;
7753 else {
7755 RetCode = SK_PNMI_ERR_GENERAL;
7759 if (RetCode == SK_PNMI_ERR_OK) {
7761 pAC->Pnmi.DiagAttached = SK_DIAG_IDLE;
7763 break;
7765 default:
7766 RetCode = SK_PNMI_ERR_BAD_VALUE;
7767 break;
7769 break;
7771 default:
7772 RetCode = SK_PNMI_ERR_GENERAL;
7775 if (RetCode == SK_PNMI_ERR_OK) {
7776 *pLen = sizeof(SK_U32);
7778 else {
7780 *pLen = 0;
7782 return (RetCode);
7784 #endif /* SK_DIAG_SUPPORT */
7786 /*****************************************************************************
7788 * Vct - OID handler function of OIDs
7790 * Description:
7791 * The code is simple. No description necessary.
7793 * Returns:
7794 * SK_PNMI_ERR_OK The request was performed successfully.
7795 * SK_PNMI_ERR_GENERAL A general severe internal error occured.
7796 * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain
7797 * the correct data (e.g. a 32bit value is
7798 * needed, but a 16 bit value was passed).
7799 * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
7800 * exist (e.g. port instance 3 on a two port
7801 * adapter).
7802 * SK_PNMI_ERR_READ_ONLY Only the Get action is allowed.
7806 PNMI_STATIC int Vct(
7807 SK_AC *pAC, /* Pointer to adapter context */
7808 SK_IOC IoC, /* IO context handle */
7809 int Action, /* GET/PRESET/SET action */
7810 SK_U32 Id, /* Object ID that is to be processed */
7811 char *pBuf, /* Buffer used for the management data transfer */
7812 unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */
7813 SK_U32 Instance, /* Instance (-1,2..n) that is to be queried */
7814 unsigned int TableIndex, /* Index to the Id table */
7815 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
7817 SK_GEPORT *pPrt;
7818 SK_PNMI_VCT *pVctBackupData;
7819 SK_U32 LogPortMax;
7820 SK_U32 PhysPortMax;
7821 SK_U32 PhysPortIndex;
7822 SK_U32 Limit;
7823 SK_U32 Offset;
7824 SK_BOOL Link;
7825 SK_U32 RetCode = SK_PNMI_ERR_GENERAL;
7826 int i;
7827 SK_EVPARA Para;
7828 SK_U32 CableLength;
7831 * Calculate the port indexes from the instance.
7833 PhysPortMax = pAC->GIni.GIMacsFound;
7834 LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax);
7836 /* Dual net mode? */
7837 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
7838 LogPortMax--;
7841 if ((Instance != (SK_U32) (-1))) {
7842 /* Check instance range. */
7843 if ((Instance < 2) || (Instance > LogPortMax)) {
7844 *pLen = 0;
7845 return (SK_PNMI_ERR_UNKNOWN_INST);
7848 if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) {
7849 PhysPortIndex = NetIndex;
7851 else {
7852 PhysPortIndex = Instance - 2;
7854 Limit = PhysPortIndex + 1;
7856 else {
7858 * Instance == (SK_U32) (-1), get all Instances of that OID.
7860 * Not implemented yet. May be used in future releases.
7862 PhysPortIndex = 0;
7863 Limit = PhysPortMax;
7866 pPrt = &pAC->GIni.GP[PhysPortIndex];
7867 if (pPrt->PHWLinkUp) {
7868 Link = SK_TRUE;
7870 else {
7871 Link = SK_FALSE;
7874 /* Check MAC type */
7875 if (pPrt->PhyType != SK_PHY_MARV_COPPER) {
7876 *pLen = 0;
7877 return (SK_PNMI_ERR_GENERAL);
7880 /* Initialize backup data pointer. */
7881 pVctBackupData = &pAC->Pnmi.VctBackup[PhysPortIndex];
7883 /* Check action type */
7884 if (Action == SK_PNMI_GET) {
7885 /* Check length */
7886 switch (Id) {
7888 case OID_SKGE_VCT_GET:
7889 if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_PNMI_VCT)) {
7890 *pLen = (Limit - PhysPortIndex) * sizeof(SK_PNMI_VCT);
7891 return (SK_PNMI_ERR_TOO_SHORT);
7893 break;
7895 case OID_SKGE_VCT_STATUS:
7896 if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U8)) {
7897 *pLen = (Limit - PhysPortIndex) * sizeof(SK_U8);
7898 return (SK_PNMI_ERR_TOO_SHORT);
7900 break;
7902 default:
7903 *pLen = 0;
7904 return (SK_PNMI_ERR_GENERAL);
7907 /* Get value */
7908 Offset = 0;
7909 for (; PhysPortIndex < Limit; PhysPortIndex++) {
7910 switch (Id) {
7912 case OID_SKGE_VCT_GET:
7913 if ((Link == SK_FALSE) &&
7914 (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING)) {
7915 RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_FALSE);
7916 if (RetCode == 0) {
7917 pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_PENDING;
7918 pAC->Pnmi.VctStatus[PhysPortIndex] |=
7919 (SK_PNMI_VCT_NEW_VCT_DATA | SK_PNMI_VCT_TEST_DONE);
7921 /* Copy results for later use to PNMI struct. */
7922 for (i = 0; i < 4; i++) {
7923 if (pPrt->PMdiPairSts[i] == SK_PNMI_VCT_NORMAL_CABLE) {
7924 if ((pPrt->PMdiPairLen[i] > 35) && (pPrt->PMdiPairLen[i] < 0xff)) {
7925 pPrt->PMdiPairSts[i] = SK_PNMI_VCT_IMPEDANCE_MISMATCH;
7928 if ((pPrt->PMdiPairLen[i] > 35) && (pPrt->PMdiPairLen[i] != 0xff)) {
7929 CableLength = 1000 * (((175 * pPrt->PMdiPairLen[i]) / 210) - 28);
7931 else {
7932 CableLength = 0;
7934 pVctBackupData->PMdiPairLen[i] = CableLength;
7935 pVctBackupData->PMdiPairSts[i] = pPrt->PMdiPairSts[i];
7938 Para.Para32[0] = PhysPortIndex;
7939 Para.Para32[1] = -1;
7940 SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para);
7941 SkEventDispatcher(pAC, IoC);
7943 else {
7944 ; /* VCT test is running. */
7948 /* Get all results. */
7949 CheckVctStatus(pAC, IoC, pBuf, Offset, PhysPortIndex);
7950 Offset += sizeof(SK_U8);
7951 *(pBuf + Offset) = pPrt->PCableLen;
7952 Offset += sizeof(SK_U8);
7953 for (i = 0; i < 4; i++) {
7954 SK_PNMI_STORE_U32((pBuf + Offset), pVctBackupData->PMdiPairLen[i]);
7955 Offset += sizeof(SK_U32);
7957 for (i = 0; i < 4; i++) {
7958 *(pBuf + Offset) = pVctBackupData->PMdiPairSts[i];
7959 Offset += sizeof(SK_U8);
7962 RetCode = SK_PNMI_ERR_OK;
7963 break;
7965 case OID_SKGE_VCT_STATUS:
7966 CheckVctStatus(pAC, IoC, pBuf, Offset, PhysPortIndex);
7967 Offset += sizeof(SK_U8);
7968 RetCode = SK_PNMI_ERR_OK;
7969 break;
7971 default:
7972 *pLen = 0;
7973 return (SK_PNMI_ERR_GENERAL);
7975 } /* for */
7976 *pLen = Offset;
7977 return (RetCode);
7979 } /* if SK_PNMI_GET */
7982 * From here SET or PRESET action. Check if the passed
7983 * buffer length is plausible.
7986 /* Check length */
7987 switch (Id) {
7988 case OID_SKGE_VCT_SET:
7989 if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U32)) {
7990 *pLen = (Limit - PhysPortIndex) * sizeof(SK_U32);
7991 return (SK_PNMI_ERR_TOO_SHORT);
7993 break;
7995 default:
7996 *pLen = 0;
7997 return (SK_PNMI_ERR_GENERAL);
8001 * Perform preset or set.
8004 /* VCT does not support PRESET action. */
8005 if (Action == SK_PNMI_PRESET) {
8006 return (SK_PNMI_ERR_OK);
8009 Offset = 0;
8010 for (; PhysPortIndex < Limit; PhysPortIndex++) {
8011 switch (Id) {
8012 case OID_SKGE_VCT_SET: /* Start VCT test. */
8013 if (Link == SK_FALSE) {
8014 SkGeStopPort(pAC, IoC, PhysPortIndex, SK_STOP_ALL, SK_SOFT_RST);
8016 RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_TRUE);
8017 if (RetCode == 0) { /* RetCode: 0 => Start! */
8018 pAC->Pnmi.VctStatus[PhysPortIndex] |= SK_PNMI_VCT_PENDING;
8019 pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_NEW_VCT_DATA;
8020 pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_LINK;
8023 * Start VCT timer counter.
8025 SK_MEMSET((char *) &Para, 0, sizeof(Para));
8026 Para.Para32[0] = PhysPortIndex;
8027 Para.Para32[1] = -1;
8028 SkTimerStart(pAC, IoC, &pAC->Pnmi.VctTimeout[PhysPortIndex].VctTimer,
8029 4000000, SKGE_PNMI, SK_PNMI_EVT_VCT_RESET, Para);
8030 SK_PNMI_STORE_U32((pBuf + Offset), RetCode);
8031 RetCode = SK_PNMI_ERR_OK;
8033 else { /* RetCode: 2 => Running! */
8034 SK_PNMI_STORE_U32((pBuf + Offset), RetCode);
8035 RetCode = SK_PNMI_ERR_OK;
8038 else { /* RetCode: 4 => Link! */
8039 RetCode = 4;
8040 SK_PNMI_STORE_U32((pBuf + Offset), RetCode);
8041 RetCode = SK_PNMI_ERR_OK;
8043 Offset += sizeof(SK_U32);
8044 break;
8046 default:
8047 *pLen = 0;
8048 return (SK_PNMI_ERR_GENERAL);
8050 } /* for */
8051 *pLen = Offset;
8052 return (RetCode);
8054 } /* Vct */
8057 PNMI_STATIC void CheckVctStatus(
8058 SK_AC *pAC,
8059 SK_IOC IoC,
8060 char *pBuf,
8061 SK_U32 Offset,
8062 SK_U32 PhysPortIndex)
8064 SK_GEPORT *pPrt;
8065 SK_PNMI_VCT *pVctData;
8066 SK_U32 RetCode;
8068 pPrt = &pAC->GIni.GP[PhysPortIndex];
8070 pVctData = (SK_PNMI_VCT *) (pBuf + Offset);
8071 pVctData->VctStatus = SK_PNMI_VCT_NONE;
8073 if (!pPrt->PHWLinkUp) {
8075 /* Was a VCT test ever made before? */
8076 if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_TEST_DONE) {
8077 if ((pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_LINK)) {
8078 pVctData->VctStatus |= SK_PNMI_VCT_OLD_VCT_DATA;
8080 else {
8081 pVctData->VctStatus |= SK_PNMI_VCT_NEW_VCT_DATA;
8085 /* Check VCT test status. */
8086 RetCode = SkGmCableDiagStatus(pAC,IoC, PhysPortIndex, SK_FALSE);
8087 if (RetCode == 2) { /* VCT test is running. */
8088 pVctData->VctStatus |= SK_PNMI_VCT_RUNNING;
8090 else { /* VCT data was copied to pAC here. Check PENDING state. */
8091 if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING) {
8092 pVctData->VctStatus |= SK_PNMI_VCT_NEW_VCT_DATA;
8096 if (pPrt->PCableLen != 0xff) { /* Old DSP value. */
8097 pVctData->VctStatus |= SK_PNMI_VCT_OLD_DSP_DATA;
8100 else {
8102 /* Was a VCT test ever made before? */
8103 if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_TEST_DONE) {
8104 pVctData->VctStatus &= ~SK_PNMI_VCT_NEW_VCT_DATA;
8105 pVctData->VctStatus |= SK_PNMI_VCT_OLD_VCT_DATA;
8108 /* DSP only valid in 100/1000 modes. */
8109 if (pAC->GIni.GP[PhysPortIndex].PLinkSpeedUsed !=
8110 SK_LSPEED_STAT_10MBPS) {
8111 pVctData->VctStatus |= SK_PNMI_VCT_NEW_DSP_DATA;
8114 } /* CheckVctStatus */
8117 /*****************************************************************************
8119 * SkPnmiGenIoctl - Handles new generic PNMI IOCTL, calls the needed
8120 * PNMI function depending on the subcommand and
8121 * returns all data belonging to the complete database
8122 * or OID request.
8124 * Description:
8125 * Looks up the requested subcommand, calls the corresponding handler
8126 * function and passes all required parameters to it.
8127 * The function is called by the driver. It is needed to handle the new
8128 * generic PNMI IOCTL. This IOCTL is given to the driver and contains both
8129 * the OID and a subcommand to decide what kind of request has to be done.
8131 * Returns:
8132 * SK_PNMI_ERR_OK The request was successfully performed
8133 * SK_PNMI_ERR_GENERAL A general severe internal error occured
8134 * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to take
8135 * the data.
8136 * SK_PNMI_ERR_UNKNOWN_OID The requested OID is unknown
8137 * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't
8138 * exist (e.g. port instance 3 on a two port
8139 * adapter.
8141 int SkPnmiGenIoctl(
8142 SK_AC *pAC, /* Pointer to adapter context struct */
8143 SK_IOC IoC, /* I/O context */
8144 void *pBuf, /* Buffer used for the management data transfer */
8145 unsigned int *pLen, /* Length of buffer */
8146 SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */
8148 SK_I32 Mode; /* Store value of subcommand. */
8149 SK_U32 Oid; /* Store value of OID. */
8150 int ReturnCode; /* Store return value to show status of PNMI action. */
8151 int HeaderLength; /* Length of desired action plus OID. */
8153 ReturnCode = SK_PNMI_ERR_GENERAL;
8155 SK_MEMCPY(&Mode, pBuf, sizeof(SK_I32));
8156 SK_MEMCPY(&Oid, (char *) pBuf + sizeof(SK_I32), sizeof(SK_U32));
8157 HeaderLength = sizeof(SK_I32) + sizeof(SK_U32);
8158 *pLen = *pLen - HeaderLength;
8159 SK_MEMCPY((char *) pBuf + sizeof(SK_I32), (char *) pBuf + HeaderLength, *pLen);
8161 switch(Mode) {
8162 case SK_GET_SINGLE_VAR:
8163 ReturnCode = SkPnmiGetVar(pAC, IoC, Oid,
8164 (char *) pBuf + sizeof(SK_I32), pLen,
8165 ((SK_U32) (-1)), NetIndex);
8166 SK_PNMI_STORE_U32(pBuf, ReturnCode);
8167 *pLen = *pLen + sizeof(SK_I32);
8168 break;
8169 case SK_PRESET_SINGLE_VAR:
8170 ReturnCode = SkPnmiPreSetVar(pAC, IoC, Oid,
8171 (char *) pBuf + sizeof(SK_I32), pLen,
8172 ((SK_U32) (-1)), NetIndex);
8173 SK_PNMI_STORE_U32(pBuf, ReturnCode);
8174 *pLen = *pLen + sizeof(SK_I32);
8175 break;
8176 case SK_SET_SINGLE_VAR:
8177 ReturnCode = SkPnmiSetVar(pAC, IoC, Oid,
8178 (char *) pBuf + sizeof(SK_I32), pLen,
8179 ((SK_U32) (-1)), NetIndex);
8180 SK_PNMI_STORE_U32(pBuf, ReturnCode);
8181 *pLen = *pLen + sizeof(SK_I32);
8182 break;
8183 case SK_GET_FULL_MIB:
8184 ReturnCode = SkPnmiGetStruct(pAC, IoC, pBuf, pLen, NetIndex);
8185 break;
8186 case SK_PRESET_FULL_MIB:
8187 ReturnCode = SkPnmiPreSetStruct(pAC, IoC, pBuf, pLen, NetIndex);
8188 break;
8189 case SK_SET_FULL_MIB:
8190 ReturnCode = SkPnmiSetStruct(pAC, IoC, pBuf, pLen, NetIndex);
8191 break;
8192 default:
8193 break;
8196 return (ReturnCode);
8198 } /* SkGeIocGen */