File: /usr/src/linux/drivers/parport/procfs.c

1     /* Sysctl interface for parport devices.
2      * 
3      * Authors: David Campbell <campbell@torque.net>
4      *          Tim Waugh <tim@cyberelk.demon.co.uk>
5      *          Philip Blundell <philb@gnu.org>
6      *          Andrea Arcangeli
7      *          Riccardo Facchetti <fizban@tin.it>
8      *
9      * based on work by Grant Guenther <grant@torque.net>
10      *              and Philip Blundell
11      *
12      * Cleaned up include files - Russell King <linux@arm.uk.linux.org>
13      */
14     
15     #include <linux/string.h>
16     #include <linux/config.h>
17     #include <linux/errno.h>
18     #include <linux/kernel.h>
19     #include <linux/slab.h>
20     #include <linux/parport.h>
21     #include <linux/ctype.h>
22     #include <linux/sysctl.h>
23     
24     #include <asm/uaccess.h>
25     
26     #if defined(CONFIG_SYSCTL) && defined(CONFIG_PROC_FS)
27     
28     #define PARPORT_MIN_TIMESLICE_VALUE 1ul 
29     #define PARPORT_MAX_TIMESLICE_VALUE ((unsigned long) HZ)
30     #define PARPORT_MIN_SPINTIME_VALUE 1
31     #define PARPORT_MAX_SPINTIME_VALUE 1000
32     
33     static int do_active_device(ctl_table *table, int write, struct file *filp,
34     		      void *result, size_t *lenp)
35     {
36     	struct parport *port = (struct parport *)table->extra1;
37     	char buffer[256];
38     	struct pardevice *dev;
39     	int len = 0;
40     
41     	if (write)		/* can't happen anyway */
42     		return -EACCES;
43     
44     	if (filp->f_pos) {
45     		*lenp = 0;
46     		return 0;
47     	}
48     	
49     	for (dev = port->devices; dev ; dev = dev->next) {
50     		if(dev == port->cad) {
51     			len += sprintf(buffer, "%s\n", dev->name);
52     		}
53     	}
54     
55     	if(!len) {
56     		len += sprintf(buffer, "%s\n", "none");
57     	}
58     
59     	if (len > *lenp)
60     		len = *lenp;
61     	else
62     		*lenp = len;
63     
64     	filp->f_pos += len;
65     
66     	return copy_to_user(result, buffer, len) ? -EFAULT : 0;
67     }
68     
69     #ifdef CONFIG_PARPORT_1284
70     static int do_autoprobe(ctl_table *table, int write, struct file *filp,
71     			void *result, size_t *lenp)
72     {
73     	struct parport_device_info *info = table->extra2;
74     	const char *str;
75     	char buffer[256];
76     	int len = 0;
77     
78     	if (write) /* permissions stop this */
79     		return -EACCES;
80     
81     	if (filp->f_pos) {
82     		*lenp = 0;
83     		return 0;
84     	}
85     	
86     	if ((str = info->class_name) != NULL)
87     		len += sprintf (buffer + len, "CLASS:%s;\n", str);
88     
89     	if ((str = info->model) != NULL)
90     		len += sprintf (buffer + len, "MODEL:%s;\n", str);
91     
92     	if ((str = info->mfr) != NULL)
93     		len += sprintf (buffer + len, "MANUFACTURER:%s;\n", str);
94     
95     	if ((str = info->description) != NULL)
96     		len += sprintf (buffer + len, "DESCRIPTION:%s;\n", str);
97     
98     	if ((str = info->cmdset) != NULL)
99     		len += sprintf (buffer + len, "COMMAND SET:%s;\n", str);
100     
101     	if (len > *lenp)
102     		len = *lenp;
103     	else
104     		*lenp = len;
105     
106     	filp->f_pos += len;
107     
108     	return copy_to_user (result, buffer, len) ? -EFAULT : 0;
109     }
110     #endif /* IEEE1284.3 support. */
111     
112     static int do_hardware_base_addr (ctl_table *table, int write,
113     				  struct file *filp, void *result,
114     				  size_t *lenp)
115     {
116     	struct parport *port = (struct parport *)table->extra1;
117     	char buffer[20];
118     	int len = 0;
119     
120     	if (filp->f_pos) {
121     		*lenp = 0;
122     		return 0;
123     	}
124     
125     	if (write) /* permissions prevent this anyway */
126     		return -EACCES;
127     
128     	len += sprintf (buffer, "%lu\t%lu\n", port->base, port->base_hi);
129     
130     	if (len > *lenp)
131     		len = *lenp;
132     	else
133     		*lenp = len;
134     
135     	filp->f_pos += len;
136     
137     	return copy_to_user(result, buffer, len) ? -EFAULT : 0;
138     }
139     
140     static int do_hardware_irq (ctl_table *table, int write,
141     			    struct file *filp, void *result,
142     			    size_t *lenp)
143     {
144     	struct parport *port = (struct parport *)table->extra1;
145     	char buffer[20];
146     	int len = 0;
147     
148     	if (filp->f_pos) {
149     		*lenp = 0;
150     		return 0;
151     	}
152     
153     	if (write) /* permissions prevent this anyway */
154     		return -EACCES;
155     
156     	len += sprintf (buffer, "%d\n", port->irq);
157     
158     	if (len > *lenp)
159     		len = *lenp;
160     	else
161     		*lenp = len;
162     
163     	filp->f_pos += len;
164     
165     	return copy_to_user(result, buffer, len) ? -EFAULT : 0;
166     }
167     
168     static int do_hardware_dma (ctl_table *table, int write,
169     			    struct file *filp, void *result,
170     			    size_t *lenp)
171     {
172     	struct parport *port = (struct parport *)table->extra1;
173     	char buffer[20];
174     	int len = 0;
175     
176     	if (filp->f_pos) {
177     		*lenp = 0;
178     		return 0;
179     	}
180     
181     	if (write) /* permissions prevent this anyway */
182     		return -EACCES;
183     
184     	len += sprintf (buffer, "%d\n", port->dma);
185     
186     	if (len > *lenp)
187     		len = *lenp;
188     	else
189     		*lenp = len;
190     
191     	filp->f_pos += len;
192     
193     	return copy_to_user(result, buffer, len) ? -EFAULT : 0;
194     }
195     
196     static int do_hardware_modes (ctl_table *table, int write,
197     			      struct file *filp, void *result,
198     			      size_t *lenp)
199     {
200     	struct parport *port = (struct parport *)table->extra1;
201     	char buffer[40];
202     	int len = 0;
203     
204     	if (filp->f_pos) {
205     		*lenp = 0;
206     		return 0;
207     	}
208     
209     	if (write) /* permissions prevent this anyway */
210     		return -EACCES;
211     
212     	{
213     #define printmode(x) {if(port->modes&PARPORT_MODE_##x){len+=sprintf(buffer+len,"%s%s",f?",":"",#x);f++;}}
214     		int f = 0;
215     		printmode(PCSPP);
216     		printmode(TRISTATE);
217     		printmode(COMPAT);
218     		printmode(EPP);
219     		printmode(ECP);
220     		printmode(DMA);
221     #undef printmode
222     	}
223     	buffer[len++] = '\n';
224     
225     	if (len > *lenp)
226     		len = *lenp;
227     	else
228     		*lenp = len;
229     
230     	filp->f_pos += len;
231     
232     	return copy_to_user(result, buffer, len) ? -EFAULT : 0;
233     }
234     
235     #define PARPORT_PORT_DIR(child) { 0, NULL, NULL, 0, 0555, child }
236     #define PARPORT_PARPORT_DIR(child) { DEV_PARPORT, "parport", \
237                                          NULL, 0, 0555, child }
238     #define PARPORT_DEV_DIR(child) { CTL_DEV, "dev", NULL, 0, 0555, child }
239     #define PARPORT_DEVICES_ROOT_DIR  { DEV_PARPORT_DEVICES, "devices", \
240                                         NULL, 0, 0555, NULL }
241     
242     static const unsigned long parport_min_timeslice_value =
243     PARPORT_MIN_TIMESLICE_VALUE;
244     
245     static const unsigned long parport_max_timeslice_value =
246     PARPORT_MAX_TIMESLICE_VALUE;
247     
248     static const  int parport_min_spintime_value =
249     PARPORT_MIN_SPINTIME_VALUE;
250     
251     static const int parport_max_spintime_value =
252     PARPORT_MAX_SPINTIME_VALUE;
253     
254     
255     struct parport_sysctl_table {
256     	struct ctl_table_header *sysctl_header;
257     	ctl_table vars[12];
258     	ctl_table device_dir[2];
259     	ctl_table port_dir[2];
260     	ctl_table parport_dir[2];
261     	ctl_table dev_dir[2];
262     };
263     
264     static const struct parport_sysctl_table parport_sysctl_template = {
265     	NULL,
266             {
267     		{ DEV_PARPORT_SPINTIME, "spintime",
268     		  NULL, sizeof(int), 0644, NULL,
269     		  &proc_dointvec_minmax, NULL, NULL,
270     		  (void*) &parport_min_spintime_value,
271     		  (void*) &parport_max_spintime_value },
272     		{ DEV_PARPORT_BASE_ADDR, "base-addr",
273     		  NULL, 0, 0444, NULL,
274     		  &do_hardware_base_addr },
275     		{ DEV_PARPORT_IRQ, "irq",
276     		  NULL, 0, 0444, NULL,
277     		  &do_hardware_irq },
278     		{ DEV_PARPORT_DMA, "dma",
279     		  NULL, 0, 0444, NULL,
280     		  &do_hardware_dma },
281     		{ DEV_PARPORT_MODES, "modes",
282     		  NULL, 0, 0444, NULL,
283     		  &do_hardware_modes },
284     		PARPORT_DEVICES_ROOT_DIR,
285     #ifdef CONFIG_PARPORT_1284
286     		{ DEV_PARPORT_AUTOPROBE, "autoprobe",
287     		  NULL, 0, 0444, NULL,
288     		  &do_autoprobe },
289     		{ DEV_PARPORT_AUTOPROBE + 1, "autoprobe0",
290     		 NULL, 0, 0444, NULL,
291     		 &do_autoprobe },
292     		{ DEV_PARPORT_AUTOPROBE + 2, "autoprobe1",
293     		  NULL, 0, 0444, NULL,
294     		  &do_autoprobe },
295     		{ DEV_PARPORT_AUTOPROBE + 3, "autoprobe2",
296     		  NULL, 0, 0444, NULL,
297     		  &do_autoprobe },
298     		{ DEV_PARPORT_AUTOPROBE + 4, "autoprobe3",
299     		  NULL, 0, 0444, NULL,
300     		  &do_autoprobe },
301     #endif /* IEEE 1284 support */
302     		{0}
303     	},
304     	{ {DEV_PARPORT_DEVICES_ACTIVE, "active", NULL, 0, 0444, NULL,
305     	  &do_active_device }, {0}},
306     	{ PARPORT_PORT_DIR(NULL), {0}},
307     	{ PARPORT_PARPORT_DIR(NULL), {0}},
308     	{ PARPORT_DEV_DIR(NULL), {0}}
309     };
310     
311     struct parport_device_sysctl_table
312     {
313     	struct ctl_table_header *sysctl_header;
314     	ctl_table vars[2];
315     	ctl_table device_dir[2];
316     	ctl_table devices_root_dir[2];
317     	ctl_table port_dir[2];
318     	ctl_table parport_dir[2];
319     	ctl_table dev_dir[2];
320     };
321     
322     static const struct parport_device_sysctl_table
323     parport_device_sysctl_template = {
324     	NULL,
325     	{
326     		{ DEV_PARPORT_DEVICE_TIMESLICE, "timeslice",
327     		  NULL, sizeof(int), 0644, NULL,
328     		  &proc_doulongvec_ms_jiffies_minmax, NULL, NULL,
329     		  (void*) &parport_min_timeslice_value,
330     		  (void*) &parport_max_timeslice_value },
331     	},
332     	{ {0, NULL, NULL, 0, 0555, NULL}, {0}},
333     	{ PARPORT_DEVICES_ROOT_DIR, {0}},
334     	{ PARPORT_PORT_DIR(NULL), {0}},
335     	{ PARPORT_PARPORT_DIR(NULL), {0}},
336     	{ PARPORT_DEV_DIR(NULL), {0}}
337     };
338     
339     struct parport_default_sysctl_table
340     {
341     	struct ctl_table_header *sysctl_header;
342     	ctl_table vars[3];
343             ctl_table default_dir[2];
344     	ctl_table parport_dir[2];
345     	ctl_table dev_dir[2];
346     };
347     
348     extern unsigned long parport_default_timeslice;
349     extern int parport_default_spintime;
350     
351     static struct parport_default_sysctl_table
352     parport_default_sysctl_table = {
353     	NULL,
354     	{
355     		{ DEV_PARPORT_DEFAULT_TIMESLICE, "timeslice",
356     		  &parport_default_timeslice,
357     		  sizeof(parport_default_timeslice), 0644, NULL,
358     		  &proc_doulongvec_ms_jiffies_minmax, NULL, NULL,
359     		  (void*) &parport_min_timeslice_value,
360     		  (void*) &parport_max_timeslice_value },
361     		{ DEV_PARPORT_DEFAULT_SPINTIME, "spintime",
362     		  &parport_default_spintime,
363     		  sizeof(parport_default_spintime), 0644, NULL,
364     		  &proc_dointvec_minmax, NULL, NULL,
365     		  (void*) &parport_min_spintime_value,
366     		  (void*) &parport_max_spintime_value },
367     		{0}
368     	},
369     	{ { DEV_PARPORT_DEFAULT, "default", NULL, 0, 0555,
370     	    parport_default_sysctl_table.vars },{0}},
371     	{
372     	PARPORT_PARPORT_DIR(parport_default_sysctl_table.default_dir), 
373     	{0}},
374     	{ PARPORT_DEV_DIR(parport_default_sysctl_table.parport_dir), {0}}
375     };
376     
377     
378     int parport_proc_register(struct parport *port)
379     {
380     	struct parport_sysctl_table *t;
381     	int i;
382     
383     	t = kmalloc(sizeof(*t), GFP_KERNEL);
384     	if (t == NULL)
385     		return -ENOMEM;
386     	memcpy(t, &parport_sysctl_template, sizeof(*t));
387     
388     	t->device_dir[0].extra1 = port;
389     
390     	for (i = 0; i < 8; i++)
391     		t->vars[i].extra1 = port;
392     
393     	t->vars[0].data = &port->spintime;
394     	t->vars[5].child = t->device_dir;
395     	
396     	for (i = 0; i < 5; i++)
397     		t->vars[6 + i].extra2 = &port->probe_info[i];
398     
399     	t->port_dir[0].procname = port->name;
400     	t->port_dir[0].ctl_name = port->number + 1; /* nb 0 isn't legal here */
401     
402     	t->port_dir[0].child = t->vars;
403     	t->parport_dir[0].child = t->port_dir;
404     	t->dev_dir[0].child = t->parport_dir;
405     
406     	t->sysctl_header = register_sysctl_table(t->dev_dir, 0);
407     	if (t->sysctl_header == NULL) {
408     		kfree(t);
409     		t = NULL;
410     	}
411     	port->sysctl_table = t;
412     	return 0;
413     }
414     
415     int parport_proc_unregister(struct parport *port)
416     {
417     	if (port->sysctl_table) {
418     		struct parport_sysctl_table *t = port->sysctl_table;
419     		port->sysctl_table = NULL;
420     		unregister_sysctl_table(t->sysctl_header);
421     		kfree(t);
422     	}
423     	return 0;
424     }
425     
426     int parport_device_proc_register(struct pardevice *device)
427     {
428     	struct parport_device_sysctl_table *t;
429     	struct parport * port = device->port;
430     	
431     	t = kmalloc(sizeof(*t), GFP_KERNEL);
432     	if (t == NULL)
433     		return -ENOMEM;
434     	memcpy(t, &parport_device_sysctl_template, sizeof(*t));
435     
436     	t->dev_dir[0].child = t->parport_dir;
437     	t->parport_dir[0].child = t->port_dir;
438     	t->port_dir[0].procname = port->name;
439     	t->port_dir[0].ctl_name = port->number + 1; /* nb 0 isn't legal here */
440     	t->port_dir[0].child = t->devices_root_dir;
441     	t->devices_root_dir[0].child = t->device_dir;
442     
443     #ifdef CONFIG_PARPORT_1284
444     
445     	t->device_dir[0].ctl_name =
446     		parport_device_num(port->number, port->muxport,
447     				   device->daisy)
448     		+ 1;  /* nb 0 isn't legal here */ 
449     
450     #else /* No IEEE 1284 support */
451     
452     	/* parport_device_num isn't available. */
453     	t->device_dir[0].ctl_name = 1;
454     	
455     #endif /* IEEE 1284 support or not */
456     
457     	t->device_dir[0].procname = device->name;
458     	t->device_dir[0].extra1 = device;
459     	t->device_dir[0].child = t->vars;
460     	t->vars[0].data = &device->timeslice;
461     
462     	t->sysctl_header = register_sysctl_table(t->dev_dir, 0);
463     	if (t->sysctl_header == NULL) {
464     		kfree(t);
465     		t = NULL;
466     	}
467     	device->sysctl_table = t;
468     	return 0;
469     }
470     
471     int parport_device_proc_unregister(struct pardevice *device)
472     {
473     	if (device->sysctl_table) {
474     		struct parport_device_sysctl_table *t = device->sysctl_table;
475     		device->sysctl_table = NULL;
476     		unregister_sysctl_table(t->sysctl_header);
477     		kfree(t);
478     	}
479     	return 0;
480     }
481     
482     int parport_default_proc_register(void)
483     {
484     	parport_default_sysctl_table.sysctl_header =
485     		register_sysctl_table(parport_default_sysctl_table.dev_dir, 0);
486     	return 0;
487     }
488     
489     int parport_default_proc_unregister(void)
490     {
491     	if (parport_default_sysctl_table.sysctl_header) {
492     		unregister_sysctl_table(parport_default_sysctl_table.
493     					sysctl_header);
494     		parport_default_sysctl_table.sysctl_header = NULL;
495     	}
496     	return 0;
497     }
498     
499     #else /* no sysctl or no procfs*/
500     
501     int parport_proc_register(struct parport *pp)
502     {
503     	return 0;
504     }
505     
506     int parport_proc_unregister(struct parport *pp)
507     {
508     	return 0;
509     }
510     
511     int parport_device_proc_register(struct pardevice *device)
512     {
513     	return 0;
514     }
515     
516     int parport_device_proc_unregister(struct pardevice *device)
517     {
518     	return 0;
519     }
520     
521     int parport_default_proc_register (void)
522     {
523     	return 0;
524     }
525     
526     int parport_default_proc_unregister (void)
527     {
528     	return 0;
529     }
530     #endif
531