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
10 #define __NO_VERSION__
11 #include <linux/module.h>
13 #include <linux/autoconf.h>
15 #include <linux/version.h>
16 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0))
17 #include <linux/malloc.h>
19 #include <linux/slab.h>
22 #include <linux/ioport.h>
24 #include "../include/main.h"
25 #include "../include/devcommon.h"
26 #include "../include/setup.h"
28 extern int sja1000_register(struct chipspecops_t *chipspecops);
29 extern int sja1000p_register(struct chipspecops_t *chipspecops);
30 extern int i82527_register(struct chipspecops_t *chipspecops);
32 int init_device_struct(int card);
33 int init_hwspecops(struct candevice_t *candev);
34 int init_chip_struct(struct candevice_t *candev);
35 int init_obj_struct(struct candevice_t *candev, struct chip_t *hostchip, int minorbase);
36 int init_chipspecops(struct candevice_t *candev, int chipnr);
38 int add_mem_to_list(void *address_p)
40 struct mem_addr *mem_new;
43 DEBUGMSG("add_mem_to_list %p, mem_head=%p\n",address_p, mem_head);
47 mem_new=(struct mem_addr *)kmalloc(sizeof(struct mem_addr),GFP_KERNEL);
48 if (mem_new == NULL) {
49 CANMSG("Memory list error.\n");
52 mem_new->next=mem_head;
53 mem_new->address=address_p;
59 int del_mem_from_list(void *address_p)
61 struct mem_addr *mem_search=NULL;
62 struct mem_addr *mem_delete=NULL;
65 DEBUGMSG("del_mem_from_list %p, mem_head=%p\n", address_p, mem_head);
68 if(mem_head == NULL) {
69 CANMSG("del_mem_from_list: mem_head == NULL address_p=%p!\n",
74 mem_search = mem_head;
76 if (mem_head->address == address_p) {
77 kfree(mem_head->address);
78 mem_head=mem_head->next;
82 while (mem_search->next->address != address_p)
83 mem_search=mem_search->next;
84 kfree(mem_search->next->address);
85 mem_delete=mem_search->next;
86 mem_search->next=mem_search->next->next;
93 int del_mem_list(void)
95 struct mem_addr *mem_old;
98 DEBUGMSG("del_mem_list, mem_head=%p\n", mem_head);
101 if(mem_head == NULL) {
102 CANMSG("del_mem_list: mem_head == NULL!\n");
106 while (mem_head->next != NULL) {
108 kfree(mem_old->address);
109 mem_head=mem_old->next;
116 int can_request_io_region(unsigned long start, unsigned long n, const char *name)
118 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0))
119 if(check_region(start,n)) return 0;
120 request_region(start,n,name);
123 return (request_region(start,n,name))?1:0;
127 void can_release_io_region(unsigned long start, unsigned long n)
129 release_region(start,n);
132 int can_request_mem_region(unsigned long start, unsigned long n, const char *name)
134 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0))
137 return (request_mem_region(start,n,name))?1:0;
141 void can_release_mem_region(unsigned long start, unsigned long n)
143 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0))
146 release_mem_region(start,n);
150 /* This function shifts all base address structures acording to address
151 translation between physical and virtual address mappings */
152 int can_base_addr_fixup(struct candevice_t *candev, unsigned long new_base)
157 offs=new_base-candev->dev_base_addr;
158 candev->dev_base_addr=new_base;
159 for(i=0;i<candev->nr_all_chips;i++){
160 candev->chip[i]->chip_base_addr += offs;
161 for(j=0;j<candev->chip[i]->max_objects;j++)
162 candev->chip[i]->msgobj[j]->obj_base_addr += offs;
167 /* The function init_hw_struct is used to initialize the hardware structure. */
168 int init_hw_struct(void)
172 hardware_p->nr_boards=0;
173 while ( (hw[i] != NULL) & (i < MAX_HW_CARDS) ) {
174 hardware_p->nr_boards++;
176 if (init_device_struct(i)) {
177 CANMSG("Error initializing candevice_t structures.\n");
186 /* The function init_device_struct is used to initialize a single device
189 int init_device_struct(int card)
191 struct candevice_t *candev;
193 candev=(struct candevice_t *)kmalloc(sizeof(struct candevice_t),GFP_KERNEL);
197 if ( add_mem_to_list(candev) )
200 memset(candev, 0, sizeof(struct candevice_t));
202 hardware_p->candevice[card]=candev;
203 candev->candev_idx=card;
207 candev->hwname=hw[card];
208 candev->io_addr=io[card];
209 candev->dev_base_addr=io[card];
211 candev->hwspecops=(struct hwspecops_t *)kmalloc(sizeof(struct hwspecops_t),GFP_KERNEL);
212 if (candev->hwspecops==NULL)
215 if ( add_mem_to_list(candev->hwspecops) )
217 memset(candev->hwspecops, 0, sizeof(struct hwspecops_t));
219 if (init_hwspecops(candev))
222 if (candev->hwspecops->init_hw_data(candev))
225 if (init_chip_struct(candev))
231 /* The function init_chip_struct is used to initialize all chip_t structures
232 * on one hardware board.
234 int init_chip_struct(struct candevice_t *candev)
236 static int irq_count=0;
239 /* Alocate and initialize the chip structures */
240 for (i=0; i < candev->nr_all_chips; i++) {
241 candev->chip[i]=(struct chip_t *)kmalloc(sizeof(struct chip_t),GFP_KERNEL);
242 if (candev->chip[i]==NULL)
245 if ( add_mem_to_list(candev->chip[i]) )
248 memset(candev->chip[i], 0, sizeof(struct chip_t));
250 candev->chip[i]->write_register=candev->hwspecops->write_register;
251 candev->chip[i]->read_register=candev->hwspecops->read_register;
253 candev->chip[i]->chipspecops=(struct chipspecops_t *)kmalloc(sizeof(struct chipspecops_t),GFP_KERNEL);
254 if (candev->chip[i]->chipspecops==NULL)
257 if ( add_mem_to_list(candev->chip[i]->chipspecops) )
260 chips_p[irq_count]=candev->chip[i];
261 candev->chip[i]->chip_idx=i;
262 candev->chip[i]->hostdevice=candev;
263 candev->chip[i]->chip_irq=irq[irq_count];
264 candev->chip[i]->flags=0x0;
266 candev->hwspecops->init_chip_data(candev,i);
268 if (init_chipspecops(candev,i))
271 init_obj_struct(candev, candev->chip[i], minor[irq_count]);
279 int init_obj_struct(struct candevice_t *candev, struct chip_t *hostchip, int minorbase)
281 struct canque_ends_t *qends;
282 static int obj_count=0;
284 struct msgobj_t *obj;
286 max_objects=hostchip->max_objects;
287 for (i=0; i<max_objects; i++) {
288 obj=(struct msgobj_t *)kmalloc(sizeof(struct msgobj_t),GFP_KERNEL);
289 hostchip->msgobj[i]=obj;
293 if ( add_mem_to_list(obj) )
296 memset(obj, 0, sizeof(struct msgobj_t));
298 atomic_set(&obj->obj_used,0);
299 INIT_LIST_HEAD(&obj->obj_users);
300 qends = (struct canque_ends_t *)kmalloc(sizeof(struct canque_ends_t), GFP_KERNEL);
301 if(qends == NULL) return -ENOMEM;
302 if(add_mem_to_list(qends)) return -ENOMEM;
303 memset(qends, 0, sizeof(struct canque_ends_t));
304 obj->hostchip=hostchip;
311 canqueue_ends_init_chip(qends, hostchip, obj);
313 if (minorbase == -1) minorbase=obj_count;
314 if ((minorbase >= 0) && (minorbase+i<MAX_TOT_MSGOBJS)){
315 objects_p[minorbase+i]=obj;
316 obj->minor=minorbase+i;
317 } else obj->minor=-1;
319 candev->hwspecops->init_obj_data(hostchip,i);
327 int init_hwspecops(struct candevice_t *candev)
329 const struct boardtype_t *brp;
331 brp = boardtype_find(candev->hwname);
334 CANMSG("Sorry, hardware \"%s\" is currently not supported.\n",candev->hwname);
338 brp->board_register(candev->hwspecops);
343 int init_chipspecops(struct candevice_t *candev, int chipnr)
345 if (!strcmp(candev->chip[chipnr]->chip_type,"i82527")) {
346 candev->chip[chipnr]->max_objects=15;
347 i82527_register(candev->chip[chipnr]->chipspecops);
349 if (!strcmp(candev->chip[chipnr]->chip_type,"sja1000")) {
350 candev->chip[chipnr]->max_objects=1;
351 sja1000_register(candev->chip[chipnr]->chipspecops);
353 if (!strcmp(candev->chip[chipnr]->chip_type,"sja1000p")) {
354 candev->chip[chipnr]->max_objects=1;
355 sja1000p_register(candev->chip[chipnr]->chipspecops);