0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
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)
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)
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
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)
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)
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)
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)
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
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
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)