Re: [PATCH] PnP Layer Rewrite V0.7 - 2.4.42

Adam Belay (ambx1@neo.rr.com)
Mon, 14 Oct 2002 21:43:34 +0000


On Mon, Oct 14, 2002 at 09:10:04PM +0200, Jaroslav Kysela wrote:
> On Mon, 14 Oct 2002, Adam Belay wrote:
>
> > Linux Plug and Play Rewrite V0.7
> >
> > After much testing the Linux PnP Rewrite is ready to be included. For
> > those who would like to try it, be sure to enable debugging or else it
> > will operate silently. Also enable both PnP protocols.
>
> A few notes. Please, could you leave the raw proc interface for ISA PnP?

Sure, a patch is included at the end of the email. Let me know what you
think.

> I mean isapnp_proc_bus_read() function. Also, encoding device/vendor to
> 7-byte string seems like wasting bytes and CPU cycles. If you use 2/2 byte
> format, you'll spare 3 bytes and comparing of two short values (or one
> int value) is always less expensive.

Actually I've been thinking about this for quite some time.
I see two advantages in using ASCII text.

1.) It allows for wildcards, for example.

the following is from the serial pnp driver:
/* Unkown PnP modems */
{ "PNPCXXX", UNKNOWN_DEV },

this will match with any device that begins as PNPC.

2.) It makes dev_id tables easier to enter and maintain.

I'll look into this some more.

>
> Anyway, I like this code. It seems that you don't use standard pci_dev /
> pci_bus structures as I was forced by Linus at ISA PnP code inclusion
> time. But it's true that we have new device model, so these things might
> be private. Also, don't forget to remove additional ISA PnP members from
> pci structures when Linus approves pnp_dev and pnp_card structures.

I appreciate your comments and recommendations.

Thanks,
Adam

diff -ur --new-file --exclude *.flags a/drivers/pnp/isapnp/Makefile b/drivers/pnp/isapnp/Makefile
--- a/drivers/pnp/isapnp/Makefile Mon Oct 14 21:18:31 2002
+++ b/drivers/pnp/isapnp/Makefile Mon Oct 14 18:31:04 2002
@@ -4,6 +4,6 @@

export-objs := core.o

-obj-y := core.o
+obj-y := core.o proc.o

include $(TOPDIR)/Rules.make
diff -ur --new-file --exclude *.flags a/drivers/pnp/isapnp/core.c b/drivers/pnp/isapnp/core.c
--- a/drivers/pnp/isapnp/core.c Mon Oct 14 21:18:32 2002
+++ b/drivers/pnp/isapnp/core.c Mon Oct 14 19:32:46 2002
@@ -1053,7 +1053,7 @@
return 0;
}

