/ src / rtapi / rtapi_proc.h
rtapi_proc.h
  1  #ifndef RTAPI_PROC_H
  2  #define RTAPI_PROC_H
  3  
  4  /** RTAPI is a library providing a uniform API for several real time
  5    operating systems.  As of ver 2.0, RTLinux and RTAI are supported.
  6  */
  7  /********************************************************************
  8  * Description:  rtai_proc.h
  9  *               This file, 'rtapi_proc.h', contains code that 
 10  *               implements several /proc filesystem entries that can 
 11  *               display the status of the RTAPI.
 12  *
 13  * Author: John Kasunich, Paul Corner
 14  * License: LGPL Version 2
 15  *    
 16  * Copyright (c) 2004 All rights reserved.
 17  *
 18  * Last change: 
 19  ********************************************************************/
 20  
 21  /** This file, 'rtapi_proc.h', contains code that implements several
 22      /proc filesystem entries that can display the status of the RTAPI.
 23      This code is common to both the RTAI and RTLinux implementations,
 24      and most likely to any other implementations under Linux.  This
 25      data is INTERNAL to the RTAPI implementation, and should not be
 26      included in any application modules.  This data also applies
 27      only to kernel modules, and should be included only in the
 28      real-time portion of the implementation.  Items that are common
 29      to both the realtime and user-space portions of the implementation
 30      are in rtapi_common.h.
 31  */
 32  
 33  /** Copyright (C) 2003 John Kasunich
 34                         <jmkasunich AT users DOT sourceforge DOT net>
 35      Copyright (C) 2003 Paul Corner
 36                         <paul_c AT users DOT sourceforge DOT net>
 37  
 38      This library is based on version 1.0, which was released into
 39      the public domain by its author, Fred Proctor.  Thanks Fred!
 40  */
 41  
 42  /* This library is free software; you can redistribute it and/or
 43    modify it under the terms of version 2.1 of the GNU Lesser General
 44    Public License as published by the Free Software Foundation.
 45    This library is distributed in the hope that it will be useful, but
 46    WITHOUT ANY WARRANTY; without even the implied warranty of
 47    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 48    Lesser General Public License for more details.
 49  
 50    You should have received a copy of the GNU Lesser General Public
 51    License along with this library; if not, write to the Free Software
 52    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 53  */
 54  
 55  /** THE AUTHORS OF THIS LIBRARY ACCEPT ABSOLUTELY NO LIABILITY FOR
 56      ANY HARM OR LOSS RESULTING FROM ITS USE.  IT IS _EXTREMELY_ UNWISE
 57      TO RELY ON SOFTWARE ALONE FOR SAFETY.  Any machinery capable of
 58      harming persons must have provisions for completely removing power
 59      from all motors, etc, before persons enter any danger area.  All
 60      machinery must be designed to comply with local and national safety
 61      codes, and the authors of this software can not, and do not, take
 62      any responsibility for such compliance.
 63  */
 64  
 65  /** This code was written as part of the EMC HAL project.  For more
 66      information, go to www.linuxcnc.org.
 67  */
 68  
 69  /* Internal function for the proc_fs system. */
 70  
 71  /* The proc file system is available in 2.2 and 2.4 kernels with 
 72    minor differences - The 2.4 kernels have a useful helper function
 73    for creating the proc_fs entries.
 74    It is unlikely that the following implimentaion will work on a 2.0
 75    series kernel..
 76  */
 77  #if defined( CONFIG_PROC_FS ) && LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)
 78  
 79  #define RTAPI_USE_PROCFS
 80  
 81  #include "procfs_macros.h"	/* macros for read functions */
 82  
 83  struct proc_dir_entry *rtapi_dir = 0;	/* /proc/rtapi directory */
 84  static struct proc_dir_entry *status_file = 0;	/* /proc/rtapi/status */
 85  static struct proc_dir_entry *modules_file = 0;	/* /proc/rtapi/modules */
 86  static struct proc_dir_entry *tasks_file = 0;	/* /proc/rtapi/tasks */
 87  static struct proc_dir_entry *shmem_file = 0;	/* /proc/rtapi/shmem */
 88  static struct proc_dir_entry *sems_file = 0;	/* /proc/rtapi/sems */
 89  static struct proc_dir_entry *fifos_file = 0;	/* /proc/rtapi/fifos */
 90  static struct proc_dir_entry *debug_file = 0;	/* /proc/rtapi/debug */
 91  
 92  /** The following are callback functions for the /proc filesystem
 93      When someone reads a /proc file, the appropriate function below
 94      is called, and it must generate output for the reader on the fly.
 95      These functions use the MOD_INC_USE_COUNT and MOD_DEC_USE_COUNT
 96      macros to make sure the RTAPI module is not removed while servicing
 97      a /proc request.
 98  */
 99  
