aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pcmcia/rsrc_mgr.c
diff options
context:
space:
mode:
authorDominik Brodowski <linux@dominikbrodowski.net>2005-12-07 06:32:20 -0500
committerDominik Brodowski <linux@dominikbrodowski.net>2006-01-05 18:27:43 -0500
commit3b27e9421a1433689704fe0a02e926d4ba971121 (patch)
treec3ca9e3e929da1c48ce5d8e9fa6d0257b5b900f5 /drivers/pcmcia/rsrc_mgr.c
parentefe3cd105f2a19e72ce9280bb22c7c80752e4314 (diff)
[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 m68k 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@dominikbrodowski.net>
Diffstat (limited to 'drivers/pcmcia/rsrc_mgr.c')
-rw-r--r--drivers/pcmcia/rsrc_mgr.c102
1 files changed, 102 insertions, 0 deletions
diff --git a/drivers/pcmcia/rsrc_mgr.c b/drivers/pcmcia/rsrc_mgr.c
index b02598a5a912..514609369836 100644
--- a/drivers/pcmcia/rsrc_mgr.c
+++ b/drivers/pcmcia/rsrc_mgr.c
@@ -166,3 +166,105 @@ struct pccard_resource_ops pccard_static_ops = {
166 .exit = NULL, 166 .exit = NULL,
167}; 167};
168EXPORT_SYMBOL(pccard_static_ops); 168EXPORT_SYMBOL(pccard_static_ops);
169
170
171#ifdef CONFIG_PCCARD_IODYN
172
173static struct resource *
174make_resource(unsigned long b, unsigned long n, int flags, char *name)
175{
176 struct resource *res = kzalloc(sizeof(*res), GFP_KERNEL);
177
178 if (res) {
179 res->name = name;
180 res->start = b;
181 res->end = b + n - 1;
182 res->flags = flags;
183 }
184 return res;
185}
186
187struct pcmcia_align_data {
188 unsigned long mask;
189 unsigned long offset;
190};
191
192static void pcmcia_align(void *align_data, struct resource *res,
193 unsigned long size, unsigned long align)
194{
195 struct pcmcia_align_data *data = align_data;
196 unsigned long start;
197
198 start = (res->start & ~data->mask) + data->offset;
199 if (start < res->start)
200 start += data->mask + 1;
201 res->start = start;
202
203#ifdef CONFIG_X86
204 if (res->flags & IORESOURCE_IO) {
205 if (start & 0x300) {
206 start = (start + 0x3ff) & ~0x3ff;
207 res->start = start;
208 }
209 }
210#endif
211
212#ifdef CONFIG_M68K
213 if (res->flags & IORESOURCE_IO) {
214 if ((res->start + size - 1) >= 1024)
215 res->start = res->end;
216 }
217#endif
218}
219
220
221static int iodyn_adjust_io_region(struct resource *res, unsigned long r_start,
222 unsigned long r_end, struct pcmcia_socket *s)
223{
224 return adjust_resource(res, r_start, r_end - r_start + 1);
225}
226
227
228static struct resource *iodyn_find_io_region(unsigned long base, int num,
229 unsigned long align, struct pcmcia_socket *s)
230{
231 struct resource *res = make_resource(0, num, IORESOURCE_IO,
232 s->dev.class_id);
233 struct pcmcia_align_data data;
234 unsigned long min = base;
235 int ret;
236
237 if (align == 0)
238 align = 0x10000;
239
240 data.mask = align - 1;
241 data.offset = base & data.mask;
242
243#ifdef CONFIG_PCI
244 if (s->cb_dev) {
245 ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num, 1,
246 min, 0, pcmcia_align, &data);
247 } else
248#endif
249 ret = allocate_resource(&ioport_resource, res, num, min, ~0UL,
250 1, pcmcia_align, &data);
251
252 if (ret != 0) {
253 kfree(res);
254 res = NULL;
255 }
256 return res;
257}
258
259struct pccard_resource_ops pccard_iodyn_ops = {
260 .validate_mem = NULL,
261 .adjust_io_region = iodyn_adjust_io_region,
262 .find_io = iodyn_find_io_region,
263 .find_mem = NULL,
264 .adjust_resource = NULL,
265 .init = static_init,
266 .exit = NULL,
267};
268EXPORT_SYMBOL(pccard_iodyn_ops);
269
270#endif /* CONFIG_PCCARD_IODYN */