1 #include <linux/slab.h>
2 #include <linux/module.h>
3 #include <linux/kernel.h>
7 #include <pcmcia/cistpl.h>
8 #include "cs_internal.h"
11 struct pcmcia_align_data {
16 static resource_size_t pcmcia_align(void *align_data,
17 const struct resource *res,
18 resource_size_t size, resource_size_t align)
20 struct pcmcia_align_data *data = align_data;
21 resource_size_t start;
23 start = (res->start & ~data->mask) + data->offset;
24 if (start < res->start)
25 start += data->mask + 1;
29 static struct resource *find_io_region(struct pcmcia_socket *s,
30 unsigned long base, int num,
33 struct resource *res = pcmcia_make_resource(0, num, IORESOURCE_IO,
35 struct pcmcia_align_data data;
38 data.mask = align - 1;
39 data.offset = base & data.mask;
41 ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num, 1,
42 base, 0, pcmcia_align, &data);
50 static int res_pci_find_io(struct pcmcia_socket *s, unsigned int attr,
51 unsigned int *base, unsigned int num,
52 unsigned int align, struct resource **parent)
56 /* Check for an already-allocated window that must conflict with
57 * what was asked for. It is a hack because it does not catch all
58 * potential conflicts, just the most obvious ones.
60 for (i = 0; i < MAX_IO_WIN; i++) {
67 if ((s->io[i].res->start & (align-1)) == *base)
71 for (i = 0; i < MAX_IO_WIN; i++) {
72 struct resource *res = s->io[i].res;
75 if (res && (res->flags & IORESOURCE_BITS) !=
76 (attr & IORESOURCE_BITS))
83 res = s->io[i].res = find_io_region(s, *base, num,
90 ((res->flags & ~IORESOURCE_BITS) |
91 (attr & IORESOURCE_BITS));
97 /* Try to extend top of window */
99 if ((*base == 0) || (*base == try)) {
100 ret = adjust_resource(s->io[i].res, res->start,
101 resource_size(res) + num);
105 s->io[i].InUse += num;
110 /* Try to extend bottom of window */
111 try = res->start - num;
112 if ((*base == 0) || (*base == try)) {
113 ret = adjust_resource(s->io[i].res,
115 resource_size(res) + num);
119 s->io[i].InUse += num;
127 static struct resource *res_pci_find_mem(u_long base, u_long num,
128 u_long align, int low, struct pcmcia_socket *s)
130 struct resource *res = pcmcia_make_resource(0, num, IORESOURCE_MEM,
132 struct pcmcia_align_data data;
138 data.mask = align - 1;
139 data.offset = base & data.mask;
145 ret = pci_bus_alloc_resource(s->cb_dev->bus,
147 pcmcia_align, &data);
157 static int res_pci_init(struct pcmcia_socket *s)
159 if (!s->cb_dev || !(s->features & SS_CAP_PAGE_REGS)) {
160 dev_err(&s->dev, "not supported by res_pci\n");
166 struct pccard_resource_ops pccard_nonstatic_ops = {
167 .validate_mem = NULL,
168 .find_io = res_pci_find_io,
169 .find_mem = res_pci_find_mem,
170 .init = res_pci_init,
173 EXPORT_SYMBOL(pccard_nonstatic_ops);