patch-2.3.40 linux/drivers/pnp/isapnp_proc.c
Next file: linux/drivers/pnp/quirks.c
Previous file: linux/drivers/pnp/isapnp.c
Back to the patch index
Back to the overall index
- Lines: 289
- Date:
Fri Jan 14 11:21:50 2000
- Orig file:
v2.3.39/linux/drivers/pnp/isapnp_proc.c
- Orig date:
Tue Jan 11 22:31:41 2000
diff -u --recursive --new-file v2.3.39/linux/drivers/pnp/isapnp_proc.c linux/drivers/pnp/isapnp_proc.c
@@ -42,6 +42,8 @@
typedef struct isapnp_info_buffer isapnp_info_buffer_t;
static struct proc_dir_entry *isapnp_proc_entry = NULL;
+static struct proc_dir_entry *isapnp_proc_bus_dir = NULL;
+static struct proc_dir_entry *isapnp_proc_devices_entry = NULL;
static void isapnp_info_read(isapnp_info_buffer_t *buffer);
static void isapnp_info_write(isapnp_info_buffer_t *buffer);
@@ -67,6 +69,18 @@
return res;
}
+static void isapnp_devid(char *str, unsigned short vendor, unsigned short device)
+{
+ sprintf(str, "%c%c%c%x%x%x%x",
+ 'A' + ((vendor >> 2) & 0x3f) - 1,
+ 'A' + (((vendor & 3) << 3) | ((vendor >> 13) & 7)) - 1,
+ 'A' + ((vendor >> 8) & 0x1f) - 1,
+ (device >> 4) & 0x0f,
+ device & 0x0f,
+ (device >> 12) & 0x0f,
+ (device >> 8) & 0x0f);
+}
+
static loff_t isapnp_info_entry_lseek(struct file *file, loff_t offset, int orig)
{
switch (orig) {
@@ -186,17 +200,6 @@
return POLLIN | POLLRDNORM;
}
-static int isapnp_info_entry_ioctl(struct inode *inode, struct file *file,
- unsigned int cmd, unsigned long arg)
-{
- return -EINVAL;
-}
-
-static int isapnp_info_entry_mmap(struct file *file, struct vm_area_struct *vma)
-{
- return -ENXIO;
-}
-
static struct file_operations isapnp_info_entry_operations =
{
isapnp_info_entry_lseek, /* lseek */
@@ -204,8 +207,8 @@
isapnp_info_entry_write, /* write */
NULL, /* readdir */
isapnp_info_entry_poll, /* poll */
- isapnp_info_entry_ioctl, /* ioctl - default */
- isapnp_info_entry_mmap, /* mmap */
+ NULL, /* ioctl - default */
+ NULL, /* mmap */
isapnp_info_entry_open, /* open */
NULL, /* flush */
isapnp_info_entry_release, /* release */
@@ -219,24 +222,210 @@
&isapnp_info_entry_operations, /* default sound info directory file-ops */
};
+static loff_t isapnp_proc_bus_lseek(struct file *file, loff_t off, int whence)
+{
+ loff_t new;
+
+ switch (whence) {
+ case 0:
+ new = off;
+ break;
+ case 1:
+ new = file->f_pos + off;
+ break;
+ case 2:
+ new = 256 + off;
+ break;
+ default:
+ return -EINVAL;
+ }
+ if (new < 0 || new > 256)
+ return -EINVAL;
+ return (file->f_pos = new);
+}
+
+static ssize_t isapnp_proc_bus_read(struct file *file, char *buf, size_t nbytes, loff_t *ppos)
+{
+ struct inode *ino = file->f_dentry->d_inode;
+ struct proc_dir_entry *dp = ino->u.generic_ip;
+ struct pci_dev *dev = dp->data;
+ int pos = *ppos;
+ int cnt, size = 256;
+
+ if (pos >= size)
+ return 0;
+ if (nbytes >= size)
+ nbytes = size;
+ if (pos + nbytes > size)
+ nbytes = size - pos;
+ cnt = nbytes;
+
+ if (!access_ok(VERIFY_WRITE, buf, cnt))
+ return -EINVAL;
+
+ isapnp_cfg_begin(dev->bus->number, dev->devfn);
+ for ( ; pos < 256 && cnt > 0; pos++, buf++, cnt--) {
+ unsigned char val;
+ val = isapnp_read_byte(pos);
+ __put_user(val, buf);
+ }
+ isapnp_cfg_end();
+
+ *ppos = pos;
+ return nbytes;
+}
+
+static struct file_operations isapnp_proc_bus_file_operations =
+{
+ isapnp_proc_bus_lseek, /* lseek */
+ isapnp_proc_bus_read, /* read */
+ NULL, /* write */
+ NULL, /* readdir */
+ NULL, /* poll */
+ NULL, /* ioctl - default */
+ NULL, /* mmap */
+ NULL, /* open */
+ NULL, /* flush */
+ NULL, /* release */
+ NULL, /* can't fsync */
+ NULL, /* fasync */
+ NULL, /* lock */
+};
+
+static struct inode_operations isapnp_proc_bus_inode_operations =
+{
+ &isapnp_proc_bus_file_operations,
+};
+
+static int isapnp_proc_attach_device(struct pci_dev *dev)
+{
+ struct pci_bus *bus = dev->bus;
+ struct proc_dir_entry *de, *e;
+ char name[16];
+
+ if (!(de = bus->procdir)) {
+ sprintf(name, "%02x", bus->number);
+ de = bus->procdir = proc_mkdir(name, isapnp_proc_bus_dir);
+ if (!de)
+ return -ENOMEM;
+ }
+ sprintf(name, "%02x", dev->devfn);
+ e = dev->procent = create_proc_entry(name, S_IFREG | S_IRUGO, de);
+ if (!e)
+ return -ENOMEM;
+ e->ops = &isapnp_proc_bus_inode_operations;
+ e->data = dev;
+ e->size = 256;
+ return 0;
+}
+
+#ifdef MODULE
+static int __exit isapnp_proc_detach_device(struct pci_dev *dev)
+{
+ struct pci_bus *bus = dev->bus;
+ struct proc_dir_entry *de;
+ char name[16];
+
+ if (!(de = bus->procdir))
+ return -EINVAL;
+ sprintf(name, "%02x", dev->devfn);
+ remove_proc_entry(name, de);
+ return 0;
+}
+
+static int __exit isapnp_proc_detach_bus(struct pci_bus *bus)
+{
+ struct proc_dir_entry *de;
+ char name[16];
+
+ if (!(de = bus->procdir))
+ return -EINVAL;
+ sprintf(name, "%02x", bus->number);
+ remove_proc_entry(name, isapnp_proc_bus_dir);
+ return 0;
+}
+#endif
+
+static int isapnp_proc_read_devices(char *buf, char **start, off_t pos, int count)
+{
+ struct pci_dev *dev;
+ off_t at = 0;
+ int len, cnt, i;
+
+ cnt = 0;
+ isapnp_for_each_dev(dev) {
+ char bus_id[8], device_id[8];
+
+ isapnp_devid(bus_id, dev->bus->vendor, dev->bus->device);
+ isapnp_devid(device_id, dev->vendor, dev->device);
+ len = sprintf(buf, "%02x%02x\t%s%s\t",
+ dev->bus->number,
+ dev->devfn,
+ bus_id,
+ device_id);
+ isapnp_cfg_begin(dev->bus->number, dev->devfn);
+ len += sprintf(buf+len, "%02x", isapnp_read_byte(ISAPNP_CFG_ACTIVATE));
+ for (i = 0; i < 8; i++)
+ len += sprintf(buf+len, "%04x", isapnp_read_word(ISAPNP_CFG_PORT + (i << 1)));
+ for (i = 0; i < 2; i++)
+ len += sprintf(buf+len, "%04x", isapnp_read_word(ISAPNP_CFG_IRQ + (i << 1)));
+ for (i = 0; i < 2; i++)
+ len += sprintf(buf+len, "%04x", isapnp_read_word(ISAPNP_CFG_DMA + i));
+ for (i = 0; i < 4; i++)
+ len += sprintf(buf+len, "%08x", isapnp_read_dword(ISAPNP_CFG_MEM + (i << 3)));
+ isapnp_cfg_end();
+ buf[len++] = '\n';
+ at += len;
+ if (at >= pos) {
+ if (!*start) {
+ *start = buf + (pos - (at - len));
+ cnt = at - pos;
+ } else
+ cnt += len;
+ buf += len;
+ }
+ }
+ return (count > cnt) ? cnt : count;
+}
+
int __init isapnp_proc_init(void)
{
struct proc_dir_entry *p;
+ struct pci_dev *dev;
isapnp_proc_entry = NULL;
p = create_proc_entry("isapnp", S_IFREG | S_IRUGO | S_IWUSR, &proc_root);
- if (!p)
- return -ENOMEM;
- p->ops = &isapnp_info_entry_inode_operations;
+ if (p)
+ p->ops = &isapnp_info_entry_inode_operations;
isapnp_proc_entry = p;
+ isapnp_proc_bus_dir = proc_mkdir("isapnp", proc_bus);
+ isapnp_proc_devices_entry = create_proc_info_entry("devices", 0,
+ isapnp_proc_bus_dir,
+ isapnp_proc_read_devices);
+ isapnp_for_each_dev(dev) {
+ isapnp_proc_attach_device(dev);
+ }
return 0;
}
#ifdef MODULE
-int isapnp_proc_done(void)
+int __exit isapnp_proc_done(void)
{
+ struct pci_dev *dev;
+ struct pci_bus *card;
+
+ isapnp_for_each_dev(dev) {
+ isapnp_proc_detach_device(dev);
+ }
+ isapnp_for_each_card(card) {
+ isapnp_proc_detach_bus(card);
+ }
+ if (isapnp_proc_devices_entry)
+ remove_proc_entry("devices", isapnp_proc_devices_entry);
+ if (isapnp_proc_bus_dir)
+ remove_proc_entry("isapnp", proc_bus);
if (isapnp_proc_entry)
- remove_proc_entry("isapnp",&proc_root);
+ remove_proc_entry("isapnp", &proc_root);
return 0;
}
#endif /* MODULE */
@@ -249,14 +438,7 @@
{
char tmp[8];
- sprintf(tmp, "%c%c%c%x%x%x%x",
- 'A' + ((vendor >> 2) & 0x3f) - 1,
- 'A' + (((vendor & 3) << 3) | ((vendor >> 13) & 7)) - 1,
- 'A' + ((vendor >> 8) & 0x1f) - 1,
- (device >> 4) & 0x0f,
- device & 0x0f,
- (device >> 12) & 0x0f,
- (device >> 8) & 0x0f);
+ isapnp_devid(tmp, vendor, device);
isapnp_printf(buffer, tmp);
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)