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
  25#include <asm/uaccess.h>
  26
  27#if defined(CONFIG_SYSCTL) && defined(CONFIG_PROC_FS)
  28
  29#define PARPORT_MIN_TIMESLICE_VALUE 1ul 
  30#define PARPORT_MAX_TIMESLICE_VALUE ((unsigned long) HZ)
  31#define PARPORT_MIN_SPINTIME_VALUE 1
  32#define PARPORT_MAX_SPINTIME_VALUE 1000
  33
  34static int do_active_device(ctl_table *table, int write,
  35                      void __user *result, size_t *lenp, loff_t *ppos)
  36{
  37        struct parport *port = (struct parport *)table->extra1;
  38        char buffer[256];
  39        struct pardevice *dev;
  40        int len = 0;
  41
  42        if (write)              /* can't happen anyway */
  43                return -EACCES;
  44
  45        if (*ppos) {
  46                *lenp = 0;
  47                return 0;
  48        }
  49        
  50        for (dev = port->devices; dev ; dev = dev->next) {
  51                if(dev == port->cad) {
  52                        len += sprintf(buffer, "%s\n", dev->name);
  53                }
  54        }
  55
  56        if(!len) {
  57                len += sprintf(buffer, "%s\n", "none");
  58        }
  59
  60        if (len > *lenp)
  61                len = *lenp;
  62        else
  63                *lenp = len;
  64
  65        *ppos += len;
  66
  67        return copy_to_user(result, buffer, len) ? -EFAULT : 0;
  68}
  69
  70#ifdef CONFIG_PARPORT_1284
  71static int do_autoprobe(ctl_table *table, int write,
  72                        void __user *result, size_t *lenp, loff_t *ppos)
  73{
  74        struct parport_device_info *info = table->extra2;
  75        const char *str;
  76        char buffer[256];
  77        int len = 0;
  78
  79        if (write) /* permissions stop this */
  80                return -EACCES;
  81
  82        if (*ppos) {
  83                *lenp = 0;
  84                return 0;
  85        }
  86        
  87        if ((str = info->class_name) != NULL)
  88                len += sprintf (buffer + len, "CLASS:%s;\n", str);
  89
  90        if ((str = info->model) != NULL)
  91                len += sprintf (buffer + len, "MODEL:%s;\n", str);
  92
  93        if ((str = info->mfr) != NULL)
  94                len += sprintf (buffer + len, "MANUFACTURER:%s;\n", str);
  95
  96        if ((str = info->description) != NULL)
  97                len += sprintf (buffer + len, "DESCRIPTION:%s;\n", str);
  98
  99        if ((str = info->cmdset) != NULL)
 100                len += sprintf (buffer + len, "COMMAND SET:%s;\n", str);
 101
 102        if (len > *lenp)
 103                len = *lenp;
 104        else
 105                *lenp = len;
 106
 107        *ppos += len;
 108
 109        return copy_to_user (result, buffer, len) ? -EFAULT : 0;
 110}
 111#endif /* IEEE1284.3 support. */
 112
 113static int do_hardware_base_addr (ctl_table *table, int write,
 114                                  void __user *result,
 115                                  size_t *lenp, loff_t *ppos)
 116{
 117        struct parport *port = (struct parport *)table->extra1;
 118        char buffer[20];
 119        int len = 0;
 120
 121        if (*ppos) {
 122                *lenp = 0;
 123                return 0;
 124        }
 125
 126        if (write) /* permissions prevent this anyway */
 127                return -EACCES;
 128
 129        len += sprintf (buffer, "%lu\t%lu\n", port->base, port->base_hi);
 130
 131        if (len > *lenp)
 132                len = *lenp;
 133        else
 134                *lenp = len;
 135
 136        *ppos += len;
 137
 138        return copy_to_user(result, buffer, len) ? -EFAULT : 0;
 139}
 140
 141static int do_hardware_irq (ctl_table *table, int write,
 142                            void __user *result,
 143                            size_t *lenp, loff_t *ppos)
 144{
 145        struct parport *port = (struct parport *)table->extra1;
 146        char buffer[20];
 147        int len = 0;
 148
 149        if (*ppos) {
 150                *lenp = 0;
 151                return 0;
 152        }
 153
 154        if (write) /* permissions prevent this anyway */
 155                return -EACCES;
 156
 157        len += sprintf (buffer, "%d\n", port->irq);
 158
 159        if (len > *lenp)
 160                len = *lenp;
 161        else
 162                *lenp = len;
 163
 164        *ppos += len;
 165
 166        return copy_to_user(result, buffer, len) ? -EFAULT : 0;
 167}
 168
 169static int do_hardware_dma (ctl_table *table, int write,
 170                            void __user *result,
 171                            size_t *lenp, loff_t *ppos)
 172{
 173        struct parport *port = (struct parport *)table->extra1;
 174        char buffer[20];
 175        int len = 0;
 176
 177        if (*ppos) {
 178                *lenp = 0;
 179                return 0;
 180        }
 181
 182        if (write) /* permissions prevent this anyway */
 183                return -EACCES;
 184
 185        len += sprintf (buffer, "%d\n", port->dma);
 186
 187        if (len > *lenp)
 188                len = *lenp;
 189        else
 190                *lenp = len;
 191
 192        *ppos += len;
 193
 194        return copy_to_user(result, buffer, len) ? -EFAULT : 0;
 195}
 196
 197static int do_hardware_modes (ctl_table *table, int write,
 198                              void __user *result,
 199                              size_t *lenp, loff_t *ppos)
 200{
 201        struct parport *port = (struct parport *)table->extra1;
 202        char buffer[40];
 203        int len = 0;
 204
 205        if (*ppos) {
 206                *lenp = 0;
 207                return 0;
 208        }
 209
 210        if (write) /* permissions prevent this anyway */
 211                return -EACCES;
 212
 213        {
 214#define printmode(x) {if(port->modes&PARPORT_MODE_##x){len+=sprintf(buffer+len,"%s%s",f?",":"",#x);f++;}}
 215                int f = 0;
 216                printmode(PCSPP);
 217                printmode(TRISTATE);
 218                printmode(COMPAT);
 219                printmode(EPP);
 220                printmode(ECP);
 221                printmode(DMA);
 222#undef printmode
 223        }
 224        buffer[len++] = '\n';
 225
 226        if (len > *lenp)
 227                len = *lenp;
 228        else
 229                *lenp = len;
 230
 231        *ppos += len;
 232
 233        return copy_to_user(result, buffer, len) ? -EFAULT : 0;
 234}
 235
 236#define PARPORT_PORT_DIR(CHILD) { .ctl_name = 0, .procname = NULL, .mode = 0555, .child = CHILD }
 237#define PARPORT_PARPORT_DIR(CHILD) { .ctl_name = DEV_PARPORT, .procname = "parport", \
 238                                     .mode = 0555, .child = CHILD }
 239#define PARPORT_DEV_DIR(CHILD) { .ctl_name = CTL_DEV, .procname = "dev", .mode = 0555, .child = CHILD }
 240#define PARPORT_DEVICES_ROOT_DIR  {  .procname = "devices", \
 241                                    .mode = 0555, .child = NULL }
 242
 243static const unsigned long parport_min_timeslice_value =
 244PARPORT_MIN_TIMESLICE_VALUE;
 245
 246static const unsigned long parport_max_timeslice_value =
 247PARPORT_MAX_TIMESLICE_VALUE;
 248
 249static const  int parport_min_spintime_value =
 250PARPORT_MIN_SPINTIME_VALUE;
 251
 252static const int parport_max_spintime_value =
 253PARPORT_MAX_SPINTIME_VALUE;
 254
 255
 256struct parport_sysctl_table {
 257        struct ctl_table_header *sysctl_header;
 258        ctl_table vars[12];
 259        ctl_table device_dir[2];
 260        ctl_table port_dir[2];
 261        ctl_table parport_dir[2];
 262        ctl_table dev_dir[2];
 263};
 264
 265static const struct parport_sysctl_table parport_sysctl_template = {
 266        .sysctl_header = NULL,
 267        {
 268                {
 269                        .procname       = "spintime",
 270                        .data           = NULL,
 271                        .maxlen         = sizeof(int),
 272                        .mode           = 0644,
 273                        .proc_handler   = &proc_dointvec_minmax,
 274                        .extra1         = (void*) &parport_min_spintime_value,
 275                        .extra2         = (void*) &parport_max_spintime_value
 276                },
 277                {
 278                        .procname       = "base-addr",
 279                        .data           = NULL,
 280                        .maxlen         = 0,
 281                        .mode           = 0444,
 282                        .proc_handler   = &do_hardware_base_addr
 283                },
 284                {
 285                        .procname       = "irq",
 286                        .data           = NULL,
 287                        .maxlen         = 0,
 288                        .mode           = 0444,
 289                        .proc_handler   = &do_hardware_irq
 290                },
 291                {
 292                        .procname       = "dma",
 293                        .data           = NULL,
 294                        .maxlen         = 0,
 295                        .mode           = 0444,
 296                        .proc_handler   = &do_hardware_dma
 297                },
 298                {
 299                        .procname       = "modes",
 300                        .data           = NULL,
 301                        .maxlen         = 0,
 302                        .mode           = 0444,
 303                        .proc_handler   = &do_hardware_modes
 304                },
 305                PARPORT_DEVICES_ROOT_DIR,
 306#ifdef CONFIG_PARPORT_1284
 307                {
 308                        .procname       = "autoprobe",
 309                        .data           = NULL,
 310                        .maxlen         = 0,
 311                        .mode           = 0444,
 312                        .proc_handler   = &do_autoprobe
 313                },
 314                {
 315                        .procname       = "autoprobe0",
 316                        .data           = NULL,
 317                        .maxlen         = 0,
 318                        .mode           = 0444,
 319                        .proc_handler   =  &do_autoprobe
 320                },
 321                {
 322                        .procname       = "autoprobe1",
 323                        .data           = NULL,
 324                        .maxlen         = 0,
 325                        .mode           = 0444,
 326                        .proc_handler   = &do_autoprobe
 327                },
 328                {
 329                        .procname       = "autoprobe2",
 330                        .data           = NULL,
 331                        .maxlen         = 0,
 332                        .mode           = 0444,
 333                        .proc_handler   = &do_autoprobe
 334                },
 335                {
 336                        .procname       = "autoprobe3",
 337                        .data           = NULL,
 338                        .maxlen         = 0,
 339                        .mode           = 0444,
 340                        .proc_handler   = &do_autoprobe
 341                },
 342#endif /* IEEE 1284 support */
 343                {}
 344        },
 345        {
 346                {
 347                        .procname       = "active",
 348                        .data           = NULL,
 349                        .maxlen         = 0,
 350                        .mode           = 0444,
 351                        .proc_handler   = &do_active_device
 352                },
 353                {}
 354        },
 355        {
 356                PARPORT_PORT_DIR(NULL),
 357                {}
 358        },
 359        {
 360                PARPORT_PARPORT_DIR(NULL),
 361                {}
 362        },
 363        {
 364                PARPORT_DEV_DIR(NULL),
 365                {}
 366        }
 367};
 368
 369struct parport_device_sysctl_table
 370{
 371        struct ctl_table_header *sysctl_header;
 372        ctl_table vars[2];
 373        ctl_table device_dir[2];
 374        ctl_table devices_root_dir[2];
 375        ctl_table port_dir[2];
 376        ctl_table parport_dir[2];
 377        ctl_table dev_dir[2];
 378};
 379
 380static const struct parport_device_sysctl_table
 381parport_device_sysctl_template = {
 382        .sysctl_header = NULL,
 383        {
 384                {
 385                        .procname       = "timeslice",
 386                        .data           = NULL,
 387                        .maxlen         = sizeof(unsigned long),
 388                        .mode           = 0644,
 389                        .proc_handler   = &proc_doulongvec_ms_jiffies_minmax,
 390                        .extra1         = (void*) &parport_min_timeslice_value,
 391                        .extra2         = (void*) &parport_max_timeslice_value
 392                },
 393        },
 394        {
 395                {
 396                        .ctl_name       = 0,
 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        ctl_table vars[3];
 427        ctl_table default_dir[2];
 428        ctl_table parport_dir[2];
 429        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                        .ctl_name       = DEV_PARPORT_DEFAULT,
 459                        .procname       = "default",
 460                        .mode           = 0555,
 461                        .child          = parport_default_sysctl_table.vars
 462                },
 463                {}
 464        },
 465        {
 466                PARPORT_PARPORT_DIR(parport_default_sysctl_table.default_dir),
 467                {}
 468        },
 469        {
 470                PARPORT_DEV_DIR(parport_default_sysctl_table.parport_dir),
 471                {}
 472        }
 473};
 474
 475
 476int parport_proc_register(struct parport *port)
 477{
 478        struct parport_sysctl_table *t;
 479        int i;
 480
 481        t = kmalloc(sizeof(*t), GFP_KERNEL);
 482        if (t == NULL)
 483                return -ENOMEM;
 484        memcpy(t, &parport_sysctl_template, sizeof(*t));
 485
 486        t->device_dir[0].extra1 = port;
 487
 488        for (i = 0; i < 5; i++)
 489                t->vars[i].extra1 = port;
 490
 491        t->vars[0].data = &port->spintime;
 492        t->vars[5].child = t->device_dir;
 493        
 494        for (i = 0; i < 5; i++)
 495                t->vars[6 + i].extra2 = &port->probe_info[i];
 496
 497        t->port_dir[0].procname = port->name;
 498        t->port_dir[0].ctl_name = 0;
 499
 500        t->port_dir[0].child = t->vars;
 501        t->parport_dir[0].child = t->port_dir;
 502        t->dev_dir[0].child = t->parport_dir;
 503
 504        t->sysctl_header = register_sysctl_table(t->dev_dir);
 505        if (t->sysctl_header == NULL) {
 506                kfree(t);
 507                t = NULL;
 508        }
 509        port->sysctl_table = t;
 510        return 0;
 511}
 512
 513int parport_proc_unregister(struct parport *port)
 514{
 515        if (port->sysctl_table) {
 516                struct parport_sysctl_table *t = port->sysctl_table;
 517                port->sysctl_table = NULL;
 518                unregister_sysctl_table(t->sysctl_header);
 519                kfree(t);
 520        }
 521        return 0;
 522}
 523
 524int parport_device_proc_register(struct pardevice *device)
 525{
 526        struct parport_device_sysctl_table *t;
 527        struct parport * port = device->port;
 528        
 529        t = kmalloc(sizeof(*t), GFP_KERNEL);
 530        if (t == NULL)
 531                return -ENOMEM;
 532        memcpy(t, &parport_device_sysctl_template, sizeof(*t));
 533
 534        t->dev_dir[0].child = t->parport_dir;
 535        t->parport_dir[0].child = t->port_dir;
 536        t->port_dir[0].procname = port->name;
 537        t->port_dir[0].ctl_name = 0;
 538        t->port_dir[0].child = t->devices_root_dir;
 539        t->devices_root_dir[0].child = t->device_dir;
 540
 541        t->device_dir[0].ctl_name = 0;
 542        t->device_dir[0].procname = device->name;
 543        t->device_dir[0].child = t->vars;
 544        t->vars[0].data = &device->timeslice;
 545
 546        t->sysctl_header = register_sysctl_table(t->dev_dir);
 547        if (t->sysctl_header == NULL) {
 548                kfree(t);
 549                t = NULL;
 550        }
 551        device->sysctl_table = t;
 552        return 0;
 553}
 554
 555int parport_device_proc_unregister(struct pardevice *device)
 556{
 557        if (device->sysctl_table) {
 558                struct parport_device_sysctl_table *t = device->sysctl_table;
 559                device->sysctl_table = NULL;
 560                unregister_sysctl_table(t->sysctl_header);
 561                kfree(t);
 562        }
 563        return 0;
 564}
 565
 566static int __init parport_default_proc_register(void)
 567{
 568        parport_default_sysctl_table.sysctl_header =
 569                register_sysctl_table(parport_default_sysctl_table.dev_dir);
 570        return 0;
 571}
 572
 573static void __exit parport_default_proc_unregister(void)
 574{
 575        if (parport_default_sysctl_table.sysctl_header) {
 576                unregister_sysctl_table(parport_default_sysctl_table.
 577                                        sysctl_header);
 578                parport_default_sysctl_table.sysctl_header = NULL;
 579        }
 580}
 581
 582#else /* no sysctl or no procfs*/
 583
 584int parport_proc_register(struct parport *pp)
 585{
 586        return 0;
 587}
 588
 589int parport_proc_unregister(struct parport *pp)
 590{
 591        return 0;
 592}
 593
 594int parport_device_proc_register(struct pardevice *device)
 595{
 596        return 0;
 597}
 598
 599int parport_device_proc_unregister(struct pardevice *device)
 600{
 601        return 0;
 602}
 603
 604static int __init parport_default_proc_register (void)
 605{
 606        return 0;
 607}
 608
 609static void __exit parport_default_proc_unregister (void)
 610{
 611}
 612#endif
 613
 614module_init(parport_default_proc_register)
 615module_exit(parport_default_proc_unregister)
 616