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.3 17 Jun 2004
10 #include "../include/can.h"
11 #include "../include/can_sysdep.h"
12 #include "../include/main.h"
13 #include "../include/proc.h"
14 #include "../include/setup.h"
16 #define __NO_VERSION__
17 #include <linux/module.h>
18 #include <linux/mutex.h>
20 int add_channel_to_procdir(struct candevice_t *candev);
21 int remove_channels_from_procdir(void);
22 int remove_channel_from_procdir(struct candevice_t *candev);
23 int add_object_to_procdir(int chip_nr);
24 int remove_object_from_procdir(int chip_nr);
26 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
27 static int can_proc_readlink(struct proc_dir_entry *ent, char *page);
30 #if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,25)
31 #define CAN_PROC_ROOT (&proc_root)
33 #define CAN_PROC_ROOT (NULL)
34 #endif /* >= 2.6.26 */
36 static int cc=0; /* static counter for each CAN chip */
38 static struct canproc_t can_proc_base;
39 static struct canproc_t *base=&can_proc_base;
40 DEFINE_MUTEX(proc_mutex); /* synchronize access to canproc_t array */
42 /* The following functions are needed only for kernel version 2.2. Kernel
43 * version 2.4 already defines them for us.
45 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(2,3,0))
46 static void can_fill_inode(struct inode *inode, int fill)
54 static struct proc_dir_entry * can_create_proc_entry(const char *name, mode_t mode,
55 struct proc_dir_entry *parent)
57 struct proc_dir_entry *new_entry = NULL;
67 new_entry = (struct proc_dir_entry *)
68 can_checked_malloc(sizeof(struct proc_dir_entry)+namelen+1);
70 if (new_entry == NULL)
73 memset(new_entry, 0, sizeof(struct proc_dir_entry));
75 /* Store copy of the proc entry name */
76 namestore = ((char *) new_entry) + sizeof(struct proc_dir_entry);
77 memcpy(namestore, name, namelen + 1);
79 new_entry->low_ino = 0;
80 new_entry->namelen = namelen;
81 new_entry->name = namestore;
82 new_entry->mode = mode;
84 new_entry->fill_inode = can_fill_inode;
85 new_entry->parent = parent;
87 proc_register(parent, new_entry);
92 static int can_remove_proc_entry(struct proc_dir_entry *del, struct proc_dir_entry *parent)
95 proc_unregister(parent, del->low_ino);
96 can_checked_free(del);
103 static int can_proc_readlink(struct proc_dir_entry *ent, char *page)
105 char *link_dest = (char*)ent->data;
107 strcpy(page, link_dest);
108 return strlen(link_dest);
113 /* This compatibility version of proc_symlink does not store local copy of destination */
114 static inline struct proc_dir_entry *can_proc_symlink(const char *name,
115 struct proc_dir_entry *parent, const char *dest)
117 struct proc_dir_entry *entry;
120 entry = can_create_proc_entry(name, S_IFLNK | S_IRUGO | S_IWUGO | S_IXUGO, parent);
123 entry->readlink_proc = can_proc_readlink;
128 #else /* Functions forwarded for kernel 2.4 and above */
130 static inline struct proc_dir_entry * can_create_proc_entry(const char *name, mode_t mode,
131 struct proc_dir_entry *parent)
133 return create_proc_entry(name, mode, parent);
137 /* This does not fully follow linux 2.4 and 2.6 prototype to simplify 2.2.x compatibility */
138 /* The newer kernels use entry name instead of pointer to the entry */
139 static int can_remove_proc_entry(struct proc_dir_entry *del, struct proc_dir_entry *parent)
141 if(!del) return -ENODEV;
142 remove_proc_entry(del->name,parent);
146 static inline struct proc_dir_entry *can_proc_symlink(const char *name,
147 struct proc_dir_entry *parent, const char *dest)
149 return proc_symlink(name, parent, dest);
152 #endif /* Functions required for kernel 2.2 */
154 /* can_init_procdir registers the entire CAN directory tree recursively at
157 int can_init_procdir(void)
160 struct candevice_t *candev;
162 mutex_init(&proc_mutex);
164 base->can_proc_entry = can_create_proc_entry("can", S_IFDIR | S_IRUGO |
165 S_IXUGO, CAN_PROC_ROOT);
166 if (base->can_proc_entry == NULL)
169 for (board=0; board<hardware_p->nr_boards; board++) {
170 candev=hardware_p->candevice[board];
171 if(candev) add_channel_to_procdir(candev);
177 /* can_init_procentry registers entry of a new board in CAN directory tree at
180 int can_init_procentry(int board)
182 struct candevice_t *candev;
183 candev=hardware_p->candevice[board];
185 return add_channel_to_procdir(candev);
189 /* can_delete_procdir removes the entire CAN tree from the proc system */
190 int can_delete_procdir(void)
192 if (remove_channels_from_procdir())
195 if (can_remove_proc_entry(base->can_proc_entry, CAN_PROC_ROOT))
201 /* can_delete_procentry removes device entries from CAN tree in the proc system */
202 int can_delete_procentry(struct candevice_t *candev)
204 if (remove_channel_from_procdir(candev))
210 static int can_chip_procinfo(char *buf, char **start, off_t offset,
211 int count, int *eof, void *data)
213 struct canchip_t *chip=data;
216 /* Generic chip info */
217 len += sprintf(buf+len,"type : %s\n",chip->chip_type);
218 len += sprintf(buf+len,"index : %d\n",chip->chip_idx);
219 len += sprintf(buf+len,"irq : %d\n",chip->chip_irq);
220 len += sprintf(buf+len,"addr : %lu\n",
221 can_ioptr2ulong(chip->chip_base_addr));
222 len += sprintf(buf+len,"config : %s\n",
223 (chip->flags & CHIP_CONFIGURED) ? "yes":"no");
224 len += sprintf(buf+len,"clock : %ld Hz\n",chip->clock);
225 len += sprintf(buf+len,"baud : %ld\n",chip->baudrate);
226 len += sprintf(buf+len,"num obj : %d\n",chip->max_objects);
230 /* Chip specific info if available */
231 if(chip->chipspecops->get_info)
232 len += (chip->chipspecops->get_info)(chip,buf+len);
240 int add_channel_to_procdir(struct candevice_t *candev)
244 mutex_lock(&proc_mutex);
245 for (i=0; i < MAX_TOT_CHIPS; i++){
246 if (!chips_p[i]) continue;
247 if (chips_p[i]->hostdevice != candev) continue;
249 base->channel[i] = (struct channelproc_t *)
250 can_checked_malloc(sizeof(struct channelproc_t));
251 if (base->channel[i] == NULL){
252 mutex_unlock(&proc_mutex);
256 sprintf(base->channel[i]->ch_name, "channel%d",i);
258 base->channel[i]->ch_entry = can_create_proc_entry(
259 base->channel[i]->ch_name,
260 S_IFDIR | S_IRUGO |S_IXUGO,
261 base->can_proc_entry);
263 if (base->channel[i]->ch_entry == NULL){
264 mutex_unlock(&proc_mutex);
268 add_object_to_procdir(i);
270 create_proc_read_entry("chip_info", /* proc entry name */
271 0, /* protection mask, 0->default */
272 base->channel[i]->ch_entry, /* parent dir, NULL->/proc */
277 mutex_unlock(&proc_mutex);
282 int remove_channels_from_procdir(void)
286 mutex_lock(&proc_mutex);
287 for (i=0; i < MAX_TOT_CHIPS; i++){
288 if (!chips_p[i]) continue;
292 if(!base->channel[i]) continue;
294 remove_proc_entry("chip_info", base->channel[i]->ch_entry);
296 if (remove_object_from_procdir(i)){
297 mutex_unlock(&proc_mutex);
301 /* name: base->channel[cc]->ch_name */
302 if (can_remove_proc_entry(base->channel[i]->ch_entry,
303 base->can_proc_entry)){
304 mutex_unlock(&proc_mutex);
308 can_checked_free(base->channel[i]);
309 base->channel[i] = NULL;
311 mutex_unlock(&proc_mutex);
316 int remove_channel_from_procdir(struct candevice_t *candev)
320 mutex_lock(&proc_mutex);
321 for (i=0; i < MAX_TOT_CHIPS; i++){
322 if (!chips_p[i]) continue;
323 if (chips_p[i]->hostdevice != candev) continue;
324 if (!base->channel[i]) continue;
326 remove_proc_entry("chip_info", base->channel[i]->ch_entry);
328 if (remove_object_from_procdir(i)){
329 mutex_unlock(&proc_mutex);
333 /* name: base->channel[cc]->ch_name */
334 if (can_remove_proc_entry(base->channel[i]->ch_entry,
335 base->can_proc_entry)){
336 mutex_unlock(&proc_mutex);
340 can_checked_free(base->channel[i]);
341 base->channel[i] = NULL;
345 mutex_unlock(&proc_mutex);
351 int add_object_to_procdir(int chip_nr)
355 max_objects=chips_p[chip_nr]->max_objects;
357 for (i=0; i<max_objects; i++) {
358 base->channel[chip_nr]->object[i] = (struct objectproc_t *)
359 can_checked_malloc(sizeof(struct objectproc_t));
361 if (base->channel[chip_nr]->object[i] == NULL)
364 sprintf(base->channel[chip_nr]->object[i]->obj_name,"object%d",i);
365 sprintf(base->channel[chip_nr]->object[i]->lnk_name,"dev");
367 base->channel[chip_nr]->object[i]->obj_entry = can_create_proc_entry(
368 base->channel[chip_nr]->object[i]->obj_name,
369 S_IFDIR | S_IRUGO | S_IXUGO,
370 base->channel[chip_nr]->ch_entry);
371 if (base->channel[chip_nr]->object[i]->obj_entry == NULL)
374 sprintf(base->channel[chip_nr]->object[i]->lnk_dev,"/dev/can%d",
375 chips_p[chip_nr]->msgobj[i]->minor);
377 base->channel[chip_nr]->object[i]->lnk = can_proc_symlink(
378 base->channel[chip_nr]->object[i]->lnk_name,
379 base->channel[chip_nr]->object[i]->obj_entry,
380 base->channel[chip_nr]->object[i]->lnk_dev);
381 if (base->channel[chip_nr]->object[i]->lnk == NULL)
388 int remove_object_from_procdir(int chip_nr)
392 obj=chips_p[chip_nr]->max_objects;
394 for (i=0; i<obj; i++) {
395 if(!base->channel[chip_nr]->object[i]) continue;
397 /* name: base->channel[chip_nr]->object[i]->lnk_name */
398 if (can_remove_proc_entry( base->channel[chip_nr]->object[i]->lnk,
399 base->channel[chip_nr]->object[i]->obj_entry))
401 /* name: base->channel[chip_nr]->object[i]->obj_name */
402 if (can_remove_proc_entry(
403 base->channel[chip_nr]->object[i]->obj_entry,
404 base->channel[chip_nr]->ch_entry))
407 can_checked_free(base->channel[chip_nr]->object[i]);
409 base->channel[chip_nr]->object[i]=NULL;