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