xref: /linux/drivers/parport/procfs.c (revision e5c86679d5e864947a52fb31e45a425dea3e7fa9)
1 /* Sysctl interface for parport devices.
2  *
3  * Authors: David Campbell
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/init.h>
17 #include <linux/module.h>
18 #include <linux/errno.h>
19 #include <linux/kernel.h>
20 #include <linux/slab.h>
21 #include <linux/parport.h>
22 #include <linux/ctype.h>
23 #include <linux/sysctl.h>
24 #include <linux/device.h>
25 
26 #include <linux/uaccess.h>
27 
28 #if defined(CONFIG_SYSCTL) && defined(CONFIG_PROC_FS)
29 
30 #define PARPORT_MIN_TIMESLICE_VALUE 1ul
31 #define PARPORT_MAX_TIMESLICE_VALUE ((unsigned long) HZ)
32 #define PARPORT_MIN_SPINTIME_VALUE 1
33 #define PARPORT_MAX_SPINTIME_VALUE 1000
34 
35 static int do_active_device(struct ctl_table *table, int write,
36 		      void __user *result, size_t *lenp, loff_t *ppos)
37 {
38 	struct parport *port = (struct parport *)table->extra1;
39 	char buffer[256];
40 	struct pardevice *dev;
41 	int len = 0;
42 
43 	if (write)		/* can't happen anyway */
44 		return -EACCES;
45 
46 	if (*ppos) {
47 		*lenp = 0;
48 		return 0;
49 	}
50 
51 	for (dev = port->devices; dev ; dev = dev->next) {
52 		if(dev == port->cad) {
53 			len += sprintf(buffer, "%s\n", dev->name);
54 		}
55 	}
56 
57 	if(!len) {
58 		len += sprintf(buffer, "%s\n", "none");
59 	}
60 
61 	if (len > *lenp)
62 		len = *lenp;
63 	else
64 		*lenp = len;
65 
66 	*ppos += len;
67 
68 	return copy_to_user(result, buffer, len) ? -EFAULT : 0;
69 }
70 
71 #ifdef CONFIG_PARPORT_1284
72 static int do_autoprobe(struct ctl_table *table, int write,
73 			void __user *result, size_t *lenp, loff_t *ppos)
74 {
75 	struct parport_device_info *info = table->extra2;
76 	const char *str;
77 	char buffer[256];
78 	int len = 0;
79 
80 	if (write) /* permissions stop this */
81 		return -EACCES;
82 
83 	if (*ppos) {
84 		*lenp = 0;
85 		return 0;
86 	}
87 
88 	if ((str = info->class_name) != NULL)
89 		len += sprintf (buffer + len, "CLASS:%s;\n", str);
90 
91 	if ((str = info->model) != NULL)
92 		len += sprintf (buffer + len, "MODEL:%s;\n", str);
93 
94 	if ((str = info->mfr) != NULL)
95 		len += sprintf (buffer + len, "MANUFACTURER:%s;\n", str);
96 
97 	if ((str = info->description) != NULL)
98 		len += sprintf (buffer + len, "DESCRIPTION:%s;\n", str);
99 
100 	if ((str = info->cmdset) != NULL)
101 		len += sprintf (buffer + len, "COMMAND SET:%s;\n", str);
102 
103 	if (len > *lenp)
104 		len = *lenp;
105 	else
106 		*lenp = len;
107 
108 	*ppos += len;
109 
110 	return copy_to_user (result, buffer, len) ? -EFAULT : 0;
111 }
112 #endif /* IEEE1284.3 support. */
113 
114 static int do_hardware_base_addr(struct ctl_table *table, int write,
115 				 void __user *result,
116 				 size_t *lenp, loff_t *ppos)
117 {
118 	struct parport *port = (struct parport *)table->extra1;
119 	char buffer[20];
120 	int len = 0;
121 
122 	if (*ppos) {
123 		*lenp = 0;
124 		return 0;
125 	}
126 
127 	if (write) /* permissions prevent this anyway */
128 		return -EACCES;
129 
130 	len += sprintf (buffer, "%lu\t%lu\n", port->base, port->base_hi);
131 
132 	if (len > *lenp)
133 		len = *lenp;
134 	else
135 		*lenp = len;
136 
137 	*ppos += len;
138 
139 	return copy_to_user(result, buffer, len) ? -EFAULT : 0;
140 }
141 
142 static int do_hardware_irq(struct ctl_table *table, int write,
143 			   void __user *result,
144 			   size_t *lenp, loff_t *ppos)
145 {
146 	struct parport *port = (struct parport *)table->extra1;
147 	char buffer[20];
148 	int len = 0;
149 
150 	if (*ppos) {
151 		*lenp = 0;
152 		return 0;
153 	}
154 
155 	if (write) /* permissions prevent this anyway */
156 		return -EACCES;
157 
158 	len += sprintf (buffer, "%d\n", port->irq);
159 
160 	if (len > *lenp)
161 		len = *lenp;
162 	else
163 		*lenp = len;
164 
165 	*ppos += len;
166 
167 	return copy_to_user(result, buffer, len) ? -EFAULT : 0;
168 }
169 
170 static int do_hardware_dma(struct ctl_table *table, int write,
171 			   void __user *result,
172 			   size_t *lenp, loff_t *ppos)
173 {
174 	struct parport *port = (struct parport *)table->extra1;
175 	char buffer[20];
176 	int len = 0;
177 
178 	if (*ppos) {
179 		*lenp = 0;
180 		return 0;
181 	}
182 
183 	if (write) /* permissions prevent this anyway */
184 		return -EACCES;
185 
186 	len += sprintf (buffer, "%d\n", port->dma);
187 
188 	if (len > *lenp)
189 		len = *lenp;
190 	else
191 		*lenp = len;
192 
193 	*ppos += len;
194 
195 	return copy_to_user(result, buffer, len) ? -EFAULT : 0;
196 }
197 
198 static int do_hardware_modes(struct ctl_table *table, int write,
199 			     void __user *result,
200 			     size_t *lenp, loff_t *ppos)
201 {
202 	struct parport *port = (struct parport *)table->extra1;
203 	char buffer[40];
204 	int len = 0;
205 
206 	if (*ppos) {
207 		*lenp = 0;
208 		return 0;
209 	}
210 
211 	if (write) /* permissions prevent this anyway */
212 		return -EACCES;
213 
214 	{
215 #define printmode(x) {if(port->modes&PARPORT_MODE_##x){len+=sprintf(buffer+len,"%s%s",f?",":"",#x);f++;}}
216 		int f = 0;
217 		printmode(PCSPP);
218 		printmode(TRISTATE);
219 		printmode(COMPAT);
220 		printmode(EPP);
221 		printmode(ECP);
222 		printmode(DMA);
223 #undef printmode
224 	}
225 	buffer[len++] = '\n';
226 
227 	if (len > *lenp)
228 		len = *lenp;
229 	else
230 		*lenp = len;
231 
232 	*ppos += len;
233 
234 	return copy_to_user(result, buffer, len) ? -EFAULT : 0;
235 }
236 
237 #define PARPORT_PORT_DIR(CHILD) { .procname = NULL, .mode = 0555, .child = CHILD }
238 #define PARPORT_PARPORT_DIR(CHILD) { .procname = "parport", \
239                                      .mode = 0555, .child = CHILD }
240 #define PARPORT_DEV_DIR(CHILD) { .procname = "dev", .mode = 0555, .child = CHILD }
241 #define PARPORT_DEVICES_ROOT_DIR  {  .procname = "devices", \
242                                     .mode = 0555, .child = NULL }
243 
244 static const unsigned long parport_min_timeslice_value =
245 PARPORT_MIN_TIMESLICE_VALUE;
246 
247 static const unsigned long parport_max_timeslice_value =
248 PARPORT_MAX_TIMESLICE_VALUE;
249 
250 static const  int parport_min_spintime_value =
251 PARPORT_MIN_SPINTIME_VALUE;
252 
253 static const int parport_max_spintime_value =
254 PARPORT_MAX_SPINTIME_VALUE;
255 
256 
257 struct parport_sysctl_table {
258 	struct ctl_table_header *sysctl_header;
259 	struct ctl_table vars[12];
260 	struct ctl_table device_dir[2];
261 	struct ctl_table port_dir[2];
262 	struct ctl_table parport_dir[2];
263 	struct ctl_table dev_dir[2];
264 };
265 
266 static const struct parport_sysctl_table parport_sysctl_template = {
267 	.sysctl_header = NULL,
268         {
269 		{
270 			.procname	= "spintime",
271 			.data		= NULL,
272 			.maxlen		= sizeof(int),
273 			.mode		= 0644,
274 			.proc_handler	= proc_dointvec_minmax,
275 			.extra1		= (void*) &parport_min_spintime_value,
276 			.extra2		= (void*) &parport_max_spintime_value
277 		},
278 		{
279 			.procname	= "base-addr",
280 			.data		= NULL,
281 			.maxlen		= 0,
282 			.mode		= 0444,
283 			.proc_handler	= do_hardware_base_addr
284 		},
285 		{
286 			.procname	= "irq",
287 			.data		= NULL,
288 			.maxlen		= 0,
289 			.mode		= 0444,
290 			.proc_handler	= do_hardware_irq
291 		},
292 		{
293 			.procname	= "dma",
294 			.data		= NULL,
295 			.maxlen		= 0,
296 			.mode		= 0444,
297 			.proc_handler	= do_hardware_dma
298 		},
299 		{
300 			.procname	= "modes",
301 			.data		= NULL,
302 			.maxlen		= 0,
303 			.mode		= 0444,
304 			.proc_handler	= do_hardware_modes
305 		},
306 		PARPORT_DEVICES_ROOT_DIR,
307 #ifdef CONFIG_PARPORT_1284
308 		{
309 			.procname	= "autoprobe",
310 			.data		= NULL,
311 			.maxlen		= 0,
312 			.mode		= 0444,
313 			.proc_handler	= do_autoprobe
314 		},
315 		{
316 			.procname	= "autoprobe0",
317 			.data		= NULL,
318 			.maxlen		= 0,
319 			.mode		= 0444,
320 			.proc_handler	= do_autoprobe
321 		},
322 		{
323 			.procname	= "autoprobe1",
324 			.data		= NULL,
325 			.maxlen		= 0,
326 			.mode		= 0444,
327 			.proc_handler	= do_autoprobe
328 		},
329 		{
330 			.procname	= "autoprobe2",
331 			.data		= NULL,
332 			.maxlen		= 0,
333 			.mode		= 0444,
334 			.proc_handler	= do_autoprobe
335 		},
336 		{
337 			.procname	= "autoprobe3",
338 			.data		= NULL,
339 			.maxlen		= 0,
340 			.mode		= 0444,
341 			.proc_handler	= do_autoprobe
342 		},
343 #endif /* IEEE 1284 support */
344 		{}
345 	},
346 	{
347 		{
348 			.procname	= "active",
349 			.data		= NULL,
350 			.maxlen		= 0,
351 			.mode		= 0444,
352 			.proc_handler	= do_active_device
353 		},
354 		{}
355 	},
356 	{
357 		PARPORT_PORT_DIR(NULL),
358 		{}
359 	},
360 	{
361 		PARPORT_PARPORT_DIR(NULL),
362 		{}
363 	},
364 	{
365 		PARPORT_DEV_DIR(NULL),
366 		{}
367 	}
368 };
369 
370 struct parport_device_sysctl_table
371 {
372 	struct ctl_table_header *sysctl_header;
373 	struct ctl_table vars[2];
374 	struct ctl_table device_dir[2];
375 	struct ctl_table devices_root_dir[2];
376 	struct ctl_table port_dir[2];
377 	struct ctl_table parport_dir[2];
378 	struct ctl_table dev_dir[2];
379 };
380 
381 static const struct parport_device_sysctl_table
382 parport_device_sysctl_template = {
383 	.sysctl_header = NULL,
384 	{
385 		{
386 			.procname 	= "timeslice",
387 			.data		= NULL,
388 			.maxlen		= sizeof(unsigned long),
389 			.mode		= 0644,
390 			.proc_handler	= proc_doulongvec_ms_jiffies_minmax,
391 			.extra1		= (void*) &parport_min_timeslice_value,
392 			.extra2		= (void*) &parport_max_timeslice_value
393 		},
394 	},
395 	{
396 		{
397 			.procname	= NULL,
398 			.data		= NULL,
399 			.maxlen		= 0,
400 			.mode		= 0555,
401 			.child		= NULL
402 		},
403 		{}
404 	},
405 	{
406 		PARPORT_DEVICES_ROOT_DIR,
407 		{}
408 	},
409 	{
410 		PARPORT_PORT_DIR(NULL),
411 		{}
412 	},
413 	{
414 		PARPORT_PARPORT_DIR(NULL),
415 		{}
416 	},
417 	{
418 		PARPORT_DEV_DIR(NULL),
419 		{}
420 	}
421 };
422 
423 struct parport_default_sysctl_table
424 {
425 	struct ctl_table_header *sysctl_header;
426 	struct ctl_table vars[3];
427 	struct ctl_table default_dir[2];
428 	struct ctl_table parport_dir[2];
429 	struct ctl_table dev_dir[2];
430 };
431 
432 static struct parport_default_sysctl_table
433 parport_default_sysctl_table = {
434 	.sysctl_header	= NULL,
435 	{
436 		{
437 			.procname	= "timeslice",
438 			.data		= &parport_default_timeslice,
439 			.maxlen		= sizeof(parport_default_timeslice),
440 			.mode		= 0644,
441 			.proc_handler	= proc_doulongvec_ms_jiffies_minmax,
442 			.extra1		= (void*) &parport_min_timeslice_value,
443 			.extra2		= (void*) &parport_max_timeslice_value
444 		},
445 		{
446 			.procname	= "spintime",
447 			.data		= &parport_default_spintime,
448 			.maxlen		= sizeof(parport_default_spintime),
449 			.mode		= 0644,
450 			.proc_handler	= proc_dointvec_minmax,
451 			.extra1		= (void*) &parport_min_spintime_value,
452 			.extra2		= (void*) &parport_max_spintime_value
453 		},
454 		{}
455 	},
456 	{
457 		{
458 			.procname	= "default",
459 			.mode		= 0555,
460 			.child		= parport_default_sysctl_table.vars
461 		},
462 		{}
463 	},
464 	{
465 		PARPORT_PARPORT_DIR(parport_default_sysctl_table.default_dir),
466 		{}
467 	},
468 	{
469 		PARPORT_DEV_DIR(parport_default_sysctl_table.parport_dir),
470 		{}
471 	}
472 };
473 
474 
475 int parport_proc_register(struct parport *port)
476 {
477 	struct parport_sysctl_table *t;
478 	int i;
479 
480 	t = kmemdup(&parport_sysctl_template, sizeof(*t), GFP_KERNEL);
481 	if (t == NULL)
482 		return -ENOMEM;
483 
484 	t->device_dir[0].extra1 = port;
485 
486 	for (i = 0; i < 5; i++)
487 		t->vars[i].extra1 = port;
488 
489 	t->vars[0].data = &port->spintime;
490 	t->vars[5].child = t->device_dir;
491 
492 	for (i = 0; i < 5; i++)
493 		t->vars[6 + i].extra2 = &port->probe_info[i];
494 
495 	t->port_dir[0].procname = port->name;
496 
497 	t->port_dir[0].child = t->vars;
498 	t->parport_dir[0].child = t->port_dir;
499 	t->dev_dir[0].child = t->parport_dir;
500 
501 	t->sysctl_header = register_sysctl_table(t->dev_dir);
502 	if (t->sysctl_header == NULL) {
503 		kfree(t);
504 		t = NULL;
505 	}
506 	port->sysctl_table = t;
507 	return 0;
508 }
509 
510 int parport_proc_unregister(struct parport *port)
511 {
512 	if (port->sysctl_table) {
513 		struct parport_sysctl_table *t = port->sysctl_table;
514 		port->sysctl_table = NULL;
515 		unregister_sysctl_table(t->sysctl_header);
516 		kfree(t);
517 	}
518 	return 0;
519 }
520 
521 int parport_device_proc_register(struct pardevice *device)
522 {
523 	struct parport_device_sysctl_table *t;
524 	struct parport * port = device->port;
525 
526 	t = kmemdup(&parport_device_sysctl_template, sizeof(*t), GFP_KERNEL);
527 	if (t == NULL)
528 		return -ENOMEM;
529 
530 	t->dev_dir[0].child = t->parport_dir;
531 	t->parport_dir[0].child = t->port_dir;
532 	t->port_dir[0].procname = port->name;
533 	t->port_dir[0].child = t->devices_root_dir;
534 	t->devices_root_dir[0].child = t->device_dir;
535 
536 	t->device_dir[0].procname = device->name;
537 	t->device_dir[0].child = t->vars;
538 	t->vars[0].data = &device->timeslice;
539 
540 	t->sysctl_header = register_sysctl_table(t->dev_dir);
541 	if (t->sysctl_header == NULL) {
542 		kfree(t);
543 		t = NULL;
544 	}
545 	device->sysctl_table = t;
546 	return 0;
547 }
548 
549 int parport_device_proc_unregister(struct pardevice *device)
550 {
551 	if (device->sysctl_table) {
552 		struct parport_device_sysctl_table *t = device->sysctl_table;
553 		device->sysctl_table = NULL;
554 		unregister_sysctl_table(t->sysctl_header);
555 		kfree(t);
556 	}
557 	return 0;
558 }
559 
560 static int __init parport_default_proc_register(void)
561 {
562 	int ret;
563 
564 	parport_default_sysctl_table.sysctl_header =
565 		register_sysctl_table(parport_default_sysctl_table.dev_dir);
566 	if (!parport_default_sysctl_table.sysctl_header)
567 		return -ENOMEM;
568 	ret = parport_bus_init();
569 	if (ret) {
570 		unregister_sysctl_table(parport_default_sysctl_table.
571 					sysctl_header);
572 		return ret;
573 	}
574 	return 0;
575 }
576 
577 static void __exit parport_default_proc_unregister(void)
578 {
579 	if (parport_default_sysctl_table.sysctl_header) {
580 		unregister_sysctl_table(parport_default_sysctl_table.
581 					sysctl_header);
582 		parport_default_sysctl_table.sysctl_header = NULL;
583 	}
584 	parport_bus_exit();
585 }
586 
587 #else /* no sysctl or no procfs*/
588 
589 int parport_proc_register(struct parport *pp)
590 {
591 	return 0;
592 }
593 
594 int parport_proc_unregister(struct parport *pp)
595 {
596 	return 0;
597 }
598 
599 int parport_device_proc_register(struct pardevice *device)
600 {
601 	return 0;
602 }
603 
604 int parport_device_proc_unregister(struct pardevice *device)
605 {
606 	return 0;
607 }
608 
609 static int __init parport_default_proc_register (void)
610 {
611 	return parport_bus_init();
612 }
613 
614 static void __exit parport_default_proc_unregister (void)
615 {
616 	parport_bus_exit();
617 }
618 #endif
619 
620 subsys_initcall(parport_default_proc_register)
621 module_exit(parport_default_proc_unregister)
622