]> rtime.felk.cvut.cz Git - lincan.git/blob - lincan/src/unican.c
Actual driver code for directly mapped SJA1000 into PCI mem region 0.
[lincan.git] / lincan / src / unican.c
1 /**************************************************************************/
2 /* File: unican.c - Unicontrols PCAN,PCAN-PCI, VCAN boards 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/unican_cl2.h"
39 #include "../include/setup.h"
40
41 #define UNICAN_PCI_VENDOR  0xFA3C
42 #define UNICAN_PCI_ID      0x0101
43
44 static void unican_delay(long msdelay)
45 {
46     #ifdef CAN_WITH_RTL
47         if(!rtl_rt_system_is_idle()) {
48                 rtl_delay(1000000l*msdelay);
49         }else
50     #endif /*CAN_WITH_RTL*/
51         {
52                 set_current_state(TASK_UNINTERRUPTIBLE);
53                 schedule_timeout((msdelay*HZ)/1000+1);
54         }
55
56 }
57
58 /* * * unican Chip Functionality * * */
59
60 int unican_enable_configuration(struct canchip_t *chip)
61 {
62         return 0;
63 }
64
65 int unican_disable_configuration(struct canchip_t *chip)
66 {
67         return 0;
68 }
69
70 /**
71  * unican_chip_config: - can chip configuration
72  * @chip: pointer to chip state structure
73  *
74  * Return Value: negative value reports error.
75  * File: src/unican.c
76  */
77 int unican_chip_config(struct canchip_t *chip)
78 {
79         int ret;
80         sCAN_CARD *chipext = (sCAN_CARD *)chip->chip_data;
81
82         unican_delay(10);
83
84         /* disable all card interrupts */
85         ret = cl2_int_mode(chipext, INT_MODE_ALL*0);
86         if(ret != CL2_OK) {
87                 CANMSG("disable interrupts by cl2_iit_mode returned %d\n",ret);
88                 return -ENODEV;
89         }
90         unican_delay(1);
91
92         if (chip->baudrate == 0)
93                 chip->baudrate=1000000;
94
95         ret = chip->chipspecops->baud_rate(chip,chip->baudrate,chip->clock,0,75,0);
96         if(ret < 0){
97                 CANMSG("can not set baudrate\n");
98                 return ret;
99         }
100
101         unican_delay(2);
102         /* set interrupt inhibit time to 1 ms */
103         ret = cl2_set_iit(chipext, 10);
104         if(ret != CL2_OK) {
105                 CANMSG("cl2_set_iit returned %d\n",ret);
106                 return -ENODEV;
107         }
108         unican_delay(1);
109
110         /* enable start interrupt inhibit time command */
111         ret = cl2_iit_mode(chipext, 1);
112         if(ret != CL2_OK) {
113                 CANMSG("cl2_iit_mode returned %d\n",ret);
114                 return -ENODEV;
115         }
116         unican_delay(1);
117
118         /* enable all card interrupts */
119         ret = cl2_int_mode(chipext, INT_MODE_ALL);
120         if(ret != CL2_OK) {
121                 CANMSG("cl2_iit_mode returned %d\n",ret);
122                 return -ENODEV;
123         }
124         unican_delay(1);
125
126         /* generate interrupt command */
127         cl2_gen_interrupt(chipext);
128
129
130         return 0;
131 }
132
133 /**
134  * unican_extended_mask: - setup of extended mask for message filtering
135  * @chip: pointer to chip state structure
136  * @code: can message acceptance code
137  * @mask: can message acceptance mask
138  *
139  * Return Value: negative value reports error.
140  * File: src/unican.c
141  */
142 int unican_extended_mask(struct canchip_t *chip, unsigned long code, unsigned  long mask)
143 {
144         return 0;
145 }
146
147 /**
148  * unican_baud_rate: - set communication parameters.
149  * @chip: pointer to chip state structure
150  * @rate: baud rate in Hz
151  * @clock: frequency of sja1000 clock in Hz (ISA osc is 14318000)
152  * @sjw: synchronization jump width (0-3) prescaled clock cycles
153  * @sampl_pt: sample point in % (0-100) sets (TSEG1+1)/(TSEG1+TSEG2+2) ratio
154  * @flags: fields %BTR1_SAM, %OCMODE, %OCPOL, %OCTP, %OCTN, %CLK_OFF, %CBP
155  *
156  * Return Value: negative value reports error.
157  * File: src/unican.c
158  */
159 int unican_baud_rate(struct canchip_t *chip, int rate, int clock, int sjw,
160                                                         int sampl_pt, int flags)
161 {
162         int ret;
163         sCAN_CARD *chipext = (sCAN_CARD *)chip->chip_data;
164         int bt_val;
165
166         switch (rate) {
167                 case 5000:   bt_val = CL2_BITRATE_5K; break;
168                 case 10000:  bt_val = CL2_BITRATE_10K; break;
169                 case 20000:  bt_val = CL2_BITRATE_20K; break;
170                 case 50000:  bt_val = CL2_BITRATE_50K; break;
171                 case 100000: bt_val = CL2_BITRATE_100K; break;
172                 case 125000: bt_val = CL2_BITRATE_125K; break;
173                 case 200000: bt_val = CL2_BITRATE_200K; break;
174                 case 250000: bt_val = CL2_BITRATE_250K; break;
175                 case 500000: bt_val = CL2_BITRATE_500K; break;
176                 case 800000: bt_val = CL2_BITRATE_800K; break;
177                 case 1000000:bt_val = CL2_BITRATE_1M; break;
178                 default: return -EINVAL;
179         }
180
181         ret=cl2_set_bitrate(chipext,bt_val);
182         if(ret == CL2_COMMAND_BUSY) return -EBUSY;
183         if(ret != CL2_OK) return -EINVAL;
184         unican_delay(2);
185
186         return 0;
187 }
188
189 /**
190  * unican_read: - reads and distributes one or more received messages
191  * @chip: pointer to chip state structure
192  * @obj: pinter to CAN message queue information
193  *
194  * This is rewritten cl2_receive_data function. The direct use of CL2
195  * function would require one more message data copy to reformat message
196  * data into different structure layout. Other way is to rewrite CL2 sources.
197  * No of these solutions is perfect.
198  *
199  * File: src/unican.c
200  */
201 void unican_read(struct canchip_t *chip, struct msgobj_t *obj) {
202         sCAN_CARD *chipext = (sCAN_CARD *)chip->chip_data;
203         __u16 *ptr16;
204         __u16 u;
205         unsigned long timestamp;
206         int i;
207
208         do {
209                 ptr16 = (__u16*)chipext->rxBufPtr;
210                 u = unican_readw(ptr16++);
211                 if ( !(u & CL2_MESSAGE_VALID) ) break; /* No more messages in the queue */
212
213                 obj->rx_msg.id = ((__u32)(u & 0xFF00 )) << 16;
214                 u = unican_readw(ptr16++);
215                 obj->rx_msg.id |= ((__u32)( u & 0x00FF )) << 16;
216                 obj->rx_msg.id |= (__u32)( u & 0xFF00 );
217                 u = unican_readw(ptr16++);
218                 obj->rx_msg.id |= (__u32)( u & 0x00FF );
219
220
221                 u >>= 8;
222
223                 if ( u & CL2_EXT_FRAME ) {      /* 2.0B frame */
224                         obj->rx_msg.id >>= 3;
225                         obj->rx_msg.flags = MSG_EXT;
226                 } else {                        /* 2.0A frame */
227                         obj->rx_msg.id >>= 21;
228                         obj->rx_msg.flags = 0;
229                 }
230
231                 /*if ( !(u & (CL2_REMOTE_FRAME<<8)) )
232                         obj->rx_msg.flags |= MSG_RTR;*/
233
234                 obj->rx_msg.length = ( (u >> 4) & 0x000F );
235                 if(obj->rx_msg.length > CAN_MSG_LENGTH) obj->rx_msg.length = CAN_MSG_LENGTH;
236
237                 for ( i = 0; i < obj->rx_msg.length; ) {
238                         u = unican_readw(ptr16++);
239                         obj->rx_msg.data[i++] = (__u8)( u );
240                         obj->rx_msg.data[i++] = (__u8)( u >> 8 );
241                 }
242                 if ( obj->rx_msg.length & 0x01 ) {      /* odd */
243                         timestamp = ( (unican_readw(ptr16++) & 0x00FF) | (u & 0xFF00) );
244                 } else {                                /* even */
245                         u = unican_readw(ptr16++);
246                         timestamp = (u << 8) | (u >> 8);
247                 }
248                 unican_writew(0x000,(__u16*)chipext->rxBufPtr);
249
250                #ifdef CAN_MSG_VERSION_2
251                 obj->rx_msg.timestamp.tv_sec = 0;
252                 obj->rx_msg.timestamp.tv_usec = timestamp;
253                #else /* CAN_MSG_VERSION_2 */
254                 obj->rx_msg.timestamp = timestamp;
255                #endif /* CAN_MSG_VERSION_2 */
256
257                 /* increment rx-buffer pointer */
258                 if ( (chipext->rxBufBase + chipext->rxBufSize*16 ) <= (chipext->rxBufPtr += 16) ) {
259                         chipext->rxBufPtr = chipext->rxBufBase;
260                 }
261
262                 canque_filter_msg2edges(obj->qends, &obj->rx_msg);
263
264         } while (1);
265 }
266
267 /**
268  * unican_pre_read_config: - prepares message object for message reception
269  * @chip: pointer to chip state structure
270  * @obj: pointer to message object state structure
271  *
272  * Return Value: negative value reports error.
273  *      Positive value indicates immediate reception of message.
274  * File: src/unican.c
275  */
276 int unican_pre_read_config(struct canchip_t *chip, struct msgobj_t *obj)
277 {
278         return 0;
279 }
280
281 #define MAX_TRANSMIT_WAIT_LOOPS 10
282 /**
283  * unican_pre_write_config: - prepares message object for message transmission
284  * @chip: pointer to chip state structure
285  * @obj: pointer to message object state structure
286  * @msg: pointer to CAN message
287  *
288  * Return Value: negative value reports error.
289  * File: src/unican.c
290  */
291 int unican_pre_write_config(struct canchip_t *chip, struct msgobj_t *obj,
292                                                         struct canmsg_t *msg)
293 {
294         return 0;
295 }
296
297 /**
298  * unican_send_msg: - initiate message transmission
299  * @chip: pointer to chip state structure
300  * @obj: pointer to message object state structure
301  * @msg: pointer to CAN message
302  *
303  * This function is called after unican_pre_write_config() function,
304  * which prepares data in chip buffer.
305  * Return Value: negative value reports error.
306  * File: src/unican.c
307  */
308 int unican_send_msg(struct canchip_t *chip, struct msgobj_t *obj,
309                                                         struct canmsg_t *msg)
310 {
311         return 0;
312 }
313
314 /**
315  * unican_check_tx_stat: - checks state of transmission engine
316  * @chip: pointer to chip state structure
317  *
318  * Return Value: negative value reports error.
319  *      Positive return value indicates transmission under way status.
320  *      Zero value indicates finishing of all issued transmission requests.
321  * File: src/unican.c
322  */
323 int unican_check_tx_stat(struct canchip_t *chip)
324 {
325         return 0;
326 }
327
328 /**
329  * unican_set_btregs: -  configures bitrate registers
330  * @chip: pointer to chip state structure
331  * @btr0: bitrate register 0
332  * @btr1: bitrate register 1
333  *
334  * Return Value: negative value reports error.
335  * File: src/unican.c
336  */
337 int unican_set_btregs(struct canchip_t *chip, unsigned short btr0,
338                                                         unsigned short btr1)
339 {
340         int ret;
341         sCAN_CARD *chipext = (sCAN_CARD *)chip->chip_data;
342         int bt_val;
343
344         bt_val=btr0 | (btr1<<8);
345         ret=cl2_set_bitrate(chipext,bt_val);
346         if(ret == CL2_COMMAND_BUSY) return -EBUSY;
347         if(ret != CL2_OK) return -EINVAL;
348
349         return 0;
350 }
351
352 /**
353  * unican_stop_chip: -  starts chip message processing
354  * @chip: pointer to chip state structure
355  *
356  * Return Value: negative value reports error.
357  * File: src/unican.c
358  */
359 int unican_start_chip(struct canchip_t *chip)
360 {
361         return 0;
362 }
363
364 /**
365  * unican_stop_chip: -  stops chip message processing
366  * @chip: pointer to chip state structure
367  *
368  * Return Value: negative value reports error.
369  * File: src/unican.c
370  */
371 int unican_stop_chip(struct canchip_t *chip)
372 {
373         return 0;
374 }
375
376 /**
377  * unican_attach_to_chip: - attaches to the chip, setups registers and state
378  * @chip: pointer to chip state structure
379  *
380  * Return Value: negative value reports error.
381  * File: src/sja1000p.c
382  */
383 int unican_attach_to_chip(struct canchip_t *chip)
384 {
385         return 0;
386 }
387
388 /**
389  * unican_release_chip: - called before chip structure removal if %CHIP_ATTACHED is set
390  * @chip: pointer to chip state structure
391  *
392  * Return Value: negative value reports error.
393  * File: src/sja1000p.c
394  */
395 int unican_release_chip(struct canchip_t *chip)
396 {
397         sCAN_CARD *chipext = (sCAN_CARD *)chip->chip_data;
398
399         unican_stop_chip(chip);
400         cl2_clear_interrupt(chipext);
401
402         return 0;
403 }
404
405 /**
406  * unican_remote_request: - configures message object and asks for RTR message
407  * @chip: pointer to chip state structure
408  * @obj: pointer to message object structure
409  *
410  * Return Value: negative value reports error.
411  * File: src/unican.c
412  */
413 int unican_remote_request(struct canchip_t *chip, struct msgobj_t *obj)
414 {
415         CANMSG("unican_remote_request not implemented\n");
416         return -ENOSYS;
417 }
418
419 /**
420  * unican_standard_mask: - setup of mask for message filtering
421  * @chip: pointer to chip state structure
422  * @code: can message acceptance code
423  * @mask: can message acceptance mask
424  *
425  * Return Value: negative value reports error.
426  * File: src/unican.c
427  */
428 int unican_standard_mask(struct canchip_t *chip, unsigned short code,
429                 unsigned short mask)
430 {
431         CANMSG("unican_standard_mask not implemented\n");
432         return -ENOSYS;
433 }
434
435 /**
436  * unican_clear_objects: - clears state of all message object residing in chip
437  * @chip: pointer to chip state structure
438  *
439  * Return Value: negative value reports error.
440  * File: src/unican.c
441  */
442 int unican_clear_objects(struct canchip_t *chip)
443 {
444         CANMSG("unican_clear_objects not implemented\n");
445         return -ENOSYS;
446 }
447
448 /**
449  * unican_config_irqs: - tunes chip hardware interrupt delivery
450  * @chip: pointer to chip state structure
451  * @irqs: requested chip IRQ configuration
452  *
453  * Return Value: negative value reports error.
454  * File: src/unican.c
455  */
456 int unican_config_irqs(struct canchip_t *chip, short irqs)
457 {
458
459         CANMSG("unican_config_irqs not implemented\n");
460         return -ENOSYS;
461 }
462
463 /**
464  * unican_irq_write_handler: - part of ISR code responsible for transmit events
465  * @chip: pointer to chip state structure
466  * @obj: pointer to attached queue description
467  *
468  * The main purpose of this function is to read message from attached queues
469  * and transfer message contents into CAN controller chip.
470  * This subroutine is called by
471  * unican_irq_write_handler() for transmit events.
472  * File: src/unican.c
473  */
474 void unican_irq_write_handler(struct canchip_t *chip, struct msgobj_t *obj)
475 {
476         int cmd;
477         sCAN_CARD *chipext = (sCAN_CARD *)chip->chip_data;
478         __u16 *ptr16 = (__u16*)chipext->rxBufPtr;
479         __u16 u;
480         unsigned long timestamp=0;
481         unsigned long cobid;
482         int i;
483         int len;
484
485        #if 0
486         if(obj->tx_slot){
487                 /* Do local transmitted message distribution if enabled */
488                 if (processlocal){
489                         obj->tx_slot->msg.flags |= MSG_LOCAL;
490                         canque_filter_msg2edges(obj->qends, &obj->tx_slot->msg);
491                 }
492                 /* Free transmitted slot */
493                 canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot);
494                 obj->tx_slot=NULL;
495         }
496        #endif
497
498         if ( chipext->asyncTxBufSize==0 ) {
499                 canque_notify_inends(obj->tx_qedge, CANQUEUE_NOTIFY_ERRTX_PREP);
500                 return; /* No asynchronous queue configured */
501         }
502
503         do {
504                 ptr16 = (__u16*)chipext->asyncTxBufPtr;
505                 if(unican_readw(ptr16) & CL2_MESSAGE_VALID)
506                         return;         /* No free space in asynchronous Tx queue */
507
508                 cmd=canque_test_outslot(obj->qends, &obj->tx_qedge, &obj->tx_slot);
509                 if(cmd<0)
510                         return;         /* No more messages to send */
511
512
513                 cobid = obj->tx_slot->msg.id;
514
515                 if ( (obj->tx_slot->msg.flags & MSG_EXT) ) {    /* 2.0B frame */
516                         cobid <<= 3;
517                 } else {                                        /* 2.0A frame */
518                         cobid <<= 5+16;
519                 }
520                 ptr16++;
521                 u = ((cobid>>16) & 0x00FF ) + (cobid & 0xFF00);
522                 unican_writew(u,ptr16++);
523
524                 len = obj->tx_slot->msg.length;
525                 if(len > CAN_MSG_LENGTH)
526                         len = CAN_MSG_LENGTH;
527                 u = (len << 12) | (cobid & 0x00FF);
528
529                 if ( !(obj->tx_slot->msg.flags & MSG_RTR) )
530                         u |= CL2_REMOTE_FRAME<<8;
531                 if ( obj->tx_slot->msg.flags & MSG_EXT )
532                         u |= CL2_EXT_FRAME<<8;
533
534                 unican_writew(u,ptr16++);
535
536                 for ( i = 0; i < len-1; )       {
537                         u = obj->tx_slot->msg.data[i++];
538                         u |= ((__u16)obj->tx_slot->msg.data[i]<<8); i++;
539                         unican_writew(u,ptr16++);
540                 }
541                 if(i == len) {
542                         unican_writew(timestamp,ptr16);
543                 } else {
544                         u = obj->tx_slot->msg.data[i++];
545                         u |= ((timestamp & 0x00FF)<<8);
546                         unican_writew(u,ptr16++);
547                         unican_writew(timestamp & 0x00FF, ptr16);
548                 }
549
550                 u = ((cobid>>16) & 0xFF00) | CL2_MESSAGE_VALID;
551                 unican_writew(u,(__u16*)chipext->asyncTxBufPtr);
552
553                 if ( (chipext->asyncTxBufBase + chipext->asyncTxBufSize*16) <=
554                                                 (chipext->asyncTxBufPtr += 16) ) {
555                         chipext->asyncTxBufPtr = chipext->asyncTxBufBase;
556                 }
557
558
559                 /* Do local transmitted message distribution if enabled. */
560                 /* This code should not be called directly there, because it breaks strict
561                    behavior of queues if O_SYNC is set. */
562                 if (processlocal){
563                         obj->tx_slot->msg.flags |= MSG_LOCAL;
564                         canque_filter_msg2edges(obj->qends, &obj->tx_slot->msg);
565                 }
566                 /* Free transmitted slot */
567                 canque_free_outslot(obj->qends, obj->tx_qedge, obj->tx_slot);
568                 obj->tx_slot=NULL;
569
570         }while(1);
571
572         return;
573
574 }
575
576 void unican_irq_sync_activities(struct canchip_t *chip, struct msgobj_t *obj)
577 {
578         while(!can_msgobj_test_and_set_fl(obj,TX_LOCK)) {
579
580                 if(can_msgobj_test_and_clear_fl(obj,TX_REQUEST)) {
581                         unican_irq_write_handler(chip, obj);
582                 }
583
584                 /*if(can_msgobj_test_and_clear_fl(obj,FILTCH_REQUEST)) {
585                         unican_irq_update_filter(chip, obj);
586                 }*/
587
588                 can_msgobj_clear_fl(obj,TX_LOCK);
589                 if(can_msgobj_test_fl(obj,TX_REQUEST))
590                         continue;
591                 if(can_msgobj_test_fl(obj,FILTCH_REQUEST) && !obj->tx_slot)
592                         continue;
593                 break;
594         }
595 }
596
597
598 #define MAX_RETR 10
599
600 /**
601  * unican_irq_handler: - interrupt service routine
602  * @irq: interrupt vector number, this value is system specific
603  * @chip: pointer to chip state structure
604  *
605  * Interrupt handler is activated when state of CAN controller chip changes,
606  * there is message to be read or there is more space for new messages or
607  * error occurs. The receive events results in reading of the message from
608  * CAN controller chip and distribution of message through attached
609  * message queues.
610  * File: src/unican.c
611  */
612 int unican_irq_handler(int irq, struct canchip_t *chip)
613 {
614         sCAN_CARD *chipext = (sCAN_CARD *)chip->chip_data;
615         struct msgobj_t *obj=chip->msgobj[0];
616         __u16 status;
617         __u16 error;
618
619         if(!(chip->flags&CHIP_CONFIGURED)) {
620                 CANMSG("unican_irq_handler: called for non-configured device\n");
621                 return CANCHIP_IRQ_NONE;
622         }
623
624         if (cl2_get_status(chipext, &status) == CL2_NO_REQUEST) {
625                 /* Reenable interrupts generation, this has to be even there,
626                  * because irq_accept disables interrupts
627                  */
628                 cl2_gen_interrupt(chipext);
629                 return CANCHIP_IRQ_NONE;
630         }
631
632         cl2_clear_interrupt(chipext);
633
634
635         if(status & CL2_CARD_ERROR) {
636                 cl2_get_error(chipext, &error);
637                 CANMSG("unican_irq_handler: card status=0x%04x error=0x%04x \n",status,error);
638         }
639         if(status & CL2_ASYNC_QUEUE_EMPTY) {
640
641         }
642         if(status & CL2_SYNC_QUEUE_EMPTY) {
643                 can_msgobj_set_fl(obj,TX_REQUEST);
644
645                 /* calls unican_irq_write_handler synchronized with other invocations */
646                 unican_irq_sync_activities(chip, obj);
647
648         }
649         if(status & CL2_DATA_IN_RBUF) {
650                 unican_read(chip, obj);
651         }
652
653         /* Reenable interrupts generation */
654         cl2_gen_interrupt(chipext);
655
656         return CANCHIP_IRQ_HANDLED;
657 }
658
659
660 /**
661  * unican_irq_accept: - fast irq accept routine, blocks further interrupts
662  * @irq: interrupt vector number, this value is system specific
663  * @chip: pointer to chip state structure
664  *
665  * This routine only accepts interrupt reception and stops further
666  * incoming interrupts, but does not handle situation causing interrupt.
667  * File: src/unican.c
668  */
669 int unican_irq_accept(int irq, struct canchip_t *chip)
670 {
671         sCAN_CARD *chipext = (sCAN_CARD *)chip->chip_data;
672
673         cl2_clear_interrupt(chipext);
674
675         return CANCHIP_IRQ_ACCEPTED;
676 }
677
678 /*void unican_do_tx_timeout(unsigned long data)
679 {
680         struct msgobj_t *obj=(struct msgobj_t *)data;
681
682 }*/
683
684 /**
685  * unican_wakeup_tx: - wakeups TX processing
686  * @chip: pointer to chip state structure
687  * @obj: pointer to message object structure
688  *
689  * Return Value: negative value reports error.
690  * File: src/unican.c
691  */
692 int unican_wakeup_tx(struct canchip_t *chip, struct msgobj_t *obj)
693 {
694         can_preempt_disable();
695
696         can_msgobj_set_fl(obj,TX_REQUEST);
697
698         /* calls unican_irq_write_handler synchronized with other invocations
699           from kernel and IRQ context */
700         unican_irq_sync_activities(chip, obj);
701
702         can_preempt_enable();
703
704         return 0;
705 }
706
707
708 /* * * unican Board Functionality * * */
709
710 #define IO_RANGE 0x1000
711
712 /**
713  * unican_request_io: - reserve io or memory range for can board
714  * @candev: pointer to candevice/board which asks for io. Field @io_addr
715  *      of @candev is used in most cases to define start of the range
716  *
717  * Return Value: The function returns zero on success or %-ENODEV on failure
718  * File: src/unican.c
719  */
720 int unican_request_io(struct candevice_t *candev)
721 {
722         can_ioptr_t remap_addr;
723         if (!can_request_mem_region(candev->io_addr,IO_RANGE,DEVICE_NAME " - unican")) {
724                 CANMSG("Unable to request IO-memory: 0x%lx\n",candev->io_addr);
725                 return -ENODEV;
726         }
727         if ( !( remap_addr = ioremap( candev->io_addr, IO_RANGE ) ) ) {
728                 CANMSG("Unable to access I/O memory at: 0x%lx\n", candev->io_addr);
729                 can_release_mem_region(candev->io_addr,IO_RANGE);
730                 return -ENODEV;
731
732         }
733         can_base_addr_fixup(candev, remap_addr);
734         DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", candev->io_addr, candev->io_addr + IO_RANGE - 1);
735         return 0;
736 }
737
738 /**
739  * unican_elease_io - free reserved io memory range
740  * @candev: pointer to candevice/board which releases io
741  *
742  * Return Value: The function always returns zero
743  * File: src/unican.c
744  */
745 int unican_release_io(struct candevice_t *candev)
746 {
747         iounmap(candev->dev_base_addr);
748         can_release_mem_region(candev->io_addr,IO_RANGE);
749         return 0;
750 }
751
752 /**
753  * unican_reset - hardware reset routine
754  * @candev: Pointer to candevice/board structure
755  *
756  * Return Value: The function returns zero on success or %-ENODEV on failure
757  * File: src/unican.c
758  */
759 int unican_reset(struct candevice_t *candev)
760 {
761         int ret;
762         int i;
763         struct canchip_t *chip = candev->chip[0];
764         sCAN_CARD *chipext;
765
766
767         if(chip->chip_data == NULL) {
768                 chip->chip_data = can_checked_malloc(sizeof(sCAN_CARD));
769                 if(!chip->chip_data) return -ENOMEM;
770                 memset(chip->chip_data,0,sizeof(sCAN_CARD));
771                 ret = cl2_init_card(chip->chip_data,(void*)chip->chip_base_addr,chip->chip_irq);
772                 if(ret != CL2_OK){
773                         CANMSG("cl2_init_card returned %d\n",ret);
774                         return -ENODEV;
775                 }
776         }
777
778         chipext = (sCAN_CARD *)chip->chip_data;
779
780         i = 0;
781         /* reset and test whether the card is present */
782         do {
783                 cl2_reset_card(chipext);
784                 unican_delay(10);
785                 i++;
786                 ret = cl2_test_card(chipext);
787         } while((ret != CL2_OK)&&(i<10));
788
789         if(ret != CL2_OK) {
790                 CANMSG("card check failed %d\n",ret);
791                 return -ENODEV;
792         }
793
794         /* start card firmware */
795         ret = cl2_start_firmware(chipext);
796         if(ret != CL2_OK){
797                 CANMSG("cl2_start_firmware returned %d\n",ret);
798                 return -ENODEV;
799         }
800
801         unican_delay(100);
802
803         return 0;
804 }
805
806 /**
807  * unican_init_hw_data - Initialize hardware cards
808  * @candev: Pointer to candevice/board structure
809  *
810  * Return Value: The function always returns zero
811  * File: src/unican.c
812  */
813 int unican_init_hw_data(struct candevice_t *candev)
814 {
815         candev->res_addr=0;
816         candev->nr_82527_chips=0;
817         candev->nr_sja1000_chips=0;
818         candev->nr_all_chips=1;
819         candev->flags |= CANDEV_PROGRAMMABLE_IRQ*0;
820
821         return 0;
822 }
823
824 /**
825  * unican_init_chip_data - Initialize chips
826  * @candev: Pointer to candevice/board structure
827  * @chipnr: Number of the CAN chip on the hardware card
828  *
829  * Return Value: The function always returns zero
830  * File: src/unican.c
831  */
832 int unican_init_chip_data(struct candevice_t *candev, int chipnr)
833 {
834         struct canchip_t *chip = candev->chip[chipnr];
835         chip->chip_type = "unican";
836         chip->chip_base_addr = 0;
837         chip->clock = 10000000;
838         chip->int_clk_reg = 0x0;
839         chip->int_bus_reg = 0x0;
840         chip->max_objects = 1;
841         chip->chip_base_addr=candev->dev_base_addr;
842
843         CANMSG("initializing unican chip operations\n");
844         chip->chipspecops->chip_config=unican_chip_config;
845         chip->chipspecops->baud_rate=unican_baud_rate;
846         chip->chipspecops->standard_mask=unican_standard_mask;
847         chip->chipspecops->extended_mask=unican_extended_mask;
848         chip->chipspecops->message15_mask=unican_extended_mask;
849         chip->chipspecops->clear_objects=unican_clear_objects;
850         chip->chipspecops->config_irqs=unican_config_irqs;
851         chip->chipspecops->pre_read_config=unican_pre_read_config;
852         chip->chipspecops->pre_write_config=unican_pre_write_config;
853         chip->chipspecops->send_msg=unican_send_msg;
854         chip->chipspecops->check_tx_stat=unican_check_tx_stat;
855         chip->chipspecops->wakeup_tx=unican_wakeup_tx;
856         chip->chipspecops->remote_request=unican_remote_request;
857         chip->chipspecops->enable_configuration=unican_enable_configuration;
858         chip->chipspecops->disable_configuration=unican_disable_configuration;
859         chip->chipspecops->set_btregs=unican_set_btregs;
860         chip->chipspecops->attach_to_chip=unican_attach_to_chip;
861         chip->chipspecops->release_chip=unican_release_chip;
862         chip->chipspecops->start_chip=unican_start_chip;
863         chip->chipspecops->stop_chip=unican_stop_chip;
864         chip->chipspecops->irq_handler=unican_irq_handler;
865         chip->chipspecops->irq_accept=unican_irq_accept;
866
867         return 0;
868 }
869
870 /**
871  * unican_init_obj_data - Initialize message buffers
872  * @chip: Pointer to chip specific structure
873  * @objnr: Number of the message buffer
874  *
875  * Return Value: The function always returns zero
876  * File: src/unican.c
877  */
878 int unican_init_obj_data(struct canchip_t *chip, int objnr)
879 {
880         struct msgobj_t *obj=chip->msgobj[objnr];
881         obj->obj_base_addr=chip->chip_base_addr;
882         /*obj->tx_timeout.function=unican_do_tx_timeout;
883         obj->tx_timeout.data=(unsigned long)obj;*/
884         return 0;
885 }
886
887 /**
888  * unican_program_irq - program interrupts
889  * @candev: Pointer to candevice/board structure
890  *
891  * Return value: The function returns zero on success or %-ENODEV on failure
892  * File: src/unican.c
893  */
894 int unican_program_irq(struct candevice_t *candev)
895 {
896         return 0;
897 }
898
899 int unican_register(struct hwspecops_t *hwspecops)
900 {
901         hwspecops->request_io = unican_request_io;
902         hwspecops->release_io = unican_release_io;
903         hwspecops->reset = unican_reset;
904         hwspecops->init_hw_data = unican_init_hw_data;
905         hwspecops->init_chip_data = unican_init_chip_data;
906         hwspecops->init_obj_data = unican_init_obj_data;
907         hwspecops->write_register = NULL;
908         hwspecops->read_register = NULL;
909         hwspecops->program_irq = unican_program_irq;
910         return 0;
911 }
912
913
914 /* Unicontrols PCI board specific functions */
915
916 #ifdef CAN_ENABLE_PCI_SUPPORT
917
918 int unican_pci_request_io(struct candevice_t *candev)
919 {
920         can_ioptr_t remap_addr;
921
922     #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))
923         if(pci_request_region(candev->sysdevptr.pcidev, 0, "unican_pci") != 0){
924                 CANMSG("Request of Unican PCI range failed\n");
925                 return -ENODEV;
926         }
927     #else /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
928         if(pci_request_regions(candev->sysdevptr.pcidev, "kv_pcican") != 0){
929                 CANMSG("Request of Unican PCI range failed\n");
930                 return -ENODEV;
931         }
932     #endif /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
933
934         candev->io_addr=pci_resource_start(candev->sysdevptr.pcidev,0);
935         candev->res_addr=candev->io_addr;
936
937         if ( !( remap_addr = ioremap( candev->io_addr, IO_RANGE ) ) ) {
938                 CANMSG("Unable to access I/O memory at: 0x%lx\n", candev->io_addr);
939             #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))
940                 pci_release_region(candev->sysdevptr.pcidev, 0);
941             #else /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
942                 pci_release_regions(candev->sysdevptr.pcidev);
943             #endif /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
944                 return -ENODEV;
945
946         }
947         can_base_addr_fixup(candev, remap_addr);
948         DEBUGMSG("Registered IO-memory: 0x%lx - 0x%lx\n", candev->io_addr, candev->io_addr + IO_RANGE - 1);
949         DEBUGMSG("VMA: dev_base_addr: 0x%lx chip_base_addr: 0x%lx\n",
950                 can_ioptr2ulong(candev->dev_base_addr),
951                 can_ioptr2ulong(candev->chip[0]->chip_base_addr));
952
953         return 0;
954 }
955
956
957 int unican_pci_release_io(struct candevice_t *candev)
958 {
959         iounmap(candev->dev_base_addr);
960     #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))
961         pci_release_region(candev->sysdevptr.pcidev, 0);
962     #else /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
963         pci_release_regions(candev->sysdevptr.pcidev);
964     #endif /*(LINUX_VERSION_CODE > KERNEL_VERSION(2,4,21))*/
965         return 0;
966 }
967
968
969 int unican_pci_init_hw_data(struct candevice_t *candev)
970 {
971         struct pci_dev *pcidev = NULL;
972
973         pcidev = can_pci_get_next_untaken_device(UNICAN_PCI_VENDOR, UNICAN_PCI_ID);
974         if(pcidev == NULL)
975                 return -ENODEV;
976
977         if (pci_enable_device (pcidev)){
978                 printk(KERN_CRIT "Setup of Unican PCI failed\n");
979                 can_pci_dev_put(pcidev);
980                 return -EIO;
981         }
982         candev->sysdevptr.pcidev=pcidev;
983
984         if(!(pci_resource_flags(pcidev,0)&IORESOURCE_MEM)){
985                 printk(KERN_CRIT "Unican PCI region 0 is not MEM\n");
986                 can_pci_dev_put(pcidev);
987                 return -EIO;
988         }
989         candev->io_addr=pci_resource_start(pcidev,0);
990         candev->res_addr=candev->io_addr;
991         candev->dev_base_addr=NULL;
992
993         /*candev->flags |= CANDEV_PROGRAMMABLE_IRQ;*/
994
995         candev->nr_82527_chips=0;
996         candev->nr_sja1000_chips=0;
997         candev->nr_all_chips=1;
998
999         return 0;
1000 }
1001
1002 void unican_pci_done_hw_data(struct candevice_t *candev)
1003 {
1004         struct pci_dev *pcidev = candev->sysdevptr.pcidev;
1005         can_pci_dev_put(pcidev);
1006 }
1007
1008 int unican_pci_init_chip_data(struct candevice_t *candev, int chipnr)
1009 {
1010         int ret;
1011         candev->chip[chipnr]->chip_irq=candev->sysdevptr.pcidev->irq;
1012         ret = unican_init_chip_data(candev, chipnr);
1013         candev->chip[chipnr]->flags |= CHIP_IRQ_PCI;
1014         return ret;
1015 }
1016
1017 int unican_pci_register(struct hwspecops_t *hwspecops)
1018 {
1019         hwspecops->request_io = unican_pci_request_io;
1020         hwspecops->release_io = unican_pci_release_io;
1021         hwspecops->reset = unican_reset;
1022         hwspecops->init_hw_data = unican_pci_init_hw_data;
1023         hwspecops->done_hw_data = unican_pci_done_hw_data;
1024         hwspecops->init_chip_data = unican_pci_init_chip_data;
1025         hwspecops->init_obj_data = unican_init_obj_data;
1026         hwspecops->write_register = NULL;
1027         hwspecops->read_register = NULL;
1028         hwspecops->program_irq = unican_program_irq;
1029         return 0;
1030 }
1031
1032 #endif /*CAN_ENABLE_PCI_SUPPORT*/
1033
1034 #ifdef CAN_ENABLE_VME_SUPPORT
1035
1036 #include "unican_vme.c"
1037
1038 #endif /*CAN_ENABLE_VME_SUPPORT*/