summaryrefslogtreecommitdiff
path: root/src/rtapi/rtapi_proc.h
blob: da740273afa772b580c8a04a0d3778860bdc9a1d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
#ifndef RTAPI_PROC_H
#define RTAPI_PROC_H

/** RTAPI is a library providing a uniform API for several real time
  operating systems.  As of ver 2.0, RTLinux and RTAI are supported.
*/
/********************************************************************
* Description:  rtai_proc.h
*               This file, 'rtapi_proc.h', contains code that 
*               implements several /proc filesystem entries that can 
*               display the status of the RTAPI.
*
* Author: John Kasunich, Paul Corner
* License: LGPL Version 2
*    
* Copyright (c) 2004 All rights reserved.
*
* Last change: 
********************************************************************/

/** This file, 'rtapi_proc.h', contains code that implements several
    /proc filesystem entries that can display the status of the RTAPI.
    This code is common to both the RTAI and RTLinux implementations,
    and most likely to any other implementations under Linux.  This
    data is INTERNAL to the RTAPI implementation, and should not be
    included in any application modules.  This data also applies
    only to kernel modules, and should be included only in the
    real-time portion of the implementation.  Items that are common
    to both the realtime and user-space portions of the implementation
    are in rtapi_common.h.
*/

/** Copyright (C) 2003 John Kasunich
                       <jmkasunich AT users DOT sourceforge DOT net>
    Copyright (C) 2003 Paul Corner
                       <paul_c AT users DOT sourceforge DOT net>

    This library is based on version 1.0, which was released into
    the public domain by its author, Fred Proctor.  Thanks Fred!
*/

/* This library is free software; you can redistribute it and/or
  modify it under the terms of version 2.1 of the GNU Lesser General
  Public License as published by the Free Software Foundation.
  This library is distributed in the hope that it will be useful, but
  WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public
  License along with this library; if not, write to the Free Software
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111 USA
*/

/** THE AUTHORS OF THIS LIBRARY ACCEPT ABSOLUTELY NO LIABILITY FOR
    ANY HARM OR LOSS RESULTING FROM ITS USE.  IT IS _EXTREMELY_ UNWISE
    TO RELY ON SOFTWARE ALONE FOR SAFETY.  Any machinery capable of
    harming persons must have provisions for completely removing power
    from all motors, etc, before persons enter any danger area.  All
    machinery must be designed to comply with local and national safety
    codes, and the authors of this software can not, and do not, take
    any responsibility for such compliance.
*/

/** This code was written as part of the EMC HAL project.  For more
    information, go to www.linuxcnc.org.
*/

/* Internal function for the proc_fs system. */

/* The proc file system is available in 2.2 and 2.4 kernels with 
  minor differences - The 2.4 kernels have a usefull helper function
  for creating the proc_fs entries.
  It is unlikely that the following implimentaion will work on a 2.0
  series kernel..
*/
#ifdef CONFIG_PROC_FS

#include "procfs_macros.h"	/* macros for read functions */

struct proc_dir_entry *rtapi_dir = 0;	/* /proc/rtapi directory */
static struct proc_dir_entry *status_file = 0;	/* /proc/rtapi/status */
static struct proc_dir_entry *modules_file = 0;	/* /proc/rtapi/modules */
static struct proc_dir_entry *tasks_file = 0;	/* /proc/rtapi/tasks */
static struct proc_dir_entry *shmem_file = 0;	/* /proc/rtapi/shmem */
static struct proc_dir_entry *sems_file = 0;	/* /proc/rtapi/sems */
static struct proc_dir_entry *fifos_file = 0;	/* /proc/rtapi/fifos */
static struct proc_dir_entry *debug_file = 0;	/* /proc/rtapi/debug */

/** The following are callback functions for the /proc filesystem
    When someone reads a /proc file, the appropriate function below
    is called, and it must generate output for the reader on the fly.
    These functions use the MOD_INC_USE_COUNT and MOD_DEC_USE_COUNT
    macros to make sure the RTAPI module is not removed while servicing
    a /proc request.
*/

static int proc_read_status(char *page, char **start, off_t off,
    int count, int *eof, void *data)
{
    PROC_PRINT_VARS;
    PROC_PRINT("******* RTAPI STATUS ********\n");
    PROC_PRINT("   RT Modules = %i\n", rtapi_data->rt_module_count);
    PROC_PRINT("   UL Modules = %i\n", rtapi_data->ul_module_count);
    PROC_PRINT("        Tasks = %i/%i\n", rtapi_data->task_count,
	RTAPI_MAX_TASKS);
    PROC_PRINT("Shared memory = %i/%i\n", rtapi_data->shmem_count,
	RTAPI_MAX_SHMEMS);
    PROC_PRINT("        FIFOs = %i/%i\n", rtapi_data->fifo_count,
	RTAPI_MAX_FIFOS);
    PROC_PRINT("   Semaphores = %i/%i\n", rtapi_data->sem_count,
	RTAPI_MAX_SEMS);
    PROC_PRINT("   Interrupts = %i\n", rtapi_data->irq_count);
    PROC_PRINT("  RT task CPU = %i\n", rtapi_data->rt_cpu);
    if (rtapi_data->timer_running) {
	PROC_PRINT(" Timer status = Running\n");
	PROC_PRINT(" Timer period = %li nSec\n", rtapi_data->timer_period);
    } else {
	PROC_PRINT(" Timer status = Stopped\n");
    }
    PROC_PRINT("Message level = %i\n", msg_level);
    PROC_PRINT("\n");
    PROC_PRINT_DONE;
}

