blob: 9325ee7e5524fa304f242ba468fc5317391cfff6 [file] [log] [blame]
wdenkeb20ad32003-09-05 23:19:14 +00001/******************************************************************************
2 *
3 * Name: skproc.c
4 * Project: GEnesis, PCI Gigabit Ethernet Adapter
5 * Version: $Revision: 1.4 $
6 * Date: $Date: 2003/02/25 14:16:37 $
7 * Purpose: Funktions to display statictic data
8 *
9 ******************************************************************************/
wdenk9c53f402003-10-15 23:53:47 +000010
wdenkeb20ad32003-09-05 23:19:14 +000011/******************************************************************************
12 *
13 * (C)Copyright 1998-2003 SysKonnect GmbH.
14 *
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * Created 22-Nov-2000
21 * Author: Mirko Lindner (mlindner@syskonnect.de)
22 *
23 * The information in this file is provided "AS IS" without warranty.
24 *
25 ******************************************************************************/
26/******************************************************************************
27 *
28 * History:
29 *
30 * $Log: skproc.c,v $
31 * Revision 1.4 2003/02/25 14:16:37 mlindner
32 * Fix: Copyright statement
wdenk9c53f402003-10-15 23:53:47 +000033 *
wdenkeb20ad32003-09-05 23:19:14 +000034 * Revision 1.3 2002/10/02 12:59:51 mlindner
35 * Add: Support for Yukon
36 * Add: Speed check and setup
37 * Add: Merge source for kernel 2.2.x and 2.4.x
38 * Add: Read sensor names directly from VPD
39 * Fix: Volt values
wdenk9c53f402003-10-15 23:53:47 +000040 *
wdenkeb20ad32003-09-05 23:19:14 +000041 * Revision 1.2.2.7 2002/01/14 12:45:15 mlindner
42 * Fix: Editorial changes
wdenk9c53f402003-10-15 23:53:47 +000043 *
wdenkeb20ad32003-09-05 23:19:14 +000044 * Revision 1.2.2.6 2001/12/06 15:26:07 mlindner
45 * Fix: Return value of proc_read
wdenk9c53f402003-10-15 23:53:47 +000046 *
wdenkeb20ad32003-09-05 23:19:14 +000047 * Revision 1.2.2.5 2001/12/06 09:57:39 mlindner
48 * New ProcFs entries
wdenk9c53f402003-10-15 23:53:47 +000049 *
wdenkeb20ad32003-09-05 23:19:14 +000050 * Revision 1.2.2.4 2001/09/05 12:16:02 mlindner
51 * Add: New ProcFs entries
52 * Fix: Counter Errors (Jumbo == to long errors)
53 * Fix: Kernel error compilation
54 * Fix: too short counters
wdenk9c53f402003-10-15 23:53:47 +000055 *
wdenkeb20ad32003-09-05 23:19:14 +000056 * Revision 1.2.2.3 2001/06/25 07:26:26 mlindner
57 * Add: More error messages
wdenk9c53f402003-10-15 23:53:47 +000058 *
wdenkeb20ad32003-09-05 23:19:14 +000059 * Revision 1.2.2.2 2001/03/15 12:50:13 mlindner
60 * fix: ProcFS owner protection
wdenk9c53f402003-10-15 23:53:47 +000061 *
wdenkeb20ad32003-09-05 23:19:14 +000062 * Revision 1.2.2.1 2001/03/12 16:43:48 mlindner
63 * chg: 2.4 requirements for procfs
wdenk9c53f402003-10-15 23:53:47 +000064 *
wdenkeb20ad32003-09-05 23:19:14 +000065 * Revision 1.1 2001/01/22 14:15:31 mlindner
66 * added ProcFs functionality
67 * Dual Net functionality integrated
68 * Rlmt networks added
wdenk9c53f402003-10-15 23:53:47 +000069 *
wdenkeb20ad32003-09-05 23:19:14 +000070 *
71 ******************************************************************************/
72
wdenkde887eb2003-09-10 18:20:28 +000073#include <config.h>
74
wdenkeb20ad32003-09-05 23:19:14 +000075#include <linux/proc_fs.h>
76
77#include "h/skdrv1st.h"
78#include "h/skdrv2nd.h"
79#define ZEROPAD 1 /* pad with zero */
80#define SIGN 2 /* unsigned/signed long */
81#define PLUS 4 /* show plus */
82#define SPACE 8 /* space if plus */
83#define LEFT 16 /* left justified */
84#define SPECIALX 32 /* 0x */
85#define LARGE 64
86
Wolfgang Denka1be4762008-05-20 16:00:29 +020087extern SK_AC *pACList;
88extern struct net_device *SkGeRootDev;
wdenkeb20ad32003-09-05 23:19:14 +000089
Wolfgang Denka1be4762008-05-20 16:00:29 +020090extern char *SkNumber (char *str,
91 long long num,
92 int base,
93 int size,
94 int precision,
95 int type);
wdenkeb20ad32003-09-05 23:19:14 +000096
97
98/*****************************************************************************
99 *
Wolfgang Denka1be4762008-05-20 16:00:29 +0200100 * proc_read - print "summaries" entry
wdenkeb20ad32003-09-05 23:19:14 +0000101 *
102 * Description:
wdenk9c53f402003-10-15 23:53:47 +0000103 * This function fills the proc entry with statistic data about
wdenkeb20ad32003-09-05 23:19:14 +0000104 * the ethernet device.
wdenk9c53f402003-10-15 23:53:47 +0000105 *
wdenkeb20ad32003-09-05 23:19:14 +0000106 *
107 * Returns: buffer with statistic data
wdenk9c53f402003-10-15 23:53:47 +0000108 *
wdenkeb20ad32003-09-05 23:19:14 +0000109 */
110int proc_read(char *buffer,
111char **buffer_location,
112off_t offset,
113int buffer_length,
114int *eof,
115void *data)
116{
117 int len = 0;
118 int t;
119 int i;
Wolfgang Denka1be4762008-05-20 16:00:29 +0200120 DEV_NET *pNet;
121 SK_AC *pAC;
122 char test_buf[100];
123 char sens_msg[50];
124 unsigned long Flags;
125 unsigned int Size;
126 struct SK_NET_DEVICE *next;
127 struct SK_NET_DEVICE *SkgeProcDev = SkGeRootDev;
wdenkeb20ad32003-09-05 23:19:14 +0000128
Wolfgang Denka1be4762008-05-20 16:00:29 +0200129 SK_PNMI_STRUCT_DATA *pPnmiStruct;
wdenkeb20ad32003-09-05 23:19:14 +0000130 SK_PNMI_STAT *pPnmiStat;
131 struct proc_dir_entry *file = (struct proc_dir_entry*) data;
132
133 while (SkgeProcDev) {
134 pNet = (DEV_NET*) SkgeProcDev->priv;
135 pAC = pNet->pAC;
136 next = pAC->Next;
137 pPnmiStruct = &pAC->PnmiStruct;
138 /* NetIndex in GetStruct is now required, zero is only dummy */
139
140 for (t=pAC->GIni.GIMacsFound; t > 0; t--) {
141 if ((pAC->GIni.GIMacsFound == 2) && pAC->RlmtNets == 1)
142 t--;
143
144 spin_lock_irqsave(&pAC->SlowPathLock, Flags);
145 Size = SK_PNMI_STRUCT_SIZE;
wdenk9c53f402003-10-15 23:53:47 +0000146 SkPnmiGetStruct(pAC, pAC->IoBase,
wdenkeb20ad32003-09-05 23:19:14 +0000147 pPnmiStruct, &Size, t-1);
148 spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
wdenk9c53f402003-10-15 23:53:47 +0000149
wdenkeb20ad32003-09-05 23:19:14 +0000150 if (strcmp(pAC->dev[t-1]->name, file->name) == 0) {
151 pPnmiStat = &pPnmiStruct->Stat[0];
wdenk9c53f402003-10-15 23:53:47 +0000152 len = sprintf(buffer,
wdenkeb20ad32003-09-05 23:19:14 +0000153 "\nDetailed statistic for device %s\n",
154 pAC->dev[t-1]->name);
155 len += sprintf(buffer + len,
156 "=======================================\n");
wdenk9c53f402003-10-15 23:53:47 +0000157
wdenkeb20ad32003-09-05 23:19:14 +0000158 /* Board statistics */
wdenk9c53f402003-10-15 23:53:47 +0000159 len += sprintf(buffer + len,
wdenkeb20ad32003-09-05 23:19:14 +0000160 "\nBoard statistics\n\n");
161 len += sprintf(buffer + len,
162 "Active Port %c\n",
163 'A' + pAC->Rlmt.Net[t-1].Port[pAC->Rlmt.
164 Net[t-1].PrefPort]->PortNumber);
165 len += sprintf(buffer + len,
166 "Preferred Port %c\n",
167 'A' + pAC->Rlmt.Net[t-1].Port[pAC->Rlmt.
168 Net[t-1].PrefPort]->PortNumber);
169
170 len += sprintf(buffer + len,
171 "Bus speed (MHz) %d\n",
172 pPnmiStruct->BusSpeed);
173
174 len += sprintf(buffer + len,
175 "Bus width (Bit) %d\n",
176 pPnmiStruct->BusWidth);
177 len += sprintf(buffer + len,
178 "Hardware revision v%d.%d\n",
179 (pAC->GIni.GIPciHwRev >> 4) & 0x0F,
180 pAC->GIni.GIPciHwRev & 0x0F);
181
182 /* Print sensor informations */
183 for (i=0; i < pAC->I2c.MaxSens; i ++) {
184 /* Check type */
185 switch (pAC->I2c.SenTable[i].SenType) {
186 case 1:
187 strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc);
188 strcat(sens_msg, " (C)");
189 len += sprintf(buffer + len,
190 "%-25s %d.%02d\n",
191 sens_msg,
192 pAC->I2c.SenTable[i].SenValue / 10,
193 pAC->I2c.SenTable[i].SenValue % 10);
194
195 strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc);
196 strcat(sens_msg, " (F)");
197 len += sprintf(buffer + len,
198 "%-25s %d.%02d\n",
199 sens_msg,
200 ((((pAC->I2c.SenTable[i].SenValue)
201 *10)*9)/5 + 3200)/100,
202 ((((pAC->I2c.SenTable[i].SenValue)
203 *10)*9)/5 + 3200) % 10);
204 break;
205 case 2:
206 strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc);
207 strcat(sens_msg, " (V)");
208 len += sprintf(buffer + len,
209 "%-25s %d.%03d\n",
210 sens_msg,
211 pAC->I2c.SenTable[i].SenValue / 1000,
212 pAC->I2c.SenTable[i].SenValue % 1000);
213 break;
214 case 3:
215 strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc);
216 strcat(sens_msg, " (rpm)");
217 len += sprintf(buffer + len,
218 "%-25s %d\n",
219 sens_msg,
220 pAC->I2c.SenTable[i].SenValue);
221 break;
222 default:
223 break;
224 }
225 }
wdenk9c53f402003-10-15 23:53:47 +0000226
wdenkeb20ad32003-09-05 23:19:14 +0000227 /*Receive statistics */
wdenk9c53f402003-10-15 23:53:47 +0000228 len += sprintf(buffer + len,
wdenkeb20ad32003-09-05 23:19:14 +0000229 "\nReceive statistics\n\n");
230
231 len += sprintf(buffer + len,
232 "Received bytes %s\n",
233 SkNumber(test_buf, pPnmiStat->StatRxOctetsOkCts,
234 10,0,-1,0));
235 len += sprintf(buffer + len,
236 "Received packets %s\n",
237 SkNumber(test_buf, pPnmiStat->StatRxOkCts,
238 10,0,-1,0));
239#if 0
wdenk9c53f402003-10-15 23:53:47 +0000240 if (pAC->GIni.GP[0].PhyType == SK_PHY_XMAC &&
wdenkeb20ad32003-09-05 23:19:14 +0000241 pAC->HWRevision < 12) {
wdenk9c53f402003-10-15 23:53:47 +0000242 pPnmiStruct->InErrorsCts = pPnmiStruct->InErrorsCts -
wdenkeb20ad32003-09-05 23:19:14 +0000243 pPnmiStat->StatRxShortsCts;
244 pPnmiStat->StatRxShortsCts = 0;
245 }
246#endif
wdenk9c53f402003-10-15 23:53:47 +0000247 if (pNet->Mtu > 1500)
wdenkeb20ad32003-09-05 23:19:14 +0000248 pPnmiStruct->InErrorsCts = pPnmiStruct->InErrorsCts -
249 pPnmiStat->StatRxTooLongCts;
250
251 len += sprintf(buffer + len,
252 "Receive errors %s\n",
253 SkNumber(test_buf, pPnmiStruct->InErrorsCts,
254 10,0,-1,0));
255 len += sprintf(buffer + len,
256 "Receive drops %s\n",
257 SkNumber(test_buf, pPnmiStruct->RxNoBufCts,
258 10,0,-1,0));
259 len += sprintf(buffer + len,
260 "Received multicast %s\n",
261 SkNumber(test_buf, pPnmiStat->StatRxMulticastOkCts,
262 10,0,-1,0));
263 len += sprintf(buffer + len,
264 "Receive error types\n");
265 len += sprintf(buffer + len,
266 " length %s\n",
267 SkNumber(test_buf, pPnmiStat->StatRxRuntCts,
268 10, 0, -1, 0));
269 len += sprintf(buffer + len,
270 " buffer overflow %s\n",
271 SkNumber(test_buf, pPnmiStat->StatRxFifoOverflowCts,
272 10, 0, -1, 0));
273 len += sprintf(buffer + len,
274 " bad crc %s\n",
275 SkNumber(test_buf, pPnmiStat->StatRxFcsCts,
276 10, 0, -1, 0));
277 len += sprintf(buffer + len,
278 " framing %s\n",
279 SkNumber(test_buf, pPnmiStat->StatRxFramingCts,
280 10, 0, -1, 0));
281 len += sprintf(buffer + len,
282 " missed frames %s\n",
283 SkNumber(test_buf, pPnmiStat->StatRxMissedCts,
284 10, 0, -1, 0));
285
286 if (pNet->Mtu > 1500)
287 pPnmiStat->StatRxTooLongCts = 0;
288
289 len += sprintf(buffer + len,
290 " too long %s\n",
291 SkNumber(test_buf, pPnmiStat->StatRxTooLongCts,
wdenk9c53f402003-10-15 23:53:47 +0000292 10, 0, -1, 0));
wdenkeb20ad32003-09-05 23:19:14 +0000293 len += sprintf(buffer + len,
294 " carrier extension %s\n",
295 SkNumber(test_buf, pPnmiStat->StatRxCextCts,
wdenk9c53f402003-10-15 23:53:47 +0000296 10, 0, -1, 0));
wdenkeb20ad32003-09-05 23:19:14 +0000297 len += sprintf(buffer + len,
298 " too short %s\n",
299 SkNumber(test_buf, pPnmiStat->StatRxShortsCts,
wdenk9c53f402003-10-15 23:53:47 +0000300 10, 0, -1, 0));
wdenkeb20ad32003-09-05 23:19:14 +0000301 len += sprintf(buffer + len,
302 " symbol %s\n",
303 SkNumber(test_buf, pPnmiStat->StatRxSymbolCts,
wdenk9c53f402003-10-15 23:53:47 +0000304 10, 0, -1, 0));
wdenkeb20ad32003-09-05 23:19:14 +0000305 len += sprintf(buffer + len,
306 " LLC MAC size %s\n",
307 SkNumber(test_buf, pPnmiStat->StatRxIRLengthCts,
wdenk9c53f402003-10-15 23:53:47 +0000308 10, 0, -1, 0));
wdenkeb20ad32003-09-05 23:19:14 +0000309 len += sprintf(buffer + len,
310 " carrier event %s\n",
311 SkNumber(test_buf, pPnmiStat->StatRxCarrierCts,
wdenk9c53f402003-10-15 23:53:47 +0000312 10, 0, -1, 0));
wdenkeb20ad32003-09-05 23:19:14 +0000313 len += sprintf(buffer + len,
314 " jabber %s\n",
315 SkNumber(test_buf, pPnmiStat->StatRxJabberCts,
wdenk9c53f402003-10-15 23:53:47 +0000316 10, 0, -1, 0));
wdenkeb20ad32003-09-05 23:19:14 +0000317
318
319 /*Transmit statistics */
wdenk9c53f402003-10-15 23:53:47 +0000320 len += sprintf(buffer + len,
wdenkeb20ad32003-09-05 23:19:14 +0000321 "\nTransmit statistics\n\n");
wdenk9c53f402003-10-15 23:53:47 +0000322
wdenkeb20ad32003-09-05 23:19:14 +0000323 len += sprintf(buffer + len,
324 "Transmited bytes %s\n",
325 SkNumber(test_buf, pPnmiStat->StatTxOctetsOkCts,
326 10,0,-1,0));
327 len += sprintf(buffer + len,
328 "Transmited packets %s\n",
329 SkNumber(test_buf, pPnmiStat->StatTxOkCts,
330 10,0,-1,0));
331 len += sprintf(buffer + len,
332 "Transmit errors %s\n",
333 SkNumber(test_buf, pPnmiStat->StatTxSingleCollisionCts,
334 10,0,-1,0));
335 len += sprintf(buffer + len,
336 "Transmit dropped %s\n",
337 SkNumber(test_buf, pPnmiStruct->TxNoBufCts,
338 10,0,-1,0));
339 len += sprintf(buffer + len,
340 "Transmit collisions %s\n",
341 SkNumber(test_buf, pPnmiStat->StatTxSingleCollisionCts,
342 10,0,-1,0));
343 len += sprintf(buffer + len,
344 "Transmit errors types\n");
345 len += sprintf(buffer + len,
346 " excessive collision %ld\n",
347 pAC->stats.tx_aborted_errors);
348 len += sprintf(buffer + len,
349 " carrier %s\n",
350 SkNumber(test_buf, pPnmiStat->StatTxCarrierCts,
351 10, 0, -1, 0));
352 len += sprintf(buffer + len,
353 " fifo underrun %s\n",
354 SkNumber(test_buf, pPnmiStat->StatTxFifoUnderrunCts,
355 10, 0, -1, 0));
356 len += sprintf(buffer + len,
357 " heartbeat %s\n",
358 SkNumber(test_buf, pPnmiStat->StatTxCarrierCts,
359 10, 0, -1, 0));
360 len += sprintf(buffer + len,
361 " window %ld\n",
362 pAC->stats.tx_window_errors);
wdenk9c53f402003-10-15 23:53:47 +0000363
wdenkeb20ad32003-09-05 23:19:14 +0000364 }
365 }
366 SkgeProcDev = next;
367 }
368 if (offset >= len) {
369 *eof = 1;
370 return 0;
371 }
372
373 *buffer_location = buffer + offset;
374 if (buffer_length >= len - offset) {
375 *eof = 1;
376 }
377 return (min_t(int, buffer_length, len - offset));
378}
379
380
wdenkeb20ad32003-09-05 23:19:14 +0000381/*****************************************************************************
382 *
383 * SkDoDiv - convert 64bit number
384 *
385 * Description:
386 * This function "converts" a long long number.
387 *
388 * Returns:
389 * remainder of division
390 */
391static long SkDoDiv (long long Dividend, int Divisor, long long *pErg)
392{
Wolfgang Denka1be4762008-05-20 16:00:29 +0200393 long Rest;
394 long long Ergebnis;
395 long Akku;
wdenkeb20ad32003-09-05 23:19:14 +0000396
397
Wolfgang Denka1be4762008-05-20 16:00:29 +0200398 Akku = Dividend >> 32;
wdenkeb20ad32003-09-05 23:19:14 +0000399
Wolfgang Denka1be4762008-05-20 16:00:29 +0200400 Ergebnis = ((long long) (Akku / Divisor)) << 32;
401 Rest = Akku % Divisor;
wdenkeb20ad32003-09-05 23:19:14 +0000402
Wolfgang Denka1be4762008-05-20 16:00:29 +0200403 Akku = Rest << 16;
404 Akku |= ((Dividend & 0xFFFF0000) >> 16);
wdenkeb20ad32003-09-05 23:19:14 +0000405
406
Wolfgang Denka1be4762008-05-20 16:00:29 +0200407 Ergebnis += ((long long) (Akku / Divisor)) << 16;
408 Rest = Akku % Divisor;
wdenkeb20ad32003-09-05 23:19:14 +0000409
Wolfgang Denka1be4762008-05-20 16:00:29 +0200410 Akku = Rest << 16;
411 Akku |= (Dividend & 0xFFFF);
wdenkeb20ad32003-09-05 23:19:14 +0000412
Wolfgang Denka1be4762008-05-20 16:00:29 +0200413 Ergebnis += (Akku / Divisor);
414 Rest = Akku % Divisor;
wdenkeb20ad32003-09-05 23:19:14 +0000415
Wolfgang Denka1be4762008-05-20 16:00:29 +0200416 *pErg = Ergebnis;
417 return (Rest);
wdenkeb20ad32003-09-05 23:19:14 +0000418}
419
420
421#if 0
422#define do_div(n,base) ({ \
423long long __res; \
424__res = ((unsigned long long) n) % (unsigned) base; \
425n = ((unsigned long long) n) / (unsigned) base; \
426__res; })
427
428#endif
429
430
431/*****************************************************************************
432 *
433 * SkNumber - Print results
434 *
435 * Description:
436 * This function converts a long long number into a string.
437 *
438 * Returns:
439 * number as string
440 */
441char * SkNumber(char * str, long long num, int base, int size, int precision
442 ,int type)
443{
444 char c,sign,tmp[66], *strorg = str;
445 const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
446 int i;
447
448 if (type & LARGE)
449 digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
450 if (type & LEFT)
451 type &= ~ZEROPAD;
452 if (base < 2 || base > 36)
453 return 0;
454 c = (type & ZEROPAD) ? '0' : ' ';
455 sign = 0;
456 if (type & SIGN) {
457 if (num < 0) {
458 sign = '-';
459 num = -num;
460 size--;
461 } else if (type & PLUS) {
462 sign = '+';
463 size--;
464 } else if (type & SPACE) {
465 sign = ' ';
466 size--;
467 }
468 }
469 if (type & SPECIALX) {
470 if (base == 16)
471 size -= 2;
472 else if (base == 8)
473 size--;
474 }
475 i = 0;
476 if (num == 0)
477 tmp[i++]='0';
478 else while (num != 0)
479 tmp[i++] = digits[SkDoDiv(num,base, &num)];
480
481 if (i > precision)
482 precision = i;
483 size -= precision;
484 if (!(type&(ZEROPAD+LEFT)))
485 while(size-->0)
486 *str++ = ' ';
487 if (sign)
488 *str++ = sign;
489 if (type & SPECIALX) {
490 if (base==8)
491 *str++ = '0';
492 else if (base==16) {
493 *str++ = '0';
494 *str++ = digits[33];
495 }
496 }
497 if (!(type & LEFT))
498 while (size-- > 0)
499 *str++ = c;
500 while (i < precision--)
501 *str++ = '0';
502 while (i-- > 0)
503 *str++ = tmp[i];
504 while (size-- > 0)
505 *str++ = ' ';
wdenk9c53f402003-10-15 23:53:47 +0000506
wdenkeb20ad32003-09-05 23:19:14 +0000507 str[0] = '\0';
wdenk9c53f402003-10-15 23:53:47 +0000508
wdenkeb20ad32003-09-05 23:19:14 +0000509 return strorg;
510}