00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139 #include <linux/module.h>
00140 #include <linux/init.h>
00141 #include <linux/kernel.h>
00142 #include <linux/version.h>
00143 #include <linux/errno.h>
00144 #include <linux/mm.h>
00145 #include <linux/vmalloc.h>
00146 #include <linux/poll.h>
00147 #include <linux/termios.h>
00148 #include <linux/tty_driver.h>
00149 #include <linux/console.h>
00150 #include <linux/slab.h>
00151 #include <linux/stat.h>
00152 #include <linux/proc_fs.h>
00153
00154 #include <rtai_fifos.h>
00155 #include <rtai_trace.h>
00156 #include <rtai_proc_fs.h>
00157 #include <rtai_sched.h>
00158 #include <rtai_lxrt.h>
00159
00160 MODULE_LICENSE("GPL");
00161
00162
00163 #define rtf_save_flags_and_cli(x) do{x=rt_spin_lock_irqsave(&rtf_lock);}while(0)
00164 #define rtf_restore_flags(x) rt_spin_unlock_irqrestore((x),&rtf_lock)
00165 #define rtf_spin_lock_irqsave(x,y) do{x=rt_spin_lock_irqsave(&(y));}while(0)
00166 #define rtf_spin_unlock_irqrestore(x,y) rt_spin_unlock_irqrestore((x),&(y))
00167 #define rtf_request_srq(x) rt_request_srq(0, (x), 0)
00168 #define rtf_free_srq(x) rt_free_srq((x))
00169 #define rtf_pend_srq(x) rt_pend_linux_srq((x))
00170
00171 #ifdef CONFIG_PROC_FS
00172 static int rtai_proc_fifo_register(void);
00173 static void rtai_proc_fifo_unregister(void);
00174 #endif
00175
00176 typedef struct lx_queue {
00177 struct lx_queue *prev;
00178 struct lx_queue *next;
00179 struct lx_task_struct *task;
00180 } F_QUEUE;
00181
00182 typedef struct lx_semaphore {
00183 int free;
00184 int qtype;
00185 F_QUEUE queue;
00186 } F_SEM;
00187
00188 typedef struct lx_task_struct {
00189 int blocked;
00190 int priority;
00191 F_QUEUE queue;
00192 struct task_struct *task;
00193 } LX_TASK;
00194
00195 typedef struct lx_mailbox {
00196 int size;
00197 int fbyte;
00198 int lbyte;
00199 int avbs;
00200 int frbs;
00201 char *bufadr;
00202 F_SEM sndsem, rcvsem;
00203 struct task_struct *waiting_task;
00204 spinlock_t buflock;
00205 } F_MBX;
00206
00207 typedef struct rt_fifo_struct {
00208 F_MBX mbx;
00209 int opncnt;
00210 int malloc_type;
00211 int pol_asyn_pended;
00212 wait_queue_head_t pollq;
00213 struct fasync_struct *asynq;
00214 rtf_handler_t handler;
00215 F_SEM sem;
00216 char name[RTF_NAMELEN+1];
00217 } FIFO;
00218
00219 static int fifo_srq, async_sig;
00220 static spinlock_t rtf_lock = SPIN_LOCK_UNLOCKED;
00221 static spinlock_t rtf_name_lock = SPIN_LOCK_UNLOCKED;
00222
00223 #define MAX_FIFOS 64
00224
00225 static FIFO *fifo;
00226
00227 #define MAXREQS 64 // KEEP IT A POWER OF 2!!!
00228 static struct { int in, out; struct task_struct *task[MAXREQS]; } taskq;
00229 static struct { int in, out; FIFO *fifo[MAXREQS]; } pol_asyn_q;
00230
00231 static int do_nothing(unsigned int arg, int rw) { return 0; }
00232
00233 static inline void enqueue_blocked(LX_TASK *task, F_QUEUE *queue, int qtype, int priority)
00234 {
00235 F_QUEUE *q;
00236
00237 task->blocked = 1;
00238 q = queue;
00239 if (!qtype) {
00240 while ((q = q->next) != queue && (q->task)->priority >= priority);
00241 }
00242 q->prev = (task->queue.prev = q->prev)->next = &(task->queue);
00243 task->queue.next = q;
00244 }
00245
00246 static inline void dequeue_blocked(LX_TASK *task)
00247 {
00248 task->blocked = 0;
00249 (task->queue.prev)->next = task->queue.next;
00250 (task->queue.next)->prev = task->queue.prev;
00251 }
00252
00253 static inline void mbx_sem_signal(F_SEM *sem, FIFO *fifop)
00254 {
00255 unsigned long flags;
00256 LX_TASK *task;
00257
00258 rtf_save_flags_and_cli(flags);
00259 if ((task = (sem->queue.next)->task)) {
00260 dequeue_blocked(task);
00261 taskq.task[taskq.in] = task->task;
00262 taskq.in = (taskq.in + 1) & (MAXREQS - 1);
00263 rtf_pend_srq(fifo_srq);
00264 } else {
00265 sem->free = 1;
00266 if (fifop && !(fifop->pol_asyn_pended) &&
00267 (((F_MBX *)fifop)->avbs || ((F_MBX *)fifop)->frbs) &&
00268 (waitqueue_active(&fifop->pollq) || fifop->asynq)) {
00269 fifop->pol_asyn_pended = 1;
00270 pol_asyn_q.fifo[pol_asyn_q.in] = fifop;
00271 pol_asyn_q.in = (pol_asyn_q.in + 1) & (MAXREQS - 1);
00272 rtf_pend_srq(fifo_srq);
00273 }
00274 }
00275 rtf_restore_flags(flags);
00276 return;
00277 }
00278
00279 static inline void mbx_signal(F_MBX *mbx)
00280 {
00281 unsigned long flags;
00282 struct task_struct *task;
00283
00284 rtf_save_flags_and_cli(flags);
00285 if ((task = mbx->waiting_task)) {
00286 mbx->waiting_task = 0;
00287 taskq.task[taskq.in] = task;
00288 taskq.in = (taskq.in + 1) & (MAXREQS - 1);
00289 rtf_pend_srq(fifo_srq);
00290 }
00291 rtf_restore_flags(flags);
00292 return;
00293 }
00294
00295 static inline int mbx_sem_wait_if(F_SEM *sem)
00296 {
00297 unsigned long flags;
00298
00299 rtf_save_flags_and_cli(flags);
00300 if (sem->free) {
00301 sem->free = 0;
00302 rtf_restore_flags(flags);
00303 return 1;
00304 }
00305 rtf_restore_flags(flags);
00306 return 0;
00307 }
00308
00309 static inline int mbx_sem_wait(F_SEM *sem)
00310 {
00311 unsigned long flags;
00312 LX_TASK task;
00313 int ret;
00314
00315 ret = 0;
00316 rtf_save_flags_and_cli(flags);
00317 if (!sem->free) {
00318 task.queue.task = &task;
00319 task.priority = current->rt_priority;
00320 enqueue_blocked(&task, &sem->queue, sem->qtype, task.priority);
00321 task.task = current;
00322 rtf_restore_flags(flags);
00323 current->state = TASK_INTERRUPTIBLE;
00324 schedule();
00325 if (signal_pending(current)) {
00326 ret = -ERESTARTSYS;
00327 }
00328 rtf_save_flags_and_cli(flags);
00329 if (task.blocked) {
00330 dequeue_blocked(&task);
00331 if (!(sem->queue.next)->task) {
00332 sem->free = 1;
00333 }
00334 if (!ret) {
00335 ret = -1;
00336 }
00337 }
00338 } else {
00339 sem->free = 0;
00340 }
00341 rtf_restore_flags(flags);
00342 return ret;
00343 }
00344
00345 static inline int mbx_wait(F_MBX *mbx, int *fravbs)
00346 {
00347 unsigned long flags;
00348
00349 rtf_save_flags_and_cli(flags);
00350 if (!(*fravbs)) {
00351 mbx->waiting_task = current;
00352 current->state = TASK_INTERRUPTIBLE;
00353 rtf_restore_flags(flags);
00354 schedule();
00355 if (signal_pending(current)) {
00356 return -ERESTARTSYS;
00357 }
00358 rtf_save_flags_and_cli(flags);
00359 if (mbx->waiting_task == current) {
00360 mbx->waiting_task = 0;
00361 rtf_restore_flags(flags);
00362 return -1;
00363 }
00364 }
00365 rtf_restore_flags(flags);
00366 return 0;
00367 }
00368
00369 static inline int mbx_sem_wait_timed(F_SEM *sem, int delay)
00370 {
00371 unsigned long flags;
00372 LX_TASK task;
00373
00374 rtf_save_flags_and_cli(flags);
00375 if (!sem->free) {
00376 task.queue.task = &task;
00377 task.priority = current->rt_priority;
00378 enqueue_blocked(&task, &sem->queue, sem->qtype, task.priority);
00379 task.task = current;
00380 rtf_restore_flags(flags);
00381 current->state = TASK_INTERRUPTIBLE;
00382 schedule_timeout(delay);
00383 if (signal_pending(current)) {
00384 return -ERESTARTSYS;
00385 }
00386 rtf_save_flags_and_cli(flags);
00387 if (task.blocked) {
00388 dequeue_blocked(&task);
00389 if (!((sem->queue.next)->task)) {
00390 sem->free = 1;
00391 }
00392 rtf_restore_flags(flags);
00393 return -1;
00394 }
00395 } else {
00396 sem->free = 0;
00397 }
00398 rtf_restore_flags(flags);
00399 return 0;
00400 }
00401
00402 static inline int mbx_wait_timed(F_MBX *mbx, int *fravbs, int delay)
00403 {
00404 unsigned long flags;
00405
00406 rtf_save_flags_and_cli(flags);
00407 if (!(*fravbs)) {
00408 mbx->waiting_task = current;
00409 rtf_restore_flags(flags);
00410 current->state = TASK_INTERRUPTIBLE;
00411 schedule_timeout(delay);
00412 if (signal_pending(current)) {
00413 return -ERESTARTSYS;
00414 }
00415 rtf_save_flags_and_cli(flags);
00416 if (mbx->waiting_task == current) {;
00417 mbx->waiting_task = 0;
00418 rtf_restore_flags(flags);
00419 return -1;
00420 }
00421 }
00422 rtf_restore_flags(flags);
00423 return 0;
00424 }
00425
00426 #define MOD_SIZE(indx) ((indx) < mbx->size ? (indx) : (indx) - mbx->size)
00427
00428 static inline int mbx_put(F_MBX *mbx, char **msg, int msg_size, int lnx)
00429 {
00430 unsigned long flags;
00431 int tocpy;
00432
00433 while (msg_size > 0 && mbx->frbs) {
00434 if ((tocpy = mbx->size - mbx->lbyte) > msg_size) {
00435 tocpy = msg_size;
00436 }
00437 if (tocpy > mbx->frbs) {
00438 tocpy = mbx->frbs;
00439 }
00440 if (lnx) {
00441 rt_copy_from_user(mbx->bufadr + mbx->lbyte, *msg, tocpy);
00442 } else {
00443 memcpy(mbx->bufadr + mbx->lbyte, *msg, tocpy);
00444 }
00445 rtf_spin_lock_irqsave(flags, mbx->buflock);
00446 mbx->lbyte = MOD_SIZE(mbx->lbyte + tocpy);
00447 mbx->frbs -= tocpy;
00448 mbx->avbs += tocpy;
00449 rtf_spin_unlock_irqrestore(flags, mbx->buflock);
00450 msg_size -= tocpy;
00451 *msg += tocpy;
00452 }
00453 return msg_size;
00454 }
00455
00456 static inline int mbx_ovrwr_put(F_MBX *mbx, char **msg, int msg_size, int lnx)
00457 {
00458 unsigned long flags;
00459 int tocpy,n;
00460
00461 if ((n = msg_size - mbx->size) > 0) {
00462 *msg += n;
00463 msg_size -= n;
00464 }
00465 while (msg_size > 0) {
00466 if (mbx->frbs) {
00467 if ((tocpy = mbx->size - mbx->lbyte) > msg_size) {
00468 tocpy = msg_size;
00469 }
00470 if (tocpy > mbx->frbs) {
00471 tocpy = mbx->frbs;
00472 }
00473 if (lnx) {
00474 rt_copy_from_user(mbx->bufadr + mbx->lbyte, *msg, tocpy);
00475 } else {
00476 memcpy(mbx->bufadr + mbx->lbyte, *msg, tocpy);
00477 }
00478 rtf_spin_lock_irqsave(flags, mbx->buflock);
00479 mbx->frbs -= tocpy;
00480 mbx->avbs += tocpy;
00481 rtf_spin_unlock_irqrestore(flags, mbx->buflock);
00482 msg_size -= tocpy;
00483 *msg += tocpy;
00484 mbx->lbyte = MOD_SIZE(mbx->lbyte + tocpy);
00485 }
00486 if (msg_size) {
00487 while ((n = msg_size - mbx->frbs) > 0) {
00488 if ((tocpy = mbx->size - mbx->fbyte) > n) {
00489 tocpy = n;
00490 }
00491 if (tocpy > mbx->avbs) {
00492 tocpy = mbx->avbs;
00493 }
00494 rtf_spin_lock_irqsave(flags, mbx->buflock);
00495 mbx->frbs += tocpy;
00496 mbx->avbs -= tocpy;
00497 rtf_spin_unlock_irqrestore(flags, mbx->buflock);
00498 mbx->fbyte = MOD_SIZE(mbx->fbyte + tocpy);
00499 }
00500 }
00501 }
00502 return 0;
00503 }
00504
00505 static inline int mbx_get(F_MBX *mbx, char **msg, int msg_size, int lnx)
00506 {
00507 unsigned long flags;
00508 int tocpy;
00509
00510 while (msg_size > 0 && mbx->avbs) {
00511 if ((tocpy = mbx->size - mbx->fbyte) > msg_size) {
00512 tocpy = msg_size;
00513 }
00514 if (tocpy > mbx->avbs) {
00515 tocpy = mbx->avbs;
00516 }
00517 if (lnx) {
00518 rt_copy_to_user(*msg, mbx->bufadr + mbx->fbyte, tocpy);
00519 } else {
00520 memcpy(*msg, mbx->bufadr + mbx->fbyte, tocpy);
00521 }
00522 rtf_spin_lock_irqsave(flags, mbx->buflock);
00523 mbx->fbyte = MOD_SIZE(mbx->fbyte + tocpy);
00524 mbx->frbs += tocpy;
00525 mbx->avbs -= tocpy;
00526 rtf_spin_unlock_irqrestore(flags, mbx->buflock);
00527 msg_size -= tocpy;
00528 *msg += tocpy;
00529 }
00530 return msg_size;
00531 }
00532
00533 static inline int mbx_evdrp(F_MBX *mbx, char **msg, int msg_size, int lnx)
00534 {
00535 int tocpy, fbyte, avbs;
00536
00537 fbyte = mbx->fbyte;
00538 avbs = mbx->avbs;
00539 while (msg_size > 0 && avbs) {
00540 if ((tocpy = mbx->size - fbyte) > msg_size) {
00541 tocpy = msg_size;
00542 }
00543 if (tocpy > avbs) {
00544 tocpy = avbs;
00545 }
00546 if (lnx) {
00547 rt_copy_to_user(*msg, mbx->bufadr + fbyte, tocpy);
00548 } else {
00549 memcpy(*msg, mbx->bufadr + fbyte, tocpy);
00550 }
00551 avbs -= tocpy;
00552 msg_size -= tocpy;
00553 *msg += tocpy;
00554 fbyte = MOD_SIZE(fbyte + tocpy);
00555 }
00556 return msg_size;
00557 }
00558
00559 static inline void mbx_sem_init(F_SEM *sem, int value)
00560 {
00561 sem->free = value;
00562 sem->qtype = 0;
00563 sem->queue.prev = &(sem->queue);
00564 sem->queue.next = &(sem->queue);
00565 sem->queue.task = 0;
00566 }
00567
00568 static inline int mbx_sem_delete(F_SEM *sem)
00569 {
00570 unsigned long flags;
00571 LX_TASK *task;
00572
00573 rtf_save_flags_and_cli(flags);
00574 while ((task = (sem->queue.next)->task)) {
00575 sem->queue.next = task->queue.next;
00576 (task->queue.next)->prev = &(sem->queue);
00577 taskq.task[taskq.in] = task->task;
00578 taskq.in = (taskq.in + 1) & (MAXREQS - 1);
00579 rtf_pend_srq(fifo_srq);
00580 }
00581 rtf_restore_flags(flags);
00582 return 0;
00583 }
00584
00585 static inline void mbx_init(F_MBX *mbx, int size, char *bufadr)
00586 {
00587 mbx_sem_init(&(mbx->sndsem), 1);
00588 mbx_sem_init(&(mbx->rcvsem), 1);
00589 mbx->waiting_task = 0;
00590 mbx->bufadr = bufadr;
00591 mbx->size = mbx->frbs = size;
00592 mbx->fbyte = mbx->lbyte = mbx->avbs = 0;
00593 #ifdef CONFIG_SMP
00594 spin_lock_init(&mbx->buflock);
00595 #endif
00596 spin_lock_init(&(mbx->buflock));
00597 }
00598
00599 static inline int mbx_delete(F_MBX *mbx)
00600 {
00601 mbx_signal(mbx);
00602 if (mbx_sem_delete(&(mbx->sndsem)) || mbx_sem_delete(&(mbx->rcvsem))) {
00603 return -EFAULT;
00604 }
00605 return 0;
00606 }
00607
00608 static inline int mbx_send(F_MBX *mbx, const char *msg, int msg_size, int lnx)
00609 {
00610 if (mbx_sem_wait(&(mbx->sndsem))) {
00611 return msg_size;
00612 }
00613 while (msg_size) {
00614 if (mbx_wait(mbx, &mbx->frbs)) {
00615 mbx_sem_signal(&(mbx->sndsem), (FIFO *)mbx);
00616 return msg_size;
00617 }
00618 msg_size = mbx_put(mbx, (char **)(&msg), msg_size, lnx);
00619 mbx_signal(mbx);
00620 }
00621 mbx_sem_signal(&(mbx->sndsem), (FIFO *)mbx);
00622 return 0;
00623 }
00624
00625 static inline int mbx_send_wp(F_MBX *mbx, const char *msg, int msg_size, int lnx)
00626 {
00627 unsigned long flags;
00628
00629 rtf_save_flags_and_cli(flags);
00630 if (mbx->sndsem.free && mbx->frbs) {
00631 mbx->sndsem.free = 0;
00632 rtf_restore_flags(flags);
00633 msg_size = mbx_put(mbx, (char **)(&msg), msg_size, lnx);
00634 mbx_signal(mbx);
00635 mbx_sem_signal(&(mbx->sndsem), (FIFO *)mbx);
00636 } else {
00637 rtf_restore_flags(flags);
00638 }
00639 return msg_size;
00640 }
00641
00642 static inline int mbx_send_if(F_MBX *mbx, const char *msg, int msg_size, int lnx)
00643 {
00644 unsigned long flags;
00645
00646 rtf_save_flags_and_cli(flags);
00647 if (mbx->sndsem.free && (mbx->frbs >= msg_size)) {
00648 mbx->sndsem.free = 0;
00649 rtf_restore_flags(flags);
00650 msg_size = mbx_put(mbx, (char **)(&msg), msg_size, lnx);
00651 mbx_signal(mbx);
00652 mbx_sem_signal(&(mbx->sndsem), (FIFO *)mbx);
00653 } else {
00654 rtf_restore_flags(flags);
00655 }
00656 return msg_size;
00657 }
00658
00659 static int mbx_send_timed(F_MBX *mbx, const char *msg, int msg_size, int delay, int lnx)
00660 {
00661 if (mbx_sem_wait_timed(&(mbx->sndsem), delay)) {
00662 return msg_size;
00663 }
00664 while (msg_size) {
00665 if (mbx_wait_timed(mbx, &(mbx->frbs), delay)) {
00666 mbx_sem_signal(&(mbx->sndsem), (FIFO *)mbx);
00667 return msg_size;
00668 }
00669 msg_size = mbx_put(mbx, (char **)(&msg), msg_size, lnx);
00670 mbx_signal(mbx);
00671 }
00672 mbx_sem_signal(&(mbx->sndsem), (FIFO *)mbx);
00673 return 0;
00674 }
00675
00676 static inline int mbx_receive(F_MBX *mbx, void *msg, int msg_size, int lnx)
00677 {
00678 if (mbx_sem_wait(&(mbx->rcvsem))) {
00679 return msg_size;
00680 }
00681 while (msg_size) {
00682 if (mbx_wait(mbx, &mbx->avbs)) {
00683 mbx_sem_signal(&(mbx->rcvsem), (FIFO *)mbx);
00684 return msg_size;
00685 }
00686 msg_size = mbx_get(mbx, (char **)(&msg), msg_size, lnx);
00687 mbx_signal(mbx);
00688 }
00689 mbx_sem_signal(&(mbx->rcvsem), (FIFO *)mbx);
00690 return 0;
00691 }
00692
00693 static inline int mbx_receive_wjo(F_MBX *mbx, void *msg, int msg_size, int lnx)
00694 {
00695 if (mbx_sem_wait(&(mbx->rcvsem))) {
00696 return msg_size;
00697 }
00698 if (msg_size) {
00699 if (mbx_wait(mbx, &mbx->avbs)) {
00700 mbx_sem_signal(&(mbx->rcvsem), (FIFO *)mbx);
00701 return msg_size;
00702 }
00703 msg_size = mbx_get(mbx, (char **)(&msg), msg_size, lnx);
00704 mbx_signal(mbx);
00705 }
00706 mbx_sem_signal(&(mbx->rcvsem), (FIFO *)mbx);
00707 return msg_size;
00708 }
00709
00710 static inline int mbx_receive_wp(F_MBX *mbx, void *msg, int msg_size, int lnx)
00711 {
00712 unsigned long flags;
00713
00714 rtf_save_flags_and_cli(flags);
00715 if (mbx->rcvsem.free && mbx->avbs) {
00716 mbx->rcvsem.free = 0;
00717 rtf_restore_flags(flags);
00718 msg_size = mbx_get(mbx, (char **)(&msg), msg_size, lnx);
00719 mbx_signal(mbx);
00720 mbx_sem_signal(&(mbx->rcvsem), (FIFO *)mbx);
00721 } else {
00722 rtf_restore_flags(flags);
00723 }
00724 return msg_size;
00725 }
00726
00727 static inline int mbx_receive_if(F_MBX *mbx, void *msg, int msg_size, int lnx)
00728 {
00729 unsigned long flags;
00730
00731 rtf_save_flags_and_cli(flags);
00732 if (mbx->rcvsem.free && mbx->avbs >= msg_size) {
00733 mbx->rcvsem.free = 0;
00734 rtf_restore_flags(flags);
00735 msg_size = mbx_get(mbx, (char **)(&msg), msg_size, lnx);
00736 mbx_signal(mbx);
00737 mbx_sem_signal(&(mbx->rcvsem), (FIFO *)mbx);
00738 } else {
00739 rtf_restore_flags(flags);
00740 }
00741 return msg_size;
00742 }
00743
00744 static int mbx_receive_timed(F_MBX *mbx, void *msg, int msg_size, int delay, int lnx)
00745 {
00746 if (mbx_sem_wait_timed(&(mbx->rcvsem), delay)) {
00747 return msg_size;
00748 }
00749 while (msg_size) {
00750 if (mbx_wait_timed(mbx, &(mbx->avbs), delay)) {
00751 mbx_sem_signal(&(mbx->rcvsem), (FIFO *)mbx);
00752 return msg_size;
00753 }
00754 msg_size = mbx_get(mbx, (char **)(&msg), msg_size, lnx);
00755 mbx_signal(mbx);
00756 }
00757 mbx_sem_signal(&(mbx->rcvsem), (FIFO *)mbx);
00758 return 0;
00759 }
00760
00761 static inline int mbx_ovrwr_send(F_MBX *mbx, void *msg, int msg_size, int lnx)
00762 {
00763 unsigned long flags;
00764
00765 rtf_save_flags_and_cli(flags);
00766 if (mbx->sndsem.free) {
00767 mbx->sndsem.free = 0;
00768 rtf_restore_flags(flags);
00769 msg_size = mbx_ovrwr_put(mbx, (char **)(&msg), msg_size, lnx);
00770 mbx_signal(mbx);
00771 mbx_sem_signal(&(mbx->sndsem), (FIFO *)mbx);
00772 } else {
00773 rtf_restore_flags(flags);
00774 }
00775 return msg_size;
00776 }
00777
00778 static void rtf_sysrq_handler(void)
00779 {
00780 FIFO *fifop;
00781 while (taskq.out != taskq.in) {
00782 if (taskq.task[taskq.out]->state == TASK_INTERRUPTIBLE) {
00783 wake_up_process(taskq.task[taskq.out]);
00784 }
00785 taskq.out = (taskq.out + 1) & (MAXREQS - 1);
00786 }
00787
00788 while (pol_asyn_q.out != pol_asyn_q.in) {
00789 fifop = pol_asyn_q.fifo[pol_asyn_q.out];
00790 fifop->pol_asyn_pended = 0;
00791 if (waitqueue_active(&(fifop = pol_asyn_q.fifo[pol_asyn_q.out])->pollq)) {
00792 wake_up_interruptible(&(fifop->pollq));
00793 }
00794 if (fifop->asynq) {
00795 kill_fasync(&fifop->asynq, async_sig, POLL_IN);
00796 }
00797 pol_asyn_q.out = (pol_asyn_q.out + 1) & (MAXREQS - 1);
00798 }
00799 set_tsk_need_resched(current);
00800 }
00801
00802 #define VALID_FIFO if (minor >= MAX_FIFOS) { return -ENODEV; } \
00803 if (!(fifo[minor].opncnt)) { return -EINVAL; }
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821 RTAI_SYSCALL_MODE int rtf_reset(unsigned int minor)
00822 {
00823 int semval;
00824 F_MBX *mbx;
00825
00826 VALID_FIFO;
00827
00828 TRACE_RTAI_FIFO(TRACE_RTAI_EV_FIFO_RESET, minor, 0);
00829
00830 mbx = &(fifo[minor].mbx);
00831 if (!mbx_sem_wait(&(mbx->rcvsem))) {
00832 while (!(semval = mbx_sem_wait_if(&mbx->sndsem)) && !mbx->waiting_task) {
00833 current->state = TASK_INTERRUPTIBLE;
00834 schedule_timeout(1);
00835 }
00836 } else {
00837 return -EBADF;
00838 }
00839 mbx->frbs = mbx->size;
00840 mbx->fbyte = mbx->lbyte = mbx->avbs = 0;
00841 if (semval) {
00842 mbx_sem_signal(&mbx->sndsem, (FIFO *)mbx);
00843 } else {
00844 mbx_signal(mbx);
00845 }
00846 mbx_sem_signal(&mbx->rcvsem, (FIFO *)mbx);
00847 return 0;
00848 }
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869
00870
00871 RTAI_SYSCALL_MODE int rtf_resize(unsigned int minor, int size)
00872 {
00873 void *oldbuf, *newbuf;
00874 int old_malloc_type, new_malloc_type, semval;
00875 F_MBX *mbx;
00876
00877 VALID_FIFO;
00878
00879 TRACE_RTAI_FIFO(TRACE_RTAI_EV_FIFO_RESIZE, minor, size);
00880
00881 mbx = &(fifo[minor].mbx);
00882 if (!size) {
00883 return -EINVAL;
00884 }
00885 if (size <= PAGE_SIZE*32) {
00886 if (!(newbuf = kmalloc(size, GFP_KERNEL))) {
00887 return -ENOMEM;
00888 }
00889 new_malloc_type = 'k';
00890 } else {
00891 if (!(newbuf = vmalloc(size))) {
00892 return -ENOMEM;
00893 }
00894 new_malloc_type = 'v';
00895 }
00896 if (!mbx_sem_wait(&(mbx->rcvsem))) {
00897 while (!(semval = mbx_sem_wait_if(&mbx->sndsem)) && !mbx->waiting_task) {
00898 current->state = TASK_INTERRUPTIBLE;
00899 schedule_timeout(1);
00900 }
00901 } else {
00902 return -EBADF;
00903 }
00904 if (size < mbx->avbs) {
00905 if (semval) {
00906 mbx_sem_signal(&mbx->sndsem, (FIFO *)mbx);
00907 }
00908 mbx_sem_signal(&mbx->rcvsem, (FIFO *)mbx);
00909 new_malloc_type == 'k' ? kfree(newbuf) : vfree(newbuf);
00910 return -EBUSY;
00911 }
00912 oldbuf = newbuf;
00913 mbx->frbs = mbx_get(mbx, (char **)(&oldbuf), size, 0);
00914 mbx->avbs = mbx->lbyte = size - mbx->frbs;
00915 mbx->fbyte = 0;
00916 oldbuf = mbx->bufadr;
00917 mbx->bufadr = newbuf;
00918 old_malloc_type = fifo[minor].malloc_type;
00919 fifo[minor].malloc_type = new_malloc_type;
00920 if (semval) {
00921 mbx->size = size;
00922 mbx_sem_signal(&mbx->sndsem, (FIFO *)mbx);
00923 } else if (size > mbx->size) {
00924 mbx->size = size;
00925 mbx_signal(mbx);
00926 }
00927 mbx_sem_signal(&mbx->rcvsem, (FIFO *)mbx);
00928 old_malloc_type == 'k' ? kfree(oldbuf) : vfree(oldbuf);
00929 return size;
00930 }
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954
00955
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971 RTAI_SYSCALL_MODE int rtf_create(unsigned int minor, int size)
00972 {
00973 void *buf;
00974
00975 if (minor >= MAX_FIFOS) {
00976 return -ENODEV;
00977 }
00978 TRACE_RTAI_FIFO(TRACE_RTAI_EV_FIFO_CREATE, minor, size);
00979 if (!atomic_cmpxchg((atomic_t *)&fifo[minor].opncnt, 0, 1)) {
00980 if (size <= PAGE_SIZE*32) {
00981 if (!(buf = kmalloc(size, GFP_KERNEL))) {
00982 fifo[minor].opncnt = 0;
00983 return -ENOMEM;
00984 }
00985 fifo[minor].malloc_type = 'k';
00986 } else {
00987 if (!(buf = vmalloc(size))) {
00988 fifo[minor].opncnt = 0;
00989 return -ENOMEM;
00990 }
00991 fifo[minor].malloc_type = 'v';
00992 }
00993 fifo[minor].handler = do_nothing;
00994 mbx_init(&(fifo[minor].mbx), size, buf);
00995 mbx_sem_init(&(fifo[minor].sem), 0);
00996 fifo[minor].pol_asyn_pended = 0;
00997 fifo[minor].asynq = 0;
00998 } else {
00999 if (size > fifo[minor].mbx.size) {
01000 rtf_resize(minor, size);
01001 }
01002 atomic_inc((atomic_t *)&fifo[minor].opncnt);
01003 }
01004 return 0;
01005 }
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020
01021
01022
01023
01024
01025
01026
01027
01028
01029
01030 RTAI_SYSCALL_MODE int rtf_destroy(unsigned int minor)
01031 {
01032 VALID_FIFO;
01033
01034 TRACE_RTAI_FIFO(TRACE_RTAI_EV_FIFO_DESTROY, minor, 0);
01035
01036 if (atomic_dec_and_test((atomic_t *)&fifo[minor].opncnt)) {
01037 if (fifo[minor].malloc_type == 'k') {
01038 kfree(fifo[minor].mbx.bufadr);
01039 } else {
01040 vfree(fifo[minor].mbx.bufadr);
01041 }
01042 fifo[minor].handler = do_nothing;
01043 mbx_delete(&(fifo[minor].mbx));
01044 fifo[minor].pol_asyn_pended = 0;
01045 fifo[minor].asynq = 0;
01046 fifo[minor].name[0] = 0;
01047 }
01048 return fifo[minor].opncnt;
01049 }
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075
01076
01077 int rtf_create_handler(unsigned int minor, void *handler)
01078 {
01079 if (minor >= MAX_FIFOS || !handler) {
01080 return -EINVAL;
01081 }
01082
01083 TRACE_RTAI_FIFO(TRACE_RTAI_EV_FIFO_CREATE_HANDLER, minor, handler);
01084
01085 fifo[minor].handler = handler;
01086 return 0;
01087 }
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113
01114
01115
01116 RTAI_SYSCALL_MODE int rtf_put(unsigned int minor, void *buf, int count)
01117 {
01118 VALID_FIFO;
01119
01120 TRACE_RTAI_FIFO(TRACE_RTAI_EV_FIFO_PUT, minor, count);
01121
01122 count -= mbx_send_wp(&(fifo[minor].mbx), buf, count, 0);
01123 return count;
01124 }
01125
01126 RTAI_SYSCALL_MODE int rtf_ovrwr_put(unsigned int minor, void *buf, int count)
01127 {
01128 VALID_FIFO;
01129 return mbx_ovrwr_send(&(fifo[minor].mbx), buf, count, 0);
01130 }
01131
01132 RTAI_SYSCALL_MODE int rtf_put_if(unsigned int minor, void *buf, int count)
01133 {
01134 VALID_FIFO;
01135
01136 count -= mbx_send_if(&(fifo[minor].mbx), buf, count, 0);
01137 return count;
01138 }
01139
01140 RTAI_SYSCALL_MODE int rtf_get_avbs(unsigned int minor)
01141 {
01142 VALID_FIFO;
01143 return fifo[minor].mbx.avbs;
01144 }
01145
01146 RTAI_SYSCALL_MODE int rtf_get_frbs(unsigned int minor)
01147 {
01148 VALID_FIFO;
01149 return fifo[minor].mbx.frbs;
01150 }
01151
01152
01153
01154
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184 RTAI_SYSCALL_MODE int rtf_get(unsigned int minor, void *buf, int count)
01185 {
01186 VALID_FIFO;
01187
01188 TRACE_RTAI_FIFO(TRACE_RTAI_EV_FIFO_GET, minor, count);
01189
01190 count -= mbx_receive_wp(&(fifo[minor].mbx), buf, count, 0);
01191 return count;
01192 }
01193
01194 int rtf_evdrp(unsigned int minor, void *msg, int msg_size)
01195 {
01196 VALID_FIFO;
01197
01198 return msg_size - mbx_evdrp(&(fifo[minor].mbx), (char **)(&msg), msg_size, 0);
01199 }
01200
01201 RTAI_SYSCALL_MODE int rtf_get_if(unsigned int minor, void *buf, int count)
01202 {
01203 VALID_FIFO;
01204
01205 return count - mbx_receive_if(&(fifo[minor].mbx), buf, count, 0);
01206 }
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229 RTAI_SYSCALL_MODE int rtf_sem_init(unsigned int minor, int value)
01230 {
01231 VALID_FIFO;
01232
01233 TRACE_RTAI_FIFO(TRACE_RTAI_EV_FIFO_SEM_INIT, minor, value);
01234
01235 mbx_sem_init(&(fifo[minor].sem), value);
01236 return 0;
01237 }
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257 RTAI_SYSCALL_MODE int rtf_sem_post(unsigned int minor)
01258 {
01259 VALID_FIFO;
01260
01261 TRACE_RTAI_FIFO(TRACE_RTAI_EV_FIFO_SEM_POST, minor, 0);
01262
01263 mbx_sem_signal(&(fifo[minor].sem), 0);
01264 return 0;
01265 }
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286 RTAI_SYSCALL_MODE int rtf_sem_trywait(unsigned int minor)
01287 {
01288 VALID_FIFO;
01289
01290 TRACE_RTAI_FIFO(TRACE_RTAI_EV_FIFO_SEM_TRY_WAIT, minor, 0);
01291
01292 return mbx_sem_wait_if(&(fifo[minor].sem));
01293 }
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313 RTAI_SYSCALL_MODE int rtf_sem_destroy(unsigned int minor)
01314 {
01315 VALID_FIFO;
01316
01317 TRACE_RTAI_FIFO(TRACE_RTAI_EV_FIFO_SEM_DESTROY, minor, 0);
01318
01319 return mbx_sem_delete(&(fifo[minor].sem));
01320 }
01321
01322 static int rtf_open(struct inode *inode, struct file *filp)
01323 {
01324 #define DEFAULT_SIZE 1000
01325 TRACE_RTAI_FIFO(TRACE_RTAI_EV_FIFO_OPEN, MINOR(inode->i_rdev), DEFAULT_SIZE);
01326
01327 return rtf_create(MINOR(inode->i_rdev), DEFAULT_SIZE);
01328 }
01329
01330 static int rtf_fasync(int fd, struct file *filp, int mode)
01331 {
01332 int minor;
01333 minor = MINOR((filp->f_dentry->d_inode)->i_rdev);
01334
01335 TRACE_RTAI_FIFO(TRACE_RTAI_EV_FIFO_FASYNC, minor, fd);
01336
01337 return fasync_helper(fd, filp, mode, &(fifo[minor].asynq));
01338 if (!mode) {
01339 fifo[minor].asynq = 0;
01340 }
01341 }
01342
01343 static int rtf_release(struct inode *inode, struct file *filp)
01344 {
01345 int minor;
01346 minor = MINOR(inode->i_rdev);
01347
01348 TRACE_RTAI_FIFO(TRACE_RTAI_EV_FIFO_RELEASE, minor, 0);
01349
01350 if (waitqueue_active(&(fifo[minor].pollq))) {
01351 wake_up_interruptible(&(fifo[minor].pollq));
01352 }
01353 rtf_fasync(-1, filp, 0);
01354 set_tsk_need_resched(current);
01355 return rtf_destroy(minor);
01356 }
01357
01358 static ssize_t rtf_read(struct file *filp, char *buf, size_t count, loff_t* ppos)
01359 {
01360 struct inode *inode = filp->f_dentry->d_inode;
01361 unsigned int minor = MINOR(inode->i_rdev);
01362 int handler_ret;
01363
01364 TRACE_RTAI_FIFO(TRACE_RTAI_EV_FIFO_READ, minor, count);
01365
01366 if (filp->f_flags & O_NONBLOCK) {
01367 count -= mbx_receive_wp(&(fifo[minor].mbx), buf, count, 1);
01368 if (!count) {
01369 return -EAGAIN;
01370 }
01371 } else {
01372 count -= mbx_receive_wjo(&(fifo[minor].mbx), buf, count, 1);
01373 }
01374
01375 if (count) {
01376 inode->i_atime = CURRENT_TIME;
01377 if ((handler_ret = (fifo[minor].handler)(minor, 'r')) < 0) {
01378 return handler_ret;
01379 }
01380 }
01381
01382 return count;
01383 }
01384
01385 static ssize_t rtf_write(struct file *filp, const char *buf, size_t count, loff_t* ppos)
01386 {
01387 struct inode *inode = filp->f_dentry->d_inode;
01388 unsigned int minor = MINOR(inode->i_rdev);
01389 int handler_ret;
01390
01391 TRACE_RTAI_FIFO(TRACE_RTAI_EV_FIFO_WRITE, minor, count);
01392
01393 if (filp->f_flags & O_NONBLOCK) {
01394 count -= mbx_send_wp(&(fifo[minor].mbx), (char *)buf, count, 1);
01395 if (!count) {
01396 return -EAGAIN;
01397 }
01398 } else {
01399 count -= mbx_send(&(fifo[minor].mbx), (char *)buf, count, 1);
01400 }
01401
01402 inode->i_ctime = inode->i_mtime = CURRENT_TIME;
01403 if ((handler_ret = (fifo[minor].handler)(minor, 'w')) < 0) {
01404 return handler_ret;
01405 }
01406
01407 return count;
01408 }
01409
01410 #define DELAY(x) (((x)*HZ + 500)/1000)
01411
01412 static int rtf_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
01413 {
01414 unsigned int minor;
01415 FIFO *fifop;
01416
01417 fifop = fifo + (minor = MINOR(inode->i_rdev));
01418
01419 TRACE_RTAI_FIFO(TRACE_RTAI_EV_FIFO_IOCTL, minor, cmd);
01420
01421 switch(cmd) {
01422 case RESET: {
01423 return rtf_reset(minor);
01424 }
01425 case RESIZE: {
01426 return rtf_resize(minor, arg);
01427 }
01428 case SUSPEND_TIMED: {
01429 TRACE_RTAI_FIFO(TRACE_RTAI_EV_FIFO_SUSPEND_TIMED, DELAY(arg), 0);
01430 current->state = TASK_INTERRUPTIBLE;
01431 schedule_timeout(DELAY(arg));
01432 if (signal_pending(current)) {
01433 return -ERESTARTSYS;
01434 }
01435 return 0;
01436 }
01437 case OPEN_SIZED: {
01438 return rtf_create(minor, arg);
01439 }
01440 case READ_ALL_AT_ONCE: {
01441 struct { char *buf; int count; } args;
01442 int handler_ret;
01443 TRACE_RTAI_FIFO(TRACE_RTAI_EV_FIFO_READ_ALLATONCE, 0, 0);
01444 rt_copy_from_user(&args, (void *)arg, sizeof(args));
01445 args.count -= mbx_receive(&(fifop->mbx), args.buf, args.count, 1);
01446 if (args.count) {
01447 inode->i_atime = CURRENT_TIME;
01448 if ((handler_ret = (fifo[minor].handler)(minor,
01449 'r')) < 0) {
01450 return handler_ret;
01451 }
01452 return args.count;
01453 }
01454 return 0;
01455 }
01456 case EAVESDROP: {
01457 struct { char *buf; int count; } args;
01458 rt_copy_from_user(&args, (void *)arg, sizeof(args));
01459 return args.count - mbx_evdrp(&(fifop->mbx), (char **)&args.buf, args.count, 1);
01460 }
01461 case READ_TIMED: {
01462 struct { char *buf; int count, delay; } args;
01463 int handler_ret;
01464 rt_copy_from_user(&args, (void *)arg, sizeof(args));
01465 TRACE_RTAI_FIFO(TRACE_RTAI_EV_FIFO_READ_TIMED, args.count, DELAY(args.delay));
01466 if (!args.delay) {
01467 args.count -= mbx_receive_wp(&(fifop->mbx), args.buf, args.count, 1);
01468 if (!args.count) {
01469 return -EAGAIN;
01470 }
01471 } else {
01472 args.count -= mbx_receive_timed(&(fifop->mbx), args.buf, args.count, DELAY(args.delay), 1);
01473 }
01474 if (args.count) {
01475 inode->i_atime = CURRENT_TIME;
01476
01477 if ((handler_ret = (fifop->handler)(minor, 'r')) < 0) {
01478 return handler_ret;
01479 }
01480 return args.count;
01481 }
01482 return 0;
01483 }
01484 case READ_IF: {
01485 struct { char *buf; int count; } args;
01486 int handler_ret;
01487 rt_copy_from_user(&args, (void *)arg, sizeof(args));
01488 args.count -= mbx_receive_if(&(fifop->mbx), args.buf, args.count, 1);
01489 if (args.count) {
01490 inode->i_atime = CURRENT_TIME;
01491 if ((handler_ret = (fifo[minor].handler)(minor, 'r')) < 0) {
01492 return handler_ret;
01493 }
01494 return args.count;
01495 }
01496 return 0;
01497 }
01498 case WRITE_TIMED: {
01499 struct { char *buf; int count, delay; } args;
01500 int handler_ret;
01501 rt_copy_from_user(&args, (void *)arg, sizeof(args));
01502 TRACE_RTAI_FIFO(TRACE_RTAI_EV_FIFO_WRITE_TIMED, args.count, DELAY(args.delay));
01503 if (!args.delay) {
01504 args.count -= mbx_send_wp(&(fifop->mbx), args.buf, args.count, 1);
01505 if (!args.count) {
01506 return -EAGAIN;
01507 }
01508 } else {
01509 args.count -= mbx_send_timed(&(fifop->mbx), args.buf, args.count, DELAY(args.delay), 1);
01510 }
01511 inode->i_ctime = inode->i_mtime = CURRENT_TIME;
01512
01513 if ((handler_ret = (fifop->handler)(minor, 'w')) < 0) {
01514 return handler_ret;
01515 }
01516 return args.count;
01517 }
01518 case WRITE_IF: {
01519 struct { char *buf; int count, delay; } args;
01520 int handler_ret;
01521 rt_copy_from_user(&args, (void *)arg, sizeof(args));
01522 if (args.count) {
01523 args.count -= mbx_send_wp(&(fifop->mbx), args.buf, args.count, 1);
01524 if (!args.count) {
01525 return -EAGAIN;
01526 }
01527 }
01528 inode->i_ctime = inode->i_mtime = CURRENT_TIME;
01529 if ((handler_ret = (fifo[minor].handler)(minor, 'w')) <
01530 0) {
01531 return handler_ret;
01532 }
01533 return args.count;
01534 }
01535 case OVRWRITE: {
01536 struct { char *buf; int count; } args;
01537 rt_copy_from_user(&args, (void *)arg, sizeof(args));
01538 return mbx_ovrwr_send(&(fifop->mbx), (char **)&args.buf, args.count, 1);
01539 }
01540 case RTF_SEM_INIT: {
01541 TRACE_RTAI_FIFO(TRACE_RTAI_EV_FIFO_SEM_INIT, minor, arg);
01542 mbx_sem_init(&(fifop->sem), arg);
01543 return 0;
01544 }
01545 case RTF_SEM_WAIT: {
01546 TRACE_RTAI_FIFO(TRACE_RTAI_EV_FIFO_SEM_WAIT, minor, 0);
01547 return mbx_sem_wait(&(fifop->sem));
01548 }
01549 case RTF_SEM_TRYWAIT: {
01550 TRACE_RTAI_FIFO(TRACE_RTAI_EV_FIFO_SEM_TRY_WAIT, minor, 0);
01551 return mbx_sem_wait_if(&(fifop->sem));
01552 }
01553 case RTF_SEM_TIMED_WAIT: {
01554 TRACE_RTAI_FIFO(TRACE_RTAI_EV_FIFO_SEM_TIMED_WAIT, minor, DELAY(arg));
01555 return mbx_sem_wait_timed(&(fifop->sem), DELAY(arg));
01556 }
01557 case RTF_SEM_POST: {
01558 TRACE_RTAI_FIFO(TRACE_RTAI_EV_FIFO_SEM_POST, minor, 0);
01559 mbx_sem_signal(&(fifop->sem), 0);
01560 return 0;
01561 }
01562 case RTF_SEM_DESTROY: {
01563 TRACE_RTAI_FIFO(TRACE_RTAI_EV_FIFO_SEM_DESTROY, minor, 0);
01564 mbx_sem_delete(&(fifop->sem));
01565 return 0;
01566 }
01567 case SET_ASYNC_SIG: {
01568 TRACE_RTAI_FIFO(TRACE_RTAI_EV_FIFO_SET_ASYNC_SIG, arg, 0);
01569 async_sig = arg;
01570 return 0;
01571 }
01572 case FIONREAD: {
01573 return put_user(fifo[minor].mbx.avbs, (int *)arg);
01574 }
01575
01576
01577
01578
01579 case RTF_GET_N_FIFOS: {
01580 return MAX_FIFOS;
01581 }
01582 case RTF_GET_FIFO_INFO: {
01583 struct rt_fifo_get_info_struct req;
01584 int i, n;
01585
01586 rt_copy_from_user(&req, (void *)arg, sizeof(req));
01587 for ( i = req.fifo, n = 0;
01588 i < MAX_FIFOS && n < req.n;
01589 i++, n++
01590 ) {
01591 struct rt_fifo_info_struct info;
01592
01593 info.fifo_number = i;
01594 info.size = fifo[i].mbx.size;
01595 info.opncnt = fifo[i].opncnt;
01596 info.avbs = fifo[i].mbx.avbs;
01597 info.frbs = fifo[i].mbx.frbs;
01598 strncpy(info.name, fifo[i].name, RTF_NAMELEN+1);
01599 rt_copy_to_user(req.ptr + n, &info, sizeof(info));
01600 }
01601 return n;
01602 }
01603 case RTF_NAMED_CREATE: {
01604 struct { char name[RTF_NAMELEN+1]; int size; } args;
01605
01606 rt_copy_from_user(&args, (void *)arg, sizeof(args));
01607 return rtf_named_create(args.name, args.size);
01608 }
01609 case RTF_CREATE_NAMED: {
01610 char name[RTF_NAMELEN+1];
01611
01612 rt_copy_from_user(name, (void *)arg, RTF_NAMELEN+1);
01613 return rtf_create_named(name);
01614 }
01615 case RTF_NAME_LOOKUP: {
01616 char name[RTF_NAMELEN+1];
01617
01618 rt_copy_from_user(name, (void *)arg, RTF_NAMELEN+1);
01619 return rtf_getfifobyname(name);
01620 }
01621 case TCGETS:
01622
01623 return -ENOTTY;
01624
01625 default : {
01626 printk("RTAI-FIFO: cmd %d is not implemented\n", cmd);
01627 return -EINVAL;
01628 }
01629 }
01630 return 0;
01631 }
01632
01633 static unsigned int rtf_poll(struct file *filp, poll_table *wait)
01634 {
01635 unsigned int retval, minor;
01636
01637 retval = 0;
01638 minor = MINOR((filp->f_dentry->d_inode)->i_rdev);
01639 TRACE_RTAI_FIFO(TRACE_RTAI_EV_FIFO_POLL, minor, 0);
01640 poll_wait(filp, &(fifo[minor].pollq), wait);
01641 if (fifo[minor].mbx.avbs) {
01642 retval |= POLLIN | POLLRDNORM;
01643 }
01644 if (fifo[minor].mbx.frbs) {
01645 retval |= POLLOUT | POLLWRNORM;
01646 }
01647 return retval;
01648 }
01649
01650 static loff_t rtf_llseek(struct file *filp, loff_t offset, int origin)
01651 {
01652 TRACE_RTAI_FIFO(TRACE_RTAI_EV_FIFO_LLSEEK, MINOR((filp->f_dentry->d_inode)->i_rdev), offset);
01653
01654 return rtf_reset(MINOR((filp->f_dentry->d_inode)->i_rdev));
01655 }
01656
01657 static struct file_operations rtf_fops =
01658 {
01659 owner: THIS_MODULE,
01660 llseek: rtf_llseek,
01661 read: rtf_read,
01662 write: rtf_write,
01663 poll: rtf_poll,
01664 ioctl: rtf_ioctl,
01665 open: rtf_open,
01666 release: rtf_release,
01667 fasync: rtf_fasync,
01668 };
01669
01670 #ifdef CONFIG_DEVFS_FS
01671 #include <linux/devfs_fs_kernel.h>
01672 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
01673 static devfs_handle_t devfs_handle;
01674 #endif
01675 #endif
01676
01677 static int MaxFifos = MAX_FIFOS;
01678 RTAI_MODULE_PARM(MaxFifos, int);
01679
01680 #define LXRTEXT
01681
01682 #ifdef LXRTEXT
01683
01684 static struct rt_fun_entry rtai_fifos_fun[] = {
01685 [_CREATE] = { 0, rtf_create },
01686 [_DESTROY] = { 0, rtf_destroy },
01687 [_PUT] = { 0, rtf_put },
01688 [_GET] = { 0, rtf_get },
01689 [_RESET] = { 0, rtf_reset },
01690 [_RESIZE] = { 0, rtf_resize },
01691 [_SEM_INIT] = { 0, rtf_sem_init },
01692 [_SEM_DESTRY] = { 0, rtf_sem_destroy },
01693 [_SEM_POST] = { 0, rtf_sem_post },
01694 [_SEM_TRY] = { 0, rtf_sem_trywait },
01695 [_CREATE_NAMED] = { 0, rtf_create_named },
01696 [_GETBY_NAME] = { 0, rtf_getfifobyname },
01697 [_OVERWRITE] = { 0, rtf_ovrwr_put },
01698 [_PUT_IF] = { 0, rtf_put_if },
01699 [_GET_IF] = { 0, rtf_get_if },
01700 [_AVBS] = { 0, rtf_get_avbs },
01701 [_FRBS] = { 0, rtf_get_frbs }
01702 };
01703
01704 static int register_lxrt_fifos_support(void)
01705 {
01706 if (set_rt_fun_ext_index(rtai_fifos_fun, FUN_FIFOS_LXRT_INDX)) {
01707 printk("LXRT EXTENSION SLOT FOR FIFOS (%d) ALREADY USED\n", FUN_FIFOS_LXRT_INDX);
01708 return -EACCES;
01709 }
01710 return 0;
01711 }
01712
01713 static void unregister_lxrt_fifos_support(void)
01714 {
01715 reset_rt_fun_ext_index(rtai_fifos_fun, FUN_FIFOS_LXRT_INDX);
01716 }
01717
01718 #else
01719
01720 static int register_lxrt_fifos_support(void) { return 0; }
01721 #define unregister_lxrt_fifos_support()
01722
01723 #endif
01724
01725 #define USE_UDEV_CLASS 1
01726
01727 #if USE_UDEV_CLASS
01728 static class_t *fifo_class = NULL;
01729 #endif
01730
01731 int __rtai_fifos_init(void)
01732 {
01733 int minor;
01734
01735 if (!(fifo = (FIFO *)kmalloc(MaxFifos*sizeof(FIFO), GFP_KERNEL))) {
01736 printk("RTAI-FIFO: cannot allocate memory for FIFOS structure.\n");
01737 return -ENOSPC;
01738 }
01739 memset(fifo, 0, MaxFifos*sizeof(FIFO));
01740
01741 #if USE_UDEV_CLASS
01742 if ((fifo_class = class_create(THIS_MODULE, "rtai_fifos")) == NULL) {
01743 printk("RTAI-FIFO: cannot create class.\n");
01744 return -EBUSY;
01745 }
01746 for (minor = 0; minor < MAX_FIFOS; minor++) {
01747 if (CLASS_DEVICE_CREATE(fifo_class, MKDEV(RTAI_FIFOS_MAJOR, minor), NULL, "rtf%d", minor) == NULL) {
01748 printk("RTAI-FIFO: cannot attach class.\n");
01749 class_destroy(fifo_class);
01750 return -EBUSY;
01751 }
01752 }
01753 #endif
01754
01755 if (register_chrdev(RTAI_FIFOS_MAJOR, "rtai_fifo", &rtf_fops)) {
01756 printk("RTAI-FIFO: cannot register major %d.\n", RTAI_FIFOS_MAJOR);
01757 return -EIO;
01758 }
01759
01760 if ((fifo_srq = rtf_request_srq(rtf_sysrq_handler)) < 0) {
01761 printk("RTAI-FIFO: no srq available in rtai.\n");
01762 return fifo_srq;
01763 }
01764 taskq.in = taskq.out = pol_asyn_q.in = pol_asyn_q.out = 0;
01765 async_sig = SIGIO;
01766
01767 for (minor = 0; minor < MAX_FIFOS; minor++) {
01768 fifo[minor].opncnt = fifo[minor].pol_asyn_pended = 0;
01769 init_waitqueue_head(&fifo[minor].pollq);
01770 fifo[minor].asynq = 0;;
01771 mbx_sem_init(&(fifo[minor].sem), 0);
01772 }
01773 #ifdef CONFIG_PROC_FS
01774 rtai_proc_fifo_register();
01775 #endif
01776 return register_lxrt_fifos_support();
01777 }
01778
01779 void __rtai_fifos_exit(void)
01780 {
01781 unregister_lxrt_fifos_support();
01782 unregister_chrdev(RTAI_FIFOS_MAJOR, "rtai_fifo");
01783
01784 #if USE_UDEV_CLASS
01785 {
01786 int minor;
01787 for (minor = 0; minor < MAX_FIFOS; minor++) {
01788 class_device_destroy(fifo_class, MKDEV(RTAI_FIFOS_MAJOR, minor));
01789 }
01790 class_destroy(fifo_class);
01791 }
01792 #endif
01793
01794 if (rtf_free_srq(fifo_srq) < 0) {
01795 printk("RTAI-FIFO: rtai srq %d illegal or already free.\n", fifo_srq);
01796 }
01797 #ifdef CONFIG_PROC_FS
01798 rtai_proc_fifo_unregister();
01799 #endif
01800 kfree(fifo);
01801 }
01802
01803 #ifndef CONFIG_RTAI_FIFOS_BUILTIN
01804 module_init(__rtai_fifos_init);
01805 module_exit(__rtai_fifos_exit);
01806 #endif
01807
01808 #ifdef CONFIG_PROC_FS
01809
01810
01811 static int rtai_read_fifos(char* buf, char** start, off_t offset,
01812 int len, int *eof, void *data)
01813 {
01814 int i;
01815
01816 len = sprintf(buf, "RTAI Real Time fifos status.\n\n" );
01817 if (len > LIMIT) {
01818 return(len);
01819 }
01820 len += sprintf(buf + len, "Maximum number of FIFOS %d.\n\n", MaxFifos);
01821 if (len > LIMIT) {
01822 return(len);
01823 }
01824 len += sprintf(buf+len, "fifo No Open Cnt Buff Size handler malloc type");
01825 if (len > LIMIT) {
01826 return(len);
01827 }
01828 len += sprintf(buf+len, " Name\n----------------");
01829 if (len > LIMIT) {
01830 return(len);
01831 }
01832 len += sprintf(buf+len, "-----------------------------------------\n");
01833 if (len > LIMIT) {
01834 return(len);
01835 }
01836
01837
01838
01839 for (i = 0; i < MAX_FIFOS; i++) {
01840 if (fifo[i].opncnt > 0) {
01841 len += sprintf( buf+len, "%-8d %-9d %-10d %-10p %-12s", i,
01842 fifo[i].opncnt, fifo[i].mbx.size,
01843 fifo[i].handler,
01844 fifo[i].malloc_type == 'v'
01845 ? "vmalloc" : "kmalloc"
01846 );
01847 if (len > LIMIT) {
01848 return(len);
01849 }
01850 len += sprintf(buf+len, "%s\n", fifo[i].name);
01851 if (len > LIMIT) {
01852 return(len);
01853 }
01854 }
01855 }
01856 return len;
01857
01858 }
01859
01860 static int rtai_proc_fifo_register(void)
01861 {
01862 struct proc_dir_entry *proc_fifo_ent;
01863 proc_fifo_ent = create_proc_entry("fifos", S_IFREG|S_IRUGO|S_IWUSR,
01864 rtai_proc_root);
01865 if (!proc_fifo_ent) {
01866 printk("Unable to initialize /proc/rtai/fifos\n");
01867 return(-1);
01868 }
01869 proc_fifo_ent->read_proc = rtai_read_fifos;
01870 return 0;
01871 }
01872
01873 static void rtai_proc_fifo_unregister(void)
01874 {
01875 remove_proc_entry("fifos", rtai_proc_root);
01876 }
01877
01878
01879 #endif
01880
01881
01882
01883
01884
01885 int rtf_named_create(const char *name, int size)
01886 {
01887 int minor, err;
01888 unsigned long flags;
01889
01890 if (strlen(name) > RTF_NAMELEN) {
01891 return -EINVAL;
01892 }
01893 rtf_spin_lock_irqsave(flags, rtf_name_lock);
01894 for (minor = 0; minor < MAX_FIFOS; minor++) {
01895 if (!strncmp(name, fifo[minor].name, RTF_NAMELEN)) {
01896 break;
01897 } else if (!fifo[minor].opncnt && !fifo[minor].name[0]) {
01898 strncpy(fifo[minor].name, name, RTF_NAMELEN + 1);
01899 rtf_spin_unlock_irqrestore(flags, rtf_name_lock);
01900 if ((err = rtf_create(minor, size)) < 0) {
01901 fifo[minor].name[0] = 0;
01902 return err;
01903 }
01904 return minor;
01905 }
01906 }
01907 rtf_spin_unlock_irqrestore(flags, rtf_name_lock);
01908 return -EBUSY;
01909 }
01910
01911 RTAI_SYSCALL_MODE int rtf_create_named(const char *name)
01912 {
01913 return rtf_named_create(name, DEFAULT_SIZE);
01914 }
01915
01916 RTAI_SYSCALL_MODE int rtf_getfifobyname(const char *name)
01917 {
01918 int minor;
01919
01920 if (strlen(name) > RTF_NAMELEN) {
01921 return -EINVAL;
01922 }
01923 for (minor = 0; minor < MAX_FIFOS; minor++) {
01924 if ( fifo[minor].opncnt &&
01925 !strncmp(name, fifo[minor].name, RTF_NAMELEN)
01926 ) {
01927 return minor;
01928 }
01929 }
01930 return -ENODEV;
01931 }
01932
01933 #ifdef CONFIG_KBUILD
01934 EXPORT_SYMBOL(rtf_create);
01935 EXPORT_SYMBOL(rtf_create_handler);
01936 EXPORT_SYMBOL(rtf_create_named);
01937 EXPORT_SYMBOL(rtf_destroy);
01938 EXPORT_SYMBOL(rtf_evdrp);
01939 EXPORT_SYMBOL(rtf_get);
01940 EXPORT_SYMBOL(rtf_get_if);
01941 EXPORT_SYMBOL(rtf_getfifobyname);
01942 EXPORT_SYMBOL(rtf_ovrwr_put);
01943 EXPORT_SYMBOL(rtf_put);
01944 EXPORT_SYMBOL(rtf_put_if);
01945 EXPORT_SYMBOL(rtf_get_avbs);
01946 EXPORT_SYMBOL(rtf_get_frbs);
01947 EXPORT_SYMBOL(rtf_reset);
01948 EXPORT_SYMBOL(rtf_resize);
01949 EXPORT_SYMBOL(rtf_sem_destroy);
01950 EXPORT_SYMBOL(rtf_sem_init);
01951 EXPORT_SYMBOL(rtf_sem_post);
01952 EXPORT_SYMBOL(rtf_sem_trywait);
01953 EXPORT_SYMBOL(rtf_named_create);
01954 #endif