1 /******************************************************************************
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
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.4 2003/02/25 14:16:37 mlindner
32 * Fix: Copyright statement
34 * 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
41 * Revision 1.2.2.7 2002/01/14 12:45:15 mlindner
42 * Fix: Editorial changes
44 * Revision 1.2.2.6 2001/12/06 15:26:07 mlindner
45 * Fix: Return value of proc_read
47 * Revision 1.2.2.5 2001/12/06 09:57:39 mlindner
50 * 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
56 * Revision 1.2.2.3 2001/06/25 07:26:26 mlindner
57 * Add: More error messages
59 * Revision 1.2.2.2 2001/03/15 12:50:13 mlindner
60 * fix: ProcFS owner protection
62 * Revision 1.2.2.1 2001/03/12 16:43:48 mlindner
63 * chg: 2.4 requirements for procfs
65 * Revision 1.1 2001/01/22 14:15:31 mlindner
66 * added ProcFs functionality
67 * Dual Net functionality integrated
71 ******************************************************************************/
73 #include <linux/proc_fs.h>
75 #include "h/skdrv1st.h"
76 #include "h/skdrv2nd.h"
77 #define ZEROPAD 1 /* pad with zero */
78 #define SIGN 2 /* unsigned/signed long */
79 #define PLUS 4 /* show plus */
80 #define SPACE 8 /* space if plus */
81 #define LEFT 16 /* left justified */
82 #define SPECIALX 32 /* 0x */
85 extern SK_AC *pACList;
86 extern struct net_device *SkGeRootDev;
88 extern char * SkNumber(
97 /*****************************************************************************
99 * proc_read - print "summaries" entry
102 * This function fills the proc entry with statistic data about
103 * the ethernet device.
106 * Returns: buffer with statistic data
109 int proc_read(char *buffer,
110 char **buffer_location,
125 struct SK_NET_DEVICE *next;
126 struct SK_NET_DEVICE *SkgeProcDev = SkGeRootDev;
128 SK_PNMI_STRUCT_DATA *pPnmiStruct;
129 SK_PNMI_STAT *pPnmiStat;
130 struct proc_dir_entry *file = (struct proc_dir_entry*) data;
132 while (SkgeProcDev) {
133 pNet = (DEV_NET*) SkgeProcDev->priv;
136 pPnmiStruct = &pAC->PnmiStruct;
137 /* NetIndex in GetStruct is now required, zero is only dummy */
139 for (t=pAC->GIni.GIMacsFound; t > 0; t--) {
140 if ((pAC->GIni.GIMacsFound == 2) && pAC->RlmtNets == 1)
143 spin_lock_irqsave(&pAC->SlowPathLock, Flags);
144 Size = SK_PNMI_STRUCT_SIZE;
145 SkPnmiGetStruct(pAC, pAC->IoBase,
146 pPnmiStruct, &Size, t-1);
147 spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
149 if (strcmp(pAC->dev[t-1]->name, file->name) == 0) {
150 pPnmiStat = &pPnmiStruct->Stat[0];
151 len = sprintf(buffer,
152 "\nDetailed statistic for device %s\n",
153 pAC->dev[t-1]->name);
154 len += sprintf(buffer + len,
155 "=======================================\n");
157 /* Board statistics */
158 len += sprintf(buffer + len,
159 "\nBoard statistics\n\n");
160 len += sprintf(buffer + len,
162 'A' + pAC->Rlmt.Net[t-1].Port[pAC->Rlmt.
163 Net[t-1].PrefPort]->PortNumber);
164 len += sprintf(buffer + len,
165 "Preferred Port %c\n",
166 'A' + pAC->Rlmt.Net[t-1].Port[pAC->Rlmt.
167 Net[t-1].PrefPort]->PortNumber);
169 len += sprintf(buffer + len,
170 "Bus speed (MHz) %d\n",
171 pPnmiStruct->BusSpeed);
173 len += sprintf(buffer + len,
174 "Bus width (Bit) %d\n",
175 pPnmiStruct->BusWidth);
176 len += sprintf(buffer + len,
177 "Hardware revision v%d.%d\n",
178 (pAC->GIni.GIPciHwRev >> 4) & 0x0F,
179 pAC->GIni.GIPciHwRev & 0x0F);
181 /* Print sensor informations */
182 for (i=0; i < pAC->I2c.MaxSens; i ++) {
184 switch (pAC->I2c.SenTable[i].SenType) {
186 strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc);
187 strcat(sens_msg, " (C)");
188 len += sprintf(buffer + len,
191 pAC->I2c.SenTable[i].SenValue / 10,
192 pAC->I2c.SenTable[i].SenValue % 10);
194 strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc);
195 strcat(sens_msg, " (F)");
196 len += sprintf(buffer + len,
199 ((((pAC->I2c.SenTable[i].SenValue)
200 *10)*9)/5 + 3200)/100,
201 ((((pAC->I2c.SenTable[i].SenValue)
202 *10)*9)/5 + 3200) % 10);
205 strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc);
206 strcat(sens_msg, " (V)");
207 len += sprintf(buffer + len,
210 pAC->I2c.SenTable[i].SenValue / 1000,
211 pAC->I2c.SenTable[i].SenValue % 1000);
214 strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc);
215 strcat(sens_msg, " (rpm)");
216 len += sprintf(buffer + len,
219 pAC->I2c.SenTable[i].SenValue);
226 /*Receive statistics */
227 len += sprintf(buffer + len,
228 "\nReceive statistics\n\n");
230 len += sprintf(buffer + len,
231 "Received bytes %s\n",
232 SkNumber(test_buf, pPnmiStat->StatRxOctetsOkCts,
234 len += sprintf(buffer + len,
235 "Received packets %s\n",
236 SkNumber(test_buf, pPnmiStat->StatRxOkCts,
239 if (pAC->GIni.GP[0].PhyType == SK_PHY_XMAC &&
240 pAC->HWRevision < 12) {
241 pPnmiStruct->InErrorsCts = pPnmiStruct->InErrorsCts -
242 pPnmiStat->StatRxShortsCts;
243 pPnmiStat->StatRxShortsCts = 0;
246 if (pNet->Mtu > 1500)
247 pPnmiStruct->InErrorsCts = pPnmiStruct->InErrorsCts -
248 pPnmiStat->StatRxTooLongCts;
250 len += sprintf(buffer + len,
251 "Receive errors %s\n",
252 SkNumber(test_buf, pPnmiStruct->InErrorsCts,
254 len += sprintf(buffer + len,
255 "Receive drops %s\n",
256 SkNumber(test_buf, pPnmiStruct->RxNoBufCts,
258 len += sprintf(buffer + len,
259 "Received multicast %s\n",
260 SkNumber(test_buf, pPnmiStat->StatRxMulticastOkCts,
262 len += sprintf(buffer + len,
263 "Receive error types\n");
264 len += sprintf(buffer + len,
266 SkNumber(test_buf, pPnmiStat->StatRxRuntCts,
268 len += sprintf(buffer + len,
269 " buffer overflow %s\n",
270 SkNumber(test_buf, pPnmiStat->StatRxFifoOverflowCts,
272 len += sprintf(buffer + len,
274 SkNumber(test_buf, pPnmiStat->StatRxFcsCts,
276 len += sprintf(buffer + len,
278 SkNumber(test_buf, pPnmiStat->StatRxFramingCts,
280 len += sprintf(buffer + len,
281 " missed frames %s\n",
282 SkNumber(test_buf, pPnmiStat->StatRxMissedCts,
285 if (pNet->Mtu > 1500)
286 pPnmiStat->StatRxTooLongCts = 0;
288 len += sprintf(buffer + len,
290 SkNumber(test_buf, pPnmiStat->StatRxTooLongCts,
292 len += sprintf(buffer + len,
293 " carrier extension %s\n",
294 SkNumber(test_buf, pPnmiStat->StatRxCextCts,
296 len += sprintf(buffer + len,
298 SkNumber(test_buf, pPnmiStat->StatRxShortsCts,
300 len += sprintf(buffer + len,
302 SkNumber(test_buf, pPnmiStat->StatRxSymbolCts,
304 len += sprintf(buffer + len,
305 " LLC MAC size %s\n",
306 SkNumber(test_buf, pPnmiStat->StatRxIRLengthCts,
308 len += sprintf(buffer + len,
309 " carrier event %s\n",
310 SkNumber(test_buf, pPnmiStat->StatRxCarrierCts,
312 len += sprintf(buffer + len,
314 SkNumber(test_buf, pPnmiStat->StatRxJabberCts,
318 /*Transmit statistics */
319 len += sprintf(buffer + len,
320 "\nTransmit statistics\n\n");
322 len += sprintf(buffer + len,
323 "Transmited bytes %s\n",
324 SkNumber(test_buf, pPnmiStat->StatTxOctetsOkCts,
326 len += sprintf(buffer + len,
327 "Transmited packets %s\n",
328 SkNumber(test_buf, pPnmiStat->StatTxOkCts,
330 len += sprintf(buffer + len,
331 "Transmit errors %s\n",
332 SkNumber(test_buf, pPnmiStat->StatTxSingleCollisionCts,
334 len += sprintf(buffer + len,
335 "Transmit dropped %s\n",
336 SkNumber(test_buf, pPnmiStruct->TxNoBufCts,
338 len += sprintf(buffer + len,
339 "Transmit collisions %s\n",
340 SkNumber(test_buf, pPnmiStat->StatTxSingleCollisionCts,
342 len += sprintf(buffer + len,
343 "Transmit errors types\n");
344 len += sprintf(buffer + len,
345 " excessive collision %ld\n",
346 pAC->stats.tx_aborted_errors);
347 len += sprintf(buffer + len,
349 SkNumber(test_buf, pPnmiStat->StatTxCarrierCts,
351 len += sprintf(buffer + len,
352 " fifo underrun %s\n",
353 SkNumber(test_buf, pPnmiStat->StatTxFifoUnderrunCts,
355 len += sprintf(buffer + len,
357 SkNumber(test_buf, pPnmiStat->StatTxCarrierCts,
359 len += sprintf(buffer + len,
361 pAC->stats.tx_window_errors);
372 *buffer_location = buffer + offset;
373 if (buffer_length >= len - offset) {
376 return (min_t(int, buffer_length, len - offset));
383 /*****************************************************************************
385 * SkDoDiv - convert 64bit number
388 * This function "converts" a long long number.
391 * remainder of division
393 static long SkDoDiv (long long Dividend, int Divisor, long long *pErg)
400 Akku = Dividend >> 32;
402 Ergebnis = ((long long) (Akku / Divisor)) << 32;
403 Rest = Akku % Divisor ;
406 Akku |= ((Dividend & 0xFFFF0000) >> 16);
409 Ergebnis += ((long long) (Akku / Divisor)) << 16;
410 Rest = Akku % Divisor ;
413 Akku |= (Dividend & 0xFFFF);
415 Ergebnis += (Akku / Divisor);
416 Rest = Akku % Divisor ;
424 #define do_div(n,base) ({ \
426 __res = ((unsigned long long) n) % (unsigned) base; \
427 n = ((unsigned long long) n) / (unsigned) base; \
433 /*****************************************************************************
435 * SkNumber - Print results
438 * This function converts a long long number into a string.
443 char * SkNumber(char * str, long long num, int base, int size, int precision
446 char c,sign,tmp[66], *strorg = str;
447 const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
451 digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
454 if (base < 2 || base > 36)
456 c = (type & ZEROPAD) ? '0' : ' ';
463 } else if (type & PLUS) {
466 } else if (type & SPACE) {
471 if (type & SPECIALX) {
480 else while (num != 0)
481 tmp[i++] = digits[SkDoDiv(num,base, &num)];
486 if (!(type&(ZEROPAD+LEFT)))
491 if (type & SPECIALX) {
502 while (i < precision--)