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(struct 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(struct 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(struct 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(struct 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(struct 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(struct 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) { .procname = NULL, .mode = 0555, .child = CHILD }
 237#define PARPORT_PARPORT_DIR(CHILD) { .procname = "parport", \
 238                                     .mode = 0555, .child = CHILD }
 239#define PARPORT_DEV_DIR(CHILD) { .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        struct ctl_table vars[12];
 259        struct ctl_table device_dir[2];
 260        struct ctl_table port_dir[2];
 261        struct ctl_table parport_dir[2];
 262        struct 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        struct ctl_table vars[2];
 373        struct ctl_table device_dir[2];
 374        struct ctl_table devices_root_dir[2];
 375        struct ctl_table port_dir[2];
 376        struct ctl_table parport_dir[2];
 377        struct 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                        .procname       = NULL,
 397                        .data           = NULL,
 398                        .maxlen         = 0,
 399                        .mode           = 0555,
 400                        .child          = NULL
 401                },
 402                {}
 403        },
 404        {
 405                PARPORT_DEVICES_ROOT_DIR,
 406                {}
 407        },
 408        {
 409                PARPORT_PORT_DIR(NULL),
 410                {}
 411        },
 412        {
 413                PARPORT_PARPORT_DIR(NULL),
 414                {}
 415        },
 416        {
 417                PARPORT_DEV_DIR(NULL),
 418                {}
 419        }
 420};
 421
 422struct parport_default_sysctl_table
 423{
 424        struct ctl_table_header *sysctl_header;
 425        struct ctl_table vars[3];
 426        struct ctl_table default_dir[2];
 427        struct ctl_table parport_dir[2];
 428        struct ctl_table dev_dir[2];
 429};
 430
 431static struct parport_default_sysctl_table
 432parport_default_sysctl_table = {
 433        .sysctl_header  = NULL,
 434        {
 435                {
 436                        .procname       = "timeslice",
 437                        .data           = &parport_default_timeslice,
 438                        .maxlen         = sizeof(parport_default_timeslice),
 439                        .mode           = 0644,
 440                        .proc_handler   = proc_doulongvec_ms_jiffies_minmax,
 441                        .extra1         = (void*) &parport_min_timeslice_value,
 442                        .extra2         = (void*) &parport_max_timeslice_value
 443                },
 444                {
 445                        .procname       = "spintime",
 446                        .data           = &parport_default_spintime,
 447                        .maxlen         = sizeof(parport_default_spintime),
 448                        .mode           = 0644,
 449                        .proc_handler   = proc_dointvec_minmax,
 450                        .extra1         = (void*) &parport_min_spintime_value,
 451                        .extra2         = (void*) &parport_max_spintime_value
 452                },
 453                {}
 454        },
 455        {
 456                {
 457                        .procname       = "default",
 458                        .mode           = 0555,
 459                        .child          = parport_default_sysctl_table.vars
 460                },
 461                {}
 462        },
 463        {
 464                PARPORT_PARPORT_DIR(parport_default_sysctl_table.default_dir),
 465                {}
 466        },
 467        {
 468                PARPORT_DEV_DIR(parport_default_sysctl_table.parport_dir),
 469                {}
 470        }
 471};
 472
 473
 474int parport_proc_register(struct parport *port)
 475{
 476        struct parport_sysctl_table *t;
 477        int i;
 478
 479        t = kmemdup(&parport_sysctl_template, sizeof(*t), GFP_KERNEL);
 480        if (t == NULL)
 481                return -ENOMEM;
 482
 483        t->device_dir[0].extra1 = port;
 484
 485        for (i = 0; i < 5; i++)
 486                t->vars[i].extra1 = port;
 487
 488        t->vars[0].data = &port->spintime;
 489        t->vars[5].child = t->device_dir;
 490        
 491        for (i = 0; i < 5; i++)
 492                t->vars[6 + i].extra2 = &port->probe_info[i];
 493
 494        t->port_dir[0].procname = port->name;
 495
 496        t->port_dir[0].child = t->vars;
 497        t->parport_dir[0].child = t->port_dir;
 498        t->dev_dir[0].child = t->parport_dir;
 499
 500        t->sysctl_header = register_sysctl_table(t->dev_dir);
 501        if (t->sysctl_header == NULL) {
 502                kfree(t);
 503                t = NULL;
 504        }
 505        port->sysctl_table = t;
 506        return 0;
 507}
 508
 509int parport_proc_unregister(struct parport *port)
 510{
 511        if (port->sysctl_table) {
 512                struct parport_sysctl_table *t = port->sysctl_table;
 513                port->sysctl_table = NULL;
 514                unregister_sysctl_table(t->sysctl_header);
 515                kfree(t);
 516        }
 517        return 0;
 518}
 519
 520int parport_device_proc_register(struct pardevice *device)
 521{
 522        struct parport_device_sysctl_table *t;
 523        struct parport * port = device->port;
 524        
 525        t = kmemdup(&parport_device_sysctl_template, sizeof(*t), GFP_KERNEL);
 526        if (t == NULL)
 527                return -ENOMEM;
 528
 529        t->dev_dir[0].child = t->parport_dir;
 530        t->parport_dir[0].child = t->port_dir;
 531        t->port_dir[0].procname = port->name;
 532        t->port_dir[0].child = t->devices_root_dir;
 533        t->devices_root_dir[0].child = t->device_dir;
 534
 535        t->device_dir[0].procname = device->name;
 536        t->device_dir[0].child = t->vars;
 537        t->vars[0].data = &device->timeslice;
 538
 539        t->sysctl_header = register_sysctl_table(t->dev_dir);
 540        if (t->sysctl_header == NULL) {
 541                kfree(t);
 542                t = NULL;
 543        }
 544        device->sysctl_table = t;
 545        return 0;
 546}
 547
 548int parport_device_proc_unregister(struct pardevice *device)
 549{
 550        if (device->sysctl_table) {
 551                struct parport_device_sysctl_table *t = device->sysctl_table;
 552                device->sysctl_table = NULL;
 553                unregister_sysctl_table(t->sysctl_header);
 554                kfree(t);
 555        }
 556        return 0;
 557}
 558
 559static int __init parport_default_proc_register(void)
 560{
 561        parport_default_sysctl_table.sysctl_header =
 562                register_sysctl_table(parport_default_sysctl_table.dev_dir);
 563        return 0;
 564}
 565
 566static void __exit parport_default_proc_unregister(void)
 567{
 568        if (parport_default_sysctl_table.sysctl_header) {
 569                unregister_sysctl_table(parport_default_sysctl_table.
 570                                        sysctl_header);
 571                parport_default_sysctl_table.sysctl_header = NULL;
 572        }
 573}
 574
 575#else /* no sysctl or no procfs*/
 576
 577int parport_proc_register(struct parport *pp)
 578{
 579        return 0;
 580}
 581
 582int parport_proc_unregister(struct parport *pp)
 583{
 584        return 0;
 585}
 586
 587int parport_device_proc_register(struct pardevice *device)
 588{
 589        return 0;
 590}
 591
 592int parport_device_proc_unregister(struct pardevice *device)
 593{
 594        return 0;
 595}
 596
 597static int __init parport_default_proc_register (void)
 598{
 599        return 0;
 600}
 601
 602static void __exit parport_default_proc_unregister (void)
 603{
 604}
 605#endif
 606
 607module_init(parport_default_proc_register)
 608module_exit(parport_default_proc_unregister)
 609