Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Sysctl interface for parport devices.
0003  * 
0004  * Authors: David Campbell
0005  *          Tim Waugh <tim@cyberelk.demon.co.uk>
0006  *          Philip Blundell <philb@gnu.org>
0007  *          Andrea Arcangeli
0008  *          Riccardo Facchetti <fizban@tin.it>
0009  *
0010  * based on work by Grant Guenther <grant@torque.net>
0011  *              and Philip Blundell
0012  *
0013  * Cleaned up include files - Russell King <linux@arm.uk.linux.org>
0014  */
0015 
0016 #include <linux/string.h>
0017 #include <linux/init.h>
0018 #include <linux/module.h>
0019 #include <linux/errno.h>
0020 #include <linux/kernel.h>
0021 #include <linux/slab.h>
0022 #include <linux/parport.h>
0023 #include <linux/ctype.h>
0024 #include <linux/sysctl.h>
0025 #include <linux/device.h>
0026 
0027 #include <linux/uaccess.h>
0028 
0029 #if defined(CONFIG_SYSCTL) && defined(CONFIG_PROC_FS)
0030 
0031 #define PARPORT_MIN_TIMESLICE_VALUE 1ul 
0032 #define PARPORT_MAX_TIMESLICE_VALUE ((unsigned long) HZ)
0033 #define PARPORT_MIN_SPINTIME_VALUE 1
0034 #define PARPORT_MAX_SPINTIME_VALUE 1000
0035 
0036 static int do_active_device(struct ctl_table *table, int write,
0037               void *result, size_t *lenp, loff_t *ppos)
0038 {
0039     struct parport *port = (struct parport *)table->extra1;
0040     char buffer[256];
0041     struct pardevice *dev;
0042     int len = 0;
0043 
0044     if (write)      /* can't happen anyway */
0045         return -EACCES;
0046 
0047     if (*ppos) {
0048         *lenp = 0;
0049         return 0;
0050     }
0051     
0052     for (dev = port->devices; dev ; dev = dev->next) {
0053         if(dev == port->cad) {
0054             len += sprintf(buffer, "%s\n", dev->name);
0055         }
0056     }
0057 
0058     if(!len) {
0059         len += sprintf(buffer, "%s\n", "none");
0060     }
0061 
0062     if (len > *lenp)
0063         len = *lenp;
0064     else
0065         *lenp = len;
0066 
0067     *ppos += len;
0068     memcpy(result, buffer, len);
0069     return 0;
0070 }
0071 
0072 #ifdef CONFIG_PARPORT_1284
0073 static int do_autoprobe(struct ctl_table *table, int write,
0074             void *result, size_t *lenp, loff_t *ppos)
0075 {
0076     struct parport_device_info *info = table->extra2;
0077     const char *str;
0078     char buffer[256];
0079     int len = 0;
0080 
0081     if (write) /* permissions stop this */
0082         return -EACCES;
0083 
0084     if (*ppos) {
0085         *lenp = 0;
0086         return 0;
0087     }
0088     
0089     if ((str = info->class_name) != NULL)
0090         len += sprintf (buffer + len, "CLASS:%s;\n", str);
0091 
0092     if ((str = info->model) != NULL)
0093         len += sprintf (buffer + len, "MODEL:%s;\n", str);
0094 
0095     if ((str = info->mfr) != NULL)
0096         len += sprintf (buffer + len, "MANUFACTURER:%s;\n", str);
0097 
0098     if ((str = info->description) != NULL)
0099         len += sprintf (buffer + len, "DESCRIPTION:%s;\n", str);
0100 
0101     if ((str = info->cmdset) != NULL)
0102         len += sprintf (buffer + len, "COMMAND SET:%s;\n", str);
0103 
0104     if (len > *lenp)
0105         len = *lenp;
0106     else
0107         *lenp = len;
0108 
0109     *ppos += len;
0110 
0111     memcpy(result, buffer, len);
0112     return 0;
0113 }
0114 #endif /* IEEE1284.3 support. */
0115 
0116 static int do_hardware_base_addr(struct ctl_table *table, int write,
0117                  void *result, size_t *lenp, loff_t *ppos)
0118 {
0119     struct parport *port = (struct parport *)table->extra1;
0120     char buffer[20];
0121     int len = 0;
0122 
0123     if (*ppos) {
0124         *lenp = 0;
0125         return 0;
0126     }
0127 
0128     if (write) /* permissions prevent this anyway */
0129         return -EACCES;
0130 
0131     len += sprintf (buffer, "%lu\t%lu\n", port->base, port->base_hi);
0132 
0133     if (len > *lenp)
0134         len = *lenp;
0135     else
0136         *lenp = len;
0137 
0138     *ppos += len;
0139     memcpy(result, buffer, len);
0140     return 0;
0141 }
0142 
0143 static int do_hardware_irq(struct ctl_table *table, int write,
0144                void *result, size_t *lenp, loff_t *ppos)
0145 {
0146     struct parport *port = (struct parport *)table->extra1;
0147     char buffer[20];
0148     int len = 0;
0149 
0150     if (*ppos) {
0151         *lenp = 0;
0152         return 0;
0153     }
0154 
0155     if (write) /* permissions prevent this anyway */
0156         return -EACCES;
0157 
0158     len += sprintf (buffer, "%d\n", port->irq);
0159 
0160     if (len > *lenp)
0161         len = *lenp;
0162     else
0163         *lenp = len;
0164 
0165     *ppos += len;
0166     memcpy(result, buffer, len);
0167     return 0;
0168 }
0169 
0170 static int do_hardware_dma(struct ctl_table *table, int write,
0171                void *result, size_t *lenp, loff_t *ppos)
0172 {
0173     struct parport *port = (struct parport *)table->extra1;
0174     char buffer[20];
0175     int len = 0;
0176 
0177     if (*ppos) {
0178         *lenp = 0;
0179         return 0;
0180     }
0181 
0182     if (write) /* permissions prevent this anyway */
0183         return -EACCES;
0184 
0185     len += sprintf (buffer, "%d\n", port->dma);
0186 
0187     if (len > *lenp)
0188         len = *lenp;
0189     else
0190         *lenp = len;
0191 
0192     *ppos += len;
0193     memcpy(result, buffer, len);
0194     return 0;
0195 }
0196 
0197 static int do_hardware_modes(struct ctl_table *table, int write,
0198                  void *result, size_t *lenp, loff_t *ppos)
0199 {
0200     struct parport *port = (struct parport *)table->extra1;
0201     char buffer[40];
0202     int len = 0;
0203 
0204     if (*ppos) {
0205         *lenp = 0;
0206         return 0;
0207     }
0208 
0209     if (write) /* permissions prevent this anyway */
0210         return -EACCES;
0211 
0212     {
0213 #define printmode(x)                            \
0214 do {                                    \
0215     if (port->modes & PARPORT_MODE_##x)             \
0216         len += sprintf(buffer + len, "%s%s", f++ ? "," : "", #x); \
0217 } while (0)
0218         int f = 0;
0219         printmode(PCSPP);
0220         printmode(TRISTATE);
0221         printmode(COMPAT);
0222         printmode(EPP);
0223         printmode(ECP);
0224         printmode(DMA);
0225 #undef printmode
0226     }
0227     buffer[len++] = '\n';
0228 
0229     if (len > *lenp)
0230         len = *lenp;
0231     else
0232         *lenp = len;
0233 
0234     *ppos += len;
0235     memcpy(result, buffer, len);
0236     return 0;
0237 }
0238 
0239 #define PARPORT_PORT_DIR(CHILD) { .procname = NULL, .mode = 0555, .child = CHILD }
0240 #define PARPORT_PARPORT_DIR(CHILD) { .procname = "parport", \
0241                                      .mode = 0555, .child = CHILD }
0242 #define PARPORT_DEV_DIR(CHILD) { .procname = "dev", .mode = 0555, .child = CHILD }
0243 #define PARPORT_DEVICES_ROOT_DIR  {  .procname = "devices", \
0244                                     .mode = 0555, .child = NULL }
0245 
0246 static const unsigned long parport_min_timeslice_value =
0247 PARPORT_MIN_TIMESLICE_VALUE;
0248 
0249 static const unsigned long parport_max_timeslice_value =
0250 PARPORT_MAX_TIMESLICE_VALUE;
0251 
0252 static const  int parport_min_spintime_value =
0253 PARPORT_MIN_SPINTIME_VALUE;
0254 
0255 static const int parport_max_spintime_value =
0256 PARPORT_MAX_SPINTIME_VALUE;
0257 
0258 
0259 struct parport_sysctl_table {
0260     struct ctl_table_header *sysctl_header;
0261     struct ctl_table vars[12];
0262     struct ctl_table device_dir[2];
0263     struct ctl_table port_dir[2];
0264     struct ctl_table parport_dir[2];
0265     struct ctl_table dev_dir[2];
0266 };
0267 
0268 static const struct parport_sysctl_table parport_sysctl_template = {
0269     .sysctl_header = NULL,
0270         {
0271         {
0272             .procname   = "spintime",
0273             .data       = NULL,
0274             .maxlen     = sizeof(int),
0275             .mode       = 0644,
0276             .proc_handler   = proc_dointvec_minmax,
0277             .extra1     = (void*) &parport_min_spintime_value,
0278             .extra2     = (void*) &parport_max_spintime_value
0279         },
0280         {
0281             .procname   = "base-addr",
0282             .data       = NULL,
0283             .maxlen     = 0,
0284             .mode       = 0444,
0285             .proc_handler   = do_hardware_base_addr
0286         },
0287         {
0288             .procname   = "irq",
0289             .data       = NULL,
0290             .maxlen     = 0,
0291             .mode       = 0444,
0292             .proc_handler   = do_hardware_irq
0293         },
0294         {
0295             .procname   = "dma",
0296             .data       = NULL,
0297             .maxlen     = 0,
0298             .mode       = 0444,
0299             .proc_handler   = do_hardware_dma
0300         },
0301         {
0302             .procname   = "modes",
0303             .data       = NULL,
0304             .maxlen     = 0,
0305             .mode       = 0444,
0306             .proc_handler   = do_hardware_modes
0307         },
0308         PARPORT_DEVICES_ROOT_DIR,
0309 #ifdef CONFIG_PARPORT_1284
0310         {
0311             .procname   = "autoprobe",
0312             .data       = NULL,
0313             .maxlen     = 0,
0314             .mode       = 0444,
0315             .proc_handler   = do_autoprobe
0316         },
0317         {
0318             .procname   = "autoprobe0",
0319             .data       = NULL,
0320             .maxlen     = 0,
0321             .mode       = 0444,
0322             .proc_handler   = do_autoprobe
0323         },
0324         {
0325             .procname   = "autoprobe1",
0326             .data       = NULL,
0327             .maxlen     = 0,
0328             .mode       = 0444,
0329             .proc_handler   = do_autoprobe
0330         },
0331         {
0332             .procname   = "autoprobe2",
0333             .data       = NULL,
0334             .maxlen     = 0,
0335             .mode       = 0444,
0336             .proc_handler   = do_autoprobe
0337         },
0338         {
0339             .procname   = "autoprobe3",
0340             .data       = NULL,
0341             .maxlen     = 0,
0342             .mode       = 0444,
0343             .proc_handler   = do_autoprobe
0344         },
0345 #endif /* IEEE 1284 support */
0346         {}
0347     },
0348     {
0349         {
0350             .procname   = "active",
0351             .data       = NULL,
0352             .maxlen     = 0,
0353             .mode       = 0444,
0354             .proc_handler   = do_active_device
0355         },
0356         {}
0357     },
0358     {
0359         PARPORT_PORT_DIR(NULL),
0360         {}
0361     },
0362     {
0363         PARPORT_PARPORT_DIR(NULL),
0364         {}
0365     },
0366     {
0367         PARPORT_DEV_DIR(NULL),
0368         {}
0369     }
0370 };
0371 
0372 struct parport_device_sysctl_table
0373 {
0374     struct ctl_table_header *sysctl_header;
0375     struct ctl_table vars[2];
0376     struct ctl_table device_dir[2];
0377     struct ctl_table devices_root_dir[2];
0378     struct ctl_table port_dir[2];
0379     struct ctl_table parport_dir[2];
0380     struct ctl_table dev_dir[2];
0381 };
0382 
0383 static const struct parport_device_sysctl_table
0384 parport_device_sysctl_template = {
0385     .sysctl_header = NULL,
0386     {
0387         {
0388             .procname   = "timeslice",
0389             .data       = NULL,
0390             .maxlen     = sizeof(unsigned long),
0391             .mode       = 0644,
0392             .proc_handler   = proc_doulongvec_ms_jiffies_minmax,
0393             .extra1     = (void*) &parport_min_timeslice_value,
0394             .extra2     = (void*) &parport_max_timeslice_value
0395         },
0396     },
0397     {
0398         {
0399             .procname   = NULL,
0400             .data       = NULL,
0401             .maxlen     = 0,
0402             .mode       = 0555,
0403             .child      = NULL
0404         },
0405         {}
0406     },
0407     {
0408         PARPORT_DEVICES_ROOT_DIR,
0409         {}
0410     },
0411     {
0412         PARPORT_PORT_DIR(NULL),
0413         {}
0414     },
0415     {
0416         PARPORT_PARPORT_DIR(NULL),
0417         {}
0418     },
0419     {
0420         PARPORT_DEV_DIR(NULL),
0421         {}
0422     }
0423 };
0424 
0425 struct parport_default_sysctl_table
0426 {
0427     struct ctl_table_header *sysctl_header;
0428     struct ctl_table vars[3];
0429     struct ctl_table default_dir[2];
0430     struct ctl_table parport_dir[2];
0431     struct ctl_table dev_dir[2];
0432 };
0433 
0434 static struct parport_default_sysctl_table
0435 parport_default_sysctl_table = {
0436     .sysctl_header  = NULL,
0437     {
0438         {
0439             .procname   = "timeslice",
0440             .data       = &parport_default_timeslice,
0441             .maxlen     = sizeof(parport_default_timeslice),
0442             .mode       = 0644,
0443             .proc_handler   = proc_doulongvec_ms_jiffies_minmax,
0444             .extra1     = (void*) &parport_min_timeslice_value,
0445             .extra2     = (void*) &parport_max_timeslice_value
0446         },
0447         {
0448             .procname   = "spintime",
0449             .data       = &parport_default_spintime,
0450             .maxlen     = sizeof(parport_default_spintime),
0451             .mode       = 0644,
0452             .proc_handler   = proc_dointvec_minmax,
0453             .extra1     = (void*) &parport_min_spintime_value,
0454             .extra2     = (void*) &parport_max_spintime_value
0455         },
0456         {}
0457     },
0458     {
0459         {
0460             .procname   = "default",
0461             .mode       = 0555,
0462             .child      = parport_default_sysctl_table.vars
0463         },
0464         {}
0465     },
0466     {
0467         PARPORT_PARPORT_DIR(parport_default_sysctl_table.default_dir),
0468         {}
0469     },
0470     {
0471         PARPORT_DEV_DIR(parport_default_sysctl_table.parport_dir),
0472         {}
0473     }
0474 };
0475 
0476 
0477 int parport_proc_register(struct parport *port)
0478 {
0479     struct parport_sysctl_table *t;
0480     int i;
0481 
0482     t = kmemdup(&parport_sysctl_template, sizeof(*t), GFP_KERNEL);
0483     if (t == NULL)
0484         return -ENOMEM;
0485 
0486     t->device_dir[0].extra1 = port;
0487 
0488     for (i = 0; i < 5; i++)
0489         t->vars[i].extra1 = port;
0490 
0491     t->vars[0].data = &port->spintime;
0492     t->vars[5].child = t->device_dir;
0493     
0494     for (i = 0; i < 5; i++)
0495         t->vars[6 + i].extra2 = &port->probe_info[i];
0496 
0497     t->port_dir[0].procname = port->name;
0498 
0499     t->port_dir[0].child = t->vars;
0500     t->parport_dir[0].child = t->port_dir;
0501     t->dev_dir[0].child = t->parport_dir;
0502 
0503     t->sysctl_header = register_sysctl_table(t->dev_dir);
0504     if (t->sysctl_header == NULL) {
0505         kfree(t);
0506         t = NULL;
0507     }
0508     port->sysctl_table = t;
0509     return 0;
0510 }
0511 
0512 int parport_proc_unregister(struct parport *port)
0513 {
0514     if (port->sysctl_table) {
0515         struct parport_sysctl_table *t = port->sysctl_table;
0516         port->sysctl_table = NULL;
0517         unregister_sysctl_table(t->sysctl_header);
0518         kfree(t);
0519     }
0520     return 0;
0521 }
0522 
0523 int parport_device_proc_register(struct pardevice *device)
0524 {
0525     struct parport_device_sysctl_table *t;
0526     struct parport * port = device->port;
0527     
0528     t = kmemdup(&parport_device_sysctl_template, sizeof(*t), GFP_KERNEL);
0529     if (t == NULL)
0530         return -ENOMEM;
0531 
0532     t->dev_dir[0].child = t->parport_dir;
0533     t->parport_dir[0].child = t->port_dir;
0534     t->port_dir[0].procname = port->name;
0535     t->port_dir[0].child = t->devices_root_dir;
0536     t->devices_root_dir[0].child = t->device_dir;
0537 
0538     t->device_dir[0].procname = device->name;
0539     t->device_dir[0].child = t->vars;
0540     t->vars[0].data = &device->timeslice;
0541 
0542     t->sysctl_header = register_sysctl_table(t->dev_dir);
0543     if (t->sysctl_header == NULL) {
0544         kfree(t);
0545         t = NULL;
0546     }
0547     device->sysctl_table = t;
0548     return 0;
0549 }
0550 
0551 int parport_device_proc_unregister(struct pardevice *device)
0552 {
0553     if (device->sysctl_table) {
0554         struct parport_device_sysctl_table *t = device->sysctl_table;
0555         device->sysctl_table = NULL;
0556         unregister_sysctl_table(t->sysctl_header);
0557         kfree(t);
0558     }
0559     return 0;
0560 }
0561 
0562 static int __init parport_default_proc_register(void)
0563 {
0564     int ret;
0565 
0566     parport_default_sysctl_table.sysctl_header =
0567         register_sysctl_table(parport_default_sysctl_table.dev_dir);
0568     if (!parport_default_sysctl_table.sysctl_header)
0569         return -ENOMEM;
0570     ret = parport_bus_init();
0571     if (ret) {
0572         unregister_sysctl_table(parport_default_sysctl_table.
0573                     sysctl_header);
0574         return ret;
0575     }
0576     return 0;
0577 }
0578 
0579 static void __exit parport_default_proc_unregister(void)
0580 {
0581     if (parport_default_sysctl_table.sysctl_header) {
0582         unregister_sysctl_table(parport_default_sysctl_table.
0583                     sysctl_header);
0584         parport_default_sysctl_table.sysctl_header = NULL;
0585     }
0586     parport_bus_exit();
0587 }
0588 
0589 #else /* no sysctl or no procfs*/
0590 
0591 int parport_proc_register(struct parport *pp)
0592 {
0593     return 0;
0594 }
0595 
0596 int parport_proc_unregister(struct parport *pp)
0597 {
0598     return 0;
0599 }
0600 
0601 int parport_device_proc_register(struct pardevice *device)
0602 {
0603     return 0;
0604 }
0605 
0606 int parport_device_proc_unregister(struct pardevice *device)
0607 {
0608     return 0;
0609 }
0610 
0611 static int __init parport_default_proc_register (void)
0612 {
0613     return parport_bus_init();
0614 }
0615 
0616 static void __exit parport_default_proc_unregister (void)
0617 {
0618     parport_bus_exit();
0619 }
0620 #endif
0621 
0622 subsys_initcall(parport_default_proc_register)
0623 module_exit(parport_default_proc_unregister)