diff options
author | Dominik Brodowski <linux@dominikbrodowski.net> | 2010-03-07 16:41:57 +0100 |
---|---|---|
committer | Dominik Brodowski <linux@dominikbrodowski.net> | 2010-05-10 10:23:18 +0200 |
commit | 49b1153adfe18a3cce7e70aa26c690f275917cd0 (patch) | |
tree | d165a9bfaacd5be3da0bce12e6fe1126ce21118d /drivers/pcmcia/rsrc_iodyn.c | |
parent | 5c128e84324ca9389bc5f7d39f6b18f6de4a58ec (diff) |
pcmcia: move all pcmcia_resource_ops providers into one module
Signed-off-by: Dominik Brodowski <linux@dominikbrodowski.net>
Diffstat (limited to 'drivers/pcmcia/rsrc_iodyn.c')
-rw-r--r-- | drivers/pcmcia/rsrc_iodyn.c | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/drivers/pcmcia/rsrc_iodyn.c b/drivers/pcmcia/rsrc_iodyn.c new file mode 100644 index 00000000000..3fa808b582f --- /dev/null +++ b/drivers/pcmcia/rsrc_iodyn.c @@ -0,0 +1,107 @@ +/* + * rsrc_iodyn.c -- Resource management routines for MEM-static sockets. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * The initial developer of the original code is David A. Hinds + * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds + * are Copyright (C) 1999 David A. Hinds. All Rights Reserved. + * + * (C) 1999 David A. Hinds + */ + +#include <linux/module.h> +#include <linux/kernel.h> + +#include <pcmcia/cs_types.h> +#include <pcmcia/ss.h> +#include <pcmcia/cs.h> +#include <pcmcia/cistpl.h> +#include "cs_internal.h" + + +struct pcmcia_align_data { + unsigned long mask; + unsigned long offset; +}; + +static resource_size_t pcmcia_align(void *align_data, + const struct resource *res, + resource_size_t size, resource_size_t align) +{ + struct pcmcia_align_data *data = align_data; + resource_size_t start; + + start = (res->start & ~data->mask) + data->offset; + if (start < res->start) + start += data->mask + 1; + +#ifdef CONFIG_X86 + if (res->flags & IORESOURCE_IO) { + if (start & 0x300) + start = (start + 0x3ff) & ~0x3ff; + } +#endif + +#ifdef CONFIG_M68K + if (res->flags & IORESOURCE_IO) { + if ((res->start + size - 1) >= 1024) + start = res->end; + } +#endif + + return start; +} + + +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 = pcmcia_make_resource(0, num, IORESOURCE_IO, + dev_name(&s->dev)); + 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, + .add_io = NULL, + .add_mem = NULL, + .init = static_init, + .exit = NULL, +}; +EXPORT_SYMBOL(pccard_iodyn_ops); |