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 #include <linux/kernel.h>
17 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0))
18 #include <linux/malloc.h>
20 #include <linux/slab.h>
22 #include <linux/proc_fs.h>
23 #include <linux/version.h>
25 #include "../include/main.h"
26 #include "../include/proc.h"
27 #include "../include/setup.h"
29 int add_channel_to_procdir(struct candevice_t *candev);
30 int remove_channel_from_procdir(void);
31 int add_object_to_procdir(int chip_nr);
32 int remove_object_from_procdir(void);
34 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
35 static int candev_readlink(struct proc_dir_entry *de, char *page);
38 static int cc=0; /* static counter for each CAN chip */
40 struct canproc_t can_proc_base;
41 struct canproc_t *base=&can_proc_base;
43 /* The following functions are needed only for kernel version 2.2. Kernel
44 * version 2.4 already defines them for us.
46 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
47 static void can_fill_inode(struct inode *inode, int fill)
55 static struct proc_dir_entry * new_can_proc_entry(unsigned short inode,
56 const char *name, mode_t mode, nlink_t nlink, struct proc_dir_entry *parent)
58 struct proc_dir_entry *new_entry = NULL;
60 new_entry = (struct proc_dir_entry *) kmalloc(sizeof(struct
61 proc_dir_entry), GFP_KERNEL);
62 if (new_entry == NULL)
65 memset(new_entry, 0, sizeof(struct proc_dir_entry));
67 new_entry->low_ino = inode;
68 new_entry->namelen = strlen(name);
69 new_entry->name = name;
70 new_entry->mode = mode;
71 new_entry->nlink = nlink;
72 new_entry->fill_inode = can_fill_inode;
73 new_entry->parent = parent;
75 proc_register(parent, new_entry);
80 int can_remove_proc_entry(struct proc_dir_entry *del, struct proc_dir_entry *parent)
83 proc_unregister(parent, del->low_ino);
90 #endif // Functions required for kernel 2.2
92 /* can_init_procdir registers the entire CAN directory tree recursively at
95 int can_init_procdir(void)
98 struct candevice_t *candev;
99 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
100 base->can_proc_entry = new_can_proc_entry(0, "can", S_IFDIR | S_IRUGO |
101 S_IXUGO, 0, &proc_root);
103 base->can_proc_entry = create_proc_entry("can", S_IFDIR | S_IRUGO |
104 S_IXUGO, &proc_root);
106 if (base->can_proc_entry == NULL)
109 for (board=0; board<hardware_p->nr_boards; board++) {
110 candev=hardware_p->candevice[board];
111 if(candev) add_channel_to_procdir(candev);
117 /* can_delete_procdir removes the entire CAN tree from the proc system */
118 int can_delete_procdir(void)
120 if (remove_channel_from_procdir())
122 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
123 if (can_remove_proc_entry(base->can_proc_entry, &proc_root))
126 remove_proc_entry("can", &proc_root);
132 int add_channel_to_procdir(struct candevice_t *candev)
136 for (i=0; i < candev->nr_all_chips; i++) {
138 base->channel[cc] = (struct channelproc_t *)
139 kmalloc(sizeof(struct channelproc_t), GFP_KERNEL);
140 if (base->channel[cc] == NULL)
142 else if (add_mem_to_list(base->channel[cc]))
145 sprintf(base->channel[cc]->ch_name, "channel%d",cc);
147 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
148 base->channel[cc]->ch_entry = new_can_proc_entry(0,
149 base->channel[cc]->ch_name,
150 S_IFDIR | S_IRUGO | S_IXUGO, 0,
151 base->can_proc_entry);
153 base->channel[cc]->ch_entry = create_proc_entry(
154 base->channel[cc]->ch_name,
155 S_IFDIR | S_IRUGO |S_IXUGO,
156 base->can_proc_entry);
158 if (base->channel[cc]->ch_entry == NULL)
161 add_object_to_procdir(cc);
169 int remove_channel_from_procdir(void)
174 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
175 if (can_remove_proc_entry(base->channel[cc]->ch_entry,
176 base->can_proc_entry))
179 remove_proc_entry(base->channel[cc]->ch_name,
180 base->can_proc_entry);
182 if (remove_object_from_procdir())
190 int add_object_to_procdir(int chip_nr)
194 max_objects=chips_p[chip_nr]->max_objects;
196 for (i=0; i<max_objects; i++) {
197 base->channel[chip_nr]->object[i] = (struct objectproc_t *)
198 kmalloc(sizeof(struct objectproc_t),GFP_KERNEL);
201 if (base->channel[chip_nr]->object[i] == NULL)
203 else if (add_mem_to_list( base->channel[chip_nr]->object[i]))
206 sprintf(base->channel[chip_nr]->object[i]->obj_name,"object%d",i);
207 sprintf(base->channel[chip_nr]->object[i]->lnk_name,"dev");
209 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
210 base->channel[chip_nr]->object[i]->obj_entry=new_can_proc_entry(
211 0, base->channel[chip_nr]->object[i]->obj_name,
212 S_IFDIR | S_IRUGO | S_IXUGO, 0,
213 base->channel[chip_nr]->ch_entry);
214 if (base->channel[chip_nr]->object[i]->obj_entry == NULL)
216 base->channel[chip_nr]->object[i]->lnk = new_can_proc_entry(
217 0, base->channel[chip_nr]->object[i]->lnk_name,
218 S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO,
219 0, base->channel[chip_nr]->object[i]->obj_entry);
220 if (base->channel[chip_nr]->object[i]->lnk == NULL)
222 sprintf(base->channel[chip_nr]->object[i]->lnk_dev,"/dev/can");
223 base->channel[chip_nr]->object[i]->lnk->readlink_proc =
227 base->channel[chip_nr]->object[i]->obj_entry = create_proc_entry(
228 base->channel[chip_nr]->object[i]->obj_name,
229 S_IFDIR | S_IRUGO | S_IXUGO,
230 base->channel[chip_nr]->ch_entry);
231 if (base->channel[chip_nr]->object[i]->obj_entry == NULL)
233 sprintf(base->channel[chip_nr]->object[i]->lnk_dev,"/dev/can%d",
234 chips_p[chip_nr]->msgobj[i]->minor);
235 base->channel[chip_nr]->object[i]->lnk = proc_symlink(
236 base->channel[chip_nr]->object[i]->lnk_name,
237 base->channel[chip_nr]->object[i]->obj_entry,
238 base->channel[chip_nr]->object[i]->lnk_dev);
239 if (base->channel[chip_nr]->object[i]->lnk == NULL)
247 int remove_object_from_procdir(void)
251 obj=chips_p[cc]->max_objects;
253 for (i=0; i<obj; i++) {
254 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
255 if (can_remove_proc_entry( base->channel[cc]->object[i]->lnk,
256 base->channel[cc]->object[i]->obj_entry))
258 if (can_remove_proc_entry(
259 base->channel[cc]->object[i]->obj_entry,
260 base->channel[cc]->ch_entry))
263 remove_proc_entry(base->channel[cc]->object[i]->lnk_name,
264 base->channel[cc]->object[i]->obj_entry);
265 remove_proc_entry(base->channel[cc]->object[i]->obj_name,
266 base->channel[cc]->ch_entry);
273 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
274 static int candev_readlink(struct proc_dir_entry *de, char *page)
276 int i=0, nchip=0, nobj=0;
277 char chip[20], object[20], tmp[6];
279 sprintf(chip, de->parent->parent->name+7);
280 sprintf(object, de->parent->name+6);
282 for (i=0; i<MAX_TOT_CHIPS; i++) {
284 if (!strcmp(chip,tmp)) {
289 for (i=0; i<MAX_MSGOBJS; i++) {
291 if (!strcmp(object,tmp)) {
297 return sprintf(page,"/dev/can%d",chips_p[nchip]->msgobj[nobj]->minor );
299 #endif //End of candev_readlink for kernel 2.2