proc_pcifr.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:10k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. /************************************************************************/
  2. /* File pcifr_proc.c created by Allan Trautman on Thu Aug  2 2001.      */
  3. /************************************************************************/
  4. /* Supports the ../proc/ppc64/pcifr for the pci flight recorder.        */
  5. /* Copyright (C) 20yy  <Allan H Trautman> <IBM Corp>                    */
  6. /*                                                                      */
  7. /* This program is free software; you can redistribute it and/or modify */
  8. /* it under the terms of the GNU General Public License as published by */
  9. /* the Free Software Foundation; either version 2 of the License, or    */
  10. /* (at your option) any later version.                                  */
  11. /*                                                                      */
  12. /* This program is distributed in the hope that it will be useful,      */ 
  13. /* but WITHOUT ANY WARRANTY; without even the implied warranty of       */
  14. /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        */
  15. /* GNU General Public License for more details.                         */
  16. /*                                                                      */
  17. /* You should have received a copy of the GNU General Public License    */ 
  18. /* along with this program; if not, write to the:                       */
  19. /* Free Software Foundation, Inc.,                                      */ 
  20. /* 59 Temple Place, Suite 330,                                          */ 
  21. /* Boston, MA  02111-1307  USA                                          */
  22. /************************************************************************/
  23. #include <stdarg.h>
  24. #include <linux/kernel.h>
  25. #include <linux/proc_fs.h>
  26. #include <asm/uaccess.h>
  27. #include <asm/time.h>
  28. #include <linux/pci.h>
  29. #include <asm/pci-bridge.h>
  30. #include <linux/netdevice.h>
  31. #include <asm/flight_recorder.h>
  32. #include <asm/iSeries/iSeries_pci.h>
  33. #include "pci.h"
  34. void pci_Fr_TestCode(void);
  35. static spinlock_t proc_pcifr_lock;
  36. struct flightRecorder* PciFr = NULL;
  37. extern long Pci_Interrupt_Count;
  38. extern long Pci_Event_Count;
  39. extern long Pci_Io_Read_Count;
  40. extern long Pci_Io_Write_Count;
  41. extern long Pci_Cfg_Read_Count;
  42. extern long Pci_Cfg_Write_Count;
  43. extern long Pci_Error_Count;
  44. /************************************************************************/
  45. /* Forward declares.                                                    */
  46. /************************************************************************/
  47. static struct proc_dir_entry *pciFr_proc_root = NULL;
  48. int proc_pciFr_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data);
  49. int proc_pciFr_write_proc(struct file *file, const char *buffer, unsigned long count, void *data);
  50. static struct proc_dir_entry *pciDev_proc_root = NULL;
  51. int proc_pciDev_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data);
  52. int proc_pciDev_write_proc(struct file *file, const char *buffer, unsigned long count, void *data);
  53. /************************************************************************/
  54. /* Create entry ../proc/ppc64/pcifr                                     */
  55. /************************************************************************/
  56. void proc_pciFr_init(struct proc_dir_entry *proc_ppc64_root)
  57. {
  58. if (proc_ppc64_root == NULL) return;
  59. /* Read = User,Group,Other, Write User */
  60. printk("PCI: Creating ../proc/ppc64/pcifr n");
  61. spin_lock(&proc_pcifr_lock);
  62. pciFr_proc_root = create_proc_entry("pcifr", S_IFREG | S_IRUGO | S_IWUSR, proc_ppc64_root);
  63. spin_unlock(&proc_pcifr_lock);
  64. if (pciFr_proc_root == NULL) return;
  65. pciFr_proc_root->nlink = 1;
  66. pciFr_proc_root->data = (void *)0;
  67. pciFr_proc_root->read_proc  = proc_pciFr_read_proc;
  68. pciFr_proc_root->write_proc = proc_pciFr_write_proc;
  69. PciFr = alloc_Flight_Recorder(NULL,"PciFr", 4096);
  70. printk("PCI: Creating ../proc/ppc64/pci n");
  71. spin_lock(&proc_pcifr_lock);
  72. pciDev_proc_root = create_proc_entry("pci", S_IFREG | S_IRUGO | S_IWUSR, proc_ppc64_root);
  73. spin_unlock(&proc_pcifr_lock);
  74. if (pciDev_proc_root == NULL) return;
  75. pciDev_proc_root->nlink = 1;
  76. pciDev_proc_root->data = (void *)0;
  77. pciDev_proc_root->read_proc  = proc_pciDev_read_proc;
  78. pciDev_proc_root->write_proc = proc_pciDev_write_proc;
  79. }
  80. static char* PciFrBuffer = NULL;
  81. static  int   PciFrBufLen = 0;
  82. static  char* PciFrBufPtr = NULL;
  83. static  int   PciFileSize = 0;
  84. /*******************************************************************************/
  85. /* Read function for ../proc/ppc64/pcifr.                                      */
  86. /*  -> Function grabs a copy of the pcifr(could change) and writes the data to */
  87. /*     the caller.  Note, it may not all fit in the buffer.  The function      */
  88. /*     handles the repeated calls until all the data has been read.            */
  89. /* Tip:                                                                        */
  90. /* ./fs/proc/generic.c::proc_file_read is the caller of this routine.          */
  91. /*******************************************************************************/
  92. int proc_pciFr_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data)
  93. {
  94. /* First call will have offset 0, get snapshot the pcifr          */
  95. if( off == 0) {
  96. spin_lock(&proc_pcifr_lock);
  97. PciFrBuffer = (char*)kmalloc(PciFr->Size, GFP_KERNEL);
  98. PciFrBufLen = fr_Dump(PciFr,PciFrBuffer, PciFr->Size);
  99. PciFrBufPtr = PciFrBuffer;
  100. PciFileSize = 0;
  101. }
  102. /* For the persistant folks, set eof and return zero length.      */
  103. else if( PciFrBuffer == NULL) {
  104. *eof = 1;
  105. return 0;
  106. }
  107. /* - If there is more data than will fit, move what will fit.     */
  108. /* - The rest will get moved on the next call.                    */
  109. int MoveSize = PciFrBufLen;
  110. if( MoveSize > count) MoveSize = count;
  111. /* Move the data info the FileSystem buffer.                      */
  112. memcpy(page+off,PciFrBufPtr,MoveSize);
  113. PciFrBufPtr += MoveSize;
  114. PciFileSize += MoveSize;
  115. PciFrBufLen -= MoveSize;
  116. /* If all the data has been moved, free the buffer and set EOF.   */
  117. if( PciFrBufLen == 0) {
  118. kfree(PciFrBuffer);
  119. PciFrBuffer = NULL;
  120. spin_unlock(&proc_pcifr_lock);
  121. *eof = 1;
  122. }
  123. return PciFileSize;
  124. }
  125. /*******************************************************************************/
  126. /* Gets called when client writes to ../proc/ppc64/pcifr                       */
  127. /*******************************************************************************/
  128. int proc_pciFr_write_proc(struct file *file, const char *buffer, unsigned long count, void *data)
  129. {
  130. return count;
  131. }
  132. static  spinlock_t ProcBufferLock;
  133. static char* ProcBuffer   = NULL;
  134. static  int   ProcBufSize  = 0;
  135. static  char* ProcBufPtr   = NULL;
  136. static  int   ProcFileSize = 0;
  137. /*******************************************************************************/
  138. /* Build Device Buffer for /proc/ppc64/pci                                     */
  139. /*******************************************************************************/
  140. static int build_PciDev_Buffer(int BufferSize) 
  141. {
  142. ProcBuffer  = (char*)kmalloc(BufferSize, GFP_KERNEL);
  143. ProcBufPtr  = ProcBuffer;
  144. int BufLen  = 0;
  145. BufLen += sprintf(ProcBuffer+BufLen,"Pci I/O Reads. %8ld  ",Pci_Io_Read_Count);
  146. BufLen += sprintf(ProcBuffer+BufLen,"Pci I/O Writes %8ldn",Pci_Io_Write_Count);
  147. BufLen += sprintf(ProcBuffer+BufLen,"Pci Cfg Reads. %8ld  ",Pci_Cfg_Read_Count);
  148. BufLen += sprintf(ProcBuffer+BufLen,"Pci Cfg Writes %8ldn",Pci_Cfg_Write_Count);
  149. BufLen += sprintf(ProcBuffer+BufLen,"Pci I/O Errors %8ldn",Pci_Error_Count);
  150. BufLen += sprintf(ProcBuffer+BufLen,"n");
  151. /***************************************************************************/
  152. /* List the devices                                                        */
  153. /***************************************************************************/
  154. struct pci_dev*    PciDev;     /* Device pointer              */
  155. struct net_device* dev;             /* net_device pointer          */
  156. int    DeviceCount  = 0;
  157. pci_for_each_dev(PciDev) {
  158. if ( BufLen > BufferSize-128) {    /* Room for another line?       */
  159. BufLen +=sprintf(ProcBuffer+BufLen,"Buffer Fulln");
  160. break;
  161. }
  162. if( PCI_SLOT(PciDev->devfn) != 0) {
  163. ++DeviceCount;
  164. BufLen += sprintf(ProcBuffer+BufLen,"%3d. ",DeviceCount);
  165. if ( PciDev->sysdata != NULL ) {
  166. BufLen += format_device_location(PciDev,ProcBuffer+BufLen,128);
  167. }
  168. else {
  169. BufLen += sprintf(ProcBuffer+BufLen,"No Device Node!n");
  170. }
  171. BufLen += sprintf(ProcBuffer+BufLen,"n");
  172. /* look for the net devices out */
  173. for (dev = dev_base; dev != NULL; dev = dev->next)  {
  174. if (dev->base_addr == PciDev->resource[0].start ) {
  175. BufLen += sprintf(ProcBuffer+BufLen, "     - Net device: %sn", dev->name);
  176. break;
  177. } /* if */
  178. } /* for */
  179. } /* if(PCI_SLOT(PciDev->devfn) != 0)  */
  180. }
  181. return BufLen;
  182. }
  183. /*******************************************************************************/
  184. /* Get called when client reads the ../proc/ppc64/pcifr.                       */
  185. /*******************************************************************************/
  186. int proc_pciDev_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data)
  187. {
  188. /* First call will have offset 0                                  */
  189. if( off == 0) {
  190. spin_lock(&ProcBufferLock);
  191. ProcBufSize  = build_PciDev_Buffer(4096);
  192. ProcFileSize = 0;
  193. }
  194. /* For the persistant folks, set eof and return zero length.      */
  195. else if( ProcBuffer == NULL) {
  196. *eof = 1;
  197. return 0;
  198. }
  199. /* How much data can be moved                                     */
  200. int MoveSize = ProcBufSize;
  201. if( MoveSize > count) MoveSize = count;
  202. /* Move the data info the FileSystem buffer.                      */
  203. memcpy(page+off,ProcBufPtr,MoveSize);
  204. ProcBufPtr   += MoveSize;
  205. ProcBufSize  -= MoveSize;
  206. ProcFileSize += MoveSize;
  207. /* If all the data has been moved, free the buffer and set EOF.   */
  208. if( ProcBufSize == 0) {
  209. kfree(ProcBuffer );
  210. ProcBuffer  = NULL;
  211. spin_unlock(&ProcBufferLock);
  212. *eof = 1;
  213. }
  214. return ProcFileSize;
  215. }
  216. /*******************************************************************************/
  217. /* Gets called when client writes to ../proc/ppc64/pcifr                       */
  218. /*******************************************************************************/
  219. int proc_pciDev_write_proc(struct file *file, const char *buffer, unsigned long count, void *data)
  220. {
  221. return count;
  222. }