]> rtime.felk.cvut.cz Git - lincan.git/blob - lincan/src/setup.c
Merge: Added CAN chip specific irq_accept routine for fast interrupt acknowledge.
[lincan.git] / lincan / src / setup.c
1 /* setup.c
2  * Linux CAN-bus device driver.
3  * Written by Arnaud Westenberg email:arnaud@wanadoo.nl
4  * Rewritten for new CAN queues by Pavel Pisa - OCERA team member
5  * email:pisa@cmp.felk.cvut.cz
6  * This software is released under the GPL-License.
7  * Version lincan-0.3  17 Jun 2004
8  */ 
9
10 #include "../include/can.h"
11 #include "../include/can_sysdep.h"
12 #include "../include/main.h"
13 #include "../include/devcommon.h"
14 #include "../include/setup.h"
15 #include "../include/finish.h"
16
17 #ifdef CAN_ENABLE_VME_SUPPORT
18 #include "ca91c042.h"
19 /* Modified version of ca91c042 driver can be found in
20  * components/comm/contrib directory. */
21 #endif
22
23 int init_hwspecops(struct candevice_t *candev, int *irqnum_p);
24 int init_device_struct(int card, int *chan_param_idx_p, int *irq_param_idx_p);
25 int init_chip_struct(struct candevice_t *candev, int chipnr, int irq, long baudrate);
26 int init_obj_struct(struct candevice_t *candev, struct canchip_t *hostchip, int objnr);
27
28 /**
29  * can_checked_malloc - memory allocation with registering of requested blocks
30  * @size: size of the requested block
31  *
32  * The function is used in the driver initialization phase to catch possible memory
33  * leaks for future driver finalization or case, that driver initialization fail.
34  * 
35  * Return Value: pointer to the allocated memory or NULL in the case of fail
36  */
37 void *can_checked_malloc(size_t size)
38 {
39         struct mem_addr *mem_new;
40         void *address_p;
41         
42         address_p=kmalloc(size,GFP_KERNEL);
43         if(address_p == NULL) {
44                 CANMSG("can_checked_malloc: out of the memory\n");
45                 return NULL;
46         }
47
48 #ifdef DEBUG_MEM
49         DEBUGMSG("can_checked_malloc: allocated %d bytes at %p, mem_head=%p\n",
50                         (int)size, address_p, mem_head);
51 #endif
52
53         mem_new=(struct mem_addr *)kmalloc(sizeof(struct mem_addr),GFP_KERNEL);
54         if (mem_new == NULL) {
55                 CANMSG("can_checked_malloc: memory list allocation error.\n");
56                 kfree(address_p);
57                 return NULL;
58         }
59         mem_new->next=mem_head;
60         mem_new->address=address_p;
61         mem_new->size=size;
62         mem_head=mem_new;
63
64         return address_p;
65 }
66
67 /**
68  * can_checked_free - free memory allocated by  can_checked_malloc()
69  * @address_p: pointer to the memory block
70  */
71 int can_checked_free(void *address_p)
72 {
73         struct mem_addr **mem_pptr;
74         struct mem_addr *mem_del=NULL;
75
76 #ifdef DEBUG_MEM
77         DEBUGMSG("can_checked_free %p, mem_head=%p\n", address_p, mem_head);
78 #endif
79
80         for(mem_pptr = &mem_head; (mem_del = *mem_pptr); mem_pptr = &mem_del->next) {
81                 if (mem_del->address != address_p)
82                         continue;
83                 *mem_pptr=mem_del->next;
84                 kfree(mem_del);
85                 kfree(address_p);
86                 return 0;
87         }
88         
89         CANMSG("can_checked_free: address %p not found on the mem list\n", address_p);
90         
91         kfree(address_p);
92         return -1;
93 }
94
95
96 /**
97  * can_del_mem_list - check for stale memory allocations at driver finalization
98  *
99  * Checks, if there are still some memory blocks allocated and releases memory
100  * occupied by such blocks back to the system
101  */
102 int can_del_mem_list(void)
103 {
104         struct mem_addr *mem;
105
106 #ifdef DEBUG_MEM
107         DEBUGMSG("can_del_mem_list, mem_head=%p\n", mem_head);
108 #endif
109         if(mem_head == NULL) {
110                 CANMSG("can_del_mem_list: no entries on the list - OK\n");
111                 return 0;
112         }
113
114         while((mem=mem_head) != NULL) {
115                 mem_head=mem->next;
116                 CANMSG("can_del_mem_list: deleting %p with size %d\n",
117                         mem->address, (int)mem->size);
118                 kfree(mem->address);
119                 kfree(mem);
120         }
121         
122         return 0;
123 }
124
125 /**
126  * can_request_io_region - request IO space region
127  * @start: the first IO port address
128  * @n: number of the consecutive IO port addresses
129  * @name: name/label for the requested region
130  *
131  * The function hides system specific implementation of the feature.
132  *
133  * Return Value: returns positive value (1) in the case, that region could
134  *      be reserved for the driver. Returns zero (0) if there is collision with
135  *      other driver or region cannot be taken for some other reason.
136  */
137 int can_request_io_region(unsigned long start, unsigned long n, const char *name)
138 {
139     #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0))
140         if(check_region(start,n)) return 0;
141         request_region(start,n,name);
142         return 1;
143     #else
144         return (request_region(start,n,name))?1:0;
145     #endif
146 }
147
148 /**
149  * can_release_io_region - release IO space region
150  * @start: the first IO port address
151  * @n: number of the consecutive IO port addresses
152  */
153 void can_release_io_region(unsigned long start, unsigned long n)
154 {
155         release_region(start,n);
156 }
157
158 /**
159  * can_request_mem_region - request memory space region
160  * @start: the first memory port physical address
161  * @n: number of the consecutive memory port addresses
162  * @name: name/label for the requested region
163  *
164  * The function hides system specific implementation of the feature.
165  *
166  * Return Value: returns positive value (1) in the case, that region could
167  *      be reserved for the driver. Returns zero (0) if there is collision with
168  *      other driver or region cannot be taken for some other reason.
169  */
170 int can_request_mem_region(unsigned long start, unsigned long n, const char *name)
171 {
172     #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0))
173         return 1;
174     #else
175         return (request_mem_region(start,n,name))?1:0;
176     #endif
177 }
178
179 /**
180  * can_release_mem_region - release memory space region
181  * @start: the first memory port physical address
182  * @n: number of the consecutive memory port addresses
183  */
184 void can_release_mem_region(unsigned long start, unsigned long n)
185 {
186     #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0))
187         return;
188     #else
189         release_mem_region(start,n);
190     #endif
191 }
192
193 /**
194  * can_base_addr_fixup - relocates board physical memory addresses to the CPU accessible ones
195  * @candev: pointer to the previously filled device/board, chips and message objects structures
196  * @new_base: @candev new base address
197  *
198  * This function adapts base addresses of all structures of one board
199  * to the new board base address.
200  * It is required for translation between physical and virtual address mappings.
201  * This function is prepared to simplify board specific xxx_request_io() function
202  * for memory mapped devices.
203  */
204 int can_base_addr_fixup(struct candevice_t *candev, unsigned long new_base)
205 {
206         unsigned long offs;
207         int i, j;
208         
209         offs=new_base-candev->dev_base_addr;
210         candev->dev_base_addr=new_base;
211         for(i=0;i<candev->nr_all_chips;i++){
212                 candev->chip[i]->chip_base_addr += offs;
213                 for(j=0;j<candev->chip[i]->max_objects;j++)
214                         candev->chip[i]->msgobj[j]->obj_base_addr += offs;
215         }
216         return 0;
217 }
218
219 /**
220  * can_check_dev_taken - checks if bus device description is already taken by driver
221  * @anydev:     pointer to bus specific Linux device description 
222  *
223  * Returns: Returns 1 if device is already used by LinCAN driver, 0 otherwise.
224  */
225 int can_check_dev_taken(void *anydev)
226 {
227         int board_nr;
228         struct candevice_t *candev;
229         void *boarddev;
230
231         for (board_nr=hardware_p->nr_boards; board_nr--; ) {
232                 if((candev=hardware_p->candevice[board_nr])==NULL)
233                         continue;
234                 boarddev=candev->sysdevptr.anydev;
235                 if(boarddev == anydev)
236                         return 1;
237         }
238         
239         return 0;
240 }
241
242
243 /**
244  * register_obj_struct - registers message object into global array
245  * @obj: the initialized message object being registered
246  * @minorbase: wanted minor number, if (-1) automatically selected
247  *
248  * Return Value: returns negative number in the case of fail
249  */
250 int register_obj_struct(struct msgobj_t *obj, int minorbase)
251 {
252         static int next_minor=0;
253         int i;
254         
255         if(minorbase>=0)
256                 next_minor=minorbase;
257         if(next_minor>=MAX_TOT_MSGOBJS)
258                 next_minor=0;
259         i=next_minor;
260         do{
261                 if(objects_p[i]==NULL){
262                         objects_p[i]=obj;
263                         obj->minor=i;
264                         next_minor=i+1;
265                         return 0;
266                 }
267                 if(++i >= MAX_TOT_MSGOBJS) i=0;
268         }while(i!=next_minor);
269         obj->minor=-1;
270         return -1;
271 }
272
273
274 /**
275  * register_chip_struct - registers chip into global array
276  * @chip: the initialized chip structure being registered
277  * @minorbase: wanted minor number base, if (-1) automatically selected
278  *
279  * Return Value: returns negative number in the case of fail
280  */
281 int register_chip_struct(struct canchip_t *chip, int minorbase)
282 {
283         static int next_chip_slot=0;
284         int i;
285         
286         if(next_chip_slot>=MAX_TOT_CHIPS)
287                 next_chip_slot=0;
288         i=next_chip_slot;
289         do{
290                 if(chips_p[i]==NULL){
291                         chips_p[i]=chip;
292
293                         next_chip_slot=i+1;
294                         return 0;
295                 }
296                 if(++i >= MAX_TOT_CHIPS) i=0;
297         }while(i!=next_chip_slot);
298         return -1;
299 }
300
301
302
303 /**
304  * init_hw_struct - initializes driver hardware description structures
305  *
306  * The function init_hw_struct() is used to initialize the hardware structure.
307  *
308  * Return Value: returns negative number in the case of fail
309  */
310 int init_hw_struct(void)
311 {
312         int i=0;
313         int irq_param_idx=0;
314         int chan_param_idx=0;
315
316         hardware_p->nr_boards=0;
317         while ( (hw[i] != NULL) & (i < MAX_HW_CARDS) ) {
318                 hardware_p->nr_boards++;
319
320                 if (init_device_struct(i, &chan_param_idx, &irq_param_idx)) {
321                         CANMSG("Error initializing candevice_t structures.\n");
322                         return -ENODEV;
323                 }
324                 i++;
325         }
326
327         return 0;
328 }
329
330 /**
331  * init_device_struct - initializes single CAN device/board
332  * @card: index into @hardware_p HW description
333  * @chan_param_idx_p: pointer to the index into arrays of the CAN channel parameters
334  * @irq_param_idx_p: pointer to the index into arrays of the per CAN channel IRQ parameters
335  *
336  * The function builds representation of the one board from parameters provided
337  * in the module parameters arrays: 
338  *      @hw[card] .. hardware type,
339  *      @io[card] .. base IO address,
340  *      @baudrate[chan_param_idx] .. per channel baudrate,
341  *      @minor[chan_param_idx] .. optional specification of requested channel minor base,
342  *      @irq[irq_param_idx] .. one or more board/chips IRQ parameters.
343  * The indexes are advanced after consumed parameters if the registration is successful.
344  *
345  * The hardware specific operations of the device/board are initialized by call to
346  * init_hwspecops() function. Then board data are initialized by board specific 
347  * init_hw_data() function. Then chips and objects representation is build by
348  * init_chip_struct() function. If all above steps are successful, chips and
349  * message objects are registered into global arrays. 
350  *
351  * Return Value: returns negative number in the case of fail
352  */
353 int init_device_struct(int card, int *chan_param_idx_p, int *irq_param_idx_p)
354 {
355         struct candevice_t *candev;
356         int ret;
357         int irqnum;
358         int chipnr;
359         long bd;
360         int irqsig=-1;
361         
362         candev=(struct candevice_t *)can_checked_malloc(sizeof(struct candevice_t));
363         if (candev==NULL)
364                 return -ENOMEM;
365
366         memset(candev, 0, sizeof(struct candevice_t));
367
368         hardware_p->candevice[card]=candev;
369         candev->candev_idx=card;
370
371         candev=candev;
372
373         candev->hwname=hw[card];
374         candev->io_addr=io[card];
375         candev->dev_base_addr=io[card];
376
377         candev->hwspecops=(struct hwspecops_t *)can_checked_malloc(sizeof(struct hwspecops_t));
378         if (candev->hwspecops==NULL)
379                 goto error_nomem;
380
381         memset(candev->hwspecops, 0, sizeof(struct hwspecops_t));
382
383         if (init_hwspecops(candev, &irqnum))
384                 goto error_nodev;
385
386         if (candev->hwspecops->init_hw_data(candev))
387                 goto error_nodev;
388
389         /* Alocate and initialize the chip structures */
390         for (chipnr=0; chipnr < candev->nr_all_chips; chipnr++) {
391
392                 if(chipnr<irqnum)
393                         irqsig=irq[*irq_param_idx_p+chipnr];
394                 
395                 bd=baudrate[*chan_param_idx_p+chipnr];
396                 if(!bd) bd=baudrate[0];
397         
398                 if ((ret=init_chip_struct(candev, chipnr, irqsig, bd*1000)))
399                         goto error_chip;
400         }
401         
402
403
404         for (chipnr=0; chipnr < candev->nr_all_chips; chipnr++) {
405                 int m=minor[*chan_param_idx_p+chipnr];
406                 struct canchip_t *chip=candev->chip[chipnr];
407                 int objnr;
408
409                 register_chip_struct(chip, m);
410                 
411                 for (objnr=0; objnr<chip->max_objects; objnr++) {
412                         register_obj_struct(chip->msgobj[objnr], m);
413                         if(m>=0) m++;
414                 }
415         }
416
417         *irq_param_idx_p += irqnum;
418         *chan_param_idx_p += candev->nr_all_chips;
419
420         return 0;
421
422     error_nodev:
423         ret=-ENODEV;
424     error_chip:
425         candevice_done(candev);
426         goto error_both;
427
428     error_nomem:
429         ret=-ENOMEM;
430
431     error_both:
432         hardware_p->candevice[card]=NULL;
433         can_checked_free(candev);
434         return ret;
435         
436 }
437
438 /**
439  * init_chip_struct - initializes one CAN chip structure
440  * @candev: pointer to the corresponding CAN device/board
441  * @chipnr: index of the chip in the corresponding device/board structure
442  * @irq: chip IRQ number or (-1) if not appropriate
443  * @baudrate: baudrate in the units of 1Bd
444  *
445  * Chip structure is allocated and chip specific operations are filled by 
446  * call to board specific init_chip_data() which calls chip specific
447  * fill_chipspecops(). The message objects are generated by 
448  * calls to init_obj_struct() function.
449  *
450  * Return Value: returns negative number in the case of fail
451  */
452 int init_chip_struct(struct candevice_t *candev, int chipnr, int irq, long baudrate)
453 {
454         struct canchip_t *chip;
455         int objnr;
456         int ret;
457
458         candev->chip[chipnr]=(struct canchip_t *)can_checked_malloc(sizeof(struct canchip_t));
459         if ((chip=candev->chip[chipnr])==NULL)
460                 return -ENOMEM;
461
462         memset(chip, 0, sizeof(struct canchip_t));
463
464         chip->write_register=candev->hwspecops->write_register;
465         chip->read_register=candev->hwspecops->read_register;
466
467         chip->chipspecops=can_checked_malloc(sizeof(struct chipspecops_t));
468         if (chip->chipspecops==NULL)
469                 return -ENOMEM;
470         memset(chip->chipspecops,0,sizeof(struct chipspecops_t));
471
472         chip->chip_idx=chipnr;
473         chip->hostdevice=candev;
474         chip->chip_irq=irq;
475         chip->baudrate=baudrate;
476         chip->flags=0x0;
477
478         if(candev->hwspecops->init_chip_data(candev,chipnr)<0)
479                 return -ENODEV;
480
481         for (objnr=0; objnr<chip->max_objects; objnr++) {
482                 ret=init_obj_struct(candev, chip, objnr);
483                 if(ret<0) return ret;
484         }
485
486         return 0;
487 }
488
489
490 /**
491  * init_obj_struct - initializes one CAN message object structure
492  * @candev: pointer to the corresponding CAN device/board
493  * @hostchip: pointer to the chip containing this object
494  * @objnr: index of the builded object in the chip structure
495  *
496  * The function initializes message object structure and allocates and initializes
497  * CAN queue chip ends structure.
498  *
499  * Return Value: returns negative number in the case of fail
500  */
501 int init_obj_struct(struct candevice_t *candev, struct canchip_t *hostchip, int objnr)
502 {
503         struct canque_ends_t *qends;
504         struct msgobj_t *obj;
505         int ret;
506
507         obj=(struct msgobj_t *)can_checked_malloc(sizeof(struct msgobj_t));
508         hostchip->msgobj[objnr]=obj;
509         if (obj == NULL) 
510                 return -ENOMEM;
511
512         memset(obj, 0, sizeof(struct msgobj_t));
513         obj->minor=-1;
514
515         atomic_set(&obj->obj_used,0);
516         INIT_LIST_HEAD(&obj->obj_users);
517         init_timer(&obj->tx_timeout);
518
519         qends = (struct canque_ends_t *)can_checked_malloc(sizeof(struct canque_ends_t));
520         if(qends == NULL) return -ENOMEM;
521         memset(qends, 0, sizeof(struct canque_ends_t));
522         obj->hostchip=hostchip;
523         obj->object=objnr+1;
524         obj->qends=qends;
525         obj->tx_qedge=NULL;
526         obj->tx_slot=NULL;
527         obj->obj_flags = 0x0;
528
529         ret=canqueue_ends_init_chip(qends, hostchip, obj);
530         if(ret<0) return ret;
531
532         ret=candev->hwspecops->init_obj_data(hostchip,objnr);
533         if(ret<0) return ret;
534         
535         return 0;
536 }
537
538
539 /**
540  * init_hwspecops - finds and initializes board/device specific operations
541  * @candev: pointer to the corresponding CAN device/board
542  * @irqnum_p: optional pointer to the number of interrupts required by board
543  *
544  * The function searches board @hwname in the list of supported boards types.
545  * The board type specific board_register() function is used to initialize
546  * @hwspecops operations.
547  *
548  * Return Value: returns negative number in the case of fail
549  */
550 int init_hwspecops(struct candevice_t *candev, int *irqnum_p)
551 {
552         const struct boardtype_t *brp;
553         
554         brp = boardtype_find(candev->hwname);
555         
556         if(!brp) {
557                 CANMSG("Sorry, hardware \"%s\" is currently not supported.\n",candev->hwname);
558                 return -EINVAL;
559         }
560         
561         if(irqnum_p)
562                 *irqnum_p=brp->irqnum;
563         brp->board_register(candev->hwspecops);
564
565         return 0;
566 }
567
568
569 #ifndef CAN_WITH_RTL
570
571 /**
572  * can_default_irq_dispatch - the first level interrupt dispatch handler
573  * @irq: interrupt vector number, this value is system specific
574  * @dev_id: driver private pointer registered at time of request_irq() call.
575  *      The CAN driver uses this pointer to store relationship of interrupt
576  *      to chip state structure - @struct canchip_t
577  * @regs: system dependent value pointing to registers stored in exception frame
578  * 
579  * File: src/setup.c
580  */
581 can_irqreturn_t can_default_irq_dispatch(int irq, void *dev_id, struct pt_regs *regs)
582 {
583         int retval;
584         struct canchip_t *chip=(struct canchip_t *)dev_id;
585
586         retval=chip->chipspecops->irq_handler(irq, chip);
587         return CAN_IRQ_RETVAL(retval);
588 }
589
590 /**
591  * can_chip_setup_irq - attaches chip to the system interrupt processing
592  * @chip: pointer to CAN chip structure
593  *
594  * Return Value: returns negative number in the case of fail
595  */
596 int can_chip_setup_irq(struct canchip_t *chip)
597 {
598         if(chip==NULL)
599                 return -1;
600         if(!chip->chipspecops->irq_handler)
601                 return 0;
602         if(chip->flags & CHIP_IRQ_CUSTOM)
603                 return 1;
604                         
605         if ((chip->flags & CHIP_IRQ_VME) == 0) {
606                 if (request_irq(chip->chip_irq,can_default_irq_dispatch,SA_SHIRQ,DEVICE_NAME,chip))
607                         return -1;
608                 else {
609                         DEBUGMSG("Registered interrupt %d\n",chip->chip_irq);
610                         chip->flags |= CHIP_IRQ_SETUP;
611                 }
612         } else {
613 #ifdef CAN_ENABLE_VME_SUPPORT
614                 if (chip->chip_irq < 1 || chip->chip_irq > 255) {
615                         CANMSG("Bad irq parameter. (1 <= irq <= 255).\n");
616                         return -EINVAL;
617                 }
618                 
619                 request_vmeirq(chip->chip_irq, can_default_irq_dispatch, chip);
620                 DEBUGMSG("Registered VME interrupt vector %d\n",chip->chip_irq);
621                 chip->flags |= CHIP_IRQ_SETUP;
622 #endif
623         }
624         return 1;
625 }
626
627
628 /**
629  * can_chip_free_irq - unregisters chip interrupt handler from the system
630  * @chip: pointer to CAN chip structure
631  */
632 void can_chip_free_irq(struct canchip_t *chip)
633 {
634         if((chip->flags & CHIP_IRQ_SETUP) && (chip->chip_irq>=0)) {
635                 if(chip->flags & CHIP_IRQ_CUSTOM)
636                         return;
637
638                 if ((chip->flags & CHIP_IRQ_VME) == 0)
639                         free_irq(chip->chip_irq, chip);
640                 else { 
641 #ifdef CAN_ENABLE_VME_SUPPORT
642                         free_vmeirq(chip->chip_irq);
643 #endif
644                 }
645                         chip->flags &= ~CHIP_IRQ_SETUP;
646         }
647 }
648
649 #endif /*CAN_WITH_RTL*/