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