proc.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. /*
  2. * ISA Plug & Play support
  3. * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU General Public License
  16. * along with this program; if not, write to the Free Software
  17. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18. */
  19. #include <linux/module.h>
  20. #include <linux/isapnp.h>
  21. #include <linux/proc_fs.h>
  22. #include <linux/init.h>
  23. #include <asm/uaccess.h>
  24. extern struct pnp_protocol isapnp_protocol;
  25. static struct proc_dir_entry *isapnp_proc_bus_dir = NULL;
  26. static loff_t isapnp_proc_bus_lseek(struct file *file, loff_t off, int whence)
  27. {
  28. loff_t new = -1;
  29. struct inode *inode = file->f_path.dentry->d_inode;
  30. mutex_lock(&inode->i_mutex);
  31. switch (whence) {
  32. case 0:
  33. new = off;
  34. break;
  35. case 1:
  36. new = file->f_pos + off;
  37. break;
  38. case 2:
  39. new = 256 + off;
  40. break;
  41. }
  42. if (new < 0 || new > 256)
  43. new = -EINVAL;
  44. else
  45. file->f_pos = new;
  46. mutex_unlock(&inode->i_mutex);
  47. return new;
  48. }
  49. static ssize_t isapnp_proc_bus_read(struct file *file, char __user * buf,
  50. size_t nbytes, loff_t * ppos)
  51. {
  52. struct inode *ino = file->f_path.dentry->d_inode;
  53. struct proc_dir_entry *dp = PDE(ino);
  54. struct pnp_dev *dev = dp->data;
  55. int pos = *ppos;
  56. int cnt, size = 256;
  57. if (pos >= size)
  58. return 0;
  59. if (nbytes >= size)
  60. nbytes = size;
  61. if (pos + nbytes > size)
  62. nbytes = size - pos;
  63. cnt = nbytes;
  64. if (!access_ok(VERIFY_WRITE, buf, cnt))
  65. return -EINVAL;
  66. isapnp_cfg_begin(dev->card->number, dev->number);
  67. for (; pos < 256 && cnt > 0; pos++, buf++, cnt--) {
  68. unsigned char val;
  69. val = isapnp_read_byte(pos);
  70. __put_user(val, buf);
  71. }
  72. isapnp_cfg_end();
  73. *ppos = pos;
  74. return nbytes;
  75. }
  76. static const struct file_operations isapnp_proc_bus_file_operations = {
  77. .owner = THIS_MODULE,
  78. .llseek = isapnp_proc_bus_lseek,
  79. .read = isapnp_proc_bus_read,
  80. };
  81. static int isapnp_proc_attach_device(struct pnp_dev *dev)
  82. {
  83. struct pnp_card *bus = dev->card;
  84. struct proc_dir_entry *de, *e;
  85. char name[16];
  86. if (!(de = bus->procdir)) {
  87. sprintf(name, "%02x", bus->number);
  88. de = bus->procdir = proc_mkdir(name, isapnp_proc_bus_dir);
  89. if (!de)
  90. return -ENOMEM;
  91. }
  92. sprintf(name, "%02x", dev->number);
  93. e = dev->procent = proc_create_data(name, S_IFREG | S_IRUGO, de,
  94. &isapnp_proc_bus_file_operations, dev);
  95. if (!e)
  96. return -ENOMEM;
  97. e->size = 256;
  98. return 0;
  99. }
  100. int __init isapnp_proc_init(void)
  101. {
  102. struct pnp_dev *dev;
  103. isapnp_proc_bus_dir = proc_mkdir("bus/isapnp", NULL);
  104. protocol_for_each_dev(&isapnp_protocol, dev) {
  105. isapnp_proc_attach_device(dev);
  106. }
  107. return 0;
  108. }