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