[PATCH 2.5] pcmcia: alternative setting of resources

From: Dominik Brodowski (linux@brodo.de)
Date: Sat Mar 29 2003 - 11:19:21 EST


With cardmgr being deprecated soon, there's a need for a different way to
set the iomem/ioport/irq resources the PCMCIA drivers (and the PCMCIA core
service) may use.

A sample new-style /etc/rc.d/pcmcia file which is based on
pcmcia-cs-3.2.3/etc/config.opts is attached. Don't rely on it yet, in-kernel
driver & device matching and hotplug support is not yet ready but will
follow soon.

        Dominik

 ds.c | 160 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 rsrc_mgr.c | 3 -
 2 files changed, 160 insertions(+), 3 deletions(-)

diff -ruN linux-original/drivers/pcmcia/ds.c linux/drivers/pcmcia/ds.c
--- linux-original/drivers/pcmcia/ds.c 2003-03-29 15:41:01.000000000 +0100
+++ linux/drivers/pcmcia/ds.c 2003-03-29 16:38:23.000000000 +0100
@@ -1213,12 +1213,171 @@
 EXPORT_SYMBOL(pcmcia_bus_type);
 
 
+#define add_MANAGED_RESOURCE ADD_MANAGED_RESOURCE
+#define remove_MANAGED_RESOURCE REMOVE_MANAGED_RESOURCE
+
+#define store_iomem(action) \
+static ssize_t store_iomem_##action (const char *buf, size_t count) \
+{ \
+ ssize_t ret = -EINVAL; \
+ unsigned long from, to; \
+ adjust_t adj; \
+ \
+ ret = sscanf (buf, "0x%lx-0x%lx", &from, &to); \
+ if (ret != 2) \
+ return -EINVAL; \
+ \
+ if (to <= from) \
+ return -EINVAL; \
+ \
+ adj.Action = action##_MANAGED_RESOURCE; \
+ adj.Resource = RES_MEMORY_RANGE; \
+ adj.resource.memory.Base = from; \
+ adj.resource.memory.Size = to - from + 1; \
+ \
+ ret = pcmcia_adjust_resource_info(0, &adj); \
+ \
+ return ret ? ret : count; \
+}
+store_iomem(add);
+store_iomem(remove);
+
+#define store_ioport(action) \
+static ssize_t store_ioport_##action (const char *buf, size_t count) \
+{ \
+ ssize_t ret = -EINVAL; \
+ unsigned int from, to, addr_lines; \
+ adjust_t adj; \
+ \
+ ret = sscanf (buf, "0x%x-0x%x:0x%x", &from, &to, &addr_lines); \
+ if ((ret != 2) && (ret != 3)) \
+ return -EINVAL; \
+ \
+ if ((to <= from) || ( to > 0xffff)) \
+ return -EINVAL; \
+ \
+ adj.Action = action##_MANAGED_RESOURCE; \
+ adj.Resource = RES_IO_RANGE; \
+ adj.resource.io.BasePort = from; \
+ adj.resource.io.NumPorts = to - from + 1; \
+ if (ret == 3) \
+ adj.resource.io.IOAddrLines = addr_lines; \
+ else \
+ adj.resource.io.IOAddrLines = 0; \
+ \
+ ret = pcmcia_adjust_resource_info(0, &adj); \
+ \
+ return ret ? ret : count; \
+}
+store_ioport(add);
+store_ioport(remove);
+
+#define store_irq(action) \
+static ssize_t store_irq_##action (const char *buf, size_t count) \
+{ \
+ ssize_t ret = -EINVAL; \
+ unsigned int irq, attr; \
+ adjust_t adj; \
+ \
+ ret = sscanf (buf, "0x%u:0x%x", &irq, &attr); \
+ if ((ret != 1) && (ret != 2)) \
+ return -EINVAL; \
+ \
+ adj.Action = action##_MANAGED_RESOURCE; \
+ adj.Resource = RES_IRQ; \
+ adj.resource.irq.IRQ = irq; \
+ if (ret == 2) \
+ adj.Attributes = attr; \
+ else \
+ adj.Attributes = 0; \
+ \
+ ret = pcmcia_adjust_resource_info(0, &adj); \
+ \
+ return ret ? ret : count; \
+}
+store_irq(add);
+store_irq(remove);
+
+static ssize_t store_resources_done (const char * buf, size_t count)
+{
+ ssize_t ret = -EINVAL;
+ unsigned int value;
+
+ ret = sscanf (buf, "%u", &value);
+ if ((ret != 1) || (value > 1))
+ return -EINVAL;
+ if (value == resources_available)
+ return count;
+ resources_available = value;
+ pcmcia_rescan_cards();
+ return count;
+}
+
+struct res_attr {
+ struct attribute attr;
+ ssize_t (*store)(const char *, size_t count);
+};
+
+#define define_one_w(_name) \
+struct res_attr _name = { \
+ .attr = { .name = __stringify(_name), .mode = 0200 }, \
+ .store = store_##_name, \
+}
+define_one_w(iomem_add);
+define_one_w(iomem_remove);
+define_one_w(ioport_add);
+define_one_w(ioport_remove);
+define_one_w(irq_add);
+define_one_w(irq_remove);
+define_one_w(resources_done);
+
+static struct attribute * default_attrs[] = {
+ &iomem_add.attr,
+ &iomem_remove.attr,
+ &ioport_add.attr,
+ &ioport_remove.attr,
+ &irq_add.attr,
+ &irq_remove.attr,
+ &resources_done.attr,
+ NULL
+};
+
+static ssize_t show(struct kobject * kobj, struct attribute * attr ,char * buf)
+{
+ return 0;
+}
+
+static ssize_t store(struct kobject * kobj, struct attribute * attr,
+ const char * buf, size_t count)
+{
+ struct res_attr * rattr = container_of(attr, struct res_attr, attr);
+ rattr->store ? rattr->store(buf,count) : 0;
+ return count;
+}
+
+static struct sysfs_ops sysfs_ops = {
+ .show = show,
+ .store = store,
+};
+
+static struct kobj_type ktype_pcmcia_resources = {
+ .sysfs_ops = &sysfs_ops,
+ .default_attrs = default_attrs,
+};
+
+static struct kobject pcmcia_resource_kobj = {
+ .name = "resources",
+ .parent = &pcmcia_bus_type.subsys.kset.kobj,
+ .ktype = &ktype_pcmcia_resources,
+};
+
 static int __init init_pcmcia_bus(void)
 {
         int i;
 
         bus_register(&pcmcia_bus_type);
         interface_register(&pcmcia_bus_interface);
+ kobject_register(&pcmcia_resource_kobj);
 
         /* Set up character device for user mode clients */
         i = register_chrdev(0, "pcmcia", &ds_fops);
@@ -1241,6 +1400,7 @@
 
 static void __exit exit_pcmcia_bus(void)
 {
+ kobject_unregister(&pcmcia_resource_kobj);
         interface_unregister(&pcmcia_bus_interface);
 
 #ifdef CONFIG_PROC_FS
diff -ruN linux-original/drivers/pcmcia/rsrc_mgr.c linux/drivers/pcmcia/rsrc_mgr.c
--- linux-original/drivers/pcmcia/rsrc_mgr.c 2003-03-29 15:16:03.000000000 +0100
+++ linux/drivers/pcmcia/rsrc_mgr.c 2003-03-29 16:38:23.000000000 +0100
@@ -848,9 +848,6 @@
 
 int pcmcia_adjust_resource_info(client_handle_t handle, adjust_t *adj)
 {
- if (CHECK_HANDLE(handle))
- return CS_BAD_HANDLE;
-
     switch (adj->Resource) {
     case RES_MEMORY_RANGE:
         return adjust_memory(adj);



-
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/



This archive was generated by hypermail 2b29 : Mon Mar 31 2003 - 22:00:34 EST