static int proc_read_modules(char *page, char **start, off_t off,
    int count, int *eof, void *data)
{
    int n;
    char *state_str;

    PROC_PRINT_VARS;
    PROC_PRINT("******* RTAPI MODULES *******\n");
    PROC_PRINT("ID  Type  Name\n");
    for (n = 1; n <= RTAPI_MAX_MODULES; n++) {
	if (module_array[n].state != NO_MODULE) {
	    switch (module_array[n].state) {
	    case REALTIME:
		state_str = "RT  ";
		break;
	    case USERSPACE:
		state_str = "USER";
		break;
	    default:
		state_str = "????";
		break;
	    }
	    PROC_PRINT("%02d  %s  %s\n", n, state_str, module_array[n].name);
	}
    }
    PROC_PRINT("\n");
    PROC_PRINT_DONE;
}

static int proc_read_tasks(char *page, char **start, off_t off,
    int count, int *eof, void *data)
{
    int n;
    char *state_str;

    PROC_PRINT_VARS;
    PROC_PRINT("******** RTAPI TASKS ********\n");
    PROC_PRINT("ID  Own  Prio  State     Code\n");
    for (n = 1; n <= RTAPI_MAX_TASKS; n++) {
	if (task_array[n].state != EMPTY) {
	    switch (task_array[n].state) {
	    case PAUSED:
		state_str = "PAUSED  ";
		break;
	    case PERIODIC:
		state_str = "PERIODIC";
		break;
	    case FREERUN:
		state_str = "FREE RUN";
		break;
	    case ENDED:
		state_str = "ENDED   ";
		break;
	    default:
		state_str = "UNKNOWN ";
		break;
	    }
	    PROC_PRINT("%02d  %02d   %3d   %s  %p\n", n, task_array[n].owner,
		task_array[n].prio, state_str, task_array[n].taskcode);
	}
    }
    PROC_PRINT("\n");
    PROC_PRINT_DONE;
}

static int proc_read_shmem(char *page, char **start, off_t off,
    int count, int *eof, void *data)
{
    int n;

    PROC_PRINT_VARS;
    PROC_PRINT("**** RTAPI SHARED MEMORY ****\n");
    PROC_PRINT("ID  Users  Key         Size\n");
    PROC_PRINT("    RT/UL                  \n");
    for (n = 1; n <= RTAPI_MAX_SHMEMS; n++) {
	if (shmem_array[n].key != 0) {
	    PROC_PRINT("%02d  %2d/%-2d  %-10d  %-10lu\n",
		n, shmem_array[n].rtusers, shmem_array[n].ulusers,
		shmem_array[n].key, shmem_array[n].size);
	}
    }
    PROC_PRINT("\n");
    PROC_PRINT_DONE;
}

static int proc_read_sems(char *page, char **start, off_t off,
    int count, int *eof, void *data)
{
    int n;

    PROC_PRINT_VARS;
    PROC_PRINT("***** RTAPI SEMAPHORES ******\n");
    PROC_PRINT("ID  Users  Key\n");
    for (n = 1; n <= RTAPI_MAX_SEMS; n++) {
	if (sem_array[n].users != 0) {
	    PROC_PRINT("%02d  %3d    %-10d\n",
		n, sem_array[n].users, sem_array[n].key);
	}
    }
    PROC_PRINT("\n");
    PROC_PRINT_DONE;
}

static int proc_read_fifos(char *page, char **start, off_t off,
    int count, int *eof, void *data)
{
    int n;
    char *state_str;

    PROC_PRINT_VARS;
    PROC_PRINT("******** RTAPI FIFOS ********\n");
    PROC_PRINT("ID  State  Key         Size\n");
    for (n = 1; n <= RTAPI_MAX_FIFOS; n++) {
	if (fifo_array[n].state != UNUSED) {
	    switch (fifo_array[n].state) {
	    case HAS_READER:
		state_str = "R-";
		break;
	    case HAS_WRITER:
		state_str = "-W";
		break;
	    case HAS_BOTH:
		state_str = "RW";
		break;
	    default:
		state_str = "UNKNOWN ";
		break;
	    }
	    PROC_PRINT("%02d   %s    %-10d  %-10ld\n",
		n, state_str, fifo_array[n].key, fifo_array[n].size);
	}
    }
    PROC_PRINT("\n");
    PROC_PRINT_DONE;
}

