linux/drivers/parport/procfs.c
<<
>>
Prefs
   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
  35static 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
  72static 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
 114static 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
 142static 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
 170static 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
 198static 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
 244static const unsigned long parport_min_timeslice_value =
 245PARPORT_MIN_TIMESLICE_VALUE;
 246
 247static const unsigned long parport_max_timeslice_value =
 248PARPORT_MAX_TIMESLICE_VALUE;
 249
 250static const  int parport_min_spintime_value =
 251PARPORT_MIN_SPINTIME_VALUE;
 252
 253static const int parport_max_spintime_value =
 254PARPORT_MAX_SPINTIME_VALUE;
 255
 256
 257struct 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
 266static 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
 370struct 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
 381static const struct parport_device_sysctl_table
 382parport_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
 423struct 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
 432static struct parport_default_sysctl_table
 433parport_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
 475int 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
 510int 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
 521int 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
 549int 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
 560static 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
 577static 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
 589int parport_proc_register(struct parport *pp)
 590{
 591        return 0;
 592}
 593
 594int parport_proc_unregister(struct parport *pp)
 595{
 596        return 0;
 597}
 598
 599int parport_device_proc_register(struct pardevice *device)
 600{
 601        return 0;
 602}
 603
 604int parport_device_proc_unregister(struct pardevice *device)
 605{
 606        return 0;
 607}
 608
 609static int __init parport_default_proc_register (void)
 610{
 611        return parport_bus_init();
 612}
 613
 614static void __exit parport_default_proc_unregister (void)
 615{
 616        parport_bus_exit();
 617}
 618#endif
 619
 620module_init(parport_default_proc_register)
 621module_exit(parport_default_proc_unregister)
 622