]> rtime.felk.cvut.cz Git - lincan.git/blob - lincan/src/setup.c
LinCAN can be compiled in mode with RT-Linux chip worker threads now.
[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.2  9 Jul 2003
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 extern int sja1000_register(struct chipspecops_t *chipspecops);
18 extern int sja1000p_register(struct chipspecops_t *chipspecops);
19 extern int i82527_register(struct chipspecops_t *chipspecops);
20
21 int init_device_struct(int card);
22 int init_hwspecops(struct candevice_t *candev);
23 int init_chip_struct(struct candevice_t *candev);
24 int init_obj_struct(struct candevice_t *candev, struct chip_t *hostchip, int minorbase);
25 int init_chipspecops(struct candevice_t *candev, int chipnr);
26
27 void *can_checked_malloc(size_t size)
28 {
29         struct mem_addr *mem_new;
30         void *address_p;
31         
32         address_p=kmalloc(size,GFP_KERNEL);
33         if(address_p == NULL) {
34                 CANMSG("can_checked_malloc: out of the memory\n");
35                 return NULL;
36         }
37
38 #ifdef DEBUG_MEM
39         DEBUGMSG("can_checked_malloc: allocated %d bytes at %p, mem_head=%p\n",
40                         (int)size, address_p, mem_head);
41 #endif
42
43         mem_new=(struct mem_addr *)kmalloc(sizeof(struct mem_addr),GFP_KERNEL);
44         if (mem_new == NULL) {
45                 CANMSG("can_checked_malloc: memory list allocation error.\n");
46                 kfree(address_p);
47                 return NULL;
48         }
49         mem_new->next=mem_head;
50         mem_new->address=address_p;
51         mem_new->size=size;
52         mem_head=mem_new;
53
54         return address_p;
55 }
56
57 int can_checked_free(void *address_p)
58 {
59         struct mem_addr **mem_pptr;
60         struct mem_addr *mem_del=NULL;
61
62 #ifdef DEBUG_MEM
63         DEBUGMSG("can_checked_free %p, mem_head=%p\n", address_p, mem_head);
64 #endif
65
66         for(mem_pptr = &mem_head; (mem_del = *mem_pptr); mem_pptr = &mem_del->next) {
67                 if (mem_del->address != address_p)
68                         continue;
69                 *mem_pptr=mem_del->next;
70                 kfree(mem_del);
71                 kfree(address_p);
72                 return 0;
73         }
74         
75         CANMSG("can_checked_free: address %p not found on the mem list\n", address_p);
76         
77         kfree(address_p);
78         return -1;
79 }
80
81
82 int can_del_mem_list(void)
83 {
84         struct mem_addr *mem;
85
86 #ifdef DEBUG_MEM
87         DEBUGMSG("can_del_mem_list, mem_head=%p\n", mem_head);
88 #endif
89         if(mem_head == NULL) {
90                 CANMSG("can_del_mem_list: no entries on the list - OK\n");
91                 return 0;
92         }
93
94         while((mem=mem_head) != NULL) {
95                 mem_head=mem->next;
96                 CANMSG("can_del_mem_list: deleting %p with size %d\n",
97                         mem->address, (int)mem->size);
98                 kfree(mem->address);
99                 kfree(mem);
100         }
101         
102         return 0;
103 }
104
105 int can_request_io_region(unsigned long start, unsigned long n, const char *name)
106 {
107     #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0))
108         if(check_region(start,n)) return 0;
109         request_region(start,n,name);
110         return 1;
111     #else
112         return (request_region(start,n,name))?1:0;
113     #endif
114 }
115
116 void can_release_io_region(unsigned long start, unsigned long n)
117 {
118         release_region(start,n);
119 }
120
121 int can_request_mem_region(unsigned long start, unsigned long n, const char *name)
122 {
123     #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0))
124         return 1;
125     #else
126         return (request_mem_region(start,n,name))?1:0;
127     #endif
128 }
129
130 void can_release_mem_region(unsigned long start, unsigned long n)
131 {
132     #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0))
133         return;
134     #else
135         release_mem_region(start,n);
136     #endif
137 }
138
139 /* This function shifts all base address structures acording to address
140    translation between physical and virtual address mappings */
141 int can_base_addr_fixup(struct candevice_t *candev, unsigned long new_base)
142 {
143         unsigned long offs;
144         int i, j;
145         
146         offs=new_base-candev->dev_base_addr;
147         candev->dev_base_addr=new_base;
148         for(i=0;i<candev->nr_all_chips;i++){
149                 candev->chip[i]->chip_base_addr += offs;
150                 for(j=0;j<candev->chip[i]->max_objects;j++)
151                         candev->chip[i]->msgobj[j]->obj_base_addr += offs;
152         }
153         return 0;
154 }
155
156 /* The function init_hw_struct is used to initialize the hardware structure. */
157 int init_hw_struct(void)
158 {
159         int i=0;
160
161         hardware_p->nr_boards=0;
162         while ( (hw[i] != NULL) & (i < MAX_HW_CARDS) ) {
163                 hardware_p->nr_boards++;
164
165                 if (init_device_struct(i)) {
166                         CANMSG("Error initializing candevice_t structures.\n");
167                         return -ENODEV;
168                 }
169                 i++;
170         }
171
172         return 0;
173 }
174
175 /* The function init_device_struct is used to initialize a single device 
176  * structure.
177  */
178 int init_device_struct(int card)
179 {
180         struct candevice_t *candev;
181         int ret;
182         
183         candev=(struct candevice_t *)can_checked_malloc(sizeof(struct candevice_t));
184         if (candev==NULL)
185                 return -ENOMEM;
186
187         memset(candev, 0, sizeof(struct candevice_t));
188
189         hardware_p->candevice[card]=candev;
190         candev->candev_idx=card;
191
192         candev=candev;
193
194         candev->hwname=hw[card];
195         candev->io_addr=io[card];
196         candev->dev_base_addr=io[card];
197
198         candev->hwspecops=(struct hwspecops_t *)can_checked_malloc(sizeof(struct hwspecops_t));
199         if (candev->hwspecops==NULL)
200                 goto error_nomem;
201
202         memset(candev->hwspecops, 0, sizeof(struct hwspecops_t));
203
204         if (init_hwspecops(candev))
205                 goto error_nodev;
206
207         if (candev->hwspecops->init_hw_data(candev))
208                 goto error_nodev;
209
210         if ((ret=init_chip_struct(candev)))
211                 goto error_chip;
212
213         return 0;
214
215     error_nodev:
216         ret=-ENODEV;
217     error_chip:
218         candevice_done(candev);
219         goto error_both;
220
221     error_nomem:
222         ret=-ENOMEM;
223
224     error_both:
225         hardware_p->candevice[card]=NULL;
226         can_checked_free(candev);
227         return ret;
228         
229 }
230
231 /* The function init_chip_struct is used to initialize all chip_t structures
232  * on one hardware board.
233  */
234 int init_chip_struct(struct candevice_t *candev)
235 {
236         struct chip_t *chip;
237         static int irq_count=0;
238         int i=0;
239
240         /* Alocate and initialize the chip structures */
241         for (i=0; i < candev->nr_all_chips; i++) {
242                 candev->chip[i]=(struct chip_t *)can_checked_malloc(sizeof(struct chip_t));
243                 if ((chip=candev->chip[i])==NULL)
244                         return -ENOMEM;
245
246                 memset(chip, 0, sizeof(struct chip_t));
247                 
248                 chip->write_register=candev->hwspecops->write_register;
249                 chip->read_register=candev->hwspecops->read_register;
250
251                 chip->chipspecops=can_checked_malloc(sizeof(struct chipspecops_t));
252                 if (chip->chipspecops==NULL)
253                         return -ENOMEM;
254                 
255                 chips_p[irq_count]=chip;
256                 chip->chip_idx=i;
257                 chip->hostdevice=candev;
258                 chip->chip_irq=irq[irq_count];
259                 chip->baudrate=baudrate[irq_count]*1000;
260                 if(!chip->baudrate)
261                         chip->baudrate=baudrate[0]*1000;
262                 chip->flags=0x0;
263
264                 candev->hwspecops->init_chip_data(candev,i);
265
266                 if (init_chipspecops(candev,i))
267                         return -ENODEV;
268                 
269                 init_obj_struct(candev, chip, minor[irq_count]);
270
271                 irq_count++;
272         } 
273
274         return 0;
275 }
276
277 int init_obj_struct(struct candevice_t *candev, struct chip_t *hostchip, int minorbase)
278 {
279         struct canque_ends_t *qends;
280         static int obj_count=0;
281         int i,max_objects;
282         struct msgobj_t *obj;
283
284         max_objects=hostchip->max_objects;
285         for (i=0; i<max_objects; i++) {
286                 obj=(struct msgobj_t *)can_checked_malloc(sizeof(struct msgobj_t));
287                 hostchip->msgobj[i]=obj;
288                 if (obj == NULL) 
289                         return -ENOMEM;
290                         
291                 memset(obj, 0, sizeof(struct msgobj_t));
292
293                 atomic_set(&obj->obj_used,0);
294                 INIT_LIST_HEAD(&obj->obj_users);
295                 init_timer(&obj->tx_timeout);
296                 
297                 qends = (struct canque_ends_t *)can_checked_malloc(sizeof(struct canque_ends_t));
298                 if(qends == NULL) return -ENOMEM;
299                 memset(qends, 0, sizeof(struct canque_ends_t));
300                 obj->hostchip=hostchip;
301                 obj->object=i+1;
302                 obj->qends=qends;
303                 obj->tx_qedge=NULL;
304                 obj->tx_slot=NULL;
305                 obj->obj_flags = 0x0;
306
307                 canqueue_ends_init_chip(qends, hostchip, obj);
308                 
309                 if (minorbase == -1) minorbase=obj_count;
310                 if ((minorbase >= 0) && (minorbase+i<MAX_TOT_MSGOBJS)){
311                   objects_p[minorbase+i]=obj;
312                   obj->minor=minorbase+i;
313                 } else obj->minor=-1;
314
315                 candev->hwspecops->init_obj_data(hostchip,i);
316
317                 obj_count++;
318         }
319         return 0;
320 }
321
322
323 int init_hwspecops(struct candevice_t *candev)
324 {
325         const struct boardtype_t *brp;
326         
327         brp = boardtype_find(candev->hwname);
328         
329         if(!brp) {
330                 CANMSG("Sorry, hardware \"%s\" is currently not supported.\n",candev->hwname);
331                 return -EINVAL;
332         }
333         
334         brp->board_register(candev->hwspecops);
335
336         return 0;
337 }
338
339 int init_chipspecops(struct candevice_t *candev, int chipnr)
340 {
341         if (!strcmp(candev->chip[chipnr]->chip_type,"i82527")) {
342                 candev->chip[chipnr]->max_objects=15;
343                 i82527_register(candev->chip[chipnr]->chipspecops);
344         } 
345         if (!strcmp(candev->chip[chipnr]->chip_type,"sja1000")) {
346                 candev->chip[chipnr]->max_objects=1;
347                 sja1000_register(candev->chip[chipnr]->chipspecops);
348         }
349         if (!strcmp(candev->chip[chipnr]->chip_type,"sja1000p")) {
350                 candev->chip[chipnr]->max_objects=1;
351                 sja1000p_register(candev->chip[chipnr]->chipspecops);
352         }
353
354         return 0;
355 }
356
357 #ifndef CAN_WITH_RTL
358
359 int can_chip_setup_irq(struct chip_t *chip)
360 {
361         if(chip==NULL)
362                 return -1;
363         if(!chip->chipspecops->irq_handler)
364                 return 0;
365                         
366         if (request_irq(chip->chip_irq,chip->chipspecops->irq_handler,SA_SHIRQ,DEVICE_NAME,chip))
367                 return -1;
368         else {
369                 DEBUGMSG("Registered interrupt %d\n",chip->chip_irq);
370                 chip->flags |= CHIP_IRQ_SETUP;
371         }
372         return 1;
373 }
374
375
376 void can_chip_free_irq(struct chip_t *chip)
377 {
378         if((chip->flags & CHIP_IRQ_SETUP) && (chip->chip_irq>=0)) {
379                 free_irq(chip->chip_irq, chip);
380                 chip->flags &= ~CHIP_IRQ_SETUP;
381         }
382 }
383
384 #endif /*CAN_WITH_RTL*/