blob: 94a6a564ac79c66785c1167a4cce28eeb3819f3a [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
75#ifdef CONFIG_SK98
76
wdenkeb20ad32003-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
Wolfgang Denka1be4762008-05-20 16:00:29 +020089extern SK_AC *pACList;
90extern struct net_device *SkGeRootDev;
wdenkeb20ad32003-09-05 23:19:14 +000091
Wolfgang Denka1be4762008-05-20 16:00:29 +020092extern char *SkNumber (char *str,
93 long long num,
94 int base,
95 int size,
96 int precision,
97 int type);
wdenkeb20ad32003-09-05 23:19:14 +000098
99
100/*****************************************************************************
101 *
Wolfgang Denka1be4762008-05-20 16:00:29 +0200102 * proc_read - print "summaries" entry
wdenkeb20ad32003-09-05 23:19:14 +0000103 *
104 * Description:
wdenk9c53f402003-10-15 23:53:47 +0000105 * This function fills the proc entry with statistic data about
wdenkeb20ad32003-09-05 23:19:14 +0000106 * the ethernet device.
wdenk9c53f402003-10-15 23:53:47 +0000107 *
wdenkeb20ad32003-09-05 23:19:14 +0000108 *
109 * Returns: buffer with statistic data
wdenk9c53f402003-10-15 23:53:47 +0000110 *
wdenkeb20ad32003-09-05 23:19:14 +0000111 */
112int proc_read(char *buffer,
113char **buffer_location,
114off_t offset,
115int buffer_length,
116int *eof,
117void *data)
118{
119 int len = 0;
120 int t;
121 int i;
Wolfgang Denka1be4762008-05-20 16:00:29 +0200122 DEV_NET *pNet;
123 SK_AC *pAC;
124 char test_buf[100];
125 char sens_msg[50];
126 unsigned long Flags;
127 unsigned int Size;
128 struct SK_NET_DEVICE *next;
129 struct SK_NET_DEVICE *SkgeProcDev = SkGeRootDev;
wdenkeb20ad32003-09-05 23:19:14 +0000130
Wolfgang Denka1be4762008-05-20 16:00:29 +0200131 SK_PNMI_STRUCT_DATA *pPnmiStruct;
wdenkeb20ad32003-09-05 23:19:14 +0000132 SK_PNMI_STAT *pPnmiStat;
133 struct proc_dir_entry *file = (struct proc_dir_entry*) data;
134
135 while (SkgeProcDev) {
136 pNet = (DEV_NET*) SkgeProcDev->priv;
137 pAC = pNet->pAC;
138 next = pAC->Next;
139 pPnmiStruct = &pAC->PnmiStruct;
140 /* NetIndex in GetStruct is now required, zero is only dummy */
141
142 for (t=pAC->GIni.GIMacsFound; t > 0; t--) {
143 if ((pAC->GIni.GIMacsFound == 2) && pAC->RlmtNets == 1)
144 t--;
145
146 spin_lock_irqsave(&pAC->SlowPathLock, Flags);
147 Size = SK_PNMI_STRUCT_SIZE;
wdenk9c53f402003-10-15 23:53:47 +0000148 SkPnmiGetStruct(pAC, pAC->IoBase,
wdenkeb20ad32003-09-05 23:19:14 +0000149 pPnmiStruct, &Size, t-1);
150 spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
wdenk9c53f402003-10-15 23:53:47 +0000151
wdenkeb20ad32003-09-05 23:19:14 +0000152 if (strcmp(pAC->dev[t-1]->name, file->name) == 0) {
153 pPnmiStat = &pPnmiStruct->Stat[0];
wdenk9c53f402003-10-15 23:53:47 +0000154 len = sprintf(buffer,
wdenkeb20ad32003-09-05 23:19:14 +0000155 "\nDetailed statistic for device %s\n",
156 pAC->dev[t-1]->name);
157 len += sprintf(buffer + len,
158 "=======================================\n");
wdenk9c53f402003-10-15 23:53:47 +0000159
wdenkeb20ad32003-09-05 23:19:14 +0000160 /* Board statistics */
wdenk9c53f402003-10-15 23:53:47 +0000161 len += sprintf(buffer + len,
wdenkeb20ad32003-09-05 23:19:14 +0000162 "\nBoard statistics\n\n");
163 len += sprintf(buffer + len,
164 "Active Port %c\n",
165 'A' + pAC->Rlmt.Net[t-1].Port[pAC->Rlmt.
166 Net[t-1].PrefPort]->PortNumber);
167 len += sprintf(buffer + len,
168 "Preferred Port %c\n",
169 'A' + pAC->Rlmt.Net[t-1].Port[pAC->Rlmt.
170 Net[t-1].PrefPort]->PortNumber);
171
172 len += sprintf(buffer + len,
173 "Bus speed (MHz) %d\n",
174 pPnmiStruct->BusSpeed);
175
176 len += sprintf(buffer + len,
177 "Bus width (Bit) %d\n",
178 pPnmiStruct->BusWidth);
179 len += sprintf(buffer + len,
180 "Hardware revision v%d.%d\n",
181 (pAC->GIni.GIPciHwRev >> 4) & 0x0F,
182 pAC->GIni.GIPciHwRev & 0x0F);
183
184 /* Print sensor informations */
185 for (i=0; i < pAC->I2c.MaxSens; i ++) {
186 /* Check type */
187 switch (pAC->I2c.SenTable[i].SenType) {
188 case 1:
189 strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc);
190 strcat(sens_msg, " (C)");
191 len += sprintf(buffer + len,
192 "%-25s %d.%02d\n",
193 sens_msg,
194 pAC->I2c.SenTable[i].SenValue / 10,
195 pAC->I2c.SenTable[i].SenValue % 10);
196
197 strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc);
198 strcat(sens_msg, " (F)");
199 len += sprintf(buffer + len,
200 "%-25s %d.%02d\n",
201 sens_msg,
202 ((((pAC->I2c.SenTable[i].SenValue)
203 *10)*9)/5 + 3200)/100,
204 ((((pAC->I2c.SenTable[i].SenValue)
205 *10)*9)/5 + 3200) % 10);
206 break;
207 case 2:
208 strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc);
209 strcat(sens_msg, " (V)");
210 len += sprintf(buffer + len,
211 "%-25s %d.%03d\n",
212 sens_msg,
213 pAC->I2c.SenTable[i].SenValue / 1000,
214 pAC->I2c.SenTable[i].SenValue % 1000);
215 break;
216 case 3:
217 strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc);
218 strcat(sens_msg, " (rpm)");
219 len += sprintf(buffer + len,
220 "%-25s %d\n",
221 sens_msg,
222 pAC->I2c.SenTable[i].SenValue);
223 break;
224 default:
225 break;
226 }
227 }
wdenk9c53f402003-10-15 23:53:47 +0000228
wdenkeb20ad32003-09-05 23:19:14 +0000229 /*Receive statistics */
wdenk9c53f402003-10-15 23:53:47 +0000230 len += sprintf(buffer + len,
wdenkeb20ad32003-09-05 23:19:14 +0000231 "\nReceive statistics\n\n");
232
233 len += sprintf(buffer + len,
234 "Received bytes %s\n",
235 SkNumber(test_buf, pPnmiStat->StatRxOctetsOkCts,
236 10,0,-1,0));
237 len += sprintf(buffer + len,
238 "Received packets %s\n",
239 SkNumber(test_buf, pPnmiStat->StatRxOkCts,
240 10,0,-1,0));
241#if 0
wdenk9c53f402003-10-15 23:53:47 +0000242 if (pAC->GIni.GP[0].PhyType == SK_PHY_XMAC &&
wdenkeb20ad32003-09-05 23:19:14 +0000243 pAC->HWRevision < 12) {
wdenk9c53f402003-10-15 23:53:47 +0000244 pPnmiStruct->InErrorsCts = pPnmiStruct->InErrorsCts -
wdenkeb20ad32003-09-05 23:19:14 +0000245 pPnmiStat->StatRxShortsCts;
246 pPnmiStat->StatRxShortsCts = 0;
247 }
248#endif
wdenk9c53f402003-10-15 23:53:47 +0000249 if (pNet->Mtu > 1500)
wdenkeb20ad32003-09-05 23:19:14 +0000250 pPnmiStruct->InErrorsCts = pPnmiStruct->InErrorsCts -
251 pPnmiStat->StatRxTooLongCts;
252
253 len += sprintf(buffer + len,
254 "Receive errors %s\n",
255 SkNumber(test_buf, pPnmiStruct->InErrorsCts,
256 10,0,-1,0));
257 len += sprintf(buffer + len,
258 "Receive drops %s\n",
259 SkNumber(test_buf, pPnmiStruct->RxNoBufCts,
260 10,0,-1,0));
261 len += sprintf(buffer + len,
262 "Received multicast %s\n",
263 SkNumber(test_buf, pPnmiStat->StatRxMulticastOkCts,
264 10,0,-1,0));
265 len += sprintf(buffer + len,
266 "Receive error types\n");
267 len += sprintf(buffer + len,
268 " length %s\n",
269 SkNumber(test_buf, pPnmiStat->StatRxRuntCts,
270 10, 0, -1, 0));
271 len += sprintf(buffer + len,
272 " buffer overflow %s\n",
273 SkNumber(test_buf, pPnmiStat->StatRxFifoOverflowCts,
274 10, 0, -1, 0));
275 len += sprintf(buffer + len,
276 " bad crc %s\n",
277 SkNumber(test_buf, pPnmiStat->StatRxFcsCts,
278 10, 0, -1, 0));
279 len += sprintf(buffer + len,
280 " framing %s\n",
281 SkNumber(test_buf, pPnmiStat->StatRxFramingCts,
282 10, 0, -1, 0));
283 len += sprintf(buffer + len,
284 " missed frames %s\n",
285 SkNumber(test_buf, pPnmiStat->StatRxMissedCts,
286 10, 0, -1, 0));
287
288 if (pNet->Mtu > 1500)
289 pPnmiStat->StatRxTooLongCts = 0;
290
291 len += sprintf(buffer + len,
292 " too long %s\n",
293 SkNumber(test_buf, pPnmiStat->StatRxTooLongCts,
wdenk9c53f402003-10-15 23:53:47 +0000294 10, 0, -1, 0));
wdenkeb20ad32003-09-05 23:19:14 +0000295 len += sprintf(buffer + len,
296 " carrier extension %s\n",
297 SkNumber(test_buf, pPnmiStat->StatRxCextCts,
wdenk9c53f402003-10-15 23:53:47 +0000298 10, 0, -1, 0));
wdenkeb20ad32003-09-05 23:19:14 +0000299 len += sprintf(buffer + len,
300 " too short %s\n",
301 SkNumber(test_buf, pPnmiStat->StatRxShortsCts,
wdenk9c53f402003-10-15 23:53:47 +0000302 10, 0, -1, 0));
wdenkeb20ad32003-09-05 23:19:14 +0000303 len += sprintf(buffer + len,
304 " symbol %s\n",
305 SkNumber(test_buf, pPnmiStat->StatRxSymbolCts,
wdenk9c53f402003-10-15 23:53:47 +0000306 10, 0, -1, 0));
wdenkeb20ad32003-09-05 23:19:14 +0000307 len += sprintf(buffer + len,
308 " LLC MAC size %s\n",
309 SkNumber(test_buf, pPnmiStat->StatRxIRLengthCts,
wdenk9c53f402003-10-15 23:53:47 +0000310 10, 0, -1, 0));
wdenkeb20ad32003-09-05 23:19:14 +0000311 len += sprintf(buffer + len,
312 " carrier event %s\n",
313 SkNumber(test_buf, pPnmiStat->StatRxCarrierCts,
wdenk9c53f402003-10-15 23:53:47 +0000314 10, 0, -1, 0));
wdenkeb20ad32003-09-05 23:19:14 +0000315 len += sprintf(buffer + len,
316 " jabber %s\n",
317 SkNumber(test_buf, pPnmiStat->StatRxJabberCts,
wdenk9c53f402003-10-15 23:53:47 +0000318 10, 0, -1, 0));
wdenkeb20ad32003-09-05 23:19:14 +0000319
320
321 /*Transmit statistics */
wdenk9c53f402003-10-15 23:53:47 +0000322 len += sprintf(buffer + len,
wdenkeb20ad32003-09-05 23:19:14 +0000323 "\nTransmit statistics\n\n");
wdenk9c53f402003-10-15 23:53:47 +0000324
wdenkeb20ad32003-09-05 23:19:14 +0000325 len += sprintf(buffer + len,
326 "Transmited bytes %s\n",
327 SkNumber(test_buf, pPnmiStat->StatTxOctetsOkCts,
328 10,0,-1,0));
329 len += sprintf(buffer + len,
330 "Transmited packets %s\n",
331 SkNumber(test_buf, pPnmiStat->StatTxOkCts,
332 10,0,-1,0));
333 len += sprintf(buffer + len,
334 "Transmit errors %s\n",
335 SkNumber(test_buf, pPnmiStat->StatTxSingleCollisionCts,
336 10,0,-1,0));
337 len += sprintf(buffer + len,
338 "Transmit dropped %s\n",
339 SkNumber(test_buf, pPnmiStruct->TxNoBufCts,
340 10,0,-1,0));
341 len += sprintf(buffer + len,
342 "Transmit collisions %s\n",
343 SkNumber(test_buf, pPnmiStat->StatTxSingleCollisionCts,
344 10,0,-1,0));
345 len += sprintf(buffer + len,
346 "Transmit errors types\n");
347 len += sprintf(buffer + len,
348 " excessive collision %ld\n",
349 pAC->stats.tx_aborted_errors);
350 len += sprintf(buffer + len,
351 " carrier %s\n",
352 SkNumber(test_buf, pPnmiStat->StatTxCarrierCts,
353 10, 0, -1, 0));
354 len += sprintf(buffer + len,
355 " fifo underrun %s\n",
356 SkNumber(test_buf, pPnmiStat->StatTxFifoUnderrunCts,
357 10, 0, -1, 0));
358 len += sprintf(buffer + len,
359 " heartbeat %s\n",
360 SkNumber(test_buf, pPnmiStat->StatTxCarrierCts,
361 10, 0, -1, 0));
362 len += sprintf(buffer + len,
363 " window %ld\n",
364 pAC->stats.tx_window_errors);
wdenk9c53f402003-10-15 23:53:47 +0000365
wdenkeb20ad32003-09-05 23:19:14 +0000366 }
367 }
368 SkgeProcDev = next;
369 }
370 if (offset >= len) {
371 *eof = 1;
372 return 0;
373 }
374
375 *buffer_location = buffer + offset;
376 if (buffer_length >= len - offset) {
377 *eof = 1;
378 }
379 return (min_t(int, buffer_length, len - offset));
380}
381
382
wdenkeb20ad32003-09-05 23:19:14 +0000383/*****************************************************************************
384 *
385 * SkDoDiv - convert 64bit number
386 *
387 * Description:
388 * This function "converts" a long long number.
389 *
390 * Returns:
391 * remainder of division
392 */
393static long SkDoDiv (long long Dividend, int Divisor, long long *pErg)
394{
Wolfgang Denka1be4762008-05-20 16:00:29 +0200395 long Rest;
396 long long Ergebnis;
397 long Akku;
wdenkeb20ad32003-09-05 23:19:14 +0000398
399
Wolfgang Denka1be4762008-05-20 16:00:29 +0200400 Akku = Dividend >> 32;
wdenkeb20ad32003-09-05 23:19:14 +0000401
Wolfgang Denka1be4762008-05-20 16:00:29 +0200402 Ergebnis = ((long long) (Akku / Divisor)) << 32;
403 Rest = Akku % Divisor;
wdenkeb20ad32003-09-05 23:19:14 +0000404
Wolfgang Denka1be4762008-05-20 16:00:29 +0200405 Akku = Rest << 16;
406 Akku |= ((Dividend & 0xFFFF0000) >> 16);
wdenkeb20ad32003-09-05 23:19:14 +0000407
408
Wolfgang Denka1be4762008-05-20 16:00:29 +0200409 Ergebnis += ((long long) (Akku / Divisor)) << 16;
410 Rest = Akku % Divisor;
wdenkeb20ad32003-09-05 23:19:14 +0000411
Wolfgang Denka1be4762008-05-20 16:00:29 +0200412 Akku = Rest << 16;
413 Akku |= (Dividend & 0xFFFF);
wdenkeb20ad32003-09-05 23:19:14 +0000414
Wolfgang Denka1be4762008-05-20 16:00:29 +0200415 Ergebnis += (Akku / Divisor);
416 Rest = Akku % Divisor;
wdenkeb20ad32003-09-05 23:19:14 +0000417
Wolfgang Denka1be4762008-05-20 16:00:29 +0200418 *pErg = Ergebnis;
419 return (Rest);
wdenkeb20ad32003-09-05 23:19:14 +0000420}
421
422
423#if 0
424#define do_div(n,base) ({ \
425long long __res; \
426__res = ((unsigned long long) n) % (unsigned) base; \
427n = ((unsigned long long) n) / (unsigned) base; \
428__res; })
429
430#endif
431
432
433/*****************************************************************************
434 *
435 * SkNumber - Print results
436 *
437 * Description:
438 * This function converts a long long number into a string.
439 *
440 * Returns:
441 * number as string
442 */
443char * SkNumber(char * str, long long num, int base, int size, int precision
444 ,int type)
445{
446 char c,sign,tmp[66], *strorg = str;
447 const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
448 int i;
449
450 if (type & LARGE)
451 digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
452 if (type & LEFT)
453 type &= ~ZEROPAD;
454 if (base < 2 || base > 36)
455 return 0;
456 c = (type & ZEROPAD) ? '0' : ' ';
457 sign = 0;
458 if (type & SIGN) {
459 if (num < 0) {
460 sign = '-';
461 num = -num;
462 size--;
463 } else if (type & PLUS) {
464 sign = '+';
465 size--;
466 } else if (type & SPACE) {
467 sign = ' ';
468 size--;
469 }
470 }
471 if (type & SPECIALX) {
472 if (base == 16)
473 size -= 2;
474 else if (base == 8)
475 size--;
476 }
477 i = 0;
478 if (num == 0)
479 tmp[i++]='0';
480 else while (num != 0)
481 tmp[i++] = digits[SkDoDiv(num,base, &num)];
482
483 if (i > precision)
484 precision = i;
485 size -= precision;
486 if (!(type&(ZEROPAD+LEFT)))
487 while(size-->0)
488 *str++ = ' ';
489 if (sign)
490 *str++ = sign;
491 if (type & SPECIALX) {
492 if (base==8)
493 *str++ = '0';
494 else if (base==16) {
495 *str++ = '0';
496 *str++ = digits[33];
497 }
498 }
499 if (!(type & LEFT))
500 while (size-- > 0)
501 *str++ = c;
502 while (i < precision--)
503 *str++ = '0';
504 while (i-- > 0)
505 *str++ = tmp[i];
506 while (size-- > 0)
507 *str++ = ' ';
wdenk9c53f402003-10-15 23:53:47 +0000508
wdenkeb20ad32003-09-05 23:19:14 +0000509 str[0] = '\0';
wdenk9c53f402003-10-15 23:53:47 +0000510
wdenkeb20ad32003-09-05 23:19:14 +0000511 return strorg;
512}
513
wdenkde887eb2003-09-10 18:20:28 +0000514#endif /* CONFIG_SK98 */