]> rtime.felk.cvut.cz Git - lincan.git/blob - lincan/src/can_devrtl.c
LinCAN can be compiled in mode with RT-Linux chip worker threads now.
[lincan.git] / lincan / src / can_devrtl.c
1 /* can_devrtl.c - CAN message queues functions for the RT-Linux
2  * Linux CAN-bus device driver.
3  * New CAN queues by Pavel Pisa - OCERA team member
4  * email:pisa@cmp.felk.cvut.cz
5  * This software is released under the GPL-License.
6  * Version lincan-0.2  9 Jul 2003
7  */
8
9 #ifdef CAN_WITH_RTL
10
11 #include "../include/can.h"
12 #include "../include/can_sysdep.h"
13 #include "../include/can_queue.h"
14 #include "../include/main.h"
15 #include "../include/setup.h"
16
17 #include <rtl_malloc.h>
18
19 unsigned int can_rtl_isr( unsigned int irq_num, struct pt_regs *r )
20 {
21         struct chip_t *chip;
22         struct candevice_t *candev;
23         int board_nr;
24         int chip_nr;
25         pthread_t thread=NULL;
26
27         DEBUGMSG("can_rtl_isr invoked for irq %d\n",irq_num);
28         
29         /* I hate next loop, but RT-Linux does not provide context to ISR */
30         for (board_nr=hardware_p->nr_boards; board_nr--; ) {
31                 if((candev=hardware_p->candevice[board_nr])==NULL)
32                         continue;
33                 for(chip_nr=candev->nr_all_chips; chip_nr--; ) {
34                         if((chip=candev->chip[chip_nr])==NULL)
35                                 continue;
36                         if(chip->chip_irq!=irq_num) continue;
37
38                         set_bit(MSGOBJ_IRQ_REQUEST_b,&chip->pend_flags);
39                         set_bit(MSGOBJ_WORKER_WAKE_b,&chip->pend_flags);
40                         
41                         if(!chip->worker_thread) continue;
42                         thread=chip->worker_thread;
43                         pthread_kill(thread,RTL_SIGNAL_WAKEUP);
44                 }
45         }
46
47         /*rtl_global_pend_irq(irq_num);*/
48
49         /*if(thread) rtl_reschedule_thread(thread);*/
50
51         rtl_schedule();
52
53         return 0;
54 }
55
56
57
58 /*
59 RTL_MARK_READY(pthread_self())
60 RTL_MARK_SUSPENDED(pthread_self());
61 return rtl_schedule();
62 can_enable_irq
63 can_disable_irq 
64 rtl_critical( state )
65 rtl_end_critical( state )
66 rtl_request_global_irq( irq, isr ); 
67 rtl_free_global_irq( irq )
68 */
69
70 void * can_chip_worker_thread(void *arg)
71 {
72         struct chip_t *chip = (struct chip_t *) arg;
73         struct msgobj_t *obj;
74         int ret, i;
75         int loop_cnt;
76         
77         if(!chip) return 0;
78         
79         
80         if (!(chip->flags & CHIP_CONFIGURED)){
81                 if (chip->chipspecops->chip_config(chip))
82                         CANMSG("Error configuring chip.\n");
83                 else
84                         chip->flags |= CHIP_CONFIGURED; 
85
86                 if((chip->msgobj[0])!=NULL)
87                         if (chip->chipspecops->pre_read_config(chip,chip->msgobj[0])<0)
88                                 CANMSG("Error initializing chip for receiving\n");
89                                 
90         } /* End of chip configuration */
91         set_bit(MSGOBJ_IRQ_REQUEST_b,&chip->pend_flags);
92         
93
94         while (1) {
95                 DEBUGMSG("Worker thread for chip %d active\n",chip->chip_idx);
96                 if(test_and_clear_bit(MSGOBJ_IRQ_REQUEST_b,&chip->pend_flags)){
97                         DEBUGMSG("IRQ_REQUEST processing ...\n");
98                         loop_cnt = 100;
99                         if(chip->chipspecops->irq_handler) do{
100                                 ret=chip->chipspecops->irq_handler(chip->chip_irq,chip,NULL);
101                         }while(ret && --loop_cnt);
102                         continue;
103                 }
104                 if(test_and_clear_bit(MSGOBJ_TX_REQUEST_b,&chip->pend_flags)){
105                         DEBUGMSG("TX_REQUEST processing ...\n");
106                         for(i=0;i<chip->max_objects;i++){
107                                 if((obj=chip->msgobj[i])==NULL)
108                                         continue;
109                                 if(!can_msgobj_test_and_clear_fl(obj,TX_REQUEST))
110                                         continue;
111                                 DEBUGMSG("Calling wakeup_tx\n");
112                                 chip->chipspecops->wakeup_tx(chip, obj);
113                         }
114                         continue;
115                 }
116
117                 /*re-enable chip IRQ, I am not sure, if this is required,
118                   but it seems to not work without that */
119                 if(chip->chip_irq>=0)
120                         can_enable_irq(chip->chip_irq);
121
122                 RTL_MARK_SUSPENDED(pthread_self());
123                 if(test_and_clear_bit(MSGOBJ_WORKER_WAKE_b,&chip->pend_flags)){
124                         RTL_MARK_READY(pthread_self());
125                         continue;
126                 }
127                 rtl_schedule();
128
129         }
130         return 0;
131 }
132
133
134 int can_chip_setup_irq(struct chip_t *chip)
135 {
136         int ret;
137         
138         if(chip==NULL)
139                 return -1;
140         if(chip->chipspecops->irq_handler){
141                 if (rtl_request_irq(chip->chip_irq,can_rtl_isr))
142                         return -1;
143                 else {
144                         DEBUGMSG("Registered interrupt %d\n",chip->chip_irq);
145                         chip->flags |= CHIP_IRQ_SETUP;
146                 }
147         }
148         ret=pthread_create(&chip->worker_thread, NULL, can_chip_worker_thread, chip);
149         if(ret<0) chip->worker_thread=NULL;
150         
151         return ret;
152 }
153
154
155 void can_chip_free_irq(struct chip_t *chip)
156 {
157         if(chip->worker_thread)
158                 pthread_delete_np(chip->worker_thread);
159         if((chip->flags & CHIP_IRQ_SETUP) && (chip->chip_irq>=0)) {
160                 rtl_free_irq(chip->chip_irq);
161                 chip->flags &= ~CHIP_IRQ_SETUP;
162         }
163 }
164
165
166 #endif /*CAN_WITH_RTL*/