3 * Copyright (c) 2003 The Regents of the University of California. All
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * - Neither the name of the University nor the names of its
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS''
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
19 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
20 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
21 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
25 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 * FUSD: the Framework for User-Space Devices
35 * Jeremy Elson <jelson@circlemud.org>
36 * Copyright (c) Sensoria Corporation 2001
38 * Private header file used by the Linux Kernel Module
48 /* magic numbers for structure checking; unique w.r.t
49 * /usr/src/linux/Documentation/magic-number.txt */
50 #define FUSD_DEV_MAGIC 0x8b43a123
51 #define FUSD_FILE_MAGIC 0x613aa8fe
53 /* number of devices that can be created with fusd */
54 #define MAX_FUSD_DEVICES 128
56 /* number of times each device can be opened simultaneously */
57 #define MIN_FILEARRAY_SIZE 8 /* initialize allocation */
58 #define MAX_FILEARRAY_SIZE 1024 /* maximum it can grow to */
60 /* maximum read/write size we're willing to service */
61 #define MAX_RW_SIZE (1024*128)
64 /********************** Structure Definitions *******************************/
66 /* Container for a fusd msg */
67 typedef struct fusd_msgC_s_t fusd_msgC_t
;
69 struct fusd_msgC_s_t
{
70 fusd_msg_t fusd_msg
; /* the message itself */
71 fusd_msgC_t
*next
; /* pointer to next one in the list */
74 unsigned int peeked
:1; /* has the first half of this been read? */
77 struct fusd_transaction
79 struct list_head list
;
87 /* magical forward declarations to break the circular dependency */
89 typedef struct fusd_dev_t_s fusd_dev_t
;
93 /* state kept per opened file (i.e., an instance of a device) */
95 /* general state management */
96 int magic
; /* magic number for sanity checking */
97 fusd_dev_t
*fusd_dev
; /* fusd device associated with this file */
98 long fusd_dev_version
; /* version number of fusd device */
99 void *private_data
; /* the user's private data (we ignore it) */
100 struct file
*file
; /* kernel's file pointer for this file */
101 int index
; /* our index in our device's file array */
102 struct semaphore file_sem
; /* Semaphore for file structure */
103 int cached_poll_state
; /* Latest result from a poll diff req */
104 int last_poll_sent
; /* Last polldiff request we sent */
106 /* structures used for messaging */
107 wait_queue_head_t file_wait
; /* Wait on this for a user->kernel msg */
108 wait_queue_head_t poll_wait
; /* Given to kernel for poll() queue */
109 struct list_head transactions
;
110 struct semaphore transactions_sem
;
115 /* state kept per device registered under fusd */
116 struct fusd_dev_t_s
{
117 int magic
; /* Magic number for sanity checking */
118 long version
; /* Instance number of this device */
119 int zombie
; /* Is the device dead? */
120 pid_t pid
; /* PID of device driver */
121 struct task_struct
* task
;
123 char *name
; /* Name of the device under devfs (/dev) */
128 struct class_device
*class_device
;
130 void *private_data
; /* User's private data */
134 fusd_file_t
**files
; /* Array of this device's open files */
135 int array_size
; /* Size of the array pointed to by 'files' */
136 int num_files
; /* Number of array entries that are valid */
137 int open_in_progress
; /* File is referencing this struct,
138 but not yet part of the file array */
140 fusd_msgC_t
*msg_head
; /* linked list head for message queue */
141 fusd_msgC_t
*msg_tail
; /* linked list tail for message queue */
143 /* synchronization */
144 wait_queue_head_t dev_wait
; /* Wait queue for kernel->user msgs */
145 struct semaphore dev_sem
; /* Sempahore for device structure */
147 /* pointer to allow a dev to be placed on a dev_list */
148 struct list_head devlist
;
152 /**** Function Prototypes ****/
154 STATIC
int maybe_free_fusd_dev(fusd_dev_t
*fusd_dev
);
156 STATIC
int find_fusd_file(fusd_dev_t
*fusd_dev
, fusd_file_t
*fusd_file
);
157 STATIC
int free_fusd_file(fusd_dev_t
*fusd_dev
, fusd_file_t
*fusd_file
);
159 STATIC
int fusd_fops_call_send(fusd_file_t
*fusd_file_arg
,
160 fusd_msg_t
*fusd_msg
, struct fusd_transaction
** transaction
);
161 STATIC
int fusd_fops_call_wait(fusd_file_t
*fusd_file_arg
,
162 fusd_msg_t
**fusd_msg_reply
, struct fusd_transaction
* transaction
);
163 STATIC
void fusd_fops_call_done(fusd_file_t
*fusd_file
);
165 STATIC
void fusd_forge_close(fusd_msg_t
*msg
, fusd_dev_t
*fusd_dev
);
167 STATIC
int fusd_add_transaction(fusd_file_t
*fusd_file
, int transid
, int subcmd
, int size
, struct fusd_transaction
** out_transaction
);
168 STATIC
void fusd_cleanup_transaction(fusd_file_t
*fusd_file
, struct fusd_transaction
* transaction
);
169 STATIC
void fusd_remove_transaction(fusd_file_t
*fusd_file
, struct fusd_transaction
* transaction
);
170 STATIC
struct fusd_transaction
* fusd_find_transaction(fusd_file_t
*fusd_file
, int transid
);
171 STATIC
struct fusd_transaction
* fusd_find_transaction_by_pid(fusd_file_t
*fusd_file
, int pid
);
175 /**** Utility functions & macros ****/
177 #ifdef CONFIG_FUSD_USE_WAKEUPSYNC
178 #define WAKE_UP_INTERRUPTIBLE_SYNC(x) wake_up_interruptible_sync(x)
180 #define WAKE_UP_INTERRUPTIBLE_SYNC(x) wake_up_interruptible(x)
181 #endif /* CONFIG_FUSD_USE_WAKEUPSYNC */
183 #ifdef CONFIG_FUSD_DEBUG
184 static void rdebug_real(char *fmt
, ...)
185 __attribute__ ((format (printf
, 1, 2)));
187 #define RDEBUG(message_level, args...) do { \
188 if (fusd_debug_level >= message_level) rdebug_real(args); \
191 #define RDEBUG(message_level, args...)
192 #endif /* CONFIG_FUSD_DEBUG */
195 #define ZOMBIE(fusd_dev) ((fusd_dev)->zombie)
198 #define GET_FUSD_DEV(candidate, fusd_dev) do { \
199 fusd_dev = candidate; \
200 if (fusd_dev == NULL || fusd_dev->magic != FUSD_DEV_MAGIC) \
204 #define GET_FUSD_FILE_AND_DEV(candidate, fusd_file, fusd_dev) do { \
205 fusd_file = candidate; \
206 if (fusd_file == NULL || fusd_file->magic != FUSD_FILE_MAGIC) \
208 GET_FUSD_DEV(fusd_file->fusd_dev, fusd_dev); \
209 if (fusd_dev->version != fusd_file->fusd_dev_version) \
214 #define LOCK_FUSD_DEV(fusd_dev) \
215 do { down(&fusd_dev->dev_sem); \
216 if (ZOMBIE(fusd_dev)) { up(&fusd_dev->dev_sem); goto zombie_dev; } \
219 /* rawlock does not do a zombie check */
220 #define RAWLOCK_FUSD_DEV(fusd_dev) \
221 do { down(&fusd_dev->dev_sem); } while (0)
223 #define UNLOCK_FUSD_DEV(fusd_dev) \
224 do { up(&fusd_dev->dev_sem); } while (0)
227 #define LOCK_FUSD_FILE(fusd_file) \
228 do { down(&fusd_file->file_sem); \
231 #define UNLOCK_FUSD_FILE(fusd_file) \
232 do { up(&fusd_file->file_sem); } while (0)
234 #define FREE_FUSD_MSGC(fusd_msgc) do { \
235 if ((fusd_msgc)->fusd_msg.data != NULL) VFREE(fusd_msgc->fusd_msg.data); \
239 #define NAME(fusd_dev) ((fusd_dev)->name == NULL ? \
240 "<noname>" : (fusd_dev)->name)
242 #ifdef CONFIG_FUSD_MEMDEBUG
243 static int fusd_mem_init(void);
244 static void fusd_mem_cleanup(void);
245 static void fusd_mem_add(void *ptr
, int line
, int size
);
246 static void fusd_mem_del(void *ptr
);
247 static void *fusd_kmalloc(size_t size
, int type
, int line
);
248 static void fusd_kfree(void *ptr
);
249 static void *fusd_vmalloc(size_t size
, int line
);
250 static void fusd_vfree(void *ptr
);
251 # define KMALLOC(size, type) fusd_kmalloc(size, type, __LINE__)
252 # define KFREE(ptr) fusd_kfree(ptr)
253 # define VMALLOC(size) fusd_vmalloc(size, __LINE__)
254 # define VFREE(ptr) fusd_vfree(ptr)
255 #else /* no memory debugging */
256 # define KMALLOC(size, type) kmalloc(size, type)
257 # define KFREE(ptr) kfree(ptr)
258 /*# define VMALLOC(size) vmalloc(size)*/
259 # define VMALLOC(size) kmalloc(size, GFP_KERNEL)
260 # define VFREE(ptr) kfree(ptr)
261 #endif /* CONFIG_FUSD_MEMDEBUG */
265 /* Functions like this should be in the kernel, but they are not. Sigh. */
268 DECLARE_MUTEX(atomic_ops
);
270 static __inline__
int atomic_inc_and_ret(int *i
)
280 static __inline__
int atomic_inc_and_ret(int *i
)
287 #endif /* __KFUSD_H__ */