static int proc_read_debug(char *page, char **start, off_t off,
    int count, int *eof, void *data)
{
    PROC_PRINT_VARS;
    PROC_PRINT("******* RTAPI MESSAGES ******\n");
    PROC_PRINT("  Message Level  = %i\n", msg_level);
    PROC_PRINT("  ERROR messages = %s\n",
	msg_level >= RTAPI_MSG_ERR ? "ON" : "OFF");
    PROC_PRINT("WARNING messages = %s\n",
	msg_level >= RTAPI_MSG_WARN ? "ON" : "OFF");
    PROC_PRINT("   INFO messages = %s\n",
	msg_level >= RTAPI_MSG_INFO ? "ON" : "OFF");
    PROC_PRINT("  DEBUG messages = %s\n",
	msg_level >= RTAPI_MSG_DBG ? "ON" : "OFF");
    PROC_PRINT("\n");
    PROC_PRINT_DONE;
}

static int proc_write_debug(struct file *file,
    const char *buffer, unsigned long count, void *data)
{
    char c;

    /* copy 1 byte from user space */
    if (copy_from_user(&c, buffer, 1)) {
	return -1;
    }
    /* check it is a digit */
    if (isdigit(c)) {
	/* convert to a number */
	msg_level = (int) (c - '0');
	/* cap the value if it is outside the valid range */
	if (msg_level < RTAPI_MSG_NONE) {
	    msg_level = RTAPI_MSG_NONE;
	}
	if (msg_level > RTAPI_MSG_ALL) {
	    msg_level = RTAPI_MSG_ALL;
	}
    }
    /* tell whoever called us that we used all the data, even though we
       really only used the first byte */
    return count;
}

/** proc_init() initializes the /proc filesystem entries,
    creating the directory and files, and linking them
    to the appropriate callback functions. This function
    is called from the init_module() function of the
    RTAPI implementation.
*/

static int proc_init(void)
{
    /* create the rtapi directory "/proc/rtapi" */
    rtapi_dir = create_proc_entry("rtapi", S_IFDIR, NULL);
    if (rtapi_dir == 0) {
	return -1;
    }

    /* create read only file "/proc/rtapi/status" */
    status_file = create_proc_entry("status", S_IRUGO, rtapi_dir);
    if (status_file == NULL) {
	return -1;
    }
    status_file->read_proc = proc_read_status;

    /* create read only file "/proc/rtapi/modules" */
    modules_file = create_proc_entry("modules", S_IRUGO, rtapi_dir);
    if (modules_file == NULL) {
	return -1;
    }
    modules_file->read_proc = proc_read_modules;

    /* create read only file "/proc/rtapi/tasks" */
    tasks_file = create_proc_entry("tasks", S_IRUGO, rtapi_dir);
    if (tasks_file == NULL) {
	return -1;
    }
    tasks_file->read_proc = proc_read_tasks;

    /* create read only file "/proc/rtapi/shmem" */
    shmem_file = create_proc_entry("shmem", S_IRUGO, rtapi_dir);
    if (shmem_file == NULL) {
	return -1;
    }
    shmem_file->read_proc = proc_read_shmem;

    /* create read only file "/proc/rtapi/sems" */
    sems_file = create_proc_entry("sems", S_IRUGO, rtapi_dir);
    if (sems_file == NULL) {
	return -1;
    }
    sems_file->read_proc = proc_read_sems;

    /* create read only file "/proc/rtapi/fifos" */
    fifos_file = create_proc_entry("fifos", S_IRUGO, rtapi_dir);
    if (fifos_file == NULL) {
	return -1;
    }
    fifos_file->read_proc = proc_read_fifos;

    /* create read/write file "/proc/rtapi/debug" */
    debug_file = create_proc_entry("debug", S_IRUGO | S_IWUGO, rtapi_dir);
    if (debug_file == NULL) {
	return -1;
    }
    debug_file->data = NULL;
    debug_file->read_proc = proc_read_debug;
    debug_file->write_proc = proc_write_debug;
    return 0;
}

/** proc_clean() is called from the cleanup_module function of
    of the RTAPI implementation.  It removes the rtapi entries
    from the /proc filesystem.  Failing to remove a /proc
    entry before the module is removed may cause kernel panics.
*/

static void proc_clean(void)
{
    /* remove /proc entries, only if they exist */
    if (rtapi_dir != NULL) {
	if (status_file != NULL) {
	    remove_proc_entry("status", rtapi_dir);
	    status_file = NULL;
	}
	if (modules_file != NULL) {
	    remove_proc_entry("modules", rtapi_dir);
	    modules_file = NULL;
	}
	if (tasks_file != NULL) {
	    remove_proc_entry("tasks", rtapi_dir);
	    tasks_file = NULL;
	}
	if (shmem_file != NULL) {
	    remove_proc_entry("shmem", rtapi_dir);
	    shmem_file = NULL;
	}
	if (sems_file != NULL) {
	    remove_proc_entry("sems", rtapi_dir);
	    sems_file = NULL;
	}
	if (fifos_file != NULL) {
	    remove_proc_entry("fifos", rtapi_dir);
	    fifos_file = NULL;
	}
	if (debug_file != NULL) {
	    remove_proc_entry("debug", rtapi_dir);
	    debug_file = NULL;
	}
	remove_proc_entry("rtapi", NULL);
    }
}

EXPORT_SYMBOL(rtapi_dir);

#endif /* CONFIG_PROC_FS */
#endif /* RTAPI_PROC_H */