#ifndef RTAPI_COMMON_H #define RTAPI_COMMON_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: rtapi_common.h * This file, 'rtapi_common.h', contains typedefs and * other items common to both the realtime and * non-realtime portions of the implementation. * * Author: John Kasunich, Paul Corner * License: LGPL Version 2 * * Copyright (c) 2004 All rights reserved. * * Last change: ********************************************************************/ /** This file, 'rtapi_common.h', contains typedefs and other items common to both the realtime and non-realtime portions of the implementation. These items are also common to both the RTAI and RTLinux implementations, and most likely to any other implementations in the Linux environment. This data is INTERNAL to the RTAPI implementation, and should not be included in any application modules. */ /** Copyright (C) 2003 John Kasunich Copyright (C) 2003 Paul Corner 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. */ /* Keep the includes here - It might get messy.. */ #ifdef RTAPI #include /* for blocking when needed */ #else #include /* for blocking when needed */ #endif #include "rtapi_bitops.h" /* maximum number of various resources */ #define RTAPI_MAX_MODULES 64 #define RTAPI_MAX_TASKS 64 #define RTAPI_MAX_SHMEMS 32 #define RTAPI_MAX_SEMS 64 #define RTAPI_MAX_FIFOS 32 #define RTAPI_MAX_IRQS 16 /* This file contains data structures that live in shared memory and are accessed by multiple different programs, both user processes and kernel modules. If the structure layouts used by various programs don't match, that's bad. So we have revision checking. Whenever a module or program is loaded, the rev_code is checked against the code in the shared memory area. If they don't match, the rtapi_init() call will faill. */ static unsigned int rev_code = 1; // increment this whenever you change the data structures /* These structs hold data associated with objects like tasks, etc. */ typedef enum { NO_MODULE = 0, REALTIME, USERSPACE } mod_type_t; typedef struct { mod_type_t state; char name[RTAPI_NAME_LEN + 1]; } module_data; typedef enum { EMPTY = 0, PAUSED, PERIODIC, FREERUN, ENDED } task_state_t; typedef struct { task_state_t state; /* task state */ int prio; /* priority */ int owner; /* owning module */ void (*taskcode) (void *); /* task code */ void *arg; /* task argument */ } task_data; typedef struct { int key; /* key to shared memory area */ int rtusers; /* number of realtime modules using block */ int ulusers; /* number of user processes using block */ unsigned long size; /* size of shared memory area */ unsigned long bitmap[(RTAPI_MAX_SHMEMS / 8) + 1]; /* which modules are using block */ } shmem_data; typedef struct { int users; /* number of modules using the semaphore */ int key; /* key to semaphore */ unsigned long bitmap[(RTAPI_MAX_SEMS / 8) + 1]; /* which modules are using sem */ } sem_data; typedef enum { UNUSED = 0, HAS_READER = 1, HAS_WRITER = 2, HAS_BOTH = 3 } fifo_state_t; /* used as bitmasks */ typedef struct { fifo_state_t state; /* task state */ int key; /* key to fifo */ int reader; /* module ID of reader */ int writer; /* module ID of writer */ unsigned long int size; /* size of fifo area */ } fifo_data; typedef struct { int irq_num; /* IRQ number */ int owner; /* owning module */ void (*handler) (void); /* interrupt handler function */ } irq_data; /* Master RTAPI data structure There is a single instance of this structure in the machine. It resides in shared memory, where it can be accessed by both realtime (RTAPI) and non-realtime (ULAPI) code. It contains all information about the current state of RTAPI/ULAPI and the associated resources (tasks, etc.). */ typedef struct { int magic; /* magic number to validate data */ int rev_code; /* revision code for matching */ unsigned long mutex; /* mutex against simultaneous access */ int rt_module_count; /* loaded RT modules */ int ul_module_count; /* running UL processes */ int task_count; /* task IDs in use */ int shmem_count; /* shared memory blocks in use */ int sem_count; /* semaphores in use */ int fifo_count; /* fifos in use */ int irq_count; /* interrupts hooked */ int timer_running; /* state of HW timer */ int rt_cpu; /* CPU to use for RT tasks */ long int timer_period; /* HW timer period */ module_data module_array[RTAPI_MAX_MODULES + 1]; /* data for modules */ task_data task_array[RTAPI_MAX_TASKS + 1]; /* data for tasks */ shmem_data shmem_array[RTAPI_MAX_SHMEMS + 1]; /* data for shared memory */ sem_data sem_array[RTAPI_MAX_SEMS + 1]; /* data for semaphores */ fifo_data fifo_array[RTAPI_MAX_FIFOS + 1]; /* data for fifos */ irq_data irq_array[RTAPI_MAX_IRQS + 1]; /* data for hooked irqs */ } rtapi_data_t; #define RTAPI_KEY 0x90280A48 /* key used to open RTAPI shared memory */ #define RTAPI_MAGIC 0x12601409 /* magic number used to verify shmem */ /* these pointers are initialized at startup to point to resource data in the master data structure above all access to the data structure should uses these pointers, they take into account the mapping of shared memory into either kernel or user space. (the RTAPI kernel module and each ULAPI user process has its own set of these vars, initialized to match that process's memory mapping.) */ rtapi_data_t *rtapi_data = NULL; module_data *module_array = NULL; task_data *task_array = NULL; shmem_data *shmem_array = NULL; sem_data *sem_array = NULL; fifo_data *fifo_array = NULL; irq_data *irq_array = NULL; /* global init code */ static void init_rtapi_data(rtapi_data_t * data) { int n, m; /* has the block already been initialized? */ if (data->magic == RTAPI_MAGIC) { /* yes, nothing to do */ return; } /* no, we need to init it, grab mutex unconditionally */ rtapi_mutex_try(&(data->mutex)); /* set magic number so nobody else init's the block */ data->magic = RTAPI_MAGIC; /* set version code so other modules can check it */ data->rev_code = rev_code; /* and get busy */ data->rt_module_count = 0; data->ul_module_count = 0; data->task_count = 0; data->shmem_count = 0; data->sem_count = 0; data->fifo_count = 0; data->irq_count = 0; data->timer_running = 0; data->timer_period = 0; /* init the arrays */ for (n = 0; n <= RTAPI_MAX_MODULES; n++) { data->module_array[n].state = EMPTY; data->module_array[n].name[0] = '\0'; } for (n = 0; n <= RTAPI_MAX_TASKS; n++) { data->task_array[n].state = EMPTY; data->task_array[n].prio = 0; data->task_array[n].owner = 0; data->task_array[n].taskcode = NULL; } for (n = 0; n <= RTAPI_MAX_SHMEMS; n++) { data->shmem_array[n].key = 0; data->shmem_array[n].rtusers = 0; data->shmem_array[n].ulusers = 0; data->shmem_array[n].size = 0; for (m = 0; m < (RTAPI_MAX_SHMEMS / 8) + 1; m++) { data->shmem_array[n].bitmap[m] = 0; } } for (n = 0; n <= RTAPI_MAX_SEMS; n++) { data->sem_array[n].users = 0; data->sem_array[n].key = 0; for (m = 0; m < (RTAPI_MAX_SEMS / 8) + 1; m++) { data->sem_array[n].bitmap[m] = 0; } } for (n = 0; n <= RTAPI_MAX_FIFOS; n++) { data->fifo_array[n].state = UNUSED; data->fifo_array[n].key = 0; data->fifo_array[n].size = 0; data->fifo_array[n].reader = 0; data->fifo_array[n].writer = 0; } for (n = 0; n <= RTAPI_MAX_IRQS; n++) { data->irq_array[n].irq_num = 0; data->irq_array[n].owner = 0; data->irq_array[n].handler = NULL; } /* done, release the mutex */ rtapi_mutex_give(&(data->mutex)); return; } #endif /* RTAPI_COMMON_H */