linux/drivers/pnp/isapnp/proc.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 *  ISA Plug & Play support
   4 *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
   5 */
   6
   7#include <linux/module.h>
   8#include <linux/isapnp.h>
   9#include <linux/proc_fs.h>
  10#include <linux/init.h>
  11#include <linux/uaccess.h>
  12
  13extern struct pnp_protocol isapnp_protocol;
  14
  15static struct proc_dir_entry *isapnp_proc_bus_dir = NULL;
  16
  17static loff_t isapnp_proc_bus_lseek(struct file *file, loff_t off, int whence)
  18{
  19        return fixed_size_llseek(file, off, whence, 256);
  20}
  21
  22static ssize_t isapnp_proc_bus_read(struct file *file, char __user * buf,
  23                                    size_t nbytes, loff_t * ppos)
  24{
  25        struct pnp_dev *dev = PDE_DATA(file_inode(file));
  26        int pos = *ppos;
  27        int cnt, size = 256;
  28
  29        if (pos >= size)
  30                return 0;
  31        if (nbytes >= size)
  32                nbytes = size;
  33        if (pos + nbytes > size)
  34                nbytes = size - pos;
  35        cnt = nbytes;
  36
  37        if (!access_ok(buf, cnt))
  38                return -EINVAL;
  39
  40        isapnp_cfg_begin(dev->card->number, dev->number);
  41        for (; pos < 256 && cnt > 0; pos++, buf++, cnt--) {
  42                unsigned char val;
  43                val = isapnp_read_byte(pos);
  44                __put_user(val, buf);
  45        }
  46        isapnp_cfg_end();
  47
  48        *ppos = pos;
  49        return nbytes;
  50}
  51
  52static const struct proc_ops isapnp_proc_bus_proc_ops = {
  53        .proc_lseek     = isapnp_proc_bus_lseek,
  54        .proc_read      = isapnp_proc_bus_read,
  55};
  56
  57static int isapnp_proc_attach_device(struct pnp_dev *dev)
  58{
  59        struct pnp_card *bus = dev->card;
  60        char name[16];
  61
  62        if (!bus->procdir) {
  63                sprintf(name, "%02x", bus->number);
  64                bus->procdir = proc_mkdir(name, isapnp_proc_bus_dir);
  65                if (!bus->procdir)
  66                        return -ENOMEM;
  67        }
  68        sprintf(name, "%02x", dev->number);
  69        dev->procent = proc_create_data(name, S_IFREG | S_IRUGO, bus->procdir,
  70                                            &isapnp_proc_bus_proc_ops, dev);
  71        if (!dev->procent)
  72                return -ENOMEM;
  73        proc_set_size(dev->procent, 256);
  74        return 0;
  75}
  76
  77int __init isapnp_proc_init(void)
  78{
  79        struct pnp_dev *dev;
  80
  81        isapnp_proc_bus_dir = proc_mkdir("bus/isapnp", NULL);
  82        protocol_for_each_dev(&isapnp_protocol, dev) {
  83                isapnp_proc_attach_device(dev);
  84        }
  85        return 0;
  86}
  87