Merge with /home/m8/git/u-boot
[platform/kernel/u-boot.git] / drivers / sk98lin / skproc.c
1 /******************************************************************************
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  ******************************************************************************/
10
11 /******************************************************************************
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
33  *
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
39  *      Fix: Volt values
40  *
41  *      Revision 1.2.2.7  2002/01/14 12:45:15  mlindner
42  *      Fix: Editorial changes
43  *
44  *      Revision 1.2.2.6  2001/12/06 15:26:07  mlindner
45  *      Fix: Return value of proc_read
46  *
47  *      Revision 1.2.2.5  2001/12/06 09:57:39  mlindner
48  *      New ProcFs entries
49  *
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
55  *
56  *      Revision 1.2.2.3  2001/06/25 07:26:26  mlindner
57  *      Add: More error messages
58  *
59  *      Revision 1.2.2.2  2001/03/15 12:50:13  mlindner
60  *      fix: ProcFS owner protection
61  *
62  *      Revision 1.2.2.1  2001/03/12 16:43:48  mlindner
63  *      chg: 2.4 requirements for procfs
64  *
65  *      Revision 1.1  2001/01/22 14:15:31  mlindner
66  *      added ProcFs functionality
67  *      Dual Net functionality integrated
68  *      Rlmt networks added
69  *
70  *
71  ******************************************************************************/
72
73 #include <config.h>
74
75 #ifdef CONFIG_SK98
76
77 #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
89 extern SK_AC                            *pACList;
90 extern struct net_device        *SkGeRootDev;
91
92 extern 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  *
103  *      proc_read - print "summaries" entry
104  *
105  * Description:
106  *  This function fills the proc entry with statistic data about
107  *  the ethernet device.
108  *
109  *
110  * Returns: buffer with statistic data
111  *
112  */
113 int proc_read(char *buffer,
114 char **buffer_location,
115 off_t offset,
116 int buffer_length,
117 int *eof,
118 void *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];
127         unsigned long                   Flags;
128         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;
149                         SkPnmiGetStruct(pAC, pAC->IoBase,
150                                 pPnmiStruct, &Size, t-1);
151                         spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
152
153                         if (strcmp(pAC->dev[t-1]->name, file->name) == 0) {
154                                 pPnmiStat = &pPnmiStruct->Stat[0];
155                                 len = sprintf(buffer,
156                                         "\nDetailed statistic for device %s\n",
157                                         pAC->dev[t-1]->name);
158                                 len += sprintf(buffer + len,
159                                         "=======================================\n");
160
161                                 /* Board statistics */
162                                 len += sprintf(buffer + len,
163                                         "\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                                 }
229
230                                 /*Receive statistics */
231                                 len += sprintf(buffer + len,
232                                 "\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
243                                 if (pAC->GIni.GP[0].PhyType == SK_PHY_XMAC &&
244                                         pAC->HWRevision < 12) {
245                                         pPnmiStruct->InErrorsCts = pPnmiStruct->InErrorsCts -
246                                                 pPnmiStat->StatRxShortsCts;
247                                         pPnmiStat->StatRxShortsCts = 0;
248                                 }
249 #endif
250                                 if (pNet->Mtu > 1500)
251                                         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,
295                                         10, 0, -1, 0));
296                                 len += sprintf(buffer + len,
297                                         "   carrier extension           %s\n",
298                                         SkNumber(test_buf, pPnmiStat->StatRxCextCts,
299                                         10, 0, -1, 0));
300                                 len += sprintf(buffer + len,
301                                         "   too short                   %s\n",
302                                         SkNumber(test_buf, pPnmiStat->StatRxShortsCts,
303                                         10, 0, -1, 0));
304                                 len += sprintf(buffer + len,
305                                         "   symbol                      %s\n",
306                                         SkNumber(test_buf, pPnmiStat->StatRxSymbolCts,
307                                         10, 0, -1, 0));
308                                 len += sprintf(buffer + len,
309                                         "   LLC MAC size                %s\n",
310                                         SkNumber(test_buf, pPnmiStat->StatRxIRLengthCts,
311                                         10, 0, -1, 0));
312                                 len += sprintf(buffer + len,
313                                         "   carrier event               %s\n",
314                                         SkNumber(test_buf, pPnmiStat->StatRxCarrierCts,
315                                         10, 0, -1, 0));
316                                 len += sprintf(buffer + len,
317                                         "   jabber                      %s\n",
318                                         SkNumber(test_buf, pPnmiStat->StatRxJabberCts,
319                                         10, 0, -1, 0));
320
321
322                                 /*Transmit statistics */
323                                 len += sprintf(buffer + len,
324                                 "\nTransmit statistics\n\n");
325
326                                 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);
366
367                         }
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
384 /*****************************************************************************
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  */
394 static 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) ({ \
426 long long __res; \
427 __res = ((unsigned long long) n) % (unsigned) base; \
428 n = ((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  */
444 char * 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++ = ' ';
509
510         str[0] = '\0';
511
512         return strorg;
513 }
514
515 #endif /* CONFIG_SK98 */