[review] [PATCH] pcmcia: properly handle static mem, but dynamic io sockets

Dominik Brodowski linux at dominikbrodowski.net
Wed Dec 7 06:28:48 EST 2005


Hi,

If nothing major with this patch shows up, I'll add it to the queue for
2.6.16. Both m68k and ppc are waiting for it :)

Thanks,
	Dominik


[PATCH] pcmcia: properly handle static mem, but dynamic io sockets

Some PCMCIA sockets have statically mapped memory windows, but dynamically
mapped IO windows. Using the "nonstatic" socket library is inpractical for
them, as they do neither need a resource database (as we can trust the
kernel resource database on m68x and ppc) nor lots of other features of that
library. Let them get a small "iodyn" socket library (105 lines of code)
instead.

Signed-off-by: Dominik Brodowski <linux at dominikbrodowski.net>

Index: working-tree/drivers/pcmcia/Kconfig
===================================================================
--- working-tree.orig/drivers/pcmcia/Kconfig
+++ working-tree/drivers/pcmcia/Kconfig
@@ -182,7 +182,7 @@ config TCIC
 config PCMCIA_M8XX
         tristate "MPC8xx PCMCIA support"
         depends on PCMCIA && PPC && 8xx 
-        select PCCARD_NONSTATIC
+        select PCCARD_IODYN
         help
         Say Y here to include support for PowerPC 8xx series PCMCIA
         controller.
@@ -266,6 +266,9 @@ config OMAP_CF
 config PCCARD_NONSTATIC
 	tristate
 
+config PCCARD_IODYN
+	bool
+
 endif	# PCCARD
 
 endmenu
Index: working-tree/drivers/pcmcia/m8xx_pcmcia.c
===================================================================
--- working-tree.orig/drivers/pcmcia/m8xx_pcmcia.c
+++ working-tree/drivers/pcmcia/m8xx_pcmcia.c
@@ -1232,7 +1232,7 @@ static int __init m8xx_init(void)
 		socket[i].socket.io_offset = 0;
 		socket[i].socket.pci_irq = i  ? 7 : 9;
 		socket[i].socket.ops = &m8xx_services;
-		socket[i].socket.resource_ops = &pccard_nonstatic_ops;
+		socket[i].socket.resource_ops = &pccard_iodyn_ops;
 		socket[i].socket.cb_dev = NULL;
 		socket[i].socket.dev.dev = &m8xx_device.dev;
 	}
Index: working-tree/drivers/pcmcia/rsrc_mgr.c
===================================================================
--- working-tree.orig/drivers/pcmcia/rsrc_mgr.c
+++ working-tree/drivers/pcmcia/rsrc_mgr.c
@@ -166,3 +166,105 @@ struct pccard_resource_ops pccard_static
 	.exit = NULL,
 };
 EXPORT_SYMBOL(pccard_static_ops);
+
+
+#ifdef CONFIG_PCCARD_IODYN
+
+static struct resource *
+make_resource(unsigned long b, unsigned long n, int flags, char *name)
+{
+	struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL);
+
+	if (res) {
+		res->name = name;
+		res->start = b;
+		res->end = b + n - 1;
+		res->flags = flags;
+	}
+	return res;
+}
+
+struct pcmcia_align_data {
+	unsigned long	mask;
+	unsigned long	offset;
+};
+
+static void pcmcia_align(void *align_data, struct resource *res,
+			unsigned long size, unsigned long align)
+{
+	struct pcmcia_align_data *data = align_data;
+	unsigned long start;
+
+	start = (res->start & ~data->mask) + data->offset;
+	if (start < res->start)
+		start += data->mask + 1;
+	res->start = start;
+
+#ifdef CONFIG_X86
+        if (res->flags & IORESOURCE_IO) {
+                if (start & 0x300) {
+                        start = (start + 0x3ff) & ~0x3ff;
+                        res->start = start;
+                }
+        }
+#endif
+
+#ifdef CONFIG_M68K
+        if (res->flags & IORESOURCE_IO) {
+		if ((res->start + size - 1) >= 1024)
+			res->start = res->end;
+	}
+#endif
+}
+
+
+static int iodyn_adjust_io_region(struct resource *res, unsigned long r_start,
+				      unsigned long r_end, struct pcmcia_socket *s)
+{
+	return adjust_resource(res, r_start, r_end - r_start + 1);
+}
+
+
+static struct resource *iodyn_find_io_region(unsigned long base, int num,
+		unsigned long align, struct pcmcia_socket *s)
+{
+	struct resource *res = make_resource(0, num, IORESOURCE_IO,
+					     s->dev.class_id);
+	struct pcmcia_align_data data;
+	unsigned long min = base;
+	int ret;
+
+	if (align == 0)
+		align = 0x10000;
+
+	data.mask = align - 1;
+	data.offset = base & data.mask;
+
+#ifdef CONFIG_PCI
+	if (s->cb_dev) {
+		ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num, 1,
+					     min, 0, pcmcia_align, &data);
+	} else
+#endif
+		ret = allocate_resource(&ioport_resource, res, num, min, ~0UL,
+					1, pcmcia_align, &data);
+
+	if (ret != 0) {
+		kfree(res);
+		res = NULL;
+	}
+	return res;
+}
+
+struct pccard_resource_ops pccard_iodyn_ops = {
+	.validate_mem = NULL,
+	.adjust_io_region = iodyn_adjust_io_region,
+	.find_io = iodyn_find_io_region,
+	.find_mem = NULL,
+	.adjust_resource = NULL,
+	.init = static_init,
+	.exit = NULL,
+};
+EXPORT_SYMBOL(pccard_iodyn_ops);
+
+#endif /* CONFIG_PCCARD_IODYN */



More information about the linux-pcmcia mailing list