-static struct pnp_protocol isapnp_protocol = {
+struct pnp_protocol isapnp_protocol = {
name: "ISA Plug and Play",
get: isapnp_get_resources,
set: isapnp_set_resources,
@@ -1164,7 +1164,7 @@
isapnp_init_device_tree();

#ifdef CONFIG_PROC_FS
- /*isapnp_proc_init();*/
+ isapnp_proc_init();
#endif
return 0;
}
diff -ur --new-file --exclude *.flags a/drivers/pnp/isapnp/proc.c b/drivers/pnp/isapnp/proc.c
--- a/drivers/pnp/isapnp/proc.c Thu Jan 1 00:00:00 1970
+++ b/drivers/pnp/isapnp/proc.c Mon Oct 14 19:20:39 2002
@@ -0,0 +1,171 @@
+/*
+ * ISA Plug & Play support
+ * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+
+#include <linux/isapnp.h>
+#include <linux/pnp.h>
+#include <linux/proc_fs.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/smp_lock.h>
+#include <asm/uaccess.h>
+
+
+static struct proc_dir_entry *isapnp_proc_bus_dir = NULL;
+
+static loff_t isapnp_proc_bus_lseek(struct file *file, loff_t off, int whence)
+{
+ loff_t new = -1;
+
+ lock_kernel();
+ switch (whence) {
+ case 0:
+ new = off;
+ break;
+ case 1:
+ new = file->f_pos + off;
+ break;
+ case 2:
+ new = 256 + off;
+ break;
+ }
+ if (new < 0 || new > 256) {
+ unlock_kernel();
+ return -EINVAL;
+ }
+ unlock_kernel();
+ 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 = PDE(ino);
+ struct pnp_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->card->number, dev->number);
+ 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 =
+{
+ llseek: isapnp_proc_bus_lseek,
+ read: isapnp_proc_bus_read,
+};
+
+static int isapnp_proc_attach_device(struct pnp_dev *dev)
+{
+ struct pnp_card *bus = dev->card;
+ 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->number);
+ e = dev->procent = create_proc_entry(name, S_IFREG | S_IRUGO, de);
+ if (!e)
+ return -ENOMEM;
+ e->proc_fops = &isapnp_proc_bus_file_operations;
+ e->owner = THIS_MODULE;
+ e->data = dev;
+ e->size = 256;
+ return 0;
+}
+
+#ifdef MODULE
+static int __exit isapnp_proc_detach_device(struct pnp_dev *dev)
+{
+ struct pnp_card *bus = dev->card;
+ struct proc_dir_entry *de;
+ char name[16];
+
+ if (!(de = bus->procdir))
+ return -EINVAL;
+ sprintf(name, "%02x", dev->number);
+ remove_proc_entry(name, de);
+ return 0;
+}
+
+static int __exit isapnp_proc_detach_bus(struct pnp_card *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 /* MODULE */
+
+int __init isapnp_proc_init(void)
+{
+ struct pnp_dev *dev;
+ isapnp_proc_bus_dir = proc_mkdir("isapnp", proc_bus);
+ isapnp_for_each_dev(dev) {
+ isapnp_proc_attach_device(dev);
+ }
+ return 0;
+}
+
+#ifdef MODULE
+int __exit isapnp_proc_done(void)
+{
+ struct pnp_dev *dev;
+ struct pnp_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_bus_dir)
+ remove_proc_entry("isapnp", proc_bus);
+ return 0;
+}
+#endif /* MODULE */
diff -ur --new-file --exclude *.flags a/include/linux/isapnp.h b/include/linux/isapnp.h
--- a/include/linux/isapnp.h Mon Oct 14 21:18:32 2002
+++ b/include/linux/isapnp.h Mon Oct 14 19:29:17 2002
@@ -220,11 +220,12 @@

extern struct list_head isapnp_cards;
extern struct list_head isapnp_devices;
+extern struct pnp_protocol isapnp_protocol;

#define isapnp_for_each_card(card) \
for(card = to_pnp_card(isapnp_cards.next); card != to_pnp_card(&isapnp_cards); card = to_pnp_card(card->node.next))
#define isapnp_for_each_dev(dev) \
- for(dev = pci_dev_g(isapnp_devices.next); dev != pci_dev_g(&isapnp_devices); dev = pci_dev_g(dev->global_list.next))
+ for(dev = protocol_to_pnp_dev(isapnp_protocol.devices.next); dev != protocol_to_pnp_dev(&isapnp_protocol.devices); dev = protocol_to_pnp_dev(dev->dev_list.next))

#else /* !CONFIG_ISAPNP */

diff -ur --new-file --exclude *.flags a/include/linux/pnp.h b/include/linux/pnp.h
--- a/include/linux/pnp.h Mon Oct 14 21:18:32 2002
+++ b/include/linux/pnp.h Mon Oct 14 19:23:34 2002
@@ -26,6 +26,7 @@
unsigned char productver; /* product version */
unsigned int serial; /* serial number */
unsigned char checksum; /* if zero - checksum passed */
+ struct proc_dir_entry *procdir; /* directory entry in /proc/bus/isapnp */
};

#define to_pnp_card(n) list_entry(n, struct pnp_card, node)
@@ -52,10 +53,12 @@
struct device dev; /* Driver Model device interface */
void * driver_data;/* data private to the driver */
void * protocol_data;
+ struct proc_dir_entry *procent; /* device entry in /proc/bus/isapnp */
};

#define global_to_pnp_dev(n) list_entry(n, struct pnp_dev, global_list)
#define card_to_pnp_dev(n) list_entry(n, struct pnp_dev, card_list)
+#define protocol_to_pnp_dev(n) list_entry(n, struct pnp_dev, dev_list)
#define to_pnp_dev(n) container_of(n, struct pnp_dev, dev)
#define pnp_for_each_dev(dev) \
for(dev = global_to_pnp_dev(pnp_global.next); \

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/