1 /****************************************************************************
3 (c) SYSTEC electronic GmbH, D-07973 Greiz, August-Bebel-Str. 29
4 www.systec-electronic.com
8 Description: proc fs entry with diagnostic information under Linux
12 Redistribution and use in source and binary forms, with or without
13 modification, are permitted provided that the following conditions
16 1. Redistributions of source code must retain the above copyright
17 notice, this list of conditions and the following disclaimer.
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.
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.
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.
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.
50 -------------------------------------------------------------------------
52 $RCSfile: proc_fs.c,v $
56 $Revision: 1.13 $ $Date: 2008/11/07 13:55:56 $
63 -------------------------------------------------------------------------
67 2006/07/31 d.k.: start of implementation
69 ****************************************************************************/
71 #include "kernel/EplNmtk.h"
72 #include "user/EplNmtu.h"
74 #if (((EPL_MODULE_INTEGRATION) & (EPL_MODULE_NMT_MN)) != 0)
75 #include "user/EplNmtMnu.h"
78 #include "kernel/EplDllkCal.h"
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>
88 #include <asm/uaccess.h>
89 #include <asm/atomic.h>
90 #include <linux/proc_fs.h>
91 #include <linux/spinlock.h>
93 #ifdef CONFIG_COLDFIRE
94 #include <asm/coldfire.h>
98 /***************************************************************************/
101 /* G L O B A L D E F I N I T I O N S */
104 /***************************************************************************/
106 //---------------------------------------------------------------------------
108 //---------------------------------------------------------------------------
110 #ifndef EPL_PROC_DEV_NAME
111 #define EPL_PROC_DEV_NAME "epl"
114 #ifndef DBG_TRACE_POINTS
115 #define DBG_TRACE_POINTS 23 // # of supported debug trace points
118 #ifndef DBG_TRACE_VALUES
119 #define DBG_TRACE_VALUES 24 // # of supported debug trace values (size of circular buffer)
122 //---------------------------------------------------------------------------
123 // modul global types
124 //---------------------------------------------------------------------------
126 //---------------------------------------------------------------------------
128 //---------------------------------------------------------------------------
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;
139 //---------------------------------------------------------------------------
140 // local function prototypes
141 //---------------------------------------------------------------------------
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);
148 void PUBLIC TgtDbgSignalTracePoint(BYTE bTracePointNumber_p);
149 void PUBLIC TgtDbgPostTraceValue(DWORD dwTraceValue_p);
151 EPLDLLEXPORT DWORD PUBLIC EplIdentuGetRunningRequests(void);
153 //=========================================================================//
155 // P U B L I C F U N C T I O N S //
157 //=========================================================================//
159 tEplKernel EplLinProcInit(void)
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
169 return kEplNoResource;
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;
179 return kEplSuccessful;
182 tEplKernel EplLinProcFree(void)
184 remove_proc_entry(EPL_PROC_DEV_NAME, NULL);
186 return kEplSuccessful;
189 //---------------------------------------------------------------------------
190 // Target specific event signaling (FEC Tx-/Rx-Interrupt, used by Edrv)
191 //---------------------------------------------------------------------------
193 #ifdef _DBG_TRACE_POINTS_
194 void PUBLIC TgtDbgSignalTracePoint(BYTE bTracePointNumber_p)
197 if (bTracePointNumber_p >=
198 (sizeof(aatmDbgTracePoint_l) / sizeof(aatmDbgTracePoint_l[0]))) {
202 atomic_inc(&aatmDbgTracePoint_l[bTracePointNumber_p]);
210 void PUBLIC TgtDbgPostTraceValue(DWORD dwTraceValue_p)
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;
220 spin_unlock_irqrestore(&spinlockDbgTraceValue_l, ulDbTraceValueFlags_l);
227 //---------------------------------------------------------------------------
228 // Read function for PROC-FS read access
229 //---------------------------------------------------------------------------
231 static int EplLinProcRead(char *pcBuffer_p,
234 int nBufferSize_p, int *pEof_p, void *pData_p)
239 tEplDllkCalStatistics *pDllkCalStats;
244 // count calls of this function
245 #ifdef _DBG_TRACE_POINTS_
246 TgtDbgSignalTracePoint(0);
249 //---------------------------------------------------------------
250 // generate static information
251 //---------------------------------------------------------------
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);
259 //---------------------------------------------------------------
260 // generate process information
261 //---------------------------------------------------------------
263 // ---- EPL state ----
264 nSize += snprintf(pcBuffer_p + nSize, nBufferSize_p - nSize,
265 "NMT state: 0x%04X\n",
266 (WORD) EplNmtkGetNmtState());
268 EplDllkCalGetStatistics(&pDllkCalStats);
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);
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());
285 // fetch state of NmtMnu module
287 unsigned int uiMandatorySlaveCount;
288 unsigned int uiSignalSlaveCount;
291 EplNmtMnuGetDiagnosticInfo(&uiMandatorySlaveCount,
292 &uiSignalSlaveCount, &wFlags);
294 nSize += snprintf(pcBuffer_p + nSize, nBufferSize_p - nSize,
295 "MN MandSlaveCount: %u SigSlaveCount: %u Flags: 0x%X\n",
296 uiMandatorySlaveCount, uiSignalSlaveCount,
302 // ---- FEC state ----
303 #ifdef CONFIG_COLDFIRE
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;
311 // Set the base address of FEC1
312 base_addr = FEC_BASE_ADDR_FEC1;
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));
324 // ---- DBG: TracePoints ----
325 #ifdef _DBG_TRACE_POINTS_
329 nSize += snprintf(pcBuffer_p + nSize, nBufferSize_p - nSize,
330 "DbgTracePoints:\n");
332 nNum < (sizeof(aatmDbgTracePoint_l) / sizeof(atomic_t));
335 snprintf(pcBuffer_p + nSize, nBufferSize_p - nSize,
336 " TracePoint[%2d]: %d\n", (int)nNum,
337 atomic_read(&aatmDbgTracePoint_l[nNum]));
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
345 snprintf(pcBuffer_p + nSize,
346 nBufferSize_p - nSize, "*%08lX",
347 adwDbgTraceValue_l[nNum]);
350 snprintf(pcBuffer_p + nSize,
351 nBufferSize_p - nSize, " %08lX",
352 adwDbgTraceValue_l[nNum]);
354 if ((nNum & 0x00000007) == 0x00000007) { // 8 values printed -> end of line reached
356 snprintf(pcBuffer_p + nSize,
357 nBufferSize_p - nSize, "\n");
360 if ((nNum & 0x00000007) != 0x00000007) { // number of values printed is not a multiple of 8 -> print new line
362 snprintf(pcBuffer_p + nSize, nBufferSize_p - nSize,
379 //---------------------------------------------------------------------------
380 // Write function for PROC-FS write access
381 //---------------------------------------------------------------------------
383 static int EplLinProcWrite(struct file *file, const char __user * buffer,
384 unsigned long count, void *data)
386 char abBuffer[count + 1];
389 tEplNmtEvent NmtEvent;
392 iErr = copy_from_user(abBuffer, buffer, count);
396 abBuffer[count] = '\0';
398 iErr = sscanf(abBuffer, "%i", &iVal);
400 if ((iVal <= 0) || (iVal > 0x2F)) {
401 NmtEvent = kEplNmtEventSwReset;
403 NmtEvent = (tEplNmtEvent) iVal;
405 // execute specified NMT command on write access of /proc/epl
406 EplNmtuNmtEvent(NmtEvent);