skproc.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510
  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. * (C)Copyright 1998-2003 SysKonnect GmbH.
  13. *
  14. * This program is free software; you can redistribute it and/or modify
  15. * it under the terms of the GNU General Public License as published by
  16. * the Free Software Foundation; either version 2 of the License, or
  17. * (at your option) any later version.
  18. *
  19. * Created 22-Nov-2000
  20. * Author: Mirko Lindner (mlindner@syskonnect.de)
  21. *
  22. * The information in this file is provided "AS IS" without warranty.
  23. *
  24. ******************************************************************************/
  25. /******************************************************************************
  26. *
  27. * History:
  28. *
  29. * $Log: skproc.c,v $
  30. * Revision 1.4 2003/02/25 14:16:37 mlindner
  31. * Fix: Copyright statement
  32. *
  33. * Revision 1.3 2002/10/02 12:59:51 mlindner
  34. * Add: Support for Yukon
  35. * Add: Speed check and setup
  36. * Add: Merge source for kernel 2.2.x and 2.4.x
  37. * Add: Read sensor names directly from VPD
  38. * Fix: Volt values
  39. *
  40. * Revision 1.2.2.7 2002/01/14 12:45:15 mlindner
  41. * Fix: Editorial changes
  42. *
  43. * Revision 1.2.2.6 2001/12/06 15:26:07 mlindner
  44. * Fix: Return value of proc_read
  45. *
  46. * Revision 1.2.2.5 2001/12/06 09:57:39 mlindner
  47. * New ProcFs entries
  48. *
  49. * Revision 1.2.2.4 2001/09/05 12:16:02 mlindner
  50. * Add: New ProcFs entries
  51. * Fix: Counter Errors (Jumbo == to long errors)
  52. * Fix: Kernel error compilation
  53. * Fix: too short counters
  54. *
  55. * Revision 1.2.2.3 2001/06/25 07:26:26 mlindner
  56. * Add: More error messages
  57. *
  58. * Revision 1.2.2.2 2001/03/15 12:50:13 mlindner
  59. * fix: ProcFS owner protection
  60. *
  61. * Revision 1.2.2.1 2001/03/12 16:43:48 mlindner
  62. * chg: 2.4 requirements for procfs
  63. *
  64. * Revision 1.1 2001/01/22 14:15:31 mlindner
  65. * added ProcFs functionality
  66. * Dual Net functionality integrated
  67. * Rlmt networks added
  68. *
  69. *
  70. ******************************************************************************/
  71. #include <config.h>
  72. #include <linux/proc_fs.h>
  73. #include "h/skdrv1st.h"
  74. #include "h/skdrv2nd.h"
  75. #define ZEROPAD 1 /* pad with zero */
  76. #define SIGN 2 /* unsigned/signed long */
  77. #define PLUS 4 /* show plus */
  78. #define SPACE 8 /* space if plus */
  79. #define LEFT 16 /* left justified */
  80. #define SPECIALX 32 /* 0x */
  81. #define LARGE 64
  82. extern SK_AC *pACList;
  83. extern struct net_device *SkGeRootDev;
  84. extern char *SkNumber (char *str,
  85. long long num,
  86. int base,
  87. int size,
  88. int precision,
  89. int type);
  90. /*****************************************************************************
  91. *
  92. * proc_read - print "summaries" entry
  93. *
  94. * Description:
  95. * This function fills the proc entry with statistic data about
  96. * the ethernet device.
  97. *
  98. *
  99. * Returns: buffer with statistic data
  100. *
  101. */
  102. int proc_read(char *buffer,
  103. char **buffer_location,
  104. off_t offset,
  105. int buffer_length,
  106. int *eof,
  107. void *data)
  108. {
  109. int len = 0;
  110. int t;
  111. int i;
  112. DEV_NET *pNet;
  113. SK_AC *pAC;
  114. char test_buf[100];
  115. char sens_msg[50];
  116. unsigned long Flags;
  117. unsigned int Size;
  118. struct SK_NET_DEVICE *next;
  119. struct SK_NET_DEVICE *SkgeProcDev = SkGeRootDev;
  120. SK_PNMI_STRUCT_DATA *pPnmiStruct;
  121. SK_PNMI_STAT *pPnmiStat;
  122. struct proc_dir_entry *file = (struct proc_dir_entry*) data;
  123. while (SkgeProcDev) {
  124. pNet = (DEV_NET*) SkgeProcDev->priv;
  125. pAC = pNet->pAC;
  126. next = pAC->Next;
  127. pPnmiStruct = &pAC->PnmiStruct;
  128. /* NetIndex in GetStruct is now required, zero is only dummy */
  129. for (t=pAC->GIni.GIMacsFound; t > 0; t--) {
  130. if ((pAC->GIni.GIMacsFound == 2) && pAC->RlmtNets == 1)
  131. t--;
  132. spin_lock_irqsave(&pAC->SlowPathLock, Flags);
  133. Size = SK_PNMI_STRUCT_SIZE;
  134. SkPnmiGetStruct(pAC, pAC->IoBase,
  135. pPnmiStruct, &Size, t-1);
  136. spin_unlock_irqrestore(&pAC->SlowPathLock, Flags);
  137. if (strcmp(pAC->dev[t-1]->name, file->name) == 0) {
  138. pPnmiStat = &pPnmiStruct->Stat[0];
  139. len = sprintf(buffer,
  140. "\nDetailed statistic for device %s\n",
  141. pAC->dev[t-1]->name);
  142. len += sprintf(buffer + len,
  143. "=======================================\n");
  144. /* Board statistics */
  145. len += sprintf(buffer + len,
  146. "\nBoard statistics\n\n");
  147. len += sprintf(buffer + len,
  148. "Active Port %c\n",
  149. 'A' + pAC->Rlmt.Net[t-1].Port[pAC->Rlmt.
  150. Net[t-1].PrefPort]->PortNumber);
  151. len += sprintf(buffer + len,
  152. "Preferred Port %c\n",
  153. 'A' + pAC->Rlmt.Net[t-1].Port[pAC->Rlmt.
  154. Net[t-1].PrefPort]->PortNumber);
  155. len += sprintf(buffer + len,
  156. "Bus speed (MHz) %d\n",
  157. pPnmiStruct->BusSpeed);
  158. len += sprintf(buffer + len,
  159. "Bus width (Bit) %d\n",
  160. pPnmiStruct->BusWidth);
  161. len += sprintf(buffer + len,
  162. "Hardware revision v%d.%d\n",
  163. (pAC->GIni.GIPciHwRev >> 4) & 0x0F,
  164. pAC->GIni.GIPciHwRev & 0x0F);
  165. /* Print sensor informations */
  166. for (i=0; i < pAC->I2c.MaxSens; i ++) {
  167. /* Check type */
  168. switch (pAC->I2c.SenTable[i].SenType) {
  169. case 1:
  170. strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc);
  171. strcat(sens_msg, " (C)");
  172. len += sprintf(buffer + len,
  173. "%-25s %d.%02d\n",
  174. sens_msg,
  175. pAC->I2c.SenTable[i].SenValue / 10,
  176. pAC->I2c.SenTable[i].SenValue % 10);
  177. strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc);
  178. strcat(sens_msg, " (F)");
  179. len += sprintf(buffer + len,
  180. "%-25s %d.%02d\n",
  181. sens_msg,
  182. ((((pAC->I2c.SenTable[i].SenValue)
  183. *10)*9)/5 + 3200)/100,
  184. ((((pAC->I2c.SenTable[i].SenValue)
  185. *10)*9)/5 + 3200) % 10);
  186. break;
  187. case 2:
  188. strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc);
  189. strcat(sens_msg, " (V)");
  190. len += sprintf(buffer + len,
  191. "%-25s %d.%03d\n",
  192. sens_msg,
  193. pAC->I2c.SenTable[i].SenValue / 1000,
  194. pAC->I2c.SenTable[i].SenValue % 1000);
  195. break;
  196. case 3:
  197. strcpy(sens_msg, pAC->I2c.SenTable[i].SenDesc);
  198. strcat(sens_msg, " (rpm)");
  199. len += sprintf(buffer + len,
  200. "%-25s %d\n",
  201. sens_msg,
  202. pAC->I2c.SenTable[i].SenValue);
  203. break;
  204. default:
  205. break;
  206. }
  207. }
  208. /*Receive statistics */
  209. len += sprintf(buffer + len,
  210. "\nReceive statistics\n\n");
  211. len += sprintf(buffer + len,
  212. "Received bytes %s\n",
  213. SkNumber(test_buf, pPnmiStat->StatRxOctetsOkCts,
  214. 10,0,-1,0));
  215. len += sprintf(buffer + len,
  216. "Received packets %s\n",
  217. SkNumber(test_buf, pPnmiStat->StatRxOkCts,
  218. 10,0,-1,0));
  219. #if 0
  220. if (pAC->GIni.GP[0].PhyType == SK_PHY_XMAC &&
  221. pAC->HWRevision < 12) {
  222. pPnmiStruct->InErrorsCts = pPnmiStruct->InErrorsCts -
  223. pPnmiStat->StatRxShortsCts;
  224. pPnmiStat->StatRxShortsCts = 0;
  225. }
  226. #endif
  227. if (pNet->Mtu > 1500)
  228. pPnmiStruct->InErrorsCts = pPnmiStruct->InErrorsCts -
  229. pPnmiStat->StatRxTooLongCts;
  230. len += sprintf(buffer + len,
  231. "Receive errors %s\n",
  232. SkNumber(test_buf, pPnmiStruct->InErrorsCts,
  233. 10,0,-1,0));
  234. len += sprintf(buffer + len,
  235. "Receive drops %s\n",
  236. SkNumber(test_buf, pPnmiStruct->RxNoBufCts,
  237. 10,0,-1,0));
  238. len += sprintf(buffer + len,
  239. "Received multicast %s\n",
  240. SkNumber(test_buf, pPnmiStat->StatRxMulticastOkCts,
  241. 10,0,-1,0));
  242. len += sprintf(buffer + len,
  243. "Receive error types\n");
  244. len += sprintf(buffer + len,
  245. " length %s\n",
  246. SkNumber(test_buf, pPnmiStat->StatRxRuntCts,
  247. 10, 0, -1, 0));
  248. len += sprintf(buffer + len,
  249. " buffer overflow %s\n",
  250. SkNumber(test_buf, pPnmiStat->StatRxFifoOverflowCts,
  251. 10, 0, -1, 0));
  252. len += sprintf(buffer + len,
  253. " bad crc %s\n",
  254. SkNumber(test_buf, pPnmiStat->StatRxFcsCts,
  255. 10, 0, -1, 0));
  256. len += sprintf(buffer + len,
  257. " framing %s\n",
  258. SkNumber(test_buf, pPnmiStat->StatRxFramingCts,
  259. 10, 0, -1, 0));
  260. len += sprintf(buffer + len,
  261. " missed frames %s\n",
  262. SkNumber(test_buf, pPnmiStat->StatRxMissedCts,
  263. 10, 0, -1, 0));
  264. if (pNet->Mtu > 1500)
  265. pPnmiStat->StatRxTooLongCts = 0;
  266. len += sprintf(buffer + len,
  267. " too long %s\n",
  268. SkNumber(test_buf, pPnmiStat->StatRxTooLongCts,
  269. 10, 0, -1, 0));
  270. len += sprintf(buffer + len,
  271. " carrier extension %s\n",
  272. SkNumber(test_buf, pPnmiStat->StatRxCextCts,
  273. 10, 0, -1, 0));
  274. len += sprintf(buffer + len,
  275. " too short %s\n",
  276. SkNumber(test_buf, pPnmiStat->StatRxShortsCts,
  277. 10, 0, -1, 0));
  278. len += sprintf(buffer + len,
  279. " symbol %s\n",
  280. SkNumber(test_buf, pPnmiStat->StatRxSymbolCts,
  281. 10, 0, -1, 0));
  282. len += sprintf(buffer + len,
  283. " LLC MAC size %s\n",
  284. SkNumber(test_buf, pPnmiStat->StatRxIRLengthCts,
  285. 10, 0, -1, 0));
  286. len += sprintf(buffer + len,
  287. " carrier event %s\n",
  288. SkNumber(test_buf, pPnmiStat->StatRxCarrierCts,
  289. 10, 0, -1, 0));
  290. len += sprintf(buffer + len,
  291. " jabber %s\n",
  292. SkNumber(test_buf, pPnmiStat->StatRxJabberCts,
  293. 10, 0, -1, 0));
  294. /*Transmit statistics */
  295. len += sprintf(buffer + len,
  296. "\nTransmit statistics\n\n");
  297. len += sprintf(buffer + len,
  298. "Transmited bytes %s\n",
  299. SkNumber(test_buf, pPnmiStat->StatTxOctetsOkCts,
  300. 10,0,-1,0));
  301. len += sprintf(buffer + len,
  302. "Transmited packets %s\n",
  303. SkNumber(test_buf, pPnmiStat->StatTxOkCts,
  304. 10,0,-1,0));
  305. len += sprintf(buffer + len,
  306. "Transmit errors %s\n",
  307. SkNumber(test_buf, pPnmiStat->StatTxSingleCollisionCts,
  308. 10,0,-1,0));
  309. len += sprintf(buffer + len,
  310. "Transmit dropped %s\n",
  311. SkNumber(test_buf, pPnmiStruct->TxNoBufCts,
  312. 10,0,-1,0));
  313. len += sprintf(buffer + len,
  314. "Transmit collisions %s\n",
  315. SkNumber(test_buf, pPnmiStat->StatTxSingleCollisionCts,
  316. 10,0,-1,0));
  317. len += sprintf(buffer + len,
  318. "Transmit errors types\n");
  319. len += sprintf(buffer + len,
  320. " excessive collision %ld\n",
  321. pAC->stats.tx_aborted_errors);
  322. len += sprintf(buffer + len,
  323. " carrier %s\n",
  324. SkNumber(test_buf, pPnmiStat->StatTxCarrierCts,
  325. 10, 0, -1, 0));
  326. len += sprintf(buffer + len,
  327. " fifo underrun %s\n",
  328. SkNumber(test_buf, pPnmiStat->StatTxFifoUnderrunCts,
  329. 10, 0, -1, 0));
  330. len += sprintf(buffer + len,
  331. " heartbeat %s\n",
  332. SkNumber(test_buf, pPnmiStat->StatTxCarrierCts,
  333. 10, 0, -1, 0));
  334. len += sprintf(buffer + len,
  335. " window %ld\n",
  336. pAC->stats.tx_window_errors);
  337. }
  338. }
  339. SkgeProcDev = next;
  340. }
  341. if (offset >= len) {
  342. *eof = 1;
  343. return 0;
  344. }
  345. *buffer_location = buffer + offset;
  346. if (buffer_length >= len - offset) {
  347. *eof = 1;
  348. }
  349. return (min_t(int, buffer_length, len - offset));
  350. }
  351. /*****************************************************************************
  352. *
  353. * SkDoDiv - convert 64bit number
  354. *
  355. * Description:
  356. * This function "converts" a long long number.
  357. *
  358. * Returns:
  359. * remainder of division
  360. */
  361. static long SkDoDiv (long long Dividend, int Divisor, long long *pErg)
  362. {
  363. long Rest;
  364. long long Ergebnis;
  365. long Akku;
  366. Akku = Dividend >> 32;
  367. Ergebnis = ((long long) (Akku / Divisor)) << 32;
  368. Rest = Akku % Divisor;
  369. Akku = Rest << 16;
  370. Akku |= ((Dividend & 0xFFFF0000) >> 16);
  371. Ergebnis += ((long long) (Akku / Divisor)) << 16;
  372. Rest = Akku % Divisor;
  373. Akku = Rest << 16;
  374. Akku |= (Dividend & 0xFFFF);
  375. Ergebnis += (Akku / Divisor);
  376. Rest = Akku % Divisor;
  377. *pErg = Ergebnis;
  378. return (Rest);
  379. }
  380. #if 0
  381. #define do_div(n,base) ({ \
  382. long long __res; \
  383. __res = ((unsigned long long) n) % (unsigned) base; \
  384. n = ((unsigned long long) n) / (unsigned) base; \
  385. __res; })
  386. #endif
  387. /*****************************************************************************
  388. *
  389. * SkNumber - Print results
  390. *
  391. * Description:
  392. * This function converts a long long number into a string.
  393. *
  394. * Returns:
  395. * number as string
  396. */
  397. char * SkNumber(char * str, long long num, int base, int size, int precision
  398. ,int type)
  399. {
  400. char c,sign,tmp[66], *strorg = str;
  401. const char *digits="0123456789abcdefghijklmnopqrstuvwxyz";
  402. int i;
  403. if (type & LARGE)
  404. digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  405. if (type & LEFT)
  406. type &= ~ZEROPAD;
  407. if (base < 2 || base > 36)
  408. return 0;
  409. c = (type & ZEROPAD) ? '0' : ' ';
  410. sign = 0;
  411. if (type & SIGN) {
  412. if (num < 0) {
  413. sign = '-';
  414. num = -num;
  415. size--;
  416. } else if (type & PLUS) {
  417. sign = '+';
  418. size--;
  419. } else if (type & SPACE) {
  420. sign = ' ';
  421. size--;
  422. }
  423. }
  424. if (type & SPECIALX) {
  425. if (base == 16)
  426. size -= 2;
  427. else if (base == 8)
  428. size--;
  429. }
  430. i = 0;
  431. if (num == 0)
  432. tmp[i++]='0';
  433. else while (num != 0)
  434. tmp[i++] = digits[SkDoDiv(num,base, &num)];
  435. if (i > precision)
  436. precision = i;
  437. size -= precision;
  438. if (!(type&(ZEROPAD+LEFT)))
  439. while(size-->0)
  440. *str++ = ' ';
  441. if (sign)
  442. *str++ = sign;
  443. if (type & SPECIALX) {
  444. if (base==8)
  445. *str++ = '0';
  446. else if (base==16) {
  447. *str++ = '0';
  448. *str++ = digits[33];
  449. }
  450. }
  451. if (!(type & LEFT))
  452. while (size-- > 0)
  453. *str++ = c;
  454. while (i < precision--)
  455. *str++ = '0';
  456. while (i-- > 0)
  457. *str++ = tmp[i];
  458. while (size-- > 0)
  459. *str++ = ' ';
  460. str[0] = '\0';
  461. return strorg;
  462. }