100  static int proc_read_status(char *page, char **start, off_t off,
101      int count, int *eof, void *data)
102  {
103      PROC_PRINT_VARS;
104      PROC_PRINT("******* RTAPI STATUS ********\n");
105      PROC_PRINT("   RT Modules = %i\n", rtapi_data->rt_module_count);
106      PROC_PRINT("   UL Modules = %i\n", rtapi_data->ul_module_count);
107      PROC_PRINT("        Tasks = %i/%i\n", rtapi_data->task_count,
108  	RTAPI_MAX_TASKS);
109      PROC_PRINT("Shared memory = %i/%i\n", rtapi_data->shmem_count,
110  	RTAPI_MAX_SHMEMS);
111      PROC_PRINT("        FIFOs = %i/%i\n", rtapi_data->fifo_count,
112  	RTAPI_MAX_FIFOS);
113      PROC_PRINT("   Semaphores = %i/%i\n", rtapi_data->sem_count,
114  	RTAPI_MAX_SEMS);
115      PROC_PRINT("   Interrupts = %i\n", rtapi_data->irq_count);
116      PROC_PRINT("  RT task CPU = %i\n", rtapi_data->rt_cpu);
117      if (rtapi_data->timer_running) {
118  	PROC_PRINT(" Timer status = Running\n");
119  	PROC_PRINT(" Timer period = %li nSec\n", rtapi_data->timer_period);
120      } else {
121  	PROC_PRINT(" Timer status = Stopped\n");
122      }
123      PROC_PRINT("Message level = %i\n", msg_level);
124      PROC_PRINT("\n");
125      PROC_PRINT_DONE;
126  }
127  
128  static int proc_read_modules(char *page, char **start, off_t off,
129      int count, int *eof, void *data)
130  {
131      int n;
132      char *state_str;
133  
134      PROC_PRINT_VARS;
135      PROC_PRINT("******* RTAPI MODULES *******\n");
136      PROC_PRINT("ID  Type  Name\n");
137      for (n = 1; n <= RTAPI_MAX_MODULES; n++) {
138  	if (module_array[n].state != NO_MODULE) {
139  	    switch (module_array[n].state) {
140  	    case REALTIME:
141  		state_str = "RT  ";
142  		break;
143  	    case USERSPACE:
144  		state_str = "USER";
145  		break;
146  	    default:
147  		state_str = "????";
148  		break;
149  	    }
150  	    PROC_PRINT("%02d  %s  %s\n", n, state_str, module_array[n].name);
151  	}
152      }
153      PROC_PRINT("\n");
154      PROC_PRINT_DONE;
155  }
156  
157  static int proc_read_tasks(char *page, char **start, off_t off,
158      int count, int *eof, void *data)
159  {
160      int n;
161      char *state_str;
162  
163      PROC_PRINT_VARS;
164      PROC_PRINT("******** RTAPI TASKS ********\n");
165      PROC_PRINT("ID  Own  Prio  State     Code\n");
166      for (n = 1; n <= RTAPI_MAX_TASKS; n++) {
167  	if (task_array[n].state != EMPTY) {
168  	    switch (task_array[n].state) {
169  	    case PAUSED:
170  		state_str = "PAUSED  ";
171  		break;
172  	    case PERIODIC:
173  		state_str = "PERIODIC";
174  		break;
175  	    case FREERUN:
176  		state_str = "FREE RUN";
177  		break;
178  	    case ENDED:
179  		state_str = "ENDED   ";
180  		break;
181  	    default:
182  		state_str = "UNKNOWN ";
183  		break;
184  	    }
185  	    PROC_PRINT("%02d  %02d   %3d   %s  %p\n", n, task_array[n].owner,
186  		task_array[n].prio, state_str, task_array[n].taskcode);
187  	}
188      }
189      PROC_PRINT("\n");
190      PROC_PRINT_DONE;
191  }
192  
193  static int proc_read_shmem(char *page, char **start, off_t off,
194      int count, int *eof, void *data)
195  {
196      int n;
197  
198      PROC_PRINT_VARS;
199      PROC_PRINT("**** RTAPI SHARED MEMORY ****\n");
200      PROC_PRINT("ID  Users  Key         Size\n");
201      PROC_PRINT("    RT/UL                  \n");
202      for (n = 1; n <= RTAPI_MAX_SHMEMS; n++) {
203  	if (shmem_array[n].key != 0) {
204  	    PROC_PRINT("%02d  %2d/%-2d  %-10d  %-10lu\n",
205  		n, shmem_array[n].rtusers, shmem_array[n].ulusers,
206  		shmem_array[n].key, shmem_array[n].size);
207  	}
208      }
209      PROC_PRINT("\n");
210      PROC_PRINT_DONE;
211  }
212  
213  static int proc_read_sems(char *page, char **start, off_t off,
214      int count, int *eof, void *data)
215  {
216      int n;
217  
218      PROC_PRINT_VARS;
219      PROC_PRINT("***** RTAPI SEMAPHORES ******\n");
220      PROC_PRINT("ID  Users  Key\n");
221      for (n = 1; n <= RTAPI_MAX_SEMS; n++) {
222  	if (sem_array[n].users != 0) {
223  	    PROC_PRINT("%02d  %3d    %-10d\n",
224  		n, sem_array[n].users, sem_array[n].key);
225  	}
226      }
227      PROC_PRINT("\n");
228      PROC_PRINT_DONE;
229  }
230  
231  static int proc_read_fifos(char *page, char **start, off_t off,
232      int count, int *eof, void *data)
233  {
234      int n;
235      char *state_str;
236  
237      PROC_PRINT_VARS;
238      PROC_PRINT("******** RTAPI FIFOS ********\n");
239      PROC_PRINT("ID  State  Key         Size\n");
240      for (n = 1; n <= RTAPI_MAX_FIFOS; n++) {
241  	if (fifo_array[n].state != UNUSED) {
242  	    switch (fifo_array[n].state) {
243  	    case HAS_READER:
244  		state_str = "R-";
245  		break;
246  	    case HAS_WRITER:
247  		state_str = "-W";
248  		break;
249  	    case HAS_BOTH:
250  		state_str = "RW";
251  		break;
252  	    default:
253  		state_str = "UNKNOWN ";
254  		break;
255  	    }
256  	    PROC_PRINT("%02d   %s    %-10d  %-10ld\n",
257  		n, state_str, fifo_array[n].key, fifo_array[n].size);
258  	}
259      }
260      PROC_PRINT("\n");
261      PROC_PRINT_DONE;
262  }
263  
264  static int proc_read_debug(char *page, char **start, off_t off,
265      int count, int *eof, void *data)
266  {
267      PROC_PRINT_VARS;
268      PROC_PRINT("******* RTAPI MESSAGES ******\n");
269      PROC_PRINT("  Message Level  = %i\n", msg_level);
270      PROC_PRINT("  ERROR messages = %s\n",
271  	msg_level >= RTAPI_MSG_ERR ? "ON" : "OFF");
272      PROC_PRINT("WARNING messages = %s\n",
273  	msg_level >= RTAPI_MSG_WARN ? "ON" : "OFF");
274      PROC_PRINT("   INFO messages = %s\n",
275  	msg_level >= RTAPI_MSG_INFO ? "ON" : "OFF");
276      PROC_PRINT("  DEBUG messages = %s\n",
277  	msg_level >= RTAPI_MSG_DBG ? "ON" : "OFF");
278      PROC_PRINT("\n");
279      PROC_PRINT_DONE;
280  }
281  
282  static int proc_write_debug(struct file *file,
283      const char *buffer, unsigned long count, void *data)
284  {
285      char c;
286  
287      /* copy 1 byte from user space */
288      if (copy_from_user(&c, buffer, 1)) {
289  	return -1;
290      }
291      /* check it is a digit */
292      if (isdigit(c)) {
293  	/* convert to a number */
294  	msg_level = (int) (c - '0');
295  	/* cap the value if it is outside the valid range */
296  	if (msg_level < RTAPI_MSG_NONE) {
297  	    msg_level = RTAPI_MSG_NONE;
298  	}
299  	if (msg_level > RTAPI_MSG_ALL) {
300  	    msg_level = RTAPI_MSG_ALL;
301  	}
302      }
303      /* tell whoever called us that we used all the data, even though we
304         really only used the first byte */
305      return count;
306  }
307  
308  /** proc_init() initializes the /proc filesystem entries,
309      creating the directory and files, and linking them
310      to the appropriate callback functions. This function
311      is called from the init_module() function of the
312      RTAPI implementation.
313  */
314  
315  static int proc_init(void)
316  {
317      /* create the rtapi directory "/proc/rtapi" */
318      rtapi_dir = create_proc_entry("rtapi", S_IFDIR, NULL);
319      if (rtapi_dir == 0) {
320  	return -1;
321      }
322  
323      /* create read only file "/proc/rtapi/status" */
324      status_file = create_proc_entry("status", S_IRUGO, rtapi_dir);
325      if (status_file == NULL) {
326  	return -1;
327      }
328      status_file->read_proc = proc_read_status;
329  
330      /* create read only file "/proc/rtapi/modules" */
331      modules_file = create_proc_entry("modules", S_IRUGO, rtapi_dir);
332      if (modules_file == NULL) {
333  	return -1;
334      }
335      modules_file->read_proc = proc_read_modules;
336  
337      /* create read only file "/proc/rtapi/tasks" */
338      tasks_file = create_proc_entry("tasks", S_IRUGO, rtapi_dir);
339      if (tasks_file == NULL) {
340  	return -1;
341      }
342      tasks_file->read_proc = proc_read_tasks;
343  
344      /* create read only file "/proc/rtapi/shmem" */
345      shmem_file = create_proc_entry("shmem", S_IRUGO, rtapi_dir);
346      if (shmem_file == NULL) {
347  	return -1;
348      }
349      shmem_file->read_proc = proc_read_shmem;
350  
351      /* create read only file "/proc/rtapi/sems" */
352      sems_file = create_proc_entry("sems", S_IRUGO, rtapi_dir);
353      if (sems_file == NULL) {
354  	return -1;
355      }
356      sems_file->read_proc = proc_read_sems;
357  
358      /* create read only file "/proc/rtapi/fifos" */
359      fifos_file = create_proc_entry("fifos", S_IRUGO, rtapi_dir);
360      if (fifos_file == NULL) {
361  	return -1;
362      }
363      fifos_file->read_proc = proc_read_fifos;
364  
365      /* create read/write file "/proc/rtapi/debug" */
366      debug_file = create_proc_entry("debug", S_IRUGO | S_IWUGO, rtapi_dir);
367      if (debug_file == NULL) {
368  	return -1;
369      }
370      debug_file->data = NULL;
371      debug_file->read_proc = proc_read_debug;
372      debug_file->write_proc = proc_write_debug;
373      return 0;
374  }
375  
376  /** proc_clean() is called from the cleanup_module function of
377      of the RTAPI implementation.  It removes the rtapi entries
378      from the /proc filesystem.  Failing to remove a /proc
379      entry before the module is removed may cause kernel panics.
380  */
381  
382  static void proc_clean(void)
383  {
384      /* remove /proc entries, only if they exist */
385      if (rtapi_dir != NULL) {
386  	if (status_file != NULL) {
387  	    remove_proc_entry("status", rtapi_dir);
388  	    status_file = NULL;
389  	}
390  	if (modules_file != NULL) {
391  	    remove_proc_entry("modules", rtapi_dir);
392  	    modules_file = NULL;
393  	}
394  	if (tasks_file != NULL) {
395  	    remove_proc_entry("tasks", rtapi_dir);
396  	    tasks_file = NULL;
397  	}
398  	if (shmem_file != NULL) {
399  	    remove_proc_entry("shmem", rtapi_dir);
400  	    shmem_file = NULL;
401  	}
402  	if (sems_file != NULL) {
403  	    remove_proc_entry("sems", rtapi_dir);
404  	    sems_file = NULL;
405  	}
406  	if (fifos_file != NULL) {
407  	    remove_proc_entry("fifos", rtapi_dir);
408  	    fifos_file = NULL;
409  	}
410  	if (debug_file != NULL) {
411  	    remove_proc_entry("debug", rtapi_dir);
412  	    debug_file = NULL;
413  	}
414  	remove_proc_entry("rtapi", NULL);
415      }
416  }
417  
418  EXPORT_SYMBOL(rtapi_dir);
419  
420  #endif /* CONFIG_PROC_FS */
421  #endif /* RTAPI_PROC_H */