File: /usr/src/linux/drivers/net/sk98lin/skproc.c

1     /******************************************************************************
2      *
3      * Name:    skproc.c
4      * Project:	GEnesis, PCI Gigabit Ethernet Adapter
5      * Version:	$Revision: 1.2.2.2 $
6      * Date:    $Date: 2001/03/15 12:50:13 $
7      * Purpose:	Funktions to display statictic data
8      *
9      ******************************************************************************/
10      
11     /******************************************************************************
12      *
13      *	(C)Copyright 1998-2001 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.2.2.2  2001/03/15 12:50:13  mlindner
32      *	fix: ProcFS owner protection
33      *	
34      *	Revision 1.2.2.1  2001/03/12 16:43:48  mlindner
35      *	chg: 2.4 requirements for procfs
36      *	
37      *	Revision 1.1  2001/01/22 14:15:31  mlindner
38      *	added ProcFs functionality
39      *	Dual Net functionality integrated
40      *	Rlmt networks added
41      *	
42      *
43      ******************************************************************************/
44     
45     #include <linux/proc_fs.h>
46     
47     #include "h/skdrv1st.h"
48     #include "h/skdrv2nd.h"
49     #define ZEROPAD	1		/* pad with zero */
50     #define SIGN	2		/* unsigned/signed long */
51     #define PLUS	4		/* show plus */
52     #define SPACE	8		/* space if plus */
53     #define LEFT	16		/* left justified */
54     //#define SPECIAL	32		/* 0x */
55     #define LARGE	64
56     
57     extern void proc_fill_inode(struct inode *inode, int fill);
58     extern char * SkNumber(char * str, long long num, int base, int size, 
59     				int precision ,int type);
60     int proc_read(char *buffer,
61     				char **buffer_location,
62     				off_t offset,
63     				int buffer_length,
64     				int *eof,
65     				void *data);
66     
67     static const char SK_Root_Dir_entry[] = "sk98lin";
68     extern struct net_device *sk98lin_root_dev;
69     
70     
71     struct proc_dir_entry pSkRootDir = { 
72     	0,
73     	sizeof(SK_Root_Dir_entry)-1,
74     	(const char*)SK_Root_Dir_entry,
75     	S_IFDIR | S_IRUGO,
76     	2, 0, 0, 0, NULL,
77     	NULL
78     };
79     
80     
81     /*****************************************************************************
82      *
83      * 	proc_read - print "summaries" entry 
84      *
85      * Description:
86      *  This function fills the proc entry with statistic data about 
87      *  the ethernet device.
88      *  
89      *
90      * Returns: buffer with statistic data
91      *	
92      */
93     int proc_read(char *buffer,
94     char **buffer_location,
95     off_t offset,
96     int buffer_length,
97     int *eof,
98     void *data)
99     {
100     	int len = 0;
101     	int t;
102     	int i;
103     	DEV_NET				*pNet;
104     	SK_AC				*pAC;
105     	char 				test_buf[100];
106     	unsigned long			Flags;		
107     	unsigned int			Size;
108     	struct net_device 		*next;
109     	struct net_device 		*SkgeProcDev = sk98lin_root_dev;
110     
111     	SK_PNMI_STRUCT_DATA 	*pPnmiStruct;
112     	SK_PNMI_STAT		*pPnmiStat;
113     	struct proc_dir_entry *file = (struct proc_dir_entry*) data;
114     
115     	while (SkgeProcDev) {
116     		pNet = (DEV_NET*) SkgeProcDev->priv;
117     		pAC = pNet->pAC;
118     		next = pAC->Next;
119     		pPnmiStruct = &pAC->PnmiStruct;
120     		/* NetIndex in GetStruct is now required, zero is only dummy */
121     
122     		for (t=pAC->GIni.GIMacsFound; t > 0; t--) {
123     			if ((pAC->GIni.GIMacsFound == 2) && pAC->RlmtNets == 1)
124     				t--;
125     			
126     			spin_lock_irqsave(&pAC->SlowPathLock, Flags);
127     			Size = SK_PNMI_STRUCT_SIZE;
128     			SkPnmiGetStruct(pAC, pAC->IoBase, 
129     				pPnmiStruct, &Size, t-1);
130     			spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
131     	
132     			if (strcmp(pAC->dev[t-1]->name, file->name) == 0) {
133     				pPnmiStat = &pPnmiStruct->Stat[0];
134     				len = sprintf(buffer, 
135     					"\nDetailed statistic for device %s\n",
136     					pAC->dev[t-1]->name);
137     				len += sprintf(buffer + len,
138     					"==================================\n");
139     	
140     				/* Board statistics */
141     				len += sprintf(buffer + len, 
142     					"\nBoard statistics\n\n");
143     				len += sprintf(buffer + len,
144     					"Active Port               %c\n",
145     					'A' + pAC->Rlmt.Net[t-1].Port[pAC->Rlmt.
146     					Net[t-1].PrefPort]->PortNumber);
147     				len += sprintf(buffer + len,
148     					"Preferred Port            %c\n",
149     					'A' + pAC->Rlmt.Net[t-1].Port[pAC->Rlmt.
150     					Net[t-1].PrefPort]->PortNumber);
151     
152     				len += sprintf(buffer + len,
153     					"Bus speed (Mhz)           %d\n",
154     					pPnmiStruct->BusSpeed);
155     
156     				len += sprintf(buffer + len,
157     					"Bus width (Bit)           %d\n",
158     					pPnmiStruct->BusWidth);
159     
160     				for (i=0; i < SK_MAX_SENSORS; i ++) {
161     					if (strcmp(pAC->I2c.SenTable[i].SenDesc,
162     							"Temperature") == 0 ) {
163     						len += sprintf(buffer + len,
164     							"Temperature (C)           %d.%d\n",
165     							pAC->I2c.SenTable[i].SenValue / 10,
166     							pAC->I2c.SenTable[i].SenValue % 10);
167     						len += sprintf(buffer + len,
168     							"Temperature (F)           %d.%d\n",
169     							((((pAC->I2c.SenTable[i].SenValue)
170     							*10)*9)/5 + 3200)/100,
171     							((((pAC->I2c.SenTable[i].SenValue)
172     							*10)*9)/5 + 3200) % 10);
173     					} else if (strcmp(pAC->I2c.SenTable[i].SenDesc,
174     							"Speed Fan") == 0 ) {
175     						len += sprintf(buffer + len,
176     							"Speed Fan                 %d\n",
177     							pAC->I2c.SenTable[i].SenValue);
178     					} else {
179     						len += sprintf(buffer + len,
180     							"%-20s      %d.%d\n",
181     							pAC->I2c.SenTable[i].SenDesc,
182     							pAC->I2c.SenTable[i].SenValue / 1000,
183     							pAC->I2c.SenTable[i].SenValue % 1000);
184     					}
185     				}
186     				
187     				/*Receive statistics */
188     				
189     				len += sprintf(buffer + len, 
190     				"\nReceive statistics\n\n");
191     
192     				len += sprintf(buffer + len,
193     					"Received bytes            %s\n",
194     					SkNumber(test_buf, pPnmiStat->StatRxOctetsOkCts,
195     					10,0,-1,0));
196     				len += sprintf(buffer + len,
197     					"Received packets          %s\n",
198     					SkNumber(test_buf, pPnmiStat->StatRxOkCts,
199     					10,0,-1,0));
200     				len += sprintf(buffer + len,
201     					"Received errors           %s\n",
202     					SkNumber(test_buf, pPnmiStat->StatRxFcsCts,
203     					10,0,-1,0));
204     				len += sprintf(buffer + len,
205     					"Received dropped          %s\n",
206     					SkNumber(test_buf, pPnmiStruct->RxNoBufCts,
207     					10,0,-1,0));
208     				len += sprintf(buffer + len,
209     					"Received multicast        %s\n",
210     					SkNumber(test_buf, pPnmiStat->StatRxMulticastOkCts,
211     					10,0,-1,0));
212     				len += sprintf(buffer + len,
213     					"Received errors types\n");
214     				len += sprintf(buffer + len,
215     					"   length errors          %s\n",
216     					SkNumber(test_buf, pPnmiStat->StatRxRuntCts,
217     					10, 0, -1, 0));
218     				len += sprintf(buffer + len,
219     					"   over errors            %s\n",
220     					SkNumber(test_buf, pPnmiStat->StatRxFifoOverflowCts,
221     					10, 0, -1, 0));
222     				len += sprintf(buffer + len,
223     					"   crc errors             %s\n",
224     					SkNumber(test_buf, pPnmiStat->StatRxFcsCts,
225     					10, 0, -1, 0));
226     				len += sprintf(buffer + len,
227     					"   frame errors           %s\n",
228     					SkNumber(test_buf, pPnmiStat->StatRxFramingCts,
229     					10, 0, -1, 0));
230     				len += sprintf(buffer + len,
231     					"   fifo errors            %s\n",
232     					SkNumber(test_buf, pPnmiStat->StatRxFifoOverflowCts,
233     					10, 0, -1, 0));
234     				len += sprintf(buffer + len,
235     					"   missed errors          %s\n",
236     					SkNumber(test_buf, pPnmiStat->StatRxMissedCts,
237     					10, 0, -1, 0));
238     				
239     				/*Transmit statistics */
240     				len += sprintf(buffer + len, 
241     				"\nTransmit statistics\n\n");
242     				
243     				len += sprintf(buffer + len,
244     					"Transmit bytes            %s\n",
245     					SkNumber(test_buf, pPnmiStat->StatTxOctetsOkCts,
246     					10,0,-1,0));
247     				len += sprintf(buffer + len,
248     					"Transmit packets          %s\n",
249     					SkNumber(test_buf, pPnmiStat->StatTxOkCts,
250     					10,0,-1,0));
251     				len += sprintf(buffer + len,
252     					"Transmit errors           %s\n",
253     					SkNumber(test_buf, pPnmiStat->StatTxSingleCollisionCts,
254     					10,0,-1,0));
255     				len += sprintf(buffer + len,
256     					"Transmit dropped          %s\n",
257     					SkNumber(test_buf, pPnmiStruct->TxNoBufCts,
258     					10,0,-1,0));
259     				len += sprintf(buffer + len,
260     					"Transmit collisions       %s\n",
261     					SkNumber(test_buf, pPnmiStat->StatTxSingleCollisionCts,
262     					10,0,-1,0));
263     				len += sprintf(buffer + len,
264     					"Transmited errors types\n");
265     				len += sprintf(buffer + len,
266     					"   aborted errors         %ld\n",
267     					pAC->stats.tx_aborted_errors);
268     				len += sprintf(buffer + len,
269     					"   carrier errors         %s\n",
270     					SkNumber(test_buf, pPnmiStat->StatTxCarrierCts,
271     					10, 0, -1, 0));
272     				len += sprintf(buffer + len,
273     					"   fifo errors            %s\n",
274     					SkNumber(test_buf, pPnmiStat->StatTxFifoUnderrunCts,
275     					10, 0, -1, 0));
276     				len += sprintf(buffer + len,
277     					"   heartbeat errors       %s\n",
278     					SkNumber(test_buf, pPnmiStat->StatTxCarrierCts,
279     					10, 0, -1, 0));
280     				len += sprintf(buffer + len,
281     					"   window errors          %ld\n",
282     					pAC->stats.tx_window_errors);
283     			}
284     		}
285     		SkgeProcDev = next;
286     	}
287     	if (offset >= len) {
288     		*eof = 1;
289     		return 0;
290     	}
291     
292     	*buffer_location = buffer + offset;
293     	if (buffer_length >= len - offset) {
294     		*eof = 1;
295     	}
296     	return (min_t(int, buffer_length, len - offset));
297     }
298     
299     
300     
301     
302     
303     /*****************************************************************************
304      *
305      * SkDoDiv - convert 64bit number
306      *
307      * Description:
308      *	This function "converts" a long long number.
309      *
310      * Returns:
311      *	remainder of division
312      */
313     static long SkDoDiv (long long Dividend, int Divisor, long long *pErg)
314     {
315      long   	Rest;
316      long long 	Ergebnis;
317      long   	Akku;
318     
319     
320      Akku  = Dividend >> 32;
321     
322      Ergebnis = ((long long) (Akku / Divisor)) << 32;
323      Rest = Akku % Divisor ;
324     
325      Akku = Rest << 16;
326      Akku |= ((Dividend & 0xFFFF0000) >> 16);
327     
328     
329      Ergebnis += ((long long) (Akku / Divisor)) << 16;
330      Rest = Akku % Divisor ;
331     
332      Akku = Rest << 16;
333      Akku |= (Dividend & 0xFFFF);
334     
335      Ergebnis += (Akku / Divisor);
336      Rest = Akku % Divisor ;
337     
338      *pErg = Ergebnis;
339      return (Rest);
340     }
341     
342     
343     #if 0
344     #define do_div(n,base) ({ \
345     long long __res; \
346     __res = ((unsigned long long) n) % (unsigned) base; \
347     n = ((unsigned long long) n) / (unsigned) base; \
348     __res; })
349     
350     #endif
351     
352     
353     /*****************************************************************************
354      *
355      * SkNumber - Print results
356      *
357      * Description:
358      *	This function converts a long long number into a string.
359      *
360      * Returns:
361      *	number as string
362      */
363     char * SkNumber(char * str, long long num, int base, int size, int precision
364     	,int type)
365     {
366     	char c,sign,tmp[66], *strorg = str;
367     	const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
368     	int i;
369     
370     	if (type & LARGE)
371     		digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
372     	if (type & LEFT)
373     		type &= ~ZEROPAD;
374     	if (base < 2 || base > 36)
375     		return 0;
376     	c = (type & ZEROPAD) ? '0' : ' ';
377     	sign = 0;
378     	if (type & SIGN) {
379     		if (num < 0) {
380     			sign = '-';
381     			num = -num;
382     			size--;
383     		} else if (type & PLUS) {
384     			sign = '+';
385     			size--;
386     		} else if (type & SPACE) {
387     			sign = ' ';
388     			size--;
389     		}
390     	}
391     	if (type & SPECIAL) {
392     		if (base == 16)
393     			size -= 2;
394     		else if (base == 8)
395     			size--;
396     	}
397     	i = 0;
398     	if (num == 0)
399     		tmp[i++]='0';
400     	else while (num != 0)
401     		tmp[i++] = digits[SkDoDiv(num,base, &num)];
402     
403     	if (i > precision)
404     		precision = i;
405     	size -= precision;
406     	if (!(type&(ZEROPAD+LEFT)))
407     		while(size-->0)
408     			*str++ = ' ';
409     	if (sign)
410     		*str++ = sign;
411     	if (type & SPECIAL) {
412     		if (base==8)
413     			*str++ = '0';
414     		else if (base==16) {
415     			*str++ = '0';
416     			*str++ = digits[33];
417     		}
418     	}
419     	if (!(type & LEFT))
420     		while (size-- > 0)
421     			*str++ = c;
422     	while (i < precision--)
423     		*str++ = '0';
424     	while (i-- > 0)
425     		*str++ = tmp[i];
426     	while (size-- > 0)
427     		*str++ = ' ';
428     	
429     	str[0] = '\0';
430     	
431     	return strorg;
432     }
433     
434     
435     
436