blob: 4e340730e56598064a39cce5283205d302e4452a [file] [log] [blame]
wdenk7152b1d2003-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 ******************************************************************************/
wdenk42d1f032003-10-15 23:53:47 +000010
wdenk7152b1d2003-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
wdenk42d1f032003-10-15 23:53:47 +000033 *
wdenk7152b1d2003-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
wdenk42d1f032003-10-15 23:53:47 +000040 *
wdenk7152b1d2003-09-05 23:19:14 +000041 * Revision 1.2.2.7 2002/01/14 12:45:15 mlindner
42 * Fix: Editorial changes
wdenk42d1f032003-10-15 23:53:47 +000043 *
wdenk7152b1d2003-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
wdenk42d1f032003-10-15 23:53:47 +000046 *
wdenk7152b1d2003-09-05 23:19:14 +000047 * Revision 1.2.2.5 2001/12/06 09:57:39 mlindner
48 * New ProcFs entries
wdenk42d1f032003-10-15 23:53:47 +000049 *
wdenk7152b1d2003-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
wdenk42d1f032003-10-15 23:53:47 +000055 *
wdenk7152b1d2003-09-05 23:19:14 +000056 * Revision 1.2.2.3 2001/06/25 07:26:26 mlindner
57 * Add: More error messages
wdenk42d1f032003-10-15 23:53:47 +000058 *
wdenk7152b1d2003-09-05 23:19:14 +000059 * Revision 1.2.2.2 2001/03/15 12:50:13 mlindner
60 * fix: ProcFS owner protection
wdenk42d1f032003-10-15 23:53:47 +000061 *
wdenk7152b1d2003-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
wdenk42d1f032003-10-15 23:53:47 +000064 *
wdenk7152b1d2003-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
wdenk42d1f032003-10-15 23:53:47 +000069 *
wdenk7152b1d2003-09-05 23:19:14 +000070 *
71 ******************************************************************************/
72
wdenk149dded2003-09-10 18:20:28 +000073#include <config.h>
74
75#ifdef CONFIG_SK98
76
wdenk7152b1d2003-09-05 23:19:14 +000077#include <linux/proc_fs.h>
78
79#include "h/skdrv1st.h"
80#include "h/skdrv2nd.h"
81#define ZEROPAD 1 /* pad with zero */
82#define SIGN 2 /* unsigned/signed long */
83#define PLUS 4 /* show plus */
84#define SPACE 8 /* space if plus */
85#define LEFT 16 /* left justified */
86#define SPECIALX 32 /* 0x */
87#define LARGE 64
88
89extern SK_AC *pACList;
90extern struct net_device *SkGeRootDev;
91
92extern char * SkNumber(
93 char * str,
94 long long num,
95 int base,
96 int size,
97 int precision,
98 int type);
99
100
101/*****************************************************************************
102 *
wdenk42d1f032003-10-15 23:53:47 +0000103 * proc_read - print "summaries" entry
wdenk7152b1d2003-09-05 23:19:14 +0000104 *
105 * Description:
wdenk42d1f032003-10-15 23:53:47 +0000106 * This function fills the proc entry with statistic data about
wdenk7152b1d2003-09-05 23:19:14 +0000107 * the ethernet device.
wdenk42d1f032003-10-15 23:53:47 +0000108 *
wdenk7152b1d2003-09-05 23:19:14 +0000109 *
110 * Returns: buffer with statistic data
wdenk42d1f032003-10-15 23:53:47 +0000111 *
wdenk7152b1d2003-09-05 23:19:14 +0000112 */
113int proc_read(char *buffer,
114char **buffer_location,
115off_t offset,
116int buffer_length,
117int *eof,
118void *data)
119{
120 int len = 0;
121 int t;
122 int i;
123 DEV_NET *pNet;
124 SK_AC *pAC;
125 char test_buf[100];
126 char sens_msg[50];
wdenk42d1f032003-10-15 23:53:47 +0000127 unsigned long Flags;
wdenk7152b1d2003-09-05 23:19:14 +0000128 unsigned int Size;
129 struct SK_NET_DEVICE *next;
130 struct SK_NET_DEVICE *SkgeProcDev = SkGeRootDev;
131
132 SK_PNMI_STRUCT_DATA *pPnmiStruct;
133 SK_PNMI_STAT *pPnmiStat;
134 struct proc_dir_entry *file = (struct proc_dir_entry*) data;
135
136 while (SkgeProcDev) {
137 pNet = (DEV_NET*) SkgeProcDev->priv;
138 pAC = pNet->pAC;
139 next = pAC->Next;
140 pPnmiStruct = &pAC->PnmiStruct;
141 /* NetIndex in GetStruct is now required, zero is only dummy */
142
143 for (t=pAC->GIni.GIMacsFound; t > 0; t--) {
144 if ((pAC->GIni.GIMacsFound == 2) && pAC->RlmtNets == 1)
145 t--;
146
147 spin_lock_irqsave(&pAC->SlowPathLock, Flags);
148 Size = SK_PNMI_STRUCT_SIZE;
wdenk42d1f032003-10-15 23:53:47 +0000149 SkPnmiGetStruct(pAC, pAC->IoBase,
wdenk7152b1d2003-09-05 23:19:14 +0000150 pPnmiStruct, &Size, t-1);
151 spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
wdenk42d1f032003-10-15 23:53:47 +0000152
wdenk7152b1d2003-09-05 23:19:14 +0000153 if (strcmp(pAC->dev[t-1]->name, file->name) == 0) {
154 pPnmiStat = &pPnmiStruct->Stat[0];
wdenk42d1f032003-10-15 23:53:47 +0000155 len = sprintf(buffer,
wdenk7152b1d2003-09-05 23:19:14 +0000156 "\nDetailed statistic for device %s\n",
157 pAC->dev[t-1]->name);
158 len += sprintf(buffer + len,
159 "=======================================\n");
wdenk42d1f032003-10-15 23:53:47 +0000160
wdenk7152b1d2003-09-05 23:19:14 +0000161 /* Board statistics */
wdenk42d1f032003-10-15 23:53:47 +0000162 len += sprintf(buffer + len,
wdenk7152b1d2003-09-05 23:19:14 +0000163 "\nBoard statistics\n\n");
164 len += sprintf(buffer + len,
165 "Active Port %c\n",
166 'A' + pAC->Rlmt.Net[t-1].Port[pAC->Rlmt.
167 Net[t-1].PrefPort]->PortNumber);
168 len += sprintf(buffer + len,
169 "Preferred Port %c\n",
170 'A' + pAC->Rlmt.Net[t-1].Port[pAC->Rlmt.
171 Net[t-1].PrefPort]->PortNumber);
172
173 len += sprintf(buffer + len,
174 "Bus speed (MHz) %d\n",
175 pPnmiStruct->BusSpeed);
176
177 len += sprintf(buffer + len,
178 "Bus width (Bit) %d\n",
179 pPnmiStruct->BusWidth);
180 len += sprintf(buffer + len,
181 "Hardware revision v%d.%d\n",
182 (pAC->GIni.GIPciHwRev >> 4) & 0x0F,
183 pAC->GIni.GIPciHwRev & 0x0F);
184
185 /* Print sensor informations */
186 for (i=0; i < pAC->I2c.MaxSens; i ++) {
187 /* Check type */
188 switch (pAC->I2c.SenTable[i].SenType) {
189 case 1:
190 strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc);
191 strcat(sens_msg, " (C)");
192 len += sprintf(buffer + len,
193 "%-25s %d.%02d\n",
194 sens_msg,
195 pAC->I2c.SenTable[i].SenValue / 10,
196 pAC->I2c.SenTable[i].SenValue % 10);
197
198 strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc);
199 strcat(sens_msg, " (F)");
200 len += sprintf(buffer + len,
201 "%-25s %d.%02d\n",
202 sens_msg,
203 ((((pAC->I2c.SenTable[i].SenValue)
204 *10)*9)/5 + 3200)/100,
205 ((((pAC->I2c.SenTable[i].SenValue)
206 *10)*9)/5 + 3200) % 10);
207 break;
208 case 2:
209 strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc);
210 strcat(sens_msg, " (V)");
211 len += sprintf(buffer + len,
212 "%-25s %d.%03d\n",
213 sens_msg,
214 pAC->I2c.SenTable[i].SenValue / 1000,
215 pAC->I2c.SenTable[i].SenValue % 1000);
216 break;
217 case 3:
218 strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc);
219 strcat(sens_msg, " (rpm)");
220 len += sprintf(buffer + len,
221 "%-25s %d\n",
222 sens_msg,
223 pAC->I2c.SenTable[i].SenValue);
224 break;
225 default:
226 break;
227 }
228 }
wdenk42d1f032003-10-15 23:53:47 +0000229
wdenk7152b1d2003-09-05 23:19:14 +0000230 /*Receive statistics */
wdenk42d1f032003-10-15 23:53:47 +0000231 len += sprintf(buffer + len,
wdenk7152b1d2003-09-05 23:19:14 +0000232 "\nReceive statistics\n\n");
233
234 len += sprintf(buffer + len,
235 "Received bytes %s\n",
236 SkNumber(test_buf, pPnmiStat->StatRxOctetsOkCts,
237 10,0,-1,0));
238 len += sprintf(buffer + len,
239 "Received packets %s\n",
240 SkNumber(test_buf, pPnmiStat->StatRxOkCts,
241 10,0,-1,0));
242#if 0
wdenk42d1f032003-10-15 23:53:47 +0000243 if (pAC->GIni.GP[0].PhyType == SK_PHY_XMAC &&
wdenk7152b1d2003-09-05 23:19:14 +0000244 pAC->HWRevision < 12) {
wdenk42d1f032003-10-15 23:53:47 +0000245 pPnmiStruct->InErrorsCts = pPnmiStruct->InErrorsCts -
wdenk7152b1d2003-09-05 23:19:14 +0000246 pPnmiStat->StatRxShortsCts;
247 pPnmiStat->StatRxShortsCts = 0;
248 }
249#endif
wdenk42d1f032003-10-15 23:53:47 +0000250 if (pNet->Mtu > 1500)
wdenk7152b1d2003-09-05 23:19:14 +0000251 pPnmiStruct->InErrorsCts = pPnmiStruct->InErrorsCts -
252 pPnmiStat->StatRxTooLongCts;
253
254 len += sprintf(buffer + len,
255 "Receive errors %s\n",
256 SkNumber(test_buf, pPnmiStruct->InErrorsCts,
257 10,0,-1,0));
258 len += sprintf(buffer + len,
259 "Receive drops %s\n",
260 SkNumber(test_buf, pPnmiStruct->RxNoBufCts,
261 10,0,-1,0));
262 len += sprintf(buffer + len,
263 "Received multicast %s\n",
264 SkNumber(test_buf, pPnmiStat->StatRxMulticastOkCts,
265 10,0,-1,0));
266 len += sprintf(buffer + len,
267 "Receive error types\n");
268 len += sprintf(buffer + len,
269 " length %s\n",
270 SkNumber(test_buf, pPnmiStat->StatRxRuntCts,
271 10, 0, -1, 0));
272 len += sprintf(buffer + len,
273 " buffer overflow %s\n",
274 SkNumber(test_buf, pPnmiStat->StatRxFifoOverflowCts,
275 10, 0, -1, 0));
276 len += sprintf(buffer + len,
277 " bad crc %s\n",
278 SkNumber(test_buf, pPnmiStat->StatRxFcsCts,
279 10, 0, -1, 0));
280 len += sprintf(buffer + len,
281 " framing %s\n",
282 SkNumber(test_buf, pPnmiStat->StatRxFramingCts,
283 10, 0, -1, 0));
284 len += sprintf(buffer + len,
285 " missed frames %s\n",
286 SkNumber(test_buf, pPnmiStat->StatRxMissedCts,
287 10, 0, -1, 0));
288
289 if (pNet->Mtu > 1500)
290 pPnmiStat->StatRxTooLongCts = 0;
291
292 len += sprintf(buffer + len,
293 " too long %s\n",
294 SkNumber(test_buf, pPnmiStat->StatRxTooLongCts,
wdenk42d1f032003-10-15 23:53:47 +0000295 10, 0, -1, 0));
wdenk7152b1d2003-09-05 23:19:14 +0000296 len += sprintf(buffer + len,
297 " carrier extension %s\n",
298 SkNumber(test_buf, pPnmiStat->StatRxCextCts,
wdenk42d1f032003-10-15 23:53:47 +0000299 10, 0, -1, 0));
wdenk7152b1d2003-09-05 23:19:14 +0000300 len += sprintf(buffer + len,
301 " too short %s\n",
302 SkNumber(test_buf, pPnmiStat->StatRxShortsCts,
wdenk42d1f032003-10-15 23:53:47 +0000303 10, 0, -1, 0));
wdenk7152b1d2003-09-05 23:19:14 +0000304 len += sprintf(buffer + len,
305 " symbol %s\n",
306 SkNumber(test_buf, pPnmiStat->StatRxSymbolCts,
wdenk42d1f032003-10-15 23:53:47 +0000307 10, 0, -1, 0));
wdenk7152b1d2003-09-05 23:19:14 +0000308 len += sprintf(buffer + len,
309 " LLC MAC size %s\n",
310 SkNumber(test_buf, pPnmiStat->StatRxIRLengthCts,
wdenk42d1f032003-10-15 23:53:47 +0000311 10, 0, -1, 0));
wdenk7152b1d2003-09-05 23:19:14 +0000312 len += sprintf(buffer + len,
313 " carrier event %s\n",
314 SkNumber(test_buf, pPnmiStat->StatRxCarrierCts,
wdenk42d1f032003-10-15 23:53:47 +0000315 10, 0, -1, 0));
wdenk7152b1d2003-09-05 23:19:14 +0000316 len += sprintf(buffer + len,
317 " jabber %s\n",
318 SkNumber(test_buf, pPnmiStat->StatRxJabberCts,
wdenk42d1f032003-10-15 23:53:47 +0000319 10, 0, -1, 0));
wdenk7152b1d2003-09-05 23:19:14 +0000320
321
322 /*Transmit statistics */
wdenk42d1f032003-10-15 23:53:47 +0000323 len += sprintf(buffer + len,
wdenk7152b1d2003-09-05 23:19:14 +0000324 "\nTransmit statistics\n\n");
wdenk42d1f032003-10-15 23:53:47 +0000325
wdenk7152b1d2003-09-05 23:19:14 +0000326 len += sprintf(buffer + len,
327 "Transmited bytes %s\n",
328 SkNumber(test_buf, pPnmiStat->StatTxOctetsOkCts,
329 10,0,-1,0));
330 len += sprintf(buffer + len,
331 "Transmited packets %s\n",
332 SkNumber(test_buf, pPnmiStat->StatTxOkCts,
333 10,0,-1,0));
334 len += sprintf(buffer + len,
335 "Transmit errors %s\n",
336 SkNumber(test_buf, pPnmiStat->StatTxSingleCollisionCts,
337 10,0,-1,0));
338 len += sprintf(buffer + len,
339 "Transmit dropped %s\n",
340 SkNumber(test_buf, pPnmiStruct->TxNoBufCts,
341 10,0,-1,0));
342 len += sprintf(buffer + len,
343 "Transmit collisions %s\n",
344 SkNumber(test_buf, pPnmiStat->StatTxSingleCollisionCts,
345 10,0,-1,0));
346 len += sprintf(buffer + len,
347 "Transmit errors types\n");
348 len += sprintf(buffer + len,
349 " excessive collision %ld\n",
350 pAC->stats.tx_aborted_errors);
351 len += sprintf(buffer + len,
352 " carrier %s\n",
353 SkNumber(test_buf, pPnmiStat->StatTxCarrierCts,
354 10, 0, -1, 0));
355 len += sprintf(buffer + len,
356 " fifo underrun %s\n",
357 SkNumber(test_buf, pPnmiStat->StatTxFifoUnderrunCts,
358 10, 0, -1, 0));
359 len += sprintf(buffer + len,
360 " heartbeat %s\n",
361 SkNumber(test_buf, pPnmiStat->StatTxCarrierCts,
362 10, 0, -1, 0));
363 len += sprintf(buffer + len,
364 " window %ld\n",
365 pAC->stats.tx_window_errors);
wdenk42d1f032003-10-15 23:53:47 +0000366
wdenk7152b1d2003-09-05 23:19:14 +0000367 }
368 }
369 SkgeProcDev = next;
370 }
371 if (offset >= len) {
372 *eof = 1;
373 return 0;
374 }
375
376 *buffer_location = buffer + offset;
377 if (buffer_length >= len - offset) {
378 *eof = 1;
379 }
380 return (min_t(int, buffer_length, len - offset));
381}
382
383
wdenk7152b1d2003-09-05 23:19:14 +0000384/*****************************************************************************
385 *
386 * SkDoDiv - convert 64bit number
387 *
388 * Description:
389 * This function "converts" a long long number.
390 *
391 * Returns:
392 * remainder of division
393 */
394static long SkDoDiv (long long Dividend, int Divisor, long long *pErg)
395{
396 long Rest;
397 long long Ergebnis;
398 long Akku;
399
400
401 Akku = Dividend >> 32;
402
403 Ergebnis = ((long long) (Akku / Divisor)) << 32;
404 Rest = Akku % Divisor ;
405
406 Akku = Rest << 16;
407 Akku |= ((Dividend & 0xFFFF0000) >> 16);
408
409
410 Ergebnis += ((long long) (Akku / Divisor)) << 16;
411 Rest = Akku % Divisor ;
412
413 Akku = Rest << 16;
414 Akku |= (Dividend & 0xFFFF);
415
416 Ergebnis += (Akku / Divisor);
417 Rest = Akku % Divisor ;
418
419 *pErg = Ergebnis;
420 return (Rest);
421}
422
423
424#if 0
425#define do_div(n,base) ({ \
426long long __res; \
427__res = ((unsigned long long) n) % (unsigned) base; \
428n = ((unsigned long long) n) / (unsigned) base; \
429__res; })
430
431#endif
432
433
434/*****************************************************************************
435 *
436 * SkNumber - Print results
437 *
438 * Description:
439 * This function converts a long long number into a string.
440 *
441 * Returns:
442 * number as string
443 */
444char * SkNumber(char * str, long long num, int base, int size, int precision
445 ,int type)
446{
447 char c,sign,tmp[66], *strorg = str;
448 const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
449 int i;
450
451 if (type & LARGE)
452 digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
453 if (type & LEFT)
454 type &= ~ZEROPAD;
455 if (base < 2 || base > 36)
456 return 0;
457 c = (type & ZEROPAD) ? '0' : ' ';
458 sign = 0;
459 if (type & SIGN) {
460 if (num < 0) {
461 sign = '-';
462 num = -num;
463 size--;
464 } else if (type & PLUS) {
465 sign = '+';
466 size--;
467 } else if (type & SPACE) {
468 sign = ' ';
469 size--;
470 }
471 }
472 if (type & SPECIALX) {
473 if (base == 16)
474 size -= 2;
475 else if (base == 8)
476 size--;
477 }
478 i = 0;
479 if (num == 0)
480 tmp[i++]='0';
481 else while (num != 0)
482 tmp[i++] = digits[SkDoDiv(num,base, &num)];
483
484 if (i > precision)
485 precision = i;
486 size -= precision;
487 if (!(type&(ZEROPAD+LEFT)))
488 while(size-->0)
489 *str++ = ' ';
490 if (sign)
491 *str++ = sign;
492 if (type & SPECIALX) {
493 if (base==8)
494 *str++ = '0';
495 else if (base==16) {
496 *str++ = '0';
497 *str++ = digits[33];
498 }
499 }
500 if (!(type & LEFT))
501 while (size-- > 0)
502 *str++ = c;
503 while (i < precision--)
504 *str++ = '0';
505 while (i-- > 0)
506 *str++ = tmp[i];
507 while (size-- > 0)
508 *str++ = ' ';
wdenk42d1f032003-10-15 23:53:47 +0000509
wdenk7152b1d2003-09-05 23:19:14 +0000510 str[0] = '\0';
wdenk42d1f032003-10-15 23:53:47 +0000511
wdenk7152b1d2003-09-05 23:19:14 +0000512 return strorg;
513}
514
wdenk149dded2003-09-10 18:20:28 +0000515#endif /* CONFIG_SK98 */