nilfs2: segment usage file
[linux-2.6] / drivers / staging / epl / proc_fs.c
1 /****************************************************************************
2
3   (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
4       www.systec-electronic.com
5
6   Project:      openPOWERLINK
7
8   Description:  proc fs entry with diagnostic information under Linux
9
10   License:
11
12     Redistribution and use in source and binary forms, with or without
13     modification, are permitted provided that the following conditions
14     are met:
15
16     1. Redistributions of source code must retain the above copyright
17        notice, this list of conditions and the following disclaimer.
18
19     2. Redistributions in binary form must reproduce the above copyright
20        notice, this list of conditions and the following disclaimer in the
21        documentation and/or other materials provided with the distribution.
22
23     3. Neither the name of SYSTEC electronic GmbH nor the names of its
24        contributors may be used to endorse or promote products derived
25        from this software without prior written permission. For written
26        permission, please contact info@systec-electronic.com.
27
28     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
31     FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
32     COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
33     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
34     BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
35     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
36     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
38     ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
39     POSSIBILITY OF SUCH DAMAGE.
40
41     Severability Clause:
42
43         If a provision of this License is or becomes illegal, invalid or
44         unenforceable in any jurisdiction, that shall not affect:
45         1. the validity or enforceability in that jurisdiction of any other
46            provision of this License; or
47         2. the validity or enforceability in other jurisdictions of that or
48            any other provision of this License.
49
50   -------------------------------------------------------------------------
51
52                 $RCSfile: proc_fs.c,v $
53
54                 $Author: D.Krueger $
55
56                 $Revision: 1.13 $  $Date: 2008/11/07 13:55:56 $
57
58                 $State: Exp $
59
60                 Build Environment:
61                     GNU
62
63   -------------------------------------------------------------------------
64
65   Revision History:
66
67   2006/07/31 d.k.:   start of implementation
68
69 ****************************************************************************/
70
71 #include "kernel/EplNmtk.h"
72 #include "user/EplNmtu.h"
73
74 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
75 #include "user/EplNmtMnu.h"
76 #endif
77
78 #include "kernel/EplDllkCal.h"
79
80 //#include <linux/config.h>
81 #include <linux/module.h>
82 #include <linux/kernel.h>
83 #include <linux/init.h>
84 #include <linux/errno.h>
85 #include <linux/major.h>
86 #include <asm/io.h>
87 #include <asm/uaccess.h>
88 #include <asm/atomic.h>
89 #include <linux/proc_fs.h>
90 #include <linux/spinlock.h>
91
92 #ifdef CONFIG_COLDFIRE
93 #include <asm/coldfire.h>
94 #include "fec.h"
95 #endif
96
97 #include "proc_fs.h"
98
99 /***************************************************************************/
100 /*                                                                         */
101 /*                                                                         */
102 /*          G L O B A L   D E F I N I T I O N S                            */
103 /*                                                                         */
104 /*                                                                         */
105 /***************************************************************************/
106
107 //---------------------------------------------------------------------------
108 // const defines
109 //---------------------------------------------------------------------------
110
111 #ifndef EPL_PROC_DEV_NAME
112 #define EPL_PROC_DEV_NAME    "epl"
113 #endif
114
115 #ifndef DBG_TRACE_POINTS
116 #define DBG_TRACE_POINTS    23  // # of supported debug trace points
117 #endif
118
119 #ifndef DBG_TRACE_VALUES
120 #define DBG_TRACE_VALUES    24  // # of supported debug trace values (size of circular buffer)
121 #endif
122
123 //---------------------------------------------------------------------------
124 // modul global types
125 //---------------------------------------------------------------------------
126
127 //---------------------------------------------------------------------------
128 // local vars
129 //---------------------------------------------------------------------------
130
131 #ifdef _DBG_TRACE_POINTS_
132 atomic_t aatmDbgTracePoint_l[DBG_TRACE_POINTS];
133 u32 adwDbgTraceValue_l[DBG_TRACE_VALUES];
134 u32 dwDbgTraceValueOld_l;
135 unsigned int uiDbgTraceValuePos_l;
136 spinlock_t spinlockDbgTraceValue_l;
137 unsigned long ulDbTraceValueFlags_l;
138 #endif
139
140 //---------------------------------------------------------------------------
141 // local function prototypes
142 //---------------------------------------------------------------------------
143
144 static int EplLinProcRead(char *pcBuffer_p, char **ppcStart_p, off_t Offset_p,
145                           int nBufferSize_p, int *pEof_p, void *pData_p);
146 static int EplLinProcWrite(struct file *file, const char __user * buffer,
147                            unsigned long count, void *data);
148
149 void TgtDbgSignalTracePoint(u8 bTracePointNumber_p);
150 void TgtDbgPostTraceValue(u32 dwTraceValue_p);
151
152 extern u32 EplIdentuGetRunningRequests(void);
153
154 //=========================================================================//
155 //                                                                         //
156 //          P U B L I C   F U N C T I O N S                                //
157 //                                                                         //
158 //=========================================================================//
159
160 tEplKernel EplLinProcInit(void)
161 {
162         struct proc_dir_entry *pProcDirEntry;
163         pProcDirEntry = create_proc_entry(EPL_PROC_DEV_NAME, S_IRUGO, NULL);
164         if (pProcDirEntry != NULL) {
165                 pProcDirEntry->read_proc = EplLinProcRead;
166                 pProcDirEntry->write_proc = EplLinProcWrite;
167                 pProcDirEntry->data = NULL;     // device number or something else
168
169         } else {
170                 return kEplNoResource;
171         }
172
173 #ifdef _DBG_TRACE_POINTS_
174         // initialize spinlock and circular buffer position
175         spin_lock_init(&spinlockDbgTraceValue_l);
176         uiDbgTraceValuePos_l = 0;
177         dwDbgTraceValueOld_l = 0;
178 #endif
179
180         return kEplSuccessful;
181 }
182
183 tEplKernel EplLinProcFree(void)
184 {
185         remove_proc_entry(EPL_PROC_DEV_NAME, NULL);
186
187         return kEplSuccessful;
188 }
189
190 //---------------------------------------------------------------------------
191 //  Target specific event signaling (FEC Tx-/Rx-Interrupt, used by Edrv)
192 //---------------------------------------------------------------------------
193
194 #ifdef _DBG_TRACE_POINTS_
195 void TgtDbgSignalTracePoint(u8 bTracePointNumber_p)
196 {
197
198         if (bTracePointNumber_p >=
199             (sizeof(aatmDbgTracePoint_l) / sizeof(aatmDbgTracePoint_l[0]))) {
200                 goto Exit;
201         }
202
203         atomic_inc(&aatmDbgTracePoint_l[bTracePointNumber_p]);
204
205       Exit:
206
207         return;
208
209 }
210
211 void TgtDbgPostTraceValue(u32 dwTraceValue_p)
212 {
213
214         spin_lock_irqsave(&spinlockDbgTraceValue_l, ulDbTraceValueFlags_l);
215         if (dwDbgTraceValueOld_l != dwTraceValue_p) {
216                 adwDbgTraceValue_l[uiDbgTraceValuePos_l] = dwTraceValue_p;
217                 uiDbgTraceValuePos_l =
218                     (uiDbgTraceValuePos_l + 1) % DBG_TRACE_VALUES;
219                 dwDbgTraceValueOld_l = dwTraceValue_p;
220         }
221         spin_unlock_irqrestore(&spinlockDbgTraceValue_l, ulDbTraceValueFlags_l);
222
223         return;
224
225 }
226 #endif
227
228 //---------------------------------------------------------------------------
229 //  Read function for PROC-FS read access
230 //---------------------------------------------------------------------------
231
232 static int EplLinProcRead(char *pcBuffer_p,
233                           char **ppcStart_p,
234                           off_t Offset_p,
235                           int nBufferSize_p, int *pEof_p, void *pData_p)
236 {
237
238         int nSize;
239         int Eof;
240         tEplDllkCalStatistics *pDllkCalStats;
241
242         nSize = 0;
243         Eof = 0;
244
245         // count calls of this function
246 #ifdef _DBG_TRACE_POINTS_
247         TgtDbgSignalTracePoint(0);
248 #endif
249
250         //---------------------------------------------------------------
251         // generate static information
252         //---------------------------------------------------------------
253
254         // ---- Driver information ----
255         nSize += snprintf(pcBuffer_p + nSize, nBufferSize_p - nSize,
256                           "%s    %s    (c) 2006 %s\n",
257                           EPL_PRODUCT_NAME, EPL_PRODUCT_VERSION,
258                           EPL_PRODUCT_MANUFACTURER);
259
260         //---------------------------------------------------------------
261         // generate process information
262         //---------------------------------------------------------------
263
264         // ---- EPL state ----
265         nSize += snprintf(pcBuffer_p + nSize, nBufferSize_p - nSize,
266                           "NMT state:                  0x%04X\n",
267                           (u16) EplNmtkGetNmtState());
268
269         EplDllkCalGetStatistics(&pDllkCalStats);
270
271         nSize += snprintf(pcBuffer_p + nSize, nBufferSize_p - nSize,
272                           "CurAsyncTxGen=%lu CurAsyncTxNmt=%lu CurAsyncRx=%lu\nMaxAsyncTxGen=%lu MaxAsyncTxNmt=%lu MaxAsyncRx=%lu\n",
273                           pDllkCalStats->m_ulCurTxFrameCountGen,
274                           pDllkCalStats->m_ulCurTxFrameCountNmt,
275                           pDllkCalStats->m_ulCurRxFrameCount,
276                           pDllkCalStats->m_ulMaxTxFrameCountGen,
277                           pDllkCalStats->m_ulMaxTxFrameCountNmt,
278                           pDllkCalStats->m_ulMaxRxFrameCount);
279
280 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
281         // fetch running IdentRequests
282         nSize += snprintf(pcBuffer_p + nSize, nBufferSize_p - nSize,
283                           "running IdentRequests:      0x%08X\n",
284                           EplIdentuGetRunningRequests());
285
286         // fetch state of NmtMnu module
287         {
288                 unsigned int uiMandatorySlaveCount;
289                 unsigned int uiSignalSlaveCount;
290                 u16 wFlags;
291
292                 EplNmtMnuGetDiagnosticInfo(&uiMandatorySlaveCount,
293                                            &uiSignalSlaveCount, &wFlags);
294
295                 nSize += snprintf(pcBuffer_p + nSize, nBufferSize_p - nSize,
296                                   "MN  MandSlaveCount: %u  SigSlaveCount: %u  Flags: 0x%X\n",
297                                   uiMandatorySlaveCount, uiSignalSlaveCount,
298                                   wFlags);
299
300         }
301 #endif
302
303         // ---- FEC state ----
304 #ifdef CONFIG_COLDFIRE
305         {
306                 // Receive the base address
307                 unsigned long base_addr;
308 #if (EDRV_USED_ETH_CTRL == 0)
309                 // Set the base address of FEC0
310                 base_addr = FEC_BASE_ADDR_FEC0;
311 #else
312                 // Set the base address of FEC1
313                 base_addr = FEC_BASE_ADDR_FEC1;
314 #endif
315
316                 nSize += snprintf(pcBuffer_p + nSize, nBufferSize_p - nSize,
317                                   "FEC_ECR = 0x%08X FEC_EIR = 0x%08X FEC_EIMR = 0x%08X\nFEC_TCR = 0x%08X FECTFSR = 0x%08X FECRFSR = 0x%08X\n",
318                                   FEC_ECR(base_addr), FEC_EIR(base_addr),
319                                   FEC_EIMR(base_addr), FEC_TCR(base_addr),
320                                   FEC_FECTFSR(base_addr),
321                                   FEC_FECRFSR(base_addr));
322         }
323 #endif
324
325         // ---- DBG: TracePoints ----
326 #ifdef _DBG_TRACE_POINTS_
327         {
328                 int nNum;
329
330                 nSize += snprintf(pcBuffer_p + nSize, nBufferSize_p - nSize,
331                                   "DbgTracePoints:\n");
332                 for (nNum = 0;
333                      nNum < (sizeof(aatmDbgTracePoint_l) / sizeof(atomic_t));
334                      nNum++) {
335                         nSize +=
336                             snprintf(pcBuffer_p + nSize, nBufferSize_p - nSize,
337                                      " TracePoint[%2d]: %d\n", (int)nNum,
338                                      atomic_read(&aatmDbgTracePoint_l[nNum]));
339                 }
340
341                 nSize += snprintf(pcBuffer_p + nSize, nBufferSize_p - nSize,
342                                   "DbgTraceValues:\n");
343                 for (nNum = 0; nNum < DBG_TRACE_VALUES; nNum++) {
344                         if (nNum == uiDbgTraceValuePos_l) {     // next value will be stored at that position
345                                 nSize +=
346                                     snprintf(pcBuffer_p + nSize,
347                                              nBufferSize_p - nSize, "*%08lX",
348                                              adwDbgTraceValue_l[nNum]);
349                         } else {
350                                 nSize +=
351                                     snprintf(pcBuffer_p + nSize,
352                                              nBufferSize_p - nSize, " %08lX",
353                                              adwDbgTraceValue_l[nNum]);
354                         }
355                         if ((nNum & 0x00000007) == 0x00000007) {        // 8 values printed -> end of line reached
356                                 nSize +=
357                                     snprintf(pcBuffer_p + nSize,
358                                              nBufferSize_p - nSize, "\n");
359                         }
360                 }
361                 if ((nNum & 0x00000007) != 0x00000007) {        // number of values printed is not a multiple of 8 -> print new line
362                         nSize +=
363                             snprintf(pcBuffer_p + nSize, nBufferSize_p - nSize,
364                                      "\n");
365                 }
366         }
367 #endif
368
369         Eof = 1;
370         goto Exit;
371
372       Exit:
373
374         *pEof_p = Eof;
375
376         return (nSize);
377
378 }
379
380 //---------------------------------------------------------------------------
381 //  Write function for PROC-FS write access
382 //---------------------------------------------------------------------------
383
384 static int EplLinProcWrite(struct file *file, const char __user * buffer,
385                            unsigned long count, void *data)
386 {
387         char abBuffer[count + 1];
388         int iErr;
389         int iVal = 0;
390         tEplNmtEvent NmtEvent;
391
392         if (count > 0) {
393                 iErr = copy_from_user(abBuffer, buffer, count);
394                 if (iErr != 0) {
395                         return count;
396                 }
397                 abBuffer[count] = '\0';
398
399                 iErr = sscanf(abBuffer, "%i", &iVal);
400         }
401         if ((iVal <= 0) || (iVal > 0x2F)) {
402                 NmtEvent = kEplNmtEventSwReset;
403         } else {
404                 NmtEvent = (tEplNmtEvent) iVal;
405         }
406         // execute specified NMT command on write access of /proc/epl
407         EplNmtuNmtEvent(NmtEvent);
408
409         return count;
410 }