• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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