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 <linux/version.h>
87 #include <asm/io.h>
88 #include <asm/uaccess.h>
89 #include <asm/atomic.h>
90 #include <linux/proc_fs.h>
91 #include <linux/spinlock.h>
92
93 #ifdef CONFIG_COLDFIRE
94 #include <asm/coldfire.h>
95 #include "fec.h"
96 #endif
97
98 /***************************************************************************/
99 /* */
100 /* */
101 /* G L O B A L D E F I N I T I O N S */
102 /* */
103 /* */
104 /***************************************************************************/
105
106 //---------------------------------------------------------------------------
107 // const defines
108 //---------------------------------------------------------------------------
109
110 #ifndef EPL_PROC_DEV_NAME
111 #define EPL_PROC_DEV_NAME "epl"
112 #endif
113
114 #ifndef DBG_TRACE_POINTS
115 #define DBG_TRACE_POINTS 23 // # of supported debug trace points
116 #endif
117
118 #ifndef DBG_TRACE_VALUES
119 #define DBG_TRACE_VALUES 24 // # of supported debug trace values (size of circular buffer)
120 #endif
121
122 //---------------------------------------------------------------------------
123 // modul global types
124 //---------------------------------------------------------------------------
125
126 //---------------------------------------------------------------------------
127 // local vars
128 //---------------------------------------------------------------------------
129
130 #ifdef _DBG_TRACE_POINTS_
131 atomic_t aatmDbgTracePoint_l[DBG_TRACE_POINTS];
132 DWORD adwDbgTraceValue_l[DBG_TRACE_VALUES];
133 DWORD dwDbgTraceValueOld_l;
134 unsigned int uiDbgTraceValuePos_l;
135 spinlock_t spinlockDbgTraceValue_l;
136 unsigned long ulDbTraceValueFlags_l;
137 #endif
138
139 //---------------------------------------------------------------------------
140 // local function prototypes
141 //---------------------------------------------------------------------------
142
143 static int EplLinProcRead(char *pcBuffer_p, char **ppcStart_p, off_t Offset_p,
144 int nBufferSize_p, int *pEof_p, void *pData_p);
145 static int EplLinProcWrite(struct file *file, const char __user * buffer,
146 unsigned long count, void *data);
147
148 void PUBLIC TgtDbgSignalTracePoint(BYTE bTracePointNumber_p);
149 void PUBLIC TgtDbgPostTraceValue(DWORD dwTraceValue_p);
150
151 EPLDLLEXPORT DWORD PUBLIC EplIdentuGetRunningRequests(void);
152
153 //=========================================================================//
154 // //
155 // P U B L I C F U N C T I O N S //
156 // //
157 //=========================================================================//
158
EplLinProcInit(void)159 tEplKernel EplLinProcInit(void)
160 {
161 struct proc_dir_entry *pProcDirEntry;
162 pProcDirEntry = create_proc_entry(EPL_PROC_DEV_NAME, S_IRUGO, NULL);
163 if (pProcDirEntry != NULL) {
164 pProcDirEntry->read_proc = EplLinProcRead;
165 pProcDirEntry->write_proc = EplLinProcWrite;
166 pProcDirEntry->data = NULL; // device number or something else
167
168 } else {
169 return kEplNoResource;
170 }
171
172 #ifdef _DBG_TRACE_POINTS_
173 // initialize spinlock and circular buffer position
174 spin_lock_init(&spinlockDbgTraceValue_l);
175 uiDbgTraceValuePos_l = 0;
176 dwDbgTraceValueOld_l = 0;
177 #endif
178
179 return kEplSuccessful;
180 }
181
EplLinProcFree(void)182 tEplKernel EplLinProcFree(void)
183 {
184 remove_proc_entry(EPL_PROC_DEV_NAME, NULL);
185
186 return kEplSuccessful;
187 }
188
189 //---------------------------------------------------------------------------
190 // Target specific event signaling (FEC Tx-/Rx-Interrupt, used by Edrv)
191 //---------------------------------------------------------------------------
192
193 #ifdef _DBG_TRACE_POINTS_
TgtDbgSignalTracePoint(BYTE bTracePointNumber_p)194 void PUBLIC TgtDbgSignalTracePoint(BYTE bTracePointNumber_p)
195 {
196
197 if (bTracePointNumber_p >=
198 (sizeof(aatmDbgTracePoint_l) / sizeof(aatmDbgTracePoint_l[0]))) {
199 goto Exit;
200 }
201
202 atomic_inc(&aatmDbgTracePoint_l[bTracePointNumber_p]);
203
204 Exit:
205
206 return;
207
208 }
209
TgtDbgPostTraceValue(DWORD dwTraceValue_p)210 void PUBLIC TgtDbgPostTraceValue(DWORD dwTraceValue_p)
211 {
212
213 spin_lock_irqsave(&spinlockDbgTraceValue_l, ulDbTraceValueFlags_l);
214 if (dwDbgTraceValueOld_l != dwTraceValue_p) {
215 adwDbgTraceValue_l[uiDbgTraceValuePos_l] = dwTraceValue_p;
216 uiDbgTraceValuePos_l =
217 (uiDbgTraceValuePos_l + 1) % DBG_TRACE_VALUES;
218 dwDbgTraceValueOld_l = dwTraceValue_p;
219 }
220 spin_unlock_irqrestore(&spinlockDbgTraceValue_l, ulDbTraceValueFlags_l);
221
222 return;
223
224 }
225 #endif
226
227 //---------------------------------------------------------------------------
228 // Read function for PROC-FS read access
229 //---------------------------------------------------------------------------
230
EplLinProcRead(char * pcBuffer_p,char ** ppcStart_p,off_t Offset_p,int nBufferSize_p,int * pEof_p,void * pData_p)231 static int EplLinProcRead(char *pcBuffer_p,
232 char **ppcStart_p,
233 off_t Offset_p,
234 int nBufferSize_p, int *pEof_p, void *pData_p)
235 {
236
237 int nSize;
238 int Eof;
239 tEplDllkCalStatistics *pDllkCalStats;
240
241 nSize = 0;
242 Eof = 0;
243
244 // count calls of this function
245 #ifdef _DBG_TRACE_POINTS_
246 TgtDbgSignalTracePoint(0);
247 #endif
248
249 //---------------------------------------------------------------
250 // generate static information
251 //---------------------------------------------------------------
252
253 // ---- Driver information ----
254 nSize += snprintf(pcBuffer_p + nSize, nBufferSize_p - nSize,
255 "%s %s (c) 2006 %s\n",
256 EPL_PRODUCT_NAME, EPL_PRODUCT_VERSION,
257 EPL_PRODUCT_MANUFACTURER);
258
259 //---------------------------------------------------------------
260 // generate process information
261 //---------------------------------------------------------------
262
263 // ---- EPL state ----
264 nSize += snprintf(pcBuffer_p + nSize, nBufferSize_p - nSize,
265 "NMT state: 0x%04X\n",
266 (WORD) EplNmtkGetNmtState());
267
268 EplDllkCalGetStatistics(&pDllkCalStats);
269
270 nSize += snprintf(pcBuffer_p + nSize, nBufferSize_p - nSize,
271 "CurAsyncTxGen=%lu CurAsyncTxNmt=%lu CurAsyncRx=%lu\nMaxAsyncTxGen=%lu MaxAsyncTxNmt=%lu MaxAsyncRx=%lu\n",
272 pDllkCalStats->m_ulCurTxFrameCountGen,
273 pDllkCalStats->m_ulCurTxFrameCountNmt,
274 pDllkCalStats->m_ulCurRxFrameCount,
275 pDllkCalStats->m_ulMaxTxFrameCountGen,
276 pDllkCalStats->m_ulMaxTxFrameCountNmt,
277 pDllkCalStats->m_ulMaxRxFrameCount);
278
279 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
280 // fetch running IdentRequests
281 nSize += snprintf(pcBuffer_p + nSize, nBufferSize_p - nSize,
282 "running IdentRequests: 0x%08lX\n",
283 EplIdentuGetRunningRequests());
284
285 // fetch state of NmtMnu module
286 {
287 unsigned int uiMandatorySlaveCount;
288 unsigned int uiSignalSlaveCount;
289 WORD wFlags;
290
291 EplNmtMnuGetDiagnosticInfo(&uiMandatorySlaveCount,
292 &uiSignalSlaveCount, &wFlags);
293
294 nSize += snprintf(pcBuffer_p + nSize, nBufferSize_p - nSize,
295 "MN MandSlaveCount: %u SigSlaveCount: %u Flags: 0x%X\n",
296 uiMandatorySlaveCount, uiSignalSlaveCount,
297 wFlags);
298
299 }
300 #endif
301
302 // ---- FEC state ----
303 #ifdef CONFIG_COLDFIRE
304 {
305 // Receive the base address
306 unsigned long base_addr;
307 #if (EDRV_USED_ETH_CTRL == 0)
308 // Set the base address of FEC0
309 base_addr = FEC_BASE_ADDR_FEC0;
310 #else
311 // Set the base address of FEC1
312 base_addr = FEC_BASE_ADDR_FEC1;
313 #endif
314
315 nSize += snprintf(pcBuffer_p + nSize, nBufferSize_p - nSize,
316 "FEC_ECR = 0x%08X FEC_EIR = 0x%08X FEC_EIMR = 0x%08X\nFEC_TCR = 0x%08X FECTFSR = 0x%08X FECRFSR = 0x%08X\n",
317 FEC_ECR(base_addr), FEC_EIR(base_addr),
318 FEC_EIMR(base_addr), FEC_TCR(base_addr),
319 FEC_FECTFSR(base_addr),
320 FEC_FECRFSR(base_addr));
321 }
322 #endif
323
324 // ---- DBG: TracePoints ----
325 #ifdef _DBG_TRACE_POINTS_
326 {
327 int nNum;
328
329 nSize += snprintf(pcBuffer_p + nSize, nBufferSize_p - nSize,
330 "DbgTracePoints:\n");
331 for (nNum = 0;
332 nNum < (sizeof(aatmDbgTracePoint_l) / sizeof(atomic_t));
333 nNum++) {
334 nSize +=
335 snprintf(pcBuffer_p + nSize, nBufferSize_p - nSize,
336 " TracePoint[%2d]: %d\n", (int)nNum,
337 atomic_read(&aatmDbgTracePoint_l[nNum]));
338 }
339
340 nSize += snprintf(pcBuffer_p + nSize, nBufferSize_p - nSize,
341 "DbgTraceValues:\n");
342 for (nNum = 0; nNum < DBG_TRACE_VALUES; nNum++) {
343 if (nNum == uiDbgTraceValuePos_l) { // next value will be stored at that position
344 nSize +=
345 snprintf(pcBuffer_p + nSize,
346 nBufferSize_p - nSize, "*%08lX",
347 adwDbgTraceValue_l[nNum]);
348 } else {
349 nSize +=
350 snprintf(pcBuffer_p + nSize,
351 nBufferSize_p - nSize, " %08lX",
352 adwDbgTraceValue_l[nNum]);
353 }
354 if ((nNum & 0x00000007) == 0x00000007) { // 8 values printed -> end of line reached
355 nSize +=
356 snprintf(pcBuffer_p + nSize,
357 nBufferSize_p - nSize, "\n");
358 }
359 }
360 if ((nNum & 0x00000007) != 0x00000007) { // number of values printed is not a multiple of 8 -> print new line
361 nSize +=
362 snprintf(pcBuffer_p + nSize, nBufferSize_p - nSize,
363 "\n");
364 }
365 }
366 #endif
367
368 Eof = 1;
369 goto Exit;
370
371 Exit:
372
373 *pEof_p = Eof;
374
375 return (nSize);
376
377 }
378
379 //---------------------------------------------------------------------------
380 // Write function for PROC-FS write access
381 //---------------------------------------------------------------------------
382
EplLinProcWrite(struct file * file,const char __user * buffer,unsigned long count,void * data)383 static int EplLinProcWrite(struct file *file, const char __user * buffer,
384 unsigned long count, void *data)
385 {
386 char abBuffer[count + 1];
387 int iErr;
388 int iVal = 0;
389 tEplNmtEvent NmtEvent;
390
391 if (count > 0) {
392 iErr = copy_from_user(abBuffer, buffer, count);
393 if (iErr != 0) {
394 return count;
395 }
396 abBuffer[count] = '\0';
397
398 iErr = sscanf(abBuffer, "%i", &iVal);
399 }
400 if ((iVal <= 0) || (iVal > 0x2F)) {
401 NmtEvent = kEplNmtEventSwReset;
402 } else {
403 NmtEvent = (tEplNmtEvent) iVal;
404 }
405 // execute specified NMT command on write access of /proc/epl
406 EplNmtuNmtEvent(NmtEvent);
407
408 return count;
409 }
410