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