1 /******************************************************************************
4 * Project: GEnesis, PCI Gigabit Ethernet Adapter
7 * Purpose: Funktions to display statictic data
9 ******************************************************************************/
11 /******************************************************************************
13 * (C)Copyright 1998-2003 SysKonnect GmbH.
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.
21 * Author: Mirko Lindner (mlindner@syskonnect.de)
23 * The information in this file is provided "AS IS" without warranty.
25 ******************************************************************************/
26 /******************************************************************************
31 * Revision 1.1.1.1 2007-03-09 09:43:58 lothar
32 * imported U-Boot 1.1.6
34 * Revision 1.4 2003/02/25 14:16:37 mlindner
35 * Fix: Copyright statement
37 * Revision 1.3 2002/10/02 12:59:51 mlindner
38 * Add: Support for Yukon
39 * Add: Speed check and setup
40 * Add: Merge source for kernel 2.2.x and 2.4.x
41 * Add: Read sensor names directly from VPD
44 * Revision 1.2.2.7 2002/01/14 12:45:15 mlindner
45 * Fix: Editorial changes
47 * Revision 1.2.2.6 2001/12/06 15:26:07 mlindner
48 * Fix: Return value of proc_read
50 * Revision 1.2.2.5 2001/12/06 09:57:39 mlindner
53 * Revision 1.2.2.4 2001/09/05 12:16:02 mlindner
54 * Add: New ProcFs entries
55 * Fix: Counter Errors (Jumbo == to long errors)
56 * Fix: Kernel error compilation
57 * Fix: too short counters
59 * Revision 1.2.2.3 2001/06/25 07:26:26 mlindner
60 * Add: More error messages
62 * Revision 1.2.2.2 2001/03/15 12:50:13 mlindner
63 * fix: ProcFS owner protection
65 * Revision 1.2.2.1 2001/03/12 16:43:48 mlindner
66 * chg: 2.4 requirements for procfs
68 * Revision 1.1 2001/01/22 14:15:31 mlindner
69 * added ProcFs functionality
70 * Dual Net functionality integrated
74 ******************************************************************************/
80 #include <linux/proc_fs.h>
82 #include "h/skdrv1st.h"
83 #include "h/skdrv2nd.h"
84 #define ZEROPAD 1 /* pad with zero */
85 #define SIGN 2 /* unsigned/signed long */
86 #define PLUS 4 /* show plus */
87 #define SPACE 8 /* space if plus */
88 #define LEFT 16 /* left justified */
89 #define SPECIALX 32 /* 0x */
92 extern SK_AC *pACList;
93 extern struct net_device *SkGeRootDev;
95 extern char * SkNumber(
104 /*****************************************************************************
106 * proc_read - print "summaries" entry
109 * This function fills the proc entry with statistic data about
110 * the ethernet device.
113 * Returns: buffer with statistic data
116 int proc_read(char *buffer,
117 char **buffer_location,
132 struct SK_NET_DEVICE *next;
133 struct SK_NET_DEVICE *SkgeProcDev = SkGeRootDev;
135 SK_PNMI_STRUCT_DATA *pPnmiStruct;
136 SK_PNMI_STAT *pPnmiStat;
137 struct proc_dir_entry *file = (struct proc_dir_entry*) data;
139 while (SkgeProcDev) {
140 pNet = (DEV_NET*) SkgeProcDev->priv;
143 pPnmiStruct = &pAC->PnmiStruct;
144 /* NetIndex in GetStruct is now required, zero is only dummy */
146 for (t=pAC->GIni.GIMacsFound; t > 0; t--) {
147 if ((pAC->GIni.GIMacsFound == 2) && pAC->RlmtNets == 1)
150 spin_lock_irqsave(&pAC->SlowPathLock, Flags);
151 Size = SK_PNMI_STRUCT_SIZE;
152 SkPnmiGetStruct(pAC, pAC->IoBase,
153 pPnmiStruct, &Size, t-1);
154 spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
156 if (strcmp(pAC->dev[t-1]->name, file->name) == 0) {
157 pPnmiStat = &pPnmiStruct->Stat[0];
158 len = sprintf(buffer,
159 "\nDetailed statistic for device %s\n",
160 pAC->dev[t-1]->name);
161 len += sprintf(buffer + len,
162 "=======================================\n");
164 /* Board statistics */
165 len += sprintf(buffer + len,
166 "\nBoard statistics\n\n");
167 len += sprintf(buffer + len,
169 'A' + pAC->Rlmt.Net[t-1].Port[pAC->Rlmt.
170 Net[t-1].PrefPort]->PortNumber);
171 len += sprintf(buffer + len,
172 "Preferred Port %c\n",
173 'A' + pAC->Rlmt.Net[t-1].Port[pAC->Rlmt.
174 Net[t-1].PrefPort]->PortNumber);
176 len += sprintf(buffer + len,
177 "Bus speed (MHz) %d\n",
178 pPnmiStruct->BusSpeed);
180 len += sprintf(buffer + len,
181 "Bus width (Bit) %d\n",
182 pPnmiStruct->BusWidth);
183 len += sprintf(buffer + len,
184 "Hardware revision v%d.%d\n",
185 (pAC->GIni.GIPciHwRev >> 4) & 0x0F,
186 pAC->GIni.GIPciHwRev & 0x0F);
188 /* Print sensor informations */
189 for (i=0; i < pAC->I2c.MaxSens; i ++) {
191 switch (pAC->I2c.SenTable[i].SenType) {
193 strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc);
194 strcat(sens_msg, " (C)");
195 len += sprintf(buffer + len,
198 pAC->I2c.SenTable[i].SenValue / 10,
199 pAC->I2c.SenTable[i].SenValue % 10);
201 strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc);
202 strcat(sens_msg, " (F)");
203 len += sprintf(buffer + len,
206 ((((pAC->I2c.SenTable[i].SenValue)
207 *10)*9)/5 + 3200)/100,
208 ((((pAC->I2c.SenTable[i].SenValue)
209 *10)*9)/5 + 3200) % 10);
212 strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc);
213 strcat(sens_msg, " (V)");
214 len += sprintf(buffer + len,
217 pAC->I2c.SenTable[i].SenValue / 1000,
218 pAC->I2c.SenTable[i].SenValue % 1000);
221 strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc);
222 strcat(sens_msg, " (rpm)");
223 len += sprintf(buffer + len,
226 pAC->I2c.SenTable[i].SenValue);
233 /*Receive statistics */
234 len += sprintf(buffer + len,
235 "\nReceive statistics\n\n");
237 len += sprintf(buffer + len,
238 "Received bytes %s\n",
239 SkNumber(test_buf, pPnmiStat->StatRxOctetsOkCts,
241 len += sprintf(buffer + len,
242 "Received packets %s\n",
243 SkNumber(test_buf, pPnmiStat->StatRxOkCts,
246 if (pAC->GIni.GP[0].PhyType == SK_PHY_XMAC &&
247 pAC->HWRevision < 12) {
248 pPnmiStruct->InErrorsCts = pPnmiStruct->InErrorsCts -
249 pPnmiStat->StatRxShortsCts;
250 pPnmiStat->StatRxShortsCts = 0;
253 if (pNet->Mtu > 1500)
254 pPnmiStruct->InErrorsCts = pPnmiStruct->InErrorsCts -
255 pPnmiStat->StatRxTooLongCts;
257 len += sprintf(buffer + len,
258 "Receive errors %s\n",
259 SkNumber(test_buf, pPnmiStruct->InErrorsCts,
261 len += sprintf(buffer + len,
262 "Receive drops %s\n",
263 SkNumber(test_buf, pPnmiStruct->RxNoBufCts,
265 len += sprintf(buffer + len,
266 "Received multicast %s\n",
267 SkNumber(test_buf, pPnmiStat->StatRxMulticastOkCts,
269 len += sprintf(buffer + len,
270 "Receive error types\n");
271 len += sprintf(buffer + len,
273 SkNumber(test_buf, pPnmiStat->StatRxRuntCts,
275 len += sprintf(buffer + len,
276 " buffer overflow %s\n",
277 SkNumber(test_buf, pPnmiStat->StatRxFifoOverflowCts,
279 len += sprintf(buffer + len,
281 SkNumber(test_buf, pPnmiStat->StatRxFcsCts,
283 len += sprintf(buffer + len,
285 SkNumber(test_buf, pPnmiStat->StatRxFramingCts,
287 len += sprintf(buffer + len,
288 " missed frames %s\n",
289 SkNumber(test_buf, pPnmiStat->StatRxMissedCts,
292 if (pNet->Mtu > 1500)
293 pPnmiStat->StatRxTooLongCts = 0;
295 len += sprintf(buffer + len,
297 SkNumber(test_buf, pPnmiStat->StatRxTooLongCts,
299 len += sprintf(buffer + len,
300 " carrier extension %s\n",
301 SkNumber(test_buf, pPnmiStat->StatRxCextCts,
303 len += sprintf(buffer + len,
305 SkNumber(test_buf, pPnmiStat->StatRxShortsCts,
307 len += sprintf(buffer + len,
309 SkNumber(test_buf, pPnmiStat->StatRxSymbolCts,
311 len += sprintf(buffer + len,
312 " LLC MAC size %s\n",
313 SkNumber(test_buf, pPnmiStat->StatRxIRLengthCts,
315 len += sprintf(buffer + len,
316 " carrier event %s\n",
317 SkNumber(test_buf, pPnmiStat->StatRxCarrierCts,
319 len += sprintf(buffer + len,
321 SkNumber(test_buf, pPnmiStat->StatRxJabberCts,
325 /*Transmit statistics */
326 len += sprintf(buffer + len,
327 "\nTransmit statistics\n\n");
329 len += sprintf(buffer + len,
330 "Transmited bytes %s\n",
331 SkNumber(test_buf, pPnmiStat->StatTxOctetsOkCts,
333 len += sprintf(buffer + len,
334 "Transmited packets %s\n",
335 SkNumber(test_buf, pPnmiStat->StatTxOkCts,
337 len += sprintf(buffer + len,
338 "Transmit errors %s\n",
339 SkNumber(test_buf, pPnmiStat->StatTxSingleCollisionCts,
341 len += sprintf(buffer + len,
342 "Transmit dropped %s\n",
343 SkNumber(test_buf, pPnmiStruct->TxNoBufCts,
345 len += sprintf(buffer + len,
346 "Transmit collisions %s\n",
347 SkNumber(test_buf, pPnmiStat->StatTxSingleCollisionCts,
349 len += sprintf(buffer + len,
350 "Transmit errors types\n");
351 len += sprintf(buffer + len,
352 " excessive collision %ld\n",
353 pAC->stats.tx_aborted_errors);
354 len += sprintf(buffer + len,
356 SkNumber(test_buf, pPnmiStat->StatTxCarrierCts,
358 len += sprintf(buffer + len,
359 " fifo underrun %s\n",
360 SkNumber(test_buf, pPnmiStat->StatTxFifoUnderrunCts,
362 len += sprintf(buffer + len,
364 SkNumber(test_buf, pPnmiStat->StatTxCarrierCts,
366 len += sprintf(buffer + len,
368 pAC->stats.tx_window_errors);
379 *buffer_location = buffer + offset;
380 if (buffer_length >= len - offset) {
383 return (min_t(int, buffer_length, len - offset));
387 /*****************************************************************************
389 * SkDoDiv - convert 64bit number
392 * This function "converts" a long long number.
395 * remainder of division
397 static long SkDoDiv (long long Dividend, int Divisor, long long *pErg)
404 Akku = Dividend >> 32;
406 Ergebnis = ((long long) (Akku / Divisor)) << 32;
407 Rest = Akku % Divisor ;
410 Akku |= ((Dividend & 0xFFFF0000) >> 16);
413 Ergebnis += ((long long) (Akku / Divisor)) << 16;
414 Rest = Akku % Divisor ;
417 Akku |= (Dividend & 0xFFFF);
419 Ergebnis += (Akku / Divisor);
420 Rest = Akku % Divisor ;
428 #define do_div(n,base) ({ \
430 __res = ((unsigned long long) n) % (unsigned) base; \
431 n = ((unsigned long long) n) / (unsigned) base; \
437 /*****************************************************************************
439 * SkNumber - Print results
442 * This function converts a long long number into a string.
447 char * SkNumber(char * str, long long num, int base, int size, int precision
450 char c,sign,tmp[66], *strorg = str;
451 const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
455 digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
458 if (base < 2 || base > 36)
460 c = (type & ZEROPAD) ? '0' : ' ';
467 } else if (type & PLUS) {
470 } else if (type & SPACE) {
475 if (type & SPECIALX) {
484 else while (num != 0)
485 tmp[i++] = digits[SkDoDiv(num,base, &num)];
490 if (!(type&(ZEROPAD+LEFT)))
495 if (type & SPECIALX) {
506 while (i < precision--)
518 #endif /* CONFIG_SK98 */