summaryrefslogtreecommitdiff
path: root/drivers/net/sk98lin/skproc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/sk98lin/skproc.c')
-rw-r--r--drivers/net/sk98lin/skproc.c515
1 files changed, 515 insertions, 0 deletions
diff --git a/drivers/net/sk98lin/skproc.c b/drivers/net/sk98lin/skproc.c
new file mode 100644
index 00000000000..4e340730e56
--- /dev/null
+++ b/drivers/net/sk98lin/skproc.c
@@ -0,0 +1,515 @@
+/******************************************************************************
+ *
+ * Name: skproc.c
+ * Project: GEnesis, PCI Gigabit Ethernet Adapter
+ * Version: $Revision: 1.4 $
+ * Date: $Date: 2003/02/25 14:16:37 $
+ * Purpose: Funktions to display statictic data
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ * (C)Copyright 1998-2003 SysKonnect GmbH.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Created 22-Nov-2000
+ * Author: Mirko Lindner (mlindner@syskonnect.de)
+ *
+ * The information in this file is provided "AS IS" without warranty.
+ *
+ ******************************************************************************/
+/******************************************************************************
+ *
+ * History:
+ *
+ * $Log: skproc.c,v $
+ * Revision 1.4 2003/02/25 14:16:37 mlindner
+ * Fix: Copyright statement
+ *
+ * Revision 1.3 2002/10/02 12:59:51 mlindner
+ * Add: Support for Yukon
+ * Add: Speed check and setup
+ * Add: Merge source for kernel 2.2.x and 2.4.x
+ * Add: Read sensor names directly from VPD
+ * Fix: Volt values
+ *
+ * Revision 1.2.2.7 2002/01/14 12:45:15 mlindner
+ * Fix: Editorial changes
+ *
+ * Revision 1.2.2.6 2001/12/06 15:26:07 mlindner
+ * Fix: Return value of proc_read
+ *
+ * Revision 1.2.2.5 2001/12/06 09:57:39 mlindner
+ * New ProcFs entries
+ *
+ * Revision 1.2.2.4 2001/09/05 12:16:02 mlindner
+ * Add: New ProcFs entries
+ * Fix: Counter Errors (Jumbo == to long errors)
+ * Fix: Kernel error compilation
+ * Fix: too short counters
+ *
+ * Revision 1.2.2.3 2001/06/25 07:26:26 mlindner
+ * Add: More error messages
+ *
+ * Revision 1.2.2.2 2001/03/15 12:50:13 mlindner
+ * fix: ProcFS owner protection
+ *
+ * Revision 1.2.2.1 2001/03/12 16:43:48 mlindner
+ * chg: 2.4 requirements for procfs
+ *
+ * Revision 1.1 2001/01/22 14:15:31 mlindner
+ * added ProcFs functionality
+ * Dual Net functionality integrated
+ * Rlmt networks added
+ *
+ *
+ ******************************************************************************/
+
+#include <config.h>
+
+#ifdef CONFIG_SK98
+
+#include <linux/proc_fs.h>
+
+#include "h/skdrv1st.h"
+#include "h/skdrv2nd.h"
+#define ZEROPAD 1 /* pad with zero */
+#define SIGN 2 /* unsigned/signed long */
+#define PLUS 4 /* show plus */
+#define SPACE 8 /* space if plus */
+#define LEFT 16 /* left justified */
+#define SPECIALX 32 /* 0x */
+#define LARGE 64
+
+extern SK_AC *pACList;
+extern struct net_device *SkGeRootDev;
+
+extern char * SkNumber(
+ char * str,
+ long long num,
+ int base,
+ int size,
+ int precision,
+ int type);
+
+
+/*****************************************************************************
+ *
+ * proc_read - print "summaries" entry
+ *
+ * Description:
+ * This function fills the proc entry with statistic data about
+ * the ethernet device.
+ *
+ *
+ * Returns: buffer with statistic data
+ *
+ */
+int proc_read(char *buffer,
+char **buffer_location,
+off_t offset,
+int buffer_length,
+int *eof,
+void *data)
+{
+ int len = 0;
+ int t;
+ int i;
+ DEV_NET *pNet;
+ SK_AC *pAC;
+ char test_buf[100];
+ char sens_msg[50];
+ unsigned long Flags;
+ unsigned int Size;
+ struct SK_NET_DEVICE *next;
+ struct SK_NET_DEVICE *SkgeProcDev = SkGeRootDev;
+
+ SK_PNMI_STRUCT_DATA *pPnmiStruct;
+ SK_PNMI_STAT *pPnmiStat;
+ struct proc_dir_entry *file = (struct proc_dir_entry*) data;
+
+ while (SkgeProcDev) {
+ pNet = (DEV_NET*) SkgeProcDev->priv;
+ pAC = pNet->pAC;
+ next = pAC->Next;
+ pPnmiStruct = &pAC->PnmiStruct;
+ /* NetIndex in GetStruct is now required, zero is only dummy */
+
+ for (t=pAC->GIni.GIMacsFound; t > 0; t--) {
+ if ((pAC->GIni.GIMacsFound == 2) && pAC->RlmtNets == 1)
+ t--;
+
+ spin_lock_irqsave(&pAC->SlowPathLock, Flags);
+ Size = SK_PNMI_STRUCT_SIZE;
+ SkPnmiGetStruct(pAC, pAC->IoBase,
+ pPnmiStruct, &Size, t-1);
+ spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
+
+ if (strcmp(pAC->dev[t-1]->name, file->name) == 0) {
+ pPnmiStat = &pPnmiStruct->Stat[0];
+ len = sprintf(buffer,
+ "\nDetailed statistic for device %s\n",
+ pAC->dev[t-1]->name);
+ len += sprintf(buffer + len,
+ "=======================================\n");
+
+ /* Board statistics */
+ len += sprintf(buffer + len,
+ "\nBoard statistics\n\n");
+ len += sprintf(buffer + len,
+ "Active Port %c\n",
+ 'A' + pAC->Rlmt.Net[t-1].Port[pAC->Rlmt.
+ Net[t-1].PrefPort]->PortNumber);
+ len += sprintf(buffer + len,
+ "Preferred Port %c\n",
+ 'A' + pAC->Rlmt.Net[t-1].Port[pAC->Rlmt.
+ Net[t-1].PrefPort]->PortNumber);
+
+ len += sprintf(buffer + len,
+ "Bus speed (MHz) %d\n",
+ pPnmiStruct->BusSpeed);
+
+ len += sprintf(buffer + len,
+ "Bus width (Bit) %d\n",
+ pPnmiStruct->BusWidth);
+ len += sprintf(buffer + len,
+ "Hardware revision v%d.%d\n",
+ (pAC->GIni.GIPciHwRev >> 4) & 0x0F,
+ pAC->GIni.GIPciHwRev & 0x0F);
+
+ /* Print sensor informations */
+ for (i=0; i < pAC->I2c.MaxSens; i ++) {
+ /* Check type */
+ switch (pAC->I2c.SenTable[i].SenType) {
+ case 1:
+ strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc);
+ strcat(sens_msg, " (C)");
+ len += sprintf(buffer + len,
+ "%-25s %d.%02d\n",
+ sens_msg,
+ pAC->I2c.SenTable[i].SenValue / 10,
+ pAC->I2c.SenTable[i].SenValue % 10);
+
+ strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc);
+ strcat(sens_msg, " (F)");
+ len += sprintf(buffer + len,
+ "%-25s %d.%02d\n",
+ sens_msg,
+ ((((pAC->I2c.SenTable[i].SenValue)
+ *10)*9)/5 + 3200)/100,
+ ((((pAC->I2c.SenTable[i].SenValue)
+ *10)*9)/5 + 3200) % 10);
+ break;
+ case 2:
+ strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc);
+ strcat(sens_msg, " (V)");
+ len += sprintf(buffer + len,
+ "%-25s %d.%03d\n",
+ sens_msg,
+ pAC->I2c.SenTable[i].SenValue / 1000,
+ pAC->I2c.SenTable[i].SenValue % 1000);
+ break;
+ case 3:
+ strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc);
+ strcat(sens_msg, " (rpm)");
+ len += sprintf(buffer + len,
+ "%-25s %d\n",
+ sens_msg,
+ pAC->I2c.SenTable[i].SenValue);
+ break;
+ default:
+ break;
+ }
+ }
+
+ /*Receive statistics */
+ len += sprintf(buffer + len,
+ "\nReceive statistics\n\n");
+
+ len += sprintf(buffer + len,
+ "Received bytes %s\n",
+ SkNumber(test_buf, pPnmiStat->StatRxOctetsOkCts,
+ 10,0,-1,0));
+ len += sprintf(buffer + len,
+ "Received packets %s\n",
+ SkNumber(test_buf, pPnmiStat->StatRxOkCts,
+ 10,0,-1,0));
+#if 0
+ if (pAC->GIni.GP[0].PhyType == SK_PHY_XMAC &&
+ pAC->HWRevision < 12) {
+ pPnmiStruct->InErrorsCts = pPnmiStruct->InErrorsCts -
+ pPnmiStat->StatRxShortsCts;
+ pPnmiStat->StatRxShortsCts = 0;
+ }
+#endif
+ if (pNet->Mtu > 1500)
+ pPnmiStruct->InErrorsCts = pPnmiStruct->InErrorsCts -
+ pPnmiStat->StatRxTooLongCts;
+
+ len += sprintf(buffer + len,
+ "Receive errors %s\n",
+ SkNumber(test_buf, pPnmiStruct->InErrorsCts,
+ 10,0,-1,0));
+ len += sprintf(buffer + len,
+ "Receive drops %s\n",
+ SkNumber(test_buf, pPnmiStruct->RxNoBufCts,
+ 10,0,-1,0));
+ len += sprintf(buffer + len,
+ "Received multicast %s\n",
+ SkNumber(test_buf, pPnmiStat->StatRxMulticastOkCts,
+ 10,0,-1,0));
+ len += sprintf(buffer + len,
+ "Receive error types\n");
+ len += sprintf(buffer + len,
+ " length %s\n",
+ SkNumber(test_buf, pPnmiStat->StatRxRuntCts,
+ 10, 0, -1, 0));
+ len += sprintf(buffer + len,
+ " buffer overflow %s\n",
+ SkNumber(test_buf, pPnmiStat->StatRxFifoOverflowCts,
+ 10, 0, -1, 0));
+ len += sprintf(buffer + len,
+ " bad crc %s\n",
+ SkNumber(test_buf, pPnmiStat->StatRxFcsCts,
+ 10, 0, -1, 0));
+ len += sprintf(buffer + len,
+ " framing %s\n",
+ SkNumber(test_buf, pPnmiStat->StatRxFramingCts,
+ 10, 0, -1, 0));
+ len += sprintf(buffer + len,
+ " missed frames %s\n",
+ SkNumber(test_buf, pPnmiStat->StatRxMissedCts,
+ 10, 0, -1, 0));
+
+ if (pNet->Mtu > 1500)
+ pPnmiStat->StatRxTooLongCts = 0;
+
+ len += sprintf(buffer + len,
+ " too long %s\n",
+ SkNumber(test_buf, pPnmiStat->StatRxTooLongCts,
+ 10, 0, -1, 0));
+ len += sprintf(buffer + len,
+ " carrier extension %s\n",
+ SkNumber(test_buf, pPnmiStat->StatRxCextCts,
+ 10, 0, -1, 0));
+ len += sprintf(buffer + len,
+ " too short %s\n",
+ SkNumber(test_buf, pPnmiStat->StatRxShortsCts,
+ 10, 0, -1, 0));
+ len += sprintf(buffer + len,
+ " symbol %s\n",
+ SkNumber(test_buf, pPnmiStat->StatRxSymbolCts,
+ 10, 0, -1, 0));
+ len += sprintf(buffer + len,
+ " LLC MAC size %s\n",
+ SkNumber(test_buf, pPnmiStat->StatRxIRLengthCts,
+ 10, 0, -1, 0));
+ len += sprintf(buffer + len,
+ " carrier event %s\n",
+ SkNumber(test_buf, pPnmiStat->StatRxCarrierCts,
+ 10, 0, -1, 0));
+ len += sprintf(buffer + len,
+ " jabber %s\n",
+ SkNumber(test_buf, pPnmiStat->StatRxJabberCts,
+ 10, 0, -1, 0));
+
+
+ /*Transmit statistics */
+ len += sprintf(buffer + len,
+ "\nTransmit statistics\n\n");
+
+ len += sprintf(buffer + len,
+ "Transmited bytes %s\n",
+ SkNumber(test_buf, pPnmiStat->StatTxOctetsOkCts,
+ 10,0,-1,0));
+ len += sprintf(buffer + len,
+ "Transmited packets %s\n",
+ SkNumber(test_buf, pPnmiStat->StatTxOkCts,
+ 10,0,-1,0));
+ len += sprintf(buffer + len,
+ "Transmit errors %s\n",
+ SkNumber(test_buf, pPnmiStat->StatTxSingleCollisionCts,
+ 10,0,-1,0));
+ len += sprintf(buffer + len,
+ "Transmit dropped %s\n",
+ SkNumber(test_buf, pPnmiStruct->TxNoBufCts,
+ 10,0,-1,0));
+ len += sprintf(buffer + len,
+ "Transmit collisions %s\n",
+ SkNumber(test_buf, pPnmiStat->StatTxSingleCollisionCts,
+ 10,0,-1,0));
+ len += sprintf(buffer + len,
+ "Transmit errors types\n");
+ len += sprintf(buffer + len,
+ " excessive collision %ld\n",
+ pAC->stats.tx_aborted_errors);
+ len += sprintf(buffer + len,
+ " carrier %s\n",
+ SkNumber(test_buf, pPnmiStat->StatTxCarrierCts,
+ 10, 0, -1, 0));
+ len += sprintf(buffer + len,
+ " fifo underrun %s\n",
+ SkNumber(test_buf, pPnmiStat->StatTxFifoUnderrunCts,
+ 10, 0, -1, 0));
+ len += sprintf(buffer + len,
+ " heartbeat %s\n",
+ SkNumber(test_buf, pPnmiStat->StatTxCarrierCts,
+ 10, 0, -1, 0));
+ len += sprintf(buffer + len,
+ " window %ld\n",
+ pAC->stats.tx_window_errors);
+
+ }
+ }
+ SkgeProcDev = next;
+ }
+ if (offset >= len) {
+ *eof = 1;
+ return 0;
+ }
+
+ *buffer_location = buffer + offset;
+ if (buffer_length >= len - offset) {
+ *eof = 1;
+ }
+ return (min_t(int, buffer_length, len - offset));
+}
+
+
+/*****************************************************************************
+ *
+ * SkDoDiv - convert 64bit number
+ *
+ * Description:
+ * This function "converts" a long long number.
+ *
+ * Returns:
+ * remainder of division
+ */
+static long SkDoDiv (long long Dividend, int Divisor, long long *pErg)
+{
+ long Rest;
+ long long Ergebnis;
+ long Akku;
+
+
+ Akku = Dividend >> 32;
+
+ Ergebnis = ((long long) (Akku / Divisor)) << 32;
+ Rest = Akku % Divisor ;
+
+ Akku = Rest << 16;
+ Akku |= ((Dividend & 0xFFFF0000) >> 16);
+
+
+ Ergebnis += ((long long) (Akku / Divisor)) << 16;
+ Rest = Akku % Divisor ;
+
+ Akku = Rest << 16;
+ Akku |= (Dividend & 0xFFFF);
+
+ Ergebnis += (Akku / Divisor);
+ Rest = Akku % Divisor ;
+
+ *pErg = Ergebnis;
+ return (Rest);
+}
+
+
+#if 0
+#define do_div(n,base) ({ \
+long long __res; \
+__res = ((unsigned long long) n) % (unsigned) base; \
+n = ((unsigned long long) n) / (unsigned) base; \
+__res; })
+
+#endif
+
+
+/*****************************************************************************
+ *
+ * SkNumber - Print results
+ *
+ * Description:
+ * This function converts a long long number into a string.
+ *
+ * Returns:
+ * number as string
+ */
+char * SkNumber(char * str, long long num, int base, int size, int precision
+ ,int type)
+{
+ char c,sign,tmp[66], *strorg = str;
+ const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
+ int i;
+
+ if (type & LARGE)
+ digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ if (type & LEFT)
+ type &= ~ZEROPAD;
+ if (base < 2 || base > 36)
+ return 0;
+ c = (type & ZEROPAD) ? '0' : ' ';
+ sign = 0;
+ if (type & SIGN) {
+ if (num < 0) {
+ sign = '-';
+ num = -num;
+ size--;
+ } else if (type & PLUS) {
+ sign = '+';
+ size--;
+ } else if (type & SPACE) {
+ sign = ' ';
+ size--;
+ }
+ }
+ if (type & SPECIALX) {
+ if (base == 16)
+ size -= 2;
+ else if (base == 8)
+ size--;
+ }
+ i = 0;
+ if (num == 0)
+ tmp[i++]='0';
+ else while (num != 0)
+ tmp[i++] = digits[SkDoDiv(num,base, &num)];
+
+ if (i > precision)
+ precision = i;
+ size -= precision;
+ if (!(type&(ZEROPAD+LEFT)))
+ while(size-->0)
+ *str++ = ' ';
+ if (sign)
+ *str++ = sign;
+ if (type & SPECIALX) {
+ if (base==8)
+ *str++ = '0';
+ else if (base==16) {
+ *str++ = '0';
+ *str++ = digits[33];
+ }
+ }
+ if (!(type & LEFT))
+ while (size-- > 0)
+ *str++ = c;
+ while (i < precision--)
+ *str++ = '0';
+ while (i-- > 0)
+ *str++ = tmp[i];
+ while (size-- > 0)
+ *str++ = ' ';
+
+ str[0] = '\0';
+
+ return strorg;
+}
+
+#endif /* CONFIG_SK98 */