2 * Linux CAN-bus device driver.
3 * Written by Arnaud Westenberg email:arnaud@wanadoo.nl
4 * This software is released under the GPL-License.
5 * Version 0.7 6 Aug 2001
9 #include <linux/module.h>
11 #include <linux/autoconf.h>
12 #if defined (CONFIG_MODVERSIONS) && !defined (MODVERSIONS)
16 #if defined (MODVERSIONS)
17 #include <linux/modversions.h>
20 #include <linux/version.h>
21 #include <linux/kernel.h>
22 #if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
23 #include <linux/malloc.h>
25 #include <linux/slab.h>
27 #include <linux/proc_fs.h>
28 #include <linux/version.h>
30 #include "../include/main.h"
31 #include "../include/proc.h"
32 #include "../include/setup.h"
34 int add_channel_to_procdir(void);
35 int remove_channel_from_procdir(void);
36 int add_object_to_procdir(void);
37 int remove_object_from_procdir(void);
39 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
40 static int candev_readlink(struct proc_dir_entry *de, char *page);
43 static int bc=0; /* static counter for each hardware board */
44 static int cc=0; /* static counter for each CAN chip */
45 static int oc=0; /* static counter for each message object */
47 struct canproc_t can_proc_base;
48 struct canproc_t *base=&can_proc_base;
50 /* The following functions are needed only for kernel version 2.2. Kernel
51 * version 2.4 already defines them for us.
53 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
54 static void can_fill_inode(struct inode *inode, int fill)
62 static struct proc_dir_entry * new_can_proc_entry(unsigned short inode,
63 const char *name, mode_t mode, nlink_t nlink, struct proc_dir_entry *parent)
65 struct proc_dir_entry *new_entry = NULL;
67 new_entry = (struct proc_dir_entry *) kmalloc(sizeof(struct
68 proc_dir_entry), GFP_KERNEL);
69 if (new_entry == NULL)
72 memset(new_entry, 0, sizeof(struct proc_dir_entry));
74 new_entry->low_ino = inode;
75 new_entry->namelen = strlen(name);
76 new_entry->name = name;
77 new_entry->mode = mode;
78 new_entry->nlink = nlink;
79 new_entry->fill_inode = can_fill_inode;
80 new_entry->parent = parent;
82 proc_register(parent, new_entry);
87 int can_remove_proc_entry(struct proc_dir_entry *del, struct proc_dir_entry *parent)
90 proc_unregister(parent, del->low_ino);
97 #endif // Functions required for kernel 2.2
99 /* can_init_procdir registers the entire CAN directory tree recursively at
102 int can_init_procdir(void)
104 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
105 base->can_proc_entry = new_can_proc_entry(0, "can", S_IFDIR | S_IRUGO |
106 S_IXUGO, 0, &proc_root);
108 base->can_proc_entry = create_proc_entry("can", S_IFDIR | S_IRUGO |
109 S_IXUGO, &proc_root);
111 if (base->can_proc_entry == NULL)
114 for (bc=0; bc<hardware_p->nr_boards; bc++) {
115 add_channel_to_procdir();
121 /* can_delete_procdir removes the entire CAN tree from the proc system */
122 int can_delete_procdir(void)
124 if (remove_channel_from_procdir())
126 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
127 if (can_remove_proc_entry(base->can_proc_entry, &proc_root))
130 remove_proc_entry("can", &proc_root);
136 int add_channel_to_procdir(void)
140 for (i=0; i < candevices_p[bc]->nr_82527_chips +
141 candevices_p[bc]->nr_sja1000_chips; i++) {
143 base->channel[cc] = (struct channelproc_t *)
144 kmalloc(sizeof(struct channelproc_t), GFP_KERNEL);
145 if (base->channel[cc] == NULL)
147 else if (add_mem_to_list(base->channel[cc]))
150 sprintf(base->channel[cc]->ch_name, "channel%d",cc);
152 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
153 base->channel[cc]->ch_entry = new_can_proc_entry(0,
154 base->channel[cc]->ch_name,
155 S_IFDIR | S_IRUGO | S_IXUGO, 0,
156 base->can_proc_entry);
158 base->channel[cc]->ch_entry = create_proc_entry(
159 base->channel[cc]->ch_name,
160 S_IFDIR | S_IRUGO |S_IXUGO,
161 base->can_proc_entry);
163 if (base->channel[cc]->ch_entry == NULL)
166 add_object_to_procdir();
174 int remove_channel_from_procdir(void)
179 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
180 if (can_remove_proc_entry(base->channel[cc]->ch_entry,
181 base->can_proc_entry))
184 remove_proc_entry(base->channel[cc]->ch_name,
185 base->can_proc_entry);
187 if (remove_object_from_procdir())
195 int add_object_to_procdir(void)
199 if (!strcmp(chips_p[cc]->chip_type,"i82527"))
201 if (!strcmp(chips_p[cc]->chip_type,"sja1000"))
204 for (i=0; i<obj; i++) {
206 base->channel[cc]->object[i] = (struct objectproc_t *)
207 kmalloc(sizeof(struct objectproc_t),GFP_KERNEL);
210 if (base->channel[cc]->object[i] == NULL)
212 else if (add_mem_to_list( base->channel[cc]->object[i]))
215 sprintf(base->channel[cc]->object[i]->obj_name,"object%d",i);
216 sprintf(base->channel[cc]->object[i]->lnk_name,"dev");
218 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
219 base->channel[cc]->object[i]->obj_entry=new_can_proc_entry(
220 0, base->channel[cc]->object[i]->obj_name,
221 S_IFDIR | S_IRUGO | S_IXUGO, 0,
222 base->channel[cc]->ch_entry);
223 if (base->channel[cc]->object[i]->obj_entry == NULL)
225 base->channel[cc]->object[i]->lnk = new_can_proc_entry(
226 0, base->channel[cc]->object[i]->lnk_name,
227 S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO,
228 0, base->channel[cc]->object[i]->obj_entry);
229 if (base->channel[cc]->object[i]->lnk == NULL)
231 sprintf(base->channel[cc]->object[i]->lnk_dev,"/dev/can");
232 base->channel[cc]->object[i]->lnk->readlink_proc =
236 base->channel[cc]->object[i]->obj_entry = create_proc_entry(
237 base->channel[cc]->object[i]->obj_name,
238 S_IFDIR | S_IRUGO | S_IXUGO,
239 base->channel[cc]->ch_entry);
240 if (base->channel[cc]->object[i]->obj_entry == NULL)
242 sprintf(base->channel[cc]->object[i]->lnk_dev,"/dev/can%d",
243 chips_p[cc]->msgobj[i]->minor);
244 base->channel[cc]->object[i]->lnk = proc_symlink(
245 base->channel[cc]->object[i]->lnk_name,
246 base->channel[cc]->object[i]->obj_entry,
247 base->channel[cc]->object[i]->lnk_dev);
248 if (base->channel[cc]->object[i]->lnk == NULL)
256 int remove_object_from_procdir(void)
260 if (!strcmp(chips_p[cc]->chip_type,"i82527"))
262 if (!strcmp(chips_p[cc]->chip_type,"sja1000"))
265 for (i=0; i<obj; i++) {
266 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
267 if (can_remove_proc_entry( base->channel[cc]->object[i]->lnk,
268 base->channel[cc]->object[i]->obj_entry))
270 if (can_remove_proc_entry(
271 base->channel[cc]->object[i]->obj_entry,
272 base->channel[cc]->ch_entry))
275 remove_proc_entry(base->channel[cc]->object[i]->lnk_name,
276 base->channel[cc]->object[i]->obj_entry);
277 remove_proc_entry(base->channel[cc]->object[i]->obj_name,
278 base->channel[cc]->ch_entry);
285 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
286 static int candev_readlink(struct proc_dir_entry *de, char *page)
288 int i=0, nchip=0, nobj=0;
289 char chip[20], object[20], tmp[6];
291 sprintf(chip, de->parent->parent->name+7);
292 sprintf(object, de->parent->name+6);
294 for (i=0; i<MAX_TOT_CHIPS; i++) {
296 if (!strcmp(chip,tmp)) {
301 for (i=0; i<MAX_MSGOBJS; i++) {
303 if (!strcmp(object,tmp)) {
309 return sprintf(page,"/dev/can%d",chips_p[nchip]->msgobj[nobj]->minor );
311 #endif //End of candev_readlink for kernel 2.2