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 */