]> rtime.felk.cvut.cz Git - lincan.git/blob - lincan/src/setup.c
72ef1a9f2b2e51faf1ec284978a2dabb6d65cb31
[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_hwspecops(struct candevice_t *candev, int *irqnum_p);
22 int init_device_struct(int card, int *chan_param_idx_p, int *irq_param_idx_p);
23 int init_chip_struct(struct candevice_t *candev, int chipnr, int irq, long baudrate);
24 int init_obj_struct(struct candevice_t *candev, struct chip_t *hostchip, int objnr);
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
157 int register_obj_struct(struct msgobj_t *obj, int minorbase)
158 {
159         static int next_minor=0;
160         int i;
161         
162         if(minorbase>=0)
163                 next_minor=minorbase;
164         if(next_minor>=MAX_TOT_MSGOBJS)
165                 next_minor=0;
166         i=next_minor;
167         do{
168                 if(objects_p[i]==NULL){
169                         objects_p[i]=obj;
170                         obj->minor=i;
171                         next_minor=i+1;
172                         return 0;
173                 }
174                 if(++i >= MAX_TOT_MSGOBJS) i=0;
175         }while(i!=next_minor);
176         obj->minor=-1;
177         return -1;
178 }
179
180
181 int register_chip_struct(struct chip_t *chip, int minorbase)
182 {
183         static int next_chip_slot=0;
184         int i;
185         
186         if(next_chip_slot>=MAX_TOT_CHIPS)
187                 next_chip_slot=0;
188         i=next_chip_slot;
189         do{
190                 if(chips_p[i]==NULL){
191                         chips_p[i]=chip;
192
193                         next_chip_slot=i+1;
194                         return 0;
195                 }
196                 if(++i >= MAX_TOT_CHIPS) i=0;
197         }while(i!=next_chip_slot);
198         return -1;
199 }
200
201
202 /* The function init_hw_struct is used to initialize the hardware structure. */
203 int init_hw_struct(void)
204 {
205         int i=0;
206         int irq_param_idx=0;
207         int chan_param_idx=0;
208
209         hardware_p->nr_boards=0;
210         while ( (hw[i] != NULL) & (i < MAX_HW_CARDS) ) {
211                 hardware_p->nr_boards++;
212
213                 if (init_device_struct(i, &chan_param_idx, &irq_param_idx)) {
214                         CANMSG("Error initializing candevice_t structures.\n");
215                         return -ENODEV;
216                 }
217                 i++;
218         }
219
220         return 0;
221 }
222
223 /* The function init_device_struct is used to initialize a single device 
224  * structure.
225  */
226 int init_device_struct(int card, int *chan_param_idx_p, int *irq_param_idx_p)
227 {
228         struct candevice_t *candev;
229         int ret;
230         int irqnum;
231         int chipnr;
232         long bd;
233         int irqsig=-1;
234         
235         candev=(struct candevice_t *)can_checked_malloc(sizeof(struct candevice_t));
236         if (candev==NULL)
237                 return -ENOMEM;
238
239         memset(candev, 0, sizeof(struct candevice_t));
240
241         hardware_p->candevice[card]=candev;
242         candev->candev_idx=card;
243
244         candev=candev;
245
246         candev->hwname=hw[card];
247         candev->io_addr=io[card];
248         candev->dev_base_addr=io[card];
249
250         candev->hwspecops=(struct hwspecops_t *)can_checked_malloc(sizeof(struct hwspecops_t));
251         if (candev->hwspecops==NULL)
252                 goto error_nomem;
253
254         memset(candev->hwspecops, 0, sizeof(struct hwspecops_t));
255
256         if (init_hwspecops(candev, &irqnum))
257                 goto error_nodev;
258
259         if (candev->hwspecops->init_hw_data(candev))
260                 goto error_nodev;
261
262         /* Alocate and initialize the chip structures */
263         for (chipnr=0; chipnr < candev->nr_all_chips; chipnr++) {
264
265                 if(chipnr<irqnum)
266                         irqsig=irq[*irq_param_idx_p+chipnr];
267                 
268                 bd=baudrate[*chan_param_idx_p+chipnr];
269                 if(!bd) bd=baudrate[0];
270         
271                 if ((ret=init_chip_struct(candev, chipnr, irqsig, bd*1000)))
272                         goto error_chip;
273         }
274         
275
276
277         for (chipnr=0; chipnr < candev->nr_all_chips; chipnr++) {
278                 int m=minor[*chan_param_idx_p+chipnr];
279                 struct chip_t *chip=candev->chip[chipnr];
280                 int objnr;
281
282                 register_chip_struct(chip, m);
283                 
284                 for (objnr=0; objnr<chip->max_objects; objnr++) {
285                         register_obj_struct(chip->msgobj[objnr], m);
286                         if(m>=0) m++;
287                 }
288         }
289
290         *irq_param_idx_p += irqnum;
291         *chan_param_idx_p += candev->nr_all_chips;
292
293         return 0;
294
295     error_nodev:
296         ret=-ENODEV;
297     error_chip:
298         candevice_done(candev);
299         goto error_both;
300
301     error_nomem:
302         ret=-ENOMEM;
303
304     error_both:
305         hardware_p->candevice[card]=NULL;
306         can_checked_free(candev);
307         return ret;
308         
309 }
310
311 /* The function init_chip_struct is used to initialize all chip_t structures
312  * on one hardware board.
313  */
314 int init_chip_struct(struct candevice_t *candev, int chipnr, int irq, long baudrate)
315 {
316         struct chip_t *chip;
317         int objnr;
318         int ret;
319
320         candev->chip[chipnr]=(struct chip_t *)can_checked_malloc(sizeof(struct chip_t));
321         if ((chip=candev->chip[chipnr])==NULL)
322                 return -ENOMEM;
323
324         memset(chip, 0, sizeof(struct chip_t));
325
326         chip->write_register=candev->hwspecops->write_register;
327         chip->read_register=candev->hwspecops->read_register;
328
329         chip->chipspecops=can_checked_malloc(sizeof(struct chipspecops_t));
330         if (chip->chipspecops==NULL)
331                 return -ENOMEM;
332
333         chip->chip_idx=chipnr;
334         chip->hostdevice=candev;
335         chip->chip_irq=irq;
336         chip->baudrate=baudrate;
337         chip->flags=0x0;
338
339         candev->hwspecops->init_chip_data(candev,chipnr);
340
341         if (init_chipspecops(candev,chipnr))
342                 return -ENODEV;
343
344         for (objnr=0; objnr<chip->max_objects; objnr++) {
345                 ret=init_obj_struct(candev, chip, objnr);
346                 if(ret<0) return ret;
347         }
348
349         return 0;
350 }
351
352
353 int init_obj_struct(struct candevice_t *candev, struct chip_t *hostchip, int objnr)
354 {
355         struct canque_ends_t *qends;
356         struct msgobj_t *obj;
357         int ret;
358
359         obj=(struct msgobj_t *)can_checked_malloc(sizeof(struct msgobj_t));
360         hostchip->msgobj[objnr]=obj;
361         if (obj == NULL) 
362                 return -ENOMEM;
363
364         memset(obj, 0, sizeof(struct msgobj_t));
365         obj->minor=-1;
366
367         atomic_set(&obj->obj_used,0);
368         INIT_LIST_HEAD(&obj->obj_users);
369         init_timer(&obj->tx_timeout);
370
371         qends = (struct canque_ends_t *)can_checked_malloc(sizeof(struct canque_ends_t));
372         if(qends == NULL) return -ENOMEM;
373         memset(qends, 0, sizeof(struct canque_ends_t));
374         obj->hostchip=hostchip;
375         obj->object=objnr+1;
376         obj->qends=qends;
377         obj->tx_qedge=NULL;
378         obj->tx_slot=NULL;
379         obj->obj_flags = 0x0;
380
381         ret=canqueue_ends_init_chip(qends, hostchip, obj);
382         if(ret<0) return ret;
383
384         ret=candev->hwspecops->init_obj_data(hostchip,objnr);
385         if(ret<0) return ret;
386         
387         return 0;
388 }
389
390
391 int init_hwspecops(struct candevice_t *candev, int *irqnum_p)
392 {
393         const struct boardtype_t *brp;
394         
395         brp = boardtype_find(candev->hwname);
396         
397         if(!brp) {
398                 CANMSG("Sorry, hardware \"%s\" is currently not supported.\n",candev->hwname);
399                 return -EINVAL;
400         }
401         
402         if(irqnum_p)
403                 *irqnum_p=brp->irqnum;
404         brp->board_register(candev->hwspecops);
405
406         return 0;
407 }
408
409
410 int init_chipspecops(struct candevice_t *candev, int chipnr)
411 {
412         if (!strcmp(candev->chip[chipnr]->chip_type,"i82527")) {
413                 candev->chip[chipnr]->max_objects=15;
414                 i82527_register(candev->chip[chipnr]->chipspecops);
415         } 
416         if (!strcmp(candev->chip[chipnr]->chip_type,"sja1000")) {
417                 candev->chip[chipnr]->max_objects=1;
418                 sja1000_register(candev->chip[chipnr]->chipspecops);
419         }
420         if (!strcmp(candev->chip[chipnr]->chip_type,"sja1000p")) {
421                 candev->chip[chipnr]->max_objects=1;
422                 sja1000p_register(candev->chip[chipnr]->chipspecops);
423         }
424
425         return 0;
426 }
427
428 #ifndef CAN_WITH_RTL
429
430 int can_chip_setup_irq(struct chip_t *chip)
431 {
432         if(chip==NULL)
433                 return -1;
434         if(!chip->chipspecops->irq_handler)
435                 return 0;
436                         
437         if (request_irq(chip->chip_irq,chip->chipspecops->irq_handler,SA_SHIRQ,DEVICE_NAME,chip))
438                 return -1;
439         else {
440                 DEBUGMSG("Registered interrupt %d\n",chip->chip_irq);
441                 chip->flags |= CHIP_IRQ_SETUP;
442         }
443         return 1;
444 }
445
446
447 void can_chip_free_irq(struct chip_t *chip)
448 {
449         if((chip->flags & CHIP_IRQ_SETUP) && (chip->chip_irq>=0)) {
450                 free_irq(chip->chip_irq, chip);
451                 chip->flags &= ~CHIP_IRQ_SETUP;
452         }
453 }
454
455 #endif /*CAN_WITH_RTL*/