Merge tag 'ceph-for-6.5-rc1' of https://github.com/ceph/ceph-client
[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         struct ctl_table vars[12];
263         struct ctl_table device_dir[2];
264 };
265
266 static const struct parport_sysctl_table parport_sysctl_template = {
267         .port_header = NULL,
268         .devices_header = NULL,
269         {
270                 {
271                         .procname       = "spintime",
272                         .data           = NULL,
273                         .maxlen         = sizeof(int),
274                         .mode           = 0644,
275                         .proc_handler   = proc_dointvec_minmax,
276                         .extra1         = (void*) &parport_min_spintime_value,
277                         .extra2         = (void*) &parport_max_spintime_value
278                 },
279                 {
280                         .procname       = "base-addr",
281                         .data           = NULL,
282                         .maxlen         = 0,
283                         .mode           = 0444,
284                         .proc_handler   = do_hardware_base_addr
285                 },
286                 {
287                         .procname       = "irq",
288                         .data           = NULL,
289                         .maxlen         = 0,
290                         .mode           = 0444,
291                         .proc_handler   = do_hardware_irq
292                 },
293                 {
294                         .procname       = "dma",
295                         .data           = NULL,
296                         .maxlen         = 0,
297                         .mode           = 0444,
298                         .proc_handler   = do_hardware_dma
299                 },
300                 {
301                         .procname       = "modes",
302                         .data           = NULL,
303                         .maxlen         = 0,
304                         .mode           = 0444,
305                         .proc_handler   = do_hardware_modes
306                 },
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
358 struct parport_device_sysctl_table
359 {
360         struct ctl_table_header *sysctl_header;
361         struct ctl_table vars[2];
362         struct ctl_table device_dir[2];
363         struct ctl_table devices_root_dir[2];
364         struct ctl_table port_dir[2];
365         struct ctl_table parport_dir[2];
366         struct ctl_table dev_dir[2];
367 };
368
369 static const struct parport_device_sysctl_table
370 parport_device_sysctl_template = {
371         .sysctl_header = NULL,
372         {
373                 {
374                         .procname       = "timeslice",
375                         .data           = NULL,
376                         .maxlen         = sizeof(unsigned long),
377                         .mode           = 0644,
378                         .proc_handler   = proc_doulongvec_ms_jiffies_minmax,
379                         .extra1         = (void*) &parport_min_timeslice_value,
380                         .extra2         = (void*) &parport_max_timeslice_value
381                 },
382                 {}
383         },
384         {
385                 {
386                         .procname       = NULL,
387                         .data           = NULL,
388                         .maxlen         = 0,
389                         .mode           = 0555,
390                 },
391                 {}
392         }
393 };
394
395 struct parport_default_sysctl_table
396 {
397         struct ctl_table_header *sysctl_header;
398         struct ctl_table vars[3];
399         struct ctl_table default_dir[2];
400         struct ctl_table parport_dir[2];
401         struct ctl_table dev_dir[2];
402 };
403
404 static struct parport_default_sysctl_table
405 parport_default_sysctl_table = {
406         .sysctl_header  = NULL,
407         {
408                 {
409                         .procname       = "timeslice",
410                         .data           = &parport_default_timeslice,
411                         .maxlen         = sizeof(parport_default_timeslice),
412                         .mode           = 0644,
413                         .proc_handler   = proc_doulongvec_ms_jiffies_minmax,
414                         .extra1         = (void*) &parport_min_timeslice_value,
415                         .extra2         = (void*) &parport_max_timeslice_value
416                 },
417                 {
418                         .procname       = "spintime",
419                         .data           = &parport_default_spintime,
420                         .maxlen         = sizeof(parport_default_spintime),
421                         .mode           = 0644,
422                         .proc_handler   = proc_dointvec_minmax,
423                         .extra1         = (void*) &parport_min_spintime_value,
424                         .extra2         = (void*) &parport_max_spintime_value
425                 },
426                 {}
427         }
428 };
429
430 int parport_proc_register(struct parport *port)
431 {
432         struct parport_sysctl_table *t;
433         char *tmp_dir_path;
434         size_t tmp_path_len, port_name_len;
435         int bytes_written, i, err = 0;
436
437         t = kmemdup(&parport_sysctl_template, sizeof(*t), GFP_KERNEL);
438         if (t == NULL)
439                 return -ENOMEM;
440
441         t->device_dir[0].extra1 = port;
442
443         t->vars[0].data = &port->spintime;
444         for (i = 0; i < 5; i++) {
445                 t->vars[i].extra1 = port;
446                 t->vars[5 + i].extra2 = &port->probe_info[i];
447         }
448
449         port_name_len = strnlen(port->name, PARPORT_NAME_MAX_LEN);
450         /*
451          * Allocate a buffer for two paths: dev/parport/PORT and dev/parport/PORT/devices.
452          * We calculate for the second as that will give us enough for the first.
453          */
454         tmp_path_len = PARPORT_BASE_DEVICES_PATH_SIZE + port_name_len;
455         tmp_dir_path = kzalloc(tmp_path_len, GFP_KERNEL);
456         if (!tmp_dir_path) {
457                 err = -ENOMEM;
458                 goto exit_free_t;
459         }
460
461         bytes_written = snprintf(tmp_dir_path, tmp_path_len,
462                                  "dev/parport/%s/devices", port->name);
463         if (tmp_path_len <= bytes_written) {
464                 err = -ENOENT;
465                 goto exit_free_tmp_dir_path;
466         }
467         t->devices_header = register_sysctl(tmp_dir_path, t->device_dir);
468         if (t->devices_header == NULL) {
469                 err = -ENOENT;
470                 goto  exit_free_tmp_dir_path;
471         }
472
473         tmp_path_len = PARPORT_BASE_PATH_SIZE + port_name_len;
474         bytes_written = snprintf(tmp_dir_path, tmp_path_len,
475                                  "dev/parport/%s", port->name);
476         if (tmp_path_len <= bytes_written) {
477                 err = -ENOENT;
478                 goto unregister_devices_h;
479         }
480
481         t->port_header = register_sysctl(tmp_dir_path, t->vars);
482         if (t->port_header == NULL) {
483                 err = -ENOENT;
484                 goto unregister_devices_h;
485         }
486
487         port->sysctl_table = t;
488
489         kfree(tmp_dir_path);
490         return 0;
491
492 unregister_devices_h:
493         unregister_sysctl_table(t->devices_header);
494
495 exit_free_tmp_dir_path:
496         kfree(tmp_dir_path);
497
498 exit_free_t:
499         kfree(t);
500         return err;
501 }
502
503 int parport_proc_unregister(struct parport *port)
504 {
505         if (port->sysctl_table) {
506                 struct parport_sysctl_table *t = port->sysctl_table;
507                 port->sysctl_table = NULL;
508                 unregister_sysctl_table(t->devices_header);
509                 unregister_sysctl_table(t->port_header);
510                 kfree(t);
511         }
512         return 0;
513 }
514
515 int parport_device_proc_register(struct pardevice *device)
516 {
517         int bytes_written, err = 0;
518         struct parport_device_sysctl_table *t;
519         struct parport * port = device->port;
520         size_t port_name_len, device_name_len, tmp_dir_path_len;
521         char *tmp_dir_path;
522         
523         t = kmemdup(&parport_device_sysctl_template, sizeof(*t), GFP_KERNEL);
524         if (t == NULL)
525                 return -ENOMEM;
526
527         port_name_len = strnlen(port->name, PARPORT_NAME_MAX_LEN);
528         device_name_len = strnlen(device->name, PATH_MAX);
529
530         /* Allocate a buffer for two paths: dev/parport/PORT/devices/DEVICE. */
531         tmp_dir_path_len = PARPORT_BASE_DEVICES_PATH_SIZE + port_name_len + device_name_len;
532         tmp_dir_path = kzalloc(tmp_dir_path_len, GFP_KERNEL);
533         if (!tmp_dir_path) {
534                 err = -ENOMEM;
535                 goto exit_free_t;
536         }
537
538         bytes_written = snprintf(tmp_dir_path, tmp_dir_path_len, "dev/parport/%s/devices/%s",
539                                  port->name, device->name);
540         if (tmp_dir_path_len <= bytes_written) {
541                 err = -ENOENT;
542                 goto exit_free_path;
543         }
544
545         t->vars[0].data = &device->timeslice;
546
547         t->sysctl_header = register_sysctl(tmp_dir_path, t->vars);
548         if (t->sysctl_header == NULL) {
549                 kfree(t);
550                 t = NULL;
551         }
552         device->sysctl_table = t;
553
554         kfree(tmp_dir_path);
555         return 0;
556
557 exit_free_path:
558         kfree(tmp_dir_path);
559
560 exit_free_t:
561         kfree(t);
562
563         return err;
564 }
565
566 int parport_device_proc_unregister(struct pardevice *device)
567 {
568         if (device->sysctl_table) {
569                 struct parport_device_sysctl_table *t = device->sysctl_table;
570                 device->sysctl_table = NULL;
571                 unregister_sysctl_table(t->sysctl_header);
572                 kfree(t);
573         }
574         return 0;
575 }
576
577 static int __init parport_default_proc_register(void)
578 {
579         int ret;
580
581         parport_default_sysctl_table.sysctl_header =
582                 register_sysctl("dev/parport/default", parport_default_sysctl_table.vars);
583         if (!parport_default_sysctl_table.sysctl_header)
584                 return -ENOMEM;
585         ret = parport_bus_init();
586         if (ret) {
587                 unregister_sysctl_table(parport_default_sysctl_table.
588                                         sysctl_header);
589                 return ret;
590         }
591         return 0;
592 }
593
594 static void __exit parport_default_proc_unregister(void)
595 {
596         if (parport_default_sysctl_table.sysctl_header) {
597                 unregister_sysctl_table(parport_default_sysctl_table.
598                                         sysctl_header);
599                 parport_default_sysctl_table.sysctl_header = NULL;
600         }
601         parport_bus_exit();
602 }
603
604 #else /* no sysctl or no procfs*/
605
606 int parport_proc_register(struct parport *pp)
607 {
608         return 0;
609 }
610
611 int parport_proc_unregister(struct parport *pp)
612 {
613         return 0;
614 }
615
616 int parport_device_proc_register(struct pardevice *device)
617 {
618         return 0;
619 }
620
621 int parport_device_proc_unregister(struct pardevice *device)
622 {
623         return 0;
624 }
625
626 static int __init parport_default_proc_register (void)
627 {
628         return parport_bus_init();
629 }
630
631 static void __exit parport_default_proc_unregister (void)
632 {
633         parport_bus_exit();
634 }
635 #endif
636
637 subsys_initcall(parport_default_proc_register)
638 module_exit(parport_default_proc_unregister)