]> rtime.felk.cvut.cz Git - lincan.git/blob - lincan/src/irq.c
caf0ac6ebda7eec416401f8c68f1b8756a3d4514
[lincan.git] / lincan / src / irq.c
1 /* irq.c
2  * Linux CAN-bus device driver.
3  * Written by Arnaud Westenberg email:arnaud@wanadoo.nl
4  * This software is released under the GPL-License.
5  * Version 0.7  6 Aug 2001
6  */
7
8 #include <linux/autoconf.h>
9 #if defined (CONFIG_MODVERSIONS) && !defined (MODVERSIONS)
10 #define MODVERSIONS
11 #endif
12
13 #if defined (MODVERSIONS)
14 #include <linux/modversions.h>
15 #endif 
16
17 #include <linux/sched.h>
18 #include <linux/version.h>
19
20 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
21 #include <asm/spinlock.h>
22 #else
23 #include <linux/spinlock.h>
24 #endif
25
26 #include "../include/main.h"
27 #include "../include/irq.h"
28 #include "../include/i82527.h"
29 #include "../include/sja1000.h"
30
31 void i82527_irq_rtr_handler(struct chip_t *chip, struct msgobj_t *msgobj, 
32                             struct rtr_id *rtr_search, unsigned long message_id);
33 void sja1000_irq_read_handler(struct chip_t *chip, struct msgobj_t *msgobj);
34 void sja1000_irq_write_handler(struct chip_t *chip, struct msgobj_t *msgobj);
35
36 /*struct candevice_t *device=NULL;
37 unsigned object=0,irq_register=0;
38 unsigned long msgbase=0;
39 struct canfifo_t *fifo=NULL;
40 unsigned long message_id=0;
41 struct rtr_id *rtr_search;
42 */
43
44 inline void i82527_irq_write_handler(struct chip_t *chip, struct msgobj_t *msgobj)
45 {
46         struct canfifo_t *fifo=msgobj->fifo;
47         unsigned long msgbase=msgobj->obj_base_addr;
48         void (*write_reg)(unsigned char data, unsigned long address);
49         unsigned (*read_reg)(unsigned long address);
50         write_reg=chip->hostdevice->hwspecops->write_register;
51         read_reg=chip->hostdevice->hwspecops->read_register;
52
53         (*write_reg)((MVAL_RES|TXIE_RES|RXIE_RES|INTPD_RES),msgbase+iMSGCTL0);
54
55         fifo->tx_readp++;
56         if (fifo->tx_readp >= fifo->buf_tx_entry + MAX_BUF_LENGTH)
57                 fifo->tx_readp = fifo->buf_tx_entry;
58         if (fifo->tx_readp == fifo->tx_writep) { // Output buffer is empty
59                 fifo->tx_in_progress = 0;
60                 if (waitqueue_active(&fifo->writeq)) {
61                         msgobj->ret = 0;
62                         wake_up_interruptible(&fifo->writeq);
63                 }
64                 return;
65         }
66         if (chip->chipspecops->pre_write_config(chip, msgobj, fifo->tx_readp)) {
67                 if (waitqueue_active(&fifo->writeq)) {
68                         msgobj->ret = -1;
69                         wake_up_interruptible(&fifo->writeq);
70                         return;
71                 }
72         }
73         if (chip->chipspecops->send_msg(chip, msgobj, fifo->tx_readp)) {
74                 if (waitqueue_active(&fifo->writeq)) {
75                         msgobj->ret = -1;
76                         wake_up_interruptible(&fifo->writeq);
77                         return;
78                 }
79         } 
80 }
81
82 inline void i82527_irq_read_handler(struct chip_t *chip, struct msgobj_t *msgobj,
83                                     unsigned long message_id)
84 {
85         int i=0, tmp=1 ;
86         struct canfifo_t *fifo=msgobj->fifo;
87         unsigned long msgbase=msgobj->obj_base_addr;
88         void (*write_reg)(unsigned char data, unsigned long address);
89         unsigned (*read_reg)(unsigned long address);
90         write_reg=chip->hostdevice->hwspecops->write_register;
91         read_reg=chip->hostdevice->hwspecops->read_register;
92         
93         while (tmp) {
94                 (*write_reg)((RMPD_RES|TXRQ_RES|MLST_RES|NEWD_RES), msgbase +
95                                                                 iMSGCTL1);
96                 (*write_reg)((MVAL_SET|TXIE_RES|RXIE_SET|INTPD_RES), msgbase +
97                                                                 iMSGCTL0);
98
99                 fifo->rx_writep->length =((*read_reg)(msgbase+iMSGCFG) & 0xf0) >> 4;
100                 fifo->rx_writep->id = message_id;
101                 for (i=0; i < fifo->rx_writep->length; i++)
102                         fifo->rx_writep->data[i] = (*read_reg)(msgbase+iMSGDAT0+i);
103
104 //FIXME: Add buffer overflow check, currently it's silently over written!
105
106                 fifo->rx_writep++;
107                 if (fifo->rx_writep >= fifo->buf_rx_entry + MAX_BUF_LENGTH)
108                         fifo->rx_writep = fifo->buf_rx_entry;
109
110                 if (!((tmp=(*read_reg)(msgbase + iMSGCTL1)) & NEWD_SET)) {
111                         break;
112                 }
113
114                 if (tmp & MLST_SET)
115                         CANMSG("Message lost!\n");
116
117         }
118         if (waitqueue_active(&fifo->readq)) {
119                 wake_up_interruptible(&fifo->readq);
120         }
121 }
122
123 void i82527_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
124 {
125         int id0=0, id1=0, id2=0, id3=0;
126
127         unsigned irq_register;
128         unsigned object;
129         struct chip_t *chip=(struct chip_t *)dev_id;
130         struct msgobj_t *msgobj;
131         unsigned long msgbase;
132         unsigned long message_id;
133         struct rtr_id *rtr_search;
134         void (*write_reg)(unsigned char data, unsigned long address);
135         unsigned (*read_reg)(unsigned long address);
136         write_reg=chip->hostdevice->hwspecops->write_register;
137         read_reg=chip->hostdevice->hwspecops->read_register;
138
139         /*put_reg=device->hwspecops->write_register;*/
140         /*get_reg=device->hwspecops->read_register;*/
141
142         if ( (chip->flags & SEGMENTED) != 0)
143                 irq_register = can_read_reg(chip, iIRQ+SPACING);
144         else 
145                 irq_register = can_read_reg(chip, iIRQ);
146
147         while (irq_register) {
148
149                 if (irq_register == 0x01) {
150                         DEBUGMSG("Status register: 0x%x\n",can_read_reg(chip, iSTAT));
151                         return;
152                 }
153                 
154                 if (irq_register == 0x02)
155                         object = 14;
156                 else
157                         object = irq_register-3;
158
159                 msgobj=chip->msgobj[object];
160                 msgbase=msgobj->obj_base_addr;
161
162                 if ((*read_reg)(msgbase+iMSGCFG) & MCFG_DIR) {
163                         i82527_irq_write_handler(chip, msgobj); 
164                 }
165                 else { 
166
167                         if (extended) {
168                                 id0=(*read_reg)(msgbase+iMSGID3);
169                                 id1=(*read_reg)(msgbase+iMSGID2)<<8;
170                                 id2=(*read_reg)(msgbase+iMSGID1)<<16;
171                                 id3=(*read_reg)(msgbase+iMSGID0)<<24;
172                                 message_id=(id0|id1|id2|id3)>>3;
173                         }
174                         else {
175                                 id0=(*read_reg)(msgbase+iMSGID1);
176                                 id1=(*read_reg)(msgbase+iMSGID0)<<8;
177                                 message_id=(id0|id1)>>5;
178                         }
179
180                         spin_lock(&hardware_p->rtr_lock);
181                         rtr_search=hardware_p->rtr_queue;
182                         while (rtr_search != NULL) {
183                                 if (rtr_search->id == message_id)
184                                         break;
185                                 rtr_search=rtr_search->next;
186                         }
187                         spin_unlock(&hardware_p->rtr_lock);
188                         if ((rtr_search!=NULL) && (rtr_search->id==message_id))
189                                 i82527_irq_rtr_handler(chip, msgobj, rtr_search, message_id);
190                         else
191                                 i82527_irq_read_handler(chip, msgobj, message_id); 
192                 }
193
194                 if ( (chip->flags & SEGMENTED) != 0)
195                         irq_register=can_read_reg(chip, iIRQ+SPACING);
196                 else
197                         irq_register=can_read_reg(chip, iIRQ);
198         }
199         
200 }
201
202 void i82527_irq_rtr_handler(struct chip_t *chip, struct msgobj_t *msgobj,
203                             struct rtr_id *rtr_search, unsigned long message_id)
204 {
205         short int i=0;
206         unsigned long msgbase=msgobj->obj_base_addr;
207         void (*write_reg)(unsigned char data, unsigned long address);
208         unsigned (*read_reg)(unsigned long address);
209         write_reg=chip->hostdevice->hwspecops->write_register;
210         read_reg=chip->hostdevice->hwspecops->read_register;
211
212         (*write_reg)((MVAL_RES|TXIE_RES|RXIE_RES|INTPD_RES),msgbase + iMSGCTL0);
213         (*write_reg)((RMPD_RES|TXRQ_RES|MLST_RES|NEWD_RES),msgbase + iMSGCTL1);
214         
215         spin_lock(&hardware_p->rtr_lock);
216
217         rtr_search->rtr_message->id=message_id;
218         rtr_search->rtr_message->length=((*read_reg)(msgbase + iMSGCFG) & 0xf0)>>4;
219         for (i=0; i<rtr_search->rtr_message->length; i++)
220                 rtr_search->rtr_message->data[i]=(*read_reg)(msgbase+iMSGDAT0+i);
221         
222         spin_unlock(&hardware_p->rtr_lock);
223
224         if (waitqueue_active(&rtr_search->rtr_wq))
225                 wake_up_interruptible(&rtr_search->rtr_wq);
226 }
227
228 void sja1000_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
229 {
230         unsigned irq_register;
231         struct chip_t *chip=(struct chip_t *)dev_id;
232         struct msgobj_t *msgobj;
233         struct canfifo_t *fifo;
234
235         irq_register=can_read_reg(chip, SJAIR);
236 //      DEBUGMSG("sja1000_irq_handler: SJAIR:%02x\n",irq_register);
237 //      DEBUGMSG("sja1000_irq_handler: SJASR:%02x\n",
238 //                                      can_read_reg(chip, SJASR));
239
240         if ((irq_register & (IR_WUI|IR_DOI|IR_EI|IR_TI|IR_RI)) == 0)
241                 return;
242
243         msgobj=chip->msgobj[0];
244         fifo=msgobj->fifo;
245
246         if ((irq_register & IR_RI) != 0) 
247                 sja1000_irq_read_handler(chip, msgobj);
248         if ((irq_register & IR_TI) != 0) 
249                 sja1000_irq_write_handler(chip, msgobj);
250         if ((irq_register & (IR_EI|IR_DOI)) != 0) { 
251                 // Some error happened
252 // FIXME: chip should be brought to usable state. Transmission cancelled if in progress.
253 // Reset flag set to 0 if chip is already off the bus. Full state report
254                 CANMSG("Error: status register: 0x%x irq_register: 0x%02x\n",
255                         can_read_reg(chip, SJASR), irq_register);
256                 chip->msgobj[0]->ret=-1;
257                 if (waitqueue_active(&fifo->writeq))
258                         wake_up_interruptible(&fifo->writeq);
259                 if (waitqueue_active(&fifo->readq))
260                         wake_up_interruptible(&fifo->readq);
261         }
262
263         return;
264 }
265
266 void sja1000_irq_read_handler(struct chip_t *chip, struct msgobj_t *msgobj)
267 {
268         int i=0, id=0;
269         struct canfifo_t *fifo=msgobj->fifo;
270
271         do {
272                 id = can_read_reg(chip, SJARXID0) | (can_read_reg(chip, SJARXID1)<<8);
273                 fifo->rx_writep->length = id & 0x0f;
274                 fifo->rx_writep->flags = id&ID0_RTR ? MSG_RTR : 0;
275                 fifo->rx_writep->timestamp = 0;
276                 fifo->rx_writep->cob = 0;
277                 fifo->rx_writep->id = id>>5;
278
279                 for (i=0; i<fifo->rx_writep->length; i++)
280                         fifo->rx_writep->data[i]=can_read_reg(chip, SJARXDAT0 + i);
281
282                 can_write_reg(chip, CMR_RRB, SJACMR);
283
284                 fifo->rx_writep++;
285                 if (fifo->rx_writep >= fifo->buf_rx_entry + MAX_BUF_LENGTH)
286                         fifo->rx_writep = fifo->buf_rx_entry;
287
288         } while(can_read_reg(chip, SJASR) & SR_RBS);
289
290         if (waitqueue_active(&fifo->readq))
291                 wake_up_interruptible(&fifo->readq);
292 }
293
294 void sja1000_irq_write_handler(struct chip_t *chip, struct msgobj_t *msgobj)
295 {
296         struct canfifo_t *fifo=msgobj->fifo;
297
298         fifo->tx_readp++;
299         if (fifo->tx_readp >= fifo->buf_tx_entry + MAX_BUF_LENGTH)
300                 fifo->tx_readp = fifo->buf_tx_entry;
301         if (fifo->tx_readp == fifo->tx_writep) { // Output buffer is empty
302                 fifo->tx_in_progress = 0;
303                 if (waitqueue_active(&fifo->writeq)) {
304                         msgobj->ret = 0;
305                         wake_up_interruptible(&fifo->writeq);
306                 }
307                 return;
308         }
309         if (chip->chipspecops->pre_write_config(chip, msgobj, fifo->tx_readp)) {
310                 if (waitqueue_active(&fifo->writeq)) {
311                         msgobj->ret = -1;
312                         wake_up_interruptible(&fifo->writeq);
313                         return;
314                 }
315         }
316         if (chip->chipspecops->send_msg(chip, msgobj, fifo->tx_readp)) {
317                 if (waitqueue_active(&fifo->writeq)) {
318                         msgobj->ret = -1;
319                         wake_up_interruptible(&fifo->writeq);
320                         return;
321                 }
322         }
323 }
324
325 void dummy_irq_handler(int irq, void *dev_id, struct pt_regs *regs) {
326         CANMSG("dummy_irq_handler called irq %d \n", irq);
327 }