]> rtime.felk.cvut.cz Git - lincan.git/blob - lincan/src/i82527.c
Update remote request code prototype to compile with latest kernels.
[lincan.git] / lincan / src / i82527.c
1 /**************************************************************************/
2 /* File: i82527.c - Intel i82527 CAN controller support                   */
3 /*                                                                        */
4 /* LinCAN - (Not only) Linux CAN bus driver                               */
5 /* Copyright (C) 2002-2009 DCE FEE CTU Prague <http://dce.felk.cvut.cz>   */
6 /* Copyright (C) 2002-2009 Pavel Pisa <pisa@cmp.felk.cvut.cz>             */
7 /* Funded by OCERA and FRESCOR IST projects                               */
8 /* Based on CAN driver code by Arnaud Westenberg <arnaud@wanadoo.nl>      */
9 /*                                                                        */
10 /* LinCAN is free software; you can redistribute it and/or modify it      */
11 /* under terms of the GNU General Public License as published by the      */
12 /* Free Software Foundation; either version 2, or (at your option) any    */
13 /* later version.  LinCAN is distributed in the hope that it will be      */
14 /* useful, but WITHOUT ANY WARRANTY; without even the implied warranty    */
15 /* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU    */
16 /* General Public License for more details. You should have received a    */
17 /* copy of the GNU General Public License along with LinCAN; see file     */
18 /* COPYING. If not, write to the Free Software Foundation, 675 Mass Ave,  */
19 /* Cambridge, MA 02139, USA.                                              */
20 /*                                                                        */
21 /* To allow use of LinCAN in the compact embedded systems firmware        */
22 /* and RT-executives (RTEMS for example), main authors agree with next    */
23 /* special exception:                                                     */
24 /*                                                                        */
25 /* Including LinCAN header files in a file, instantiating LinCAN generics */
26 /* or templates, or linking other files with LinCAN objects to produce    */
27 /* an application image/executable, does not by itself cause the          */
28 /* resulting application image/executable to be covered by                */
29 /* the GNU General Public License.                                        */
30 /* This exception does not however invalidate any other reasons           */
31 /* why the executable file might be covered by the GNU Public License.    */
32 /* Publication of enhanced or derived LinCAN files is required although.  */
33 /**************************************************************************/
34
35 #include "../include/can.h"
36 #include "../include/can_sysdep.h"
37 #include "../include/main.h"
38 #include "../include/i82527.h"
39
40 void i82527_irq_rtr_handler(struct canchip_t *chip, struct msgobj_t *obj,
41                             struct rtr_id *rtr_search, unsigned long message_id);
42
43
44 extern int stdmask;
45 extern int extmask;
46 extern int mo15mask;
47
48 /* helper functions for segmented cards read and write configuration and status registers
49    above 0xf offset */
50
51 void i82527_seg_write_reg(const struct canchip_t *chip, unsigned char data, unsigned address)
52 {
53         if((address > 0xf) && (chip->flags & CHIP_SEGMENTED))
54                 canobj_write_reg(chip, chip->msgobj[(address>>4)-1],data, address & 0xf);
55         else
56                 can_write_reg(chip, data, address);
57 }
58
59 unsigned i82527_seg_read_reg(const struct canchip_t *chip, unsigned address)
60 {
61         if((address > 0xf) && (chip->flags & CHIP_SEGMENTED))
62                 return canobj_read_reg(chip, chip->msgobj[(address>>4)-1], address & 0xf);
63         else
64                 return can_read_reg(chip, address);
65 }
66
67 int i82527_enable_configuration(struct canchip_t *chip)
68 {
69         unsigned short flags=0;
70
71         flags = can_read_reg(chip, iCTL) & (iCTL_IE|iCTL_SIE|iCTL_EIE);
72         can_write_reg(chip, flags|iCTL_CCE, iCTL);
73
74         return 0;
75 }
76
77 int i82527_disable_configuration(struct canchip_t *chip)
78 {
79         unsigned short flags=0;
80
81         flags = can_read_reg(chip, iCTL) & (iCTL_IE|iCTL_SIE|iCTL_EIE);
82         can_write_reg(chip, flags, iCTL);
83
84         return 0;
85 }
86
87 int i82527_chip_config(struct canchip_t *chip)
88 {
89         can_write_reg(chip,chip->int_cpu_reg,iCPU); // Configure cpu interface
90         can_write_reg(chip,(iCTL_CCE|iCTL_INI),iCTL); // Enable configuration
91         i82527_seg_write_reg(chip,chip->int_clk_reg,iCLK); // Set clock out slew rates
92         i82527_seg_write_reg(chip,chip->int_bus_reg,iBUS); /* Bus configuration */
93         can_write_reg(chip,0x00,iSTAT); /* Clear error status register */
94
95         /* Check if we can at least read back some arbitrary data from the
96          * card. If we can not, the card is not properly configured!
97          */
98         canobj_write_reg(chip,chip->msgobj[1],0x25,iMSGDAT1);
99         canobj_write_reg(chip,chip->msgobj[2],0x52,iMSGDAT3);
100         canobj_write_reg(chip,chip->msgobj[10],0xc3,iMSGDAT6);
101         if ( (canobj_read_reg(chip,chip->msgobj[1],iMSGDAT1) != 0x25) ||
102               (canobj_read_reg(chip,chip->msgobj[2],iMSGDAT3) != 0x52) ||
103               (canobj_read_reg(chip,chip->msgobj[10],iMSGDAT6) != 0xc3) ) {
104                 CANMSG("Could not read back from the hardware.\n");
105                 CANMSG("This probably means that your hardware is not correctly configured!\n");
106                 return -1;
107         }
108         else
109                 DEBUGMSG("Could read back, hardware is probably configured correctly\n");
110
111         if (chip->baudrate == 0)
112                 chip->baudrate=1000000;
113
114         if (i82527_baud_rate(chip,chip->baudrate,chip->clock,0,75,0)) {
115                 CANMSG("Error configuring baud rate\n");
116                 return -ENODEV;
117         }
118         if (i82527_standard_mask(chip,0x0000,stdmask)) {
119                 CANMSG("Error configuring standard mask\n");
120                 return -ENODEV;
121         }
122         if (i82527_extended_mask(chip,0x00000000,extmask)) {
123                 CANMSG("Error configuring extended mask\n");
124                 return -ENODEV;
125         }
126         if (i82527_message15_mask(chip,0x00000000,mo15mask)) {
127                 CANMSG("Error configuring message 15 mask\n");
128                 return -ENODEV;
129         }
130         if (i82527_clear_objects(chip)) {
131                 CANMSG("Error clearing message objects\n");
132                 return -ENODEV;
133         }
134         if (i82527_config_irqs(chip,iCTL_IE|iCTL_EIE)) { /* has been 0x0a */
135                 CANMSG("Error configuring interrupts\n");
136                 return -ENODEV;
137         }
138
139         return 0;
140 }
141
142 /* Set communication parameters.
143  * param rate baud rate in Hz
144  * param clock frequency of i82527 clock in Hz (ISA osc is 14318000)
145  * param sjw synchronization jump width (0-3) prescaled clock cycles
146  * param sampl_pt sample point in % (0-100) sets (TSEG1+2)/(TSEG1+TSEG2+3) ratio
147  * param flags fields BTR1_SAM, OCMODE, OCPOL, OCTP, OCTN, CLK_OFF, CBP
148  */
149 int i82527_baud_rate(struct canchip_t *chip, int rate, int clock, int sjw,
150                                                         int sampl_pt, int flags)
151 {
152         int best_error = 1000000000, error;
153         int best_tseg=0, best_brp=0, best_rate=0, brp=0;
154         int tseg=0, tseg1=0, tseg2=0;
155
156         if (i82527_enable_configuration(chip))
157                 return -ENODEV;
158
159         if(chip->int_cpu_reg & iCPU_DSC)
160                 clock /=2;
161
162         /* tseg even = round down, odd = round up */
163         for (tseg=(0+0+2)*2; tseg<=(MAX_TSEG2+MAX_TSEG1+2)*2+1; tseg++) {
164                 brp = clock/((1+tseg/2)*rate)+tseg%2;
165                 if (brp == 0 || brp > 64)
166                         continue;
167                 error = rate - clock/(brp*(1+tseg/2));
168                 if (error < 0)
169                         error = -error;
170                 if (error <= best_error) {
171                         best_error = error;
172                         best_tseg = tseg/2;
173                         best_brp = brp-1;
174                         best_rate = clock/(brp*(1+tseg/2));
175                 }
176         }
177         if (best_error && (rate/best_error < 10)) {
178                 CANMSG("baud rate %d is not possible with %d Hz clock\n",
179                                                                 rate, 2*clock);
180                 CANMSG("%d bps. brp=%d, best_tseg=%d, tseg1=%d, tseg2=%d\n",
181                                 best_rate, best_brp, best_tseg, tseg1, tseg2);
182                 return -EINVAL;
183         }
184         tseg2 = best_tseg-(sampl_pt*(best_tseg+1))/100;
185         if (tseg2 < 0)
186                 tseg2 = 0;
187         if (tseg2 > MAX_TSEG2)
188                 tseg2 = MAX_TSEG2;
189
190         tseg1 = best_tseg-tseg2-2;
191         if (tseg1>MAX_TSEG1) {
192                 tseg1 = MAX_TSEG1;
193                 tseg2 = best_tseg-tseg1-2;
194         }
195
196         DEBUGMSG("Setting %d bps.\n", best_rate);
197         DEBUGMSG("brp=%d, best_tseg=%d, tseg1=%d, tseg2=%d, sampl_pt=%d\n",
198                                         best_brp, best_tseg, tseg1, tseg2,
199                                         (100*(best_tseg-tseg2)/(best_tseg+1)));
200
201
202         i82527_seg_write_reg(chip, sjw<<6 | best_brp, iBT0);
203         can_write_reg(chip, ((flags & BTR1_SAM) != 0)<<7 | tseg2<<4 | tseg1,
204                                                                 iBT1);
205         DEBUGMSG("Writing 0x%x to iBT0\n",(sjw<<6 | best_brp));
206         DEBUGMSG("Writing 0x%x to iBT1\n",((flags & BTR1_SAM) != 0)<<7 |
207                                                         tseg2<<4 | tseg1);
208
209         i82527_disable_configuration(chip);
210
211         return 0;
212 }
213
214 int i82527_standard_mask(struct canchip_t *chip, unsigned short code, unsigned short mask)
215 {
216         unsigned char mask0, mask1;
217
218         mask0 = (unsigned char) (mask >> 3);
219         mask1 = (unsigned char) (mask << 5);
220
221         can_write_reg(chip,mask0,iSGM0);
222         can_write_reg(chip,mask1,iSGM1);
223
224         DEBUGMSG("Setting standard mask to 0x%lx\n",(unsigned long)mask);
225
226         return 0;
227 }
228
229 int i82527_extended_mask(struct canchip_t *chip, unsigned long code, unsigned long mask)
230 {
231         unsigned char mask0, mask1, mask2, mask3;
232
233         mask0 = (unsigned char) (mask >> 21);
234         mask1 = (unsigned char) (mask >> 13);
235         mask2 = (unsigned char) (mask >> 5);
236         mask3 = (unsigned char) (mask << 3);
237
238         can_write_reg(chip,mask0,iEGM0);
239         can_write_reg(chip,mask1,iEGM1);
240         can_write_reg(chip,mask2,iEGM2);
241         can_write_reg(chip,mask3,iEGM3);
242
243         DEBUGMSG("Setting extended mask to 0x%lx\n",(unsigned long)mask);
244
245         return 0;
246 }
247
248 int i82527_message15_mask(struct canchip_t *chip, unsigned long code, unsigned long mask)
249 {
250         unsigned char mask0, mask1, mask2, mask3;
251
252         mask0 = (unsigned char) (mask >> 21);
253         mask1 = (unsigned char) (mask >> 13);
254         mask2 = (unsigned char) (mask >> 5);
255         mask3 = (unsigned char) (mask << 3);
256
257         can_write_reg(chip,mask0,i15M0);
258         can_write_reg(chip,mask1,i15M1);
259         can_write_reg(chip,mask2,i15M2);
260         can_write_reg(chip,mask3,i15M3);
261
262         DEBUGMSG("Setting message 15 mask to 0x%lx\n",mask);
263
264         return 0;
265
266
267 }
268
269 int i82527_clear_objects(struct canchip_t *chip)
270 {
271         int i=0,id=0,data=0;
272         struct msgobj_t *obj;
273
274         DEBUGMSG("Cleared all message objects on chip\n");
275
276         for (i=0; i<chip->max_objects; i++) {
277                 obj=chip->msgobj[i];
278                 canobj_write_reg(chip,obj,(INTPD_RES|RXIE_RES|TXIE_RES|MVAL_RES),iMSGCTL0);
279                 canobj_write_reg(chip,obj,(NEWD_RES|MLST_RES|TXRQ_RES|RMPD_RES), iMSGCTL1);
280                 for (data=0x07; data<0x0f; data++)
281                         canobj_write_reg(chip,obj,0x00,data);
282                 for (id=2; id<6; id++) {
283                         canobj_write_reg(chip,obj,0x00,id);
284                 }
285                 if (extended==0) {
286                         canobj_write_reg(chip,obj,0x00,iMSGCFG);
287                 }
288                 else {
289                         canobj_write_reg(chip,obj,MCFG_XTD,iMSGCFG);
290                 }
291         }
292         if (extended==0)
293                 DEBUGMSG("All message ID's set to standard\n");
294         else
295                 DEBUGMSG("All message ID's set to extended\n");
296
297         return 0;
298 }
299
300 int i82527_config_irqs(struct canchip_t *chip, short irqs)
301 {
302         can_write_reg(chip,irqs,iCTL);
303         DEBUGMSG("Configured hardware interrupt delivery\n");
304         return 0;
305 }
306
307 int i82527_pre_read_config(struct canchip_t *chip, struct msgobj_t *obj)
308 {
309         unsigned long id=obj->rx_preconfig_id;
310
311         can_msgobj_set_fl(obj,RX_MODE);
312
313         if (extended || can_msgobj_test_fl(obj,RX_MODE_EXT)) {
314                 id<<=3;
315                 canobj_write_reg(chip,obj,id,iMSGID3);
316                 canobj_write_reg(chip,obj,id>>8,iMSGID2);
317                 canobj_write_reg(chip,obj,id>>16,iMSGID1);
318                 canobj_write_reg(chip,obj,id>>24,iMSGID0);
319                 canobj_write_reg(chip,obj,MCFG_XTD,iMSGCFG);
320         } else {
321                 id<<=5;
322                 canobj_write_reg(chip,obj,id,iMSGID1);
323                 canobj_write_reg(chip,obj,id>>8,iMSGID0);
324                 canobj_write_reg(chip,obj,0x00,iMSGCFG);
325         }
326
327         canobj_write_reg(chip,obj,(NEWD_RES|MLST_RES|TXRQ_RES|RMPD_RES), iMSGCTL1);
328         canobj_write_reg(chip,obj,(MVAL_SET|TXIE_RES|RXIE_SET|INTPD_RES),iMSGCTL0);
329
330         DEBUGMSG("i82527_pre_read_config: configured obj at 0x%08lx\n",obj->obj_base_addr);
331
332         return 0;
333 }
334
335 int i82527_pre_write_config(struct canchip_t *chip, struct msgobj_t *obj,
336                                                         struct canmsg_t *msg)
337 {
338         int i=0,id0=0,id1=0,id2=0,id3=0;
339         int len;
340
341         len = msg->length;
342         if(len > CAN_MSG_LENGTH) len = CAN_MSG_LENGTH;
343
344         can_msgobj_clear_fl(obj,RX_MODE);
345
346         canobj_write_reg(chip,obj,(MVAL_SET|TXIE_SET|RXIE_RES|INTPD_RES),iMSGCTL0);
347         canobj_write_reg(chip,obj,(RMPD_RES|TXRQ_RES|CPUU_SET|NEWD_RES),iMSGCTL1);
348
349         if (extended || (msg->flags&MSG_EXT)) {
350                 canobj_write_reg(chip,obj,(len<<4)|(MCFG_DIR|MCFG_XTD),iMSGCFG);
351                 id0 = (unsigned char) (msg->id<<3);
352                 id1 = (unsigned char) (msg->id>>5);
353                 id2 = (unsigned char) (msg->id>>13);
354                 id3 = (unsigned char) (msg->id>>21);
355                 canobj_write_reg(chip,obj,id0,iMSGID3);
356                 canobj_write_reg(chip,obj,id1,iMSGID2);
357                 canobj_write_reg(chip,obj,id2,iMSGID1);
358                 canobj_write_reg(chip,obj,id3,iMSGID0);
359         }
360         else {
361                 canobj_write_reg(chip,obj,(len<<4)|MCFG_DIR,iMSGCFG);
362                 id1 = (unsigned char) (msg->id<<5);
363                 id0 = (unsigned char) (msg->id>>3);
364                 canobj_write_reg(chip,obj,id1,iMSGID1);
365                 canobj_write_reg(chip,obj,id0,iMSGID0);
366         }
367         canobj_write_reg(chip,obj,RMPD_UNC|TXRQ_UNC|CPUU_SET|NEWD_SET,iMSGCTL1);
368         for (i=0; i<len; i++) {
369                 canobj_write_reg(chip,obj,msg->data[i],iMSGDAT0+i);
370         }
371
372         return 0;
373 }
374
375 int i82527_send_msg(struct canchip_t *chip, struct msgobj_t *obj,
376                                                         struct canmsg_t *msg)
377 {
378         canobj_write_reg(chip,obj,(MVAL_SET|TXIE_SET|RXIE_RES|INTPD_RES),iMSGCTL0);
379
380         if (msg->flags & MSG_RTR) {
381                 canobj_write_reg(chip,obj,(RMPD_RES|TXRQ_RES|CPUU_RES|NEWD_SET),iMSGCTL1);
382         }
383         else {
384                 canobj_write_reg(chip,obj,(RMPD_RES|TXRQ_SET|CPUU_RES|NEWD_SET),iMSGCTL1);
385         }
386
387         return 0;
388 }
389
390 int i82527_check_tx_stat(struct canchip_t *chip)
391 {
392         if (can_read_reg(chip,iSTAT) & iSTAT_TXOK) {
393                 can_write_reg(chip,0x0,iSTAT);
394                 return 0;
395         }
396         else {
397                 can_write_reg(chip,0x0,iSTAT);
398                 return 1;
399         }
400 }
401
402 int i82527_remote_request(struct canchip_t *chip, struct msgobj_t *obj)
403 {
404         canobj_write_reg(chip,obj,(MVAL_SET|TXIE_RES|RXIE_SET|INTPD_RES),iMSGCTL0);
405         canobj_write_reg(chip,obj,(RMPD_RES|TXRQ_SET|MLST_RES|NEWD_RES),iMSGCTL1);
406
407         return 0;
408 }
409
410 int i82527_set_btregs(struct canchip_t *chip, unsigned short btr0,
411                                                         unsigned short btr1)
412 {
413         if (i82527_enable_configuration(chip))
414                 return -ENODEV;
415
416         i82527_seg_write_reg(chip, btr0, iBT0);
417         i82527_seg_write_reg(chip, btr1, iBT1);
418
419         i82527_disable_configuration(chip);
420
421         return 0;
422 }
423
424 int i82527_start_chip(struct canchip_t *chip)
425 {
426         unsigned short flags = 0;
427
428         flags = can_read_reg(chip, iCTL) & (iCTL_IE|iCTL_SIE|iCTL_EIE);
429         can_write_reg(chip, flags, iCTL);
430
431         return 0;
432 }
433
434 int i82527_stop_chip(struct canchip_t *chip)
435 {
436         unsigned short flags = 0;
437
438         flags = can_read_reg(chip, iCTL) & (iCTL_IE|iCTL_SIE|iCTL_EIE);
439         can_write_reg(chip, flags|(iCTL_CCE|iCTL_INI), iCTL);
440
441         return 0;
442 }
443
444 int i82527_attach_to_chip(struct canchip_t *chip)
445 {
446         return 0;
447 }
448
449 int i82527_release_chip(struct canchip_t *chip)
450 {
451         i82527_stop_chip(chip);
452         can_write_reg(chip, (iCTL_CCE|iCTL_INI), iCTL);
453
454         return 0;
455 }
456
457 static inline
458 void i82527_irq_write_handler(struct canchip_t *chip, struct msgobj_t *obj)
459 {
460         int cmd;
461
462         canobj_write_reg(chip,obj,(MVAL_RES|TXIE_RES|RXIE_RES|INTPD_RES),iMSGCTL0);
463
464         if(obj->tx_slot){
465                 /* Do local transmitted message distribution if enabled */
466                 if (processlocal){
467                         /* fill CAN message timestamp */
468                         can_filltimestamp(&obj->tx_slot->msg.timestamp);
469
470                         obj->tx_slot->msg.flags |= MSG_LOCAL;
471                         canque_filter_msg2edges(obj->qends, &obj->tx_slot->msg);
472                 }
473                 /* Free transmitted slot */
474                 canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot);
475                 obj->tx_slot=NULL;
476         }
477
478         cmd=canque_test_outslot(obj->qends, &obj->tx_qedge, &obj->tx_slot);
479         if(cmd<0)
480                 return;
481
482         if (chip->chipspecops->pre_write_config(chip, obj, &obj->tx_slot->msg)) {
483                 obj->ret = -1;
484                 canque_notify_inends(obj->tx_qedge, CANQUEUE_NOTIFY_ERRTX_PREP);
485                 canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot);
486                 obj->tx_slot=NULL;
487                 return;
488         }
489         if (chip->chipspecops->send_msg(chip, obj, &obj->tx_slot->msg)) {
490                 obj->ret = -1;
491                 canque_notify_inends(obj->tx_qedge, CANQUEUE_NOTIFY_ERRTX_SEND);
492                 canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot);
493                 obj->tx_slot=NULL;
494                 return;
495         }
496         return;
497 }
498
499 static inline
500 void i82527_irq_read_handler(struct canchip_t *chip, struct msgobj_t *obj, int objnum)
501 {
502         int i;
503         unsigned long message_id;
504         int msgcfg, msgctl1;
505
506         msgctl1=canobj_read_reg(chip,obj,iMSGCTL1);
507         if(msgctl1 & NEWD_RES)
508                 return;
509
510         do {
511                 if(objnum != 14) {
512                         canobj_write_reg(chip,obj,(RMPD_RES|TXRQ_RES|MLST_UNC|NEWD_RES),iMSGCTL1);
513                         canobj_write_reg(chip,obj,(MVAL_SET|TXIE_RES|RXIE_SET|INTPD_RES),iMSGCTL0);
514                 }
515
516                 msgcfg = canobj_read_reg(chip,obj,iMSGCFG);
517
518                 if (msgcfg&MCFG_XTD) {
519                         message_id =canobj_read_reg(chip,obj,iMSGID3);
520                         message_id|=canobj_read_reg(chip,obj,iMSGID2)<<8;
521                         message_id|=canobj_read_reg(chip,obj,iMSGID1)<<16;
522                         message_id|=canobj_read_reg(chip,obj,iMSGID0)<<24;
523                         message_id>>=3;
524                         obj->rx_msg.flags = MSG_EXT;
525
526                 }
527                 else {
528                         message_id =canobj_read_reg(chip,obj,iMSGID1);
529                         message_id|=canobj_read_reg(chip,obj,iMSGID0)<<8;
530                         message_id>>=5;
531                         obj->rx_msg.flags = 0;
532                 }
533
534                 obj->rx_msg.length = (msgcfg >> 4) & 0xf;
535                 if(obj->rx_msg.length > CAN_MSG_LENGTH) obj->rx_msg.length = CAN_MSG_LENGTH;
536
537                 obj->rx_msg.id = message_id;
538
539                 for (i=0; i < obj->rx_msg.length; i++)
540                         obj->rx_msg.data[i] = canobj_read_reg(chip,obj,iMSGDAT0+i);
541
542
543                 if(objnum != 14) {
544                         /* if NEWD is set after data read, then read data are likely inconsistent */
545                         msgctl1=canobj_read_reg(chip,obj,iMSGCTL1);
546                         if(msgctl1 & NEWD_SET) {
547                                 CANMSG("i82527_irq_read_handler: object %d data overwritten\n",objnum);
548                                 continue;
549                         }
550                 }
551                 else {
552                         /* this object is special and data are queued in the shadow register */
553                         canobj_write_reg(chip,obj,(MVAL_SET|TXIE_RES|RXIE_SET|INTPD_RES),iMSGCTL0);
554                         canobj_write_reg(chip,obj,(RMPD_RES|TXRQ_RES|MLST_UNC|NEWD_RES),iMSGCTL1);
555                         msgctl1=canobj_read_reg(chip,obj,iMSGCTL1);
556                 }
557
558
559                 /* fill CAN message timestamp */
560                 can_filltimestamp(&obj->rx_msg.timestamp);
561
562                 canque_filter_msg2edges(obj->qends, &obj->rx_msg);
563
564                 if (msgctl1 & NEWD_SET)
565                         continue;
566
567                 if (msgctl1 & MLST_SET) {
568                         canobj_write_reg(chip,obj,(RMPD_UNC|TXRQ_UNC|MLST_RES|NEWD_UNC),iMSGCTL1);
569                         CANMSG("i82527_irq_read_handler: object %d message lost\n",objnum);
570                 }
571
572                 return;
573
574         } while(1);
575 }
576
577 /*
578                         if (msgcfg&MCFG_XTD) {
579                                 message_id =canobj_read_reg(chip,obj,iMSGID3);
580                                 message_id|=canobj_read_reg(chip,obj,iMSGID2)<<8;
581                                 message_id|=canobj_read_reg(chip,obj,iMSGID1)<<16;
582                                 message_id|=canobj_read_reg(chip,obj,iMSGID0)<<24;
583                                 message_id>>=3;
584                         }
585                         else {
586                                 message_id =canobj_read_reg(chip,obj,iMSGID1);
587                                 message_id|=canobj_read_reg(chip,obj,iMSGID0)<<8;
588                                 message_id>>=5;
589                         }
590
591                         can_spin_lock(&hardware_p->rtr_lock);
592                         rtr_search=hardware_p->rtr_queue;
593                         while (rtr_search != NULL) {
594                                 if (rtr_search->id == message_id)
595                                         break;
596                                 rtr_search=rtr_search->next;
597                         }
598                         can_spin_unlock(&hardware_p->rtr_lock);
599                         if ((rtr_search!=NULL) && (rtr_search->id==message_id))
600                                 i82527_irq_rtr_handler(chip, obj, rtr_search, message_id);
601                         else
602                                 i82527_irq_read_handler(chip, obj, message_id);
603 */
604
605
606 static inline
607 void i82527_irq_update_filter(struct canchip_t *chip, struct msgobj_t *obj)
608 {
609         struct canfilt_t filt;
610
611         if(canqueue_ends_filt_conjuction(obj->qends, &filt)) {
612                 obj->rx_preconfig_id=filt.id;
613                 canobj_write_reg(chip,obj,(MVAL_RES|TXIE_RES|RXIE_RES|INTPD_RES),iMSGCTL0);
614                 if(obj->object == 15) {
615                         i82527_message15_mask(chip,filt.id,filt.mask);
616                 }
617                 if (filt.flags&MSG_EXT)
618                         can_msgobj_set_fl(obj,RX_MODE_EXT);
619                 else
620                         can_msgobj_clear_fl(obj,RX_MODE_EXT);
621
622                 i82527_pre_read_config(chip, obj);
623
624                 CANMSG("i82527_irq_update_filter: obj at 0x%08lx\n",
625                         can_ioptr2ulong(obj->obj_base_addr));
626         }
627 }
628
629
630 int i82527_irq_sync_activities(struct canchip_t *chip, struct msgobj_t *obj)
631 {
632         int job_done=0;
633
634         while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)) {
635
636                 if(can_msgobj_test_and_clear_fl(obj,TX_REQUEST)) {
637                         if(canobj_read_reg(chip,obj,iMSGCTL1)&TXRQ_RES)
638                                 i82527_irq_write_handler(chip, obj);
639                 }
640
641                 if(!obj->tx_slot) {
642                         if(can_msgobj_test_and_clear_fl(obj,FILTCH_REQUEST)) {
643                                 i82527_irq_update_filter(chip, obj);
644                         }
645                 }
646
647                 job_done=1;
648
649                 mb();
650
651                 can_msgobj_clear_fl(obj,TX_LOCK);
652                 if(can_msgobj_test_fl(obj,TX_REQUEST))
653                         continue;
654                 if(can_msgobj_test_fl(obj,FILTCH_REQUEST) && !obj->tx_slot)
655                         continue;
656                 break;
657         }
658
659         return job_done;
660 }
661
662 int i82527_irq_handler(int irq, struct canchip_t *chip)
663 {
664         unsigned char msgcfg;
665
666         unsigned irq_register;
667         unsigned status_register;
668         unsigned object;
669         struct msgobj_t *obj;
670         int loop_cnt=CHIP_MAX_IRQLOOP;
671
672         /*put_reg=device->hwspecops->write_register;*/
673         /*get_reg=device->hwspecops->read_register;*/
674
675         irq_register = i82527_seg_read_reg(chip, iIRQ);
676
677         if(!irq_register) {
678                 DEBUGMSG("i82527: spurious IRQ\n");
679                 return CANCHIP_IRQ_NONE;
680         }
681
682
683         do {
684
685                 if(!loop_cnt--) {
686                         CANMSG("i82527_irq_handler IRQ %d stuck\n",irq);
687                         CANMSG("i82527_irq_register 0x%x\n",irq_register);
688                         return CANCHIP_IRQ_STUCK;
689                 }
690
691                 DEBUGMSG("i82527: iIRQ 0x%02x\n",irq_register);
692
693                 if (irq_register == 0x01) {
694                         status_register=can_read_reg(chip, iSTAT);
695                         CANMSG("Status register: 0x%x\n",status_register);
696                         continue;
697                         /*return CANCHIP_IRQ_NONE;*/
698                 }
699
700                 if (irq_register == 0x02)
701                         object = 14;
702                 else if(irq_register <= 13+3)
703                         object = irq_register-3;
704                 else
705                         return CANCHIP_IRQ_NONE;
706
707                 obj=chip->msgobj[object];
708
709                 msgcfg = canobj_read_reg(chip,obj,iMSGCFG);
710                 if (msgcfg & MCFG_DIR) {
711                         can_msgobj_set_fl(obj,TX_REQUEST);
712
713                         /* calls i82527_irq_write_handler synchronized with other invocations */
714                         if(i82527_irq_sync_activities(chip, obj)<=0){
715                                 /* The interrupt has to be cleared anyway */
716                                 canobj_write_reg(chip,obj,(MVAL_UNC|TXIE_UNC|RXIE_UNC|INTPD_RES),iMSGCTL0);
717
718                                 /*
719                                  * Rerun for case, that parallel activity on SMP or fully-preemptive
720                                  * kernel result in preparation and finished sending of message
721                                  * between above if and canobj_write_reg.
722                                  */
723                                 i82527_irq_sync_activities(chip, obj);
724                         }
725                 }
726                 else {
727
728                         i82527_irq_read_handler(chip, obj, object);
729                 }
730
731         } while((irq_register=i82527_seg_read_reg(chip, iIRQ)) != 0);
732
733         return CANCHIP_IRQ_HANDLED;
734 }
735
736 void i82527_irq_rtr_handler(struct canchip_t *chip, struct msgobj_t *obj,
737                             struct rtr_id *rtr_search, unsigned long message_id)
738 {
739         short int i=0;
740
741         canobj_write_reg(chip,obj,(MVAL_RES|TXIE_RES|RXIE_RES|INTPD_RES),iMSGCTL0);
742         canobj_write_reg(chip,obj,(RMPD_RES|TXRQ_RES|MLST_RES|NEWD_RES),iMSGCTL1);
743
744         can_spin_lock(&hardware_p->rtr_lock);
745
746         rtr_search->rtr_message->id=message_id;
747         rtr_search->rtr_message->length=(canobj_read_reg(chip,obj,iMSGCFG) & 0xf0)>>4;
748         for (i=0; i<rtr_search->rtr_message->length; i++)
749                 rtr_search->rtr_message->data[i]=canobj_read_reg(chip,obj,iMSGDAT0+i);
750
751         can_spin_unlock(&hardware_p->rtr_lock);
752
753         rtr_search->ready_fl = 1;
754         if (waitqueue_active(&rtr_search->rtr_wq))
755                 wake_up(&rtr_search->rtr_wq);
756 }
757
758 /**
759  * i82527_wakeup_tx: - wakeups TX processing
760  * @chip: pointer to chip state structure
761  * @obj: pointer to message object structure
762  *
763  * Function is responsible for initiating message transmition.
764  * It is responsible for clearing of object TX_REQUEST flag
765  *
766  * Return Value: negative value reports error.
767  * File: src/i82527.c
768  */
769 int i82527_wakeup_tx(struct canchip_t *chip, struct msgobj_t *obj)
770 {
771         can_preempt_disable();
772
773         can_msgobj_set_fl(obj,TX_REQUEST);
774
775         /* calls i82527_irq_write_handler synchronized with other invocations
776           from kernel and IRQ context */
777         i82527_irq_sync_activities(chip, obj);
778
779         can_preempt_enable();
780         return 0;
781 }
782
783 int i82527_filtch_rq(struct canchip_t *chip, struct msgobj_t *obj)
784 {
785         can_preempt_disable();
786
787         can_msgobj_set_fl(obj,FILTCH_REQUEST);
788
789         /* setups filter synchronized with other invocations from kernel and IRQ context */
790         i82527_irq_sync_activities(chip, obj);
791
792         can_preempt_enable();
793         return 0;
794 }
795
796 int i82527_register(struct chipspecops_t *chipspecops)
797 {
798         chipspecops->chip_config = i82527_chip_config;
799         chipspecops->baud_rate = i82527_baud_rate;
800         chipspecops->standard_mask = i82527_standard_mask;
801         chipspecops->extended_mask = i82527_extended_mask;
802         chipspecops->message15_mask = i82527_message15_mask;
803         chipspecops->clear_objects = i82527_clear_objects;
804         chipspecops->config_irqs = i82527_config_irqs;
805         chipspecops->pre_read_config = i82527_pre_read_config;
806         chipspecops->pre_write_config = i82527_pre_write_config;
807         chipspecops->send_msg = i82527_send_msg;
808         chipspecops->check_tx_stat = i82527_check_tx_stat;
809         chipspecops->wakeup_tx = i82527_wakeup_tx;
810         chipspecops->filtch_rq = i82527_filtch_rq;
811         chipspecops->remote_request = i82527_remote_request;
812         chipspecops->enable_configuration = i82527_enable_configuration;
813         chipspecops->disable_configuration = i82527_disable_configuration;
814         chipspecops->set_btregs = i82527_set_btregs;
815         chipspecops->attach_to_chip = i82527_attach_to_chip;
816         chipspecops->release_chip = i82527_release_chip;
817         chipspecops->start_chip = i82527_start_chip;
818         chipspecops->stop_chip = i82527_stop_chip;
819         chipspecops->irq_handler = i82527_irq_handler;
820         chipspecops->irq_accept = NULL;
821         return 0;
822 }
823
824 int i82527_fill_chipspecops(struct canchip_t *chip)
825 {
826         chip->chip_type="i82527";
827         chip->max_objects=15;
828         i82527_register(chip->chipspecops);
829         return 0;
830 }