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