]> bbs.cooldavid.org Git - net-next-2.6.git/blame - drivers/pcmcia/rsrc_nonstatic.c
pcmcia: move all pcmcia_resource_ops providers into one module
[net-next-2.6.git] / drivers / pcmcia / rsrc_nonstatic.c
CommitLineData
1da177e4
LT
1/*
2 * rsrc_nonstatic.c -- Resource management routines for !SS_CAP_STATIC_MAP sockets
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * The initial developer of the original code is David A. Hinds
9 * <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
10 * are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
11 *
12 * (C) 1999 David A. Hinds
13 */
14
1da177e4
LT
15#include <linux/module.h>
16#include <linux/moduleparam.h>
17#include <linux/init.h>
18#include <linux/interrupt.h>
19#include <linux/kernel.h>
20#include <linux/errno.h>
21#include <linux/types.h>
22#include <linux/slab.h>
23#include <linux/ioport.h>
24#include <linux/timer.h>
25#include <linux/pci.h>
26#include <linux/device.h>
9fea84f4 27#include <linux/io.h>
1da177e4
LT
28
29#include <asm/irq.h>
1da177e4
LT
30
31#include <pcmcia/cs_types.h>
32#include <pcmcia/ss.h>
33#include <pcmcia/cs.h>
1da177e4
LT
34#include <pcmcia/cistpl.h>
35#include "cs_internal.h"
36
49b1153a 37/* moved to rsrc_mgr.c
1da177e4
LT
38MODULE_AUTHOR("David A. Hinds, Dominik Brodowski");
39MODULE_LICENSE("GPL");
49b1153a 40*/
1da177e4
LT
41
42/* Parameters that can be set with 'insmod' */
43
44#define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0444)
45
46INT_MODULE_PARM(probe_mem, 1); /* memory probe? */
47#ifdef CONFIG_PCMCIA_PROBE
48INT_MODULE_PARM(probe_io, 1); /* IO port probe? */
49INT_MODULE_PARM(mem_limit, 0x10000);
50#endif
51
52/* for io_db and mem_db */
53struct resource_map {
54 u_long base, num;
55 struct resource_map *next;
56};
57
58struct socket_data {
59 struct resource_map mem_db;
7b4884ca 60 struct resource_map mem_db_valid;
1da177e4 61 struct resource_map io_db;
1da177e4
LT
62};
63
1da177e4
LT
64#define MEM_PROBE_LOW (1 << 0)
65#define MEM_PROBE_HIGH (1 << 1)
66
67
68/*======================================================================
69
70 Linux resource management extensions
71
72======================================================================*/
73
1da177e4 74static struct resource *
2427ddd8
GKH
75claim_region(struct pcmcia_socket *s, resource_size_t base,
76 resource_size_t size, int type, char *name)
1da177e4
LT
77{
78 struct resource *res, *parent;
79
80 parent = type & IORESOURCE_MEM ? &iomem_resource : &ioport_resource;
49b1153a 81 res = pcmcia_make_resource(base, size, type | IORESOURCE_BUSY, name);
1da177e4
LT
82
83 if (res) {
84#ifdef CONFIG_PCI
85 if (s && s->cb_dev)
86 parent = pci_find_parent_resource(s->cb_dev, res);
87#endif
88 if (!parent || request_resource(parent, res)) {
89 kfree(res);
90 res = NULL;
91 }
92 }
93 return res;
94}
95
96static void free_region(struct resource *res)
97{
98 if (res) {
99 release_resource(res);
100 kfree(res);
101 }
102}
103
104/*======================================================================
105
106 These manage the internal databases of available resources.
107
108======================================================================*/
109
110static int add_interval(struct resource_map *map, u_long base, u_long num)
111{
1168386a 112 struct resource_map *p, *q;
1da177e4 113
1168386a 114 for (p = map; ; p = p->next) {
f309cb3e
DB
115 if ((p != map) && (p->base+p->num >= base)) {
116 p->num = max(num + base - p->base, p->num);
117 return 0;
118 }
1168386a
DB
119 if ((p->next == map) || (p->next->base > base+num-1))
120 break;
121 }
122 q = kmalloc(sizeof(struct resource_map), GFP_KERNEL);
123 if (!q) {
124 printk(KERN_WARNING "out of memory to update resources\n");
125 return -ENOMEM;
126 }
127 q->base = base; q->num = num;
128 q->next = p->next; p->next = q;
129 return 0;
1da177e4
LT
130}
131
132/*====================================================================*/
133
134static int sub_interval(struct resource_map *map, u_long base, u_long num)
135{
9fea84f4
DB
136 struct resource_map *p, *q;
137
138 for (p = map; ; p = q) {
139 q = p->next;
140 if (q == map)
141 break;
142 if ((q->base+q->num > base) && (base+num > q->base)) {
143 if (q->base >= base) {
144 if (q->base+q->num <= base+num) {
145 /* Delete whole block */
146 p->next = q->next;
147 kfree(q);
148 /* don't advance the pointer yet */
149 q = p;
150 } else {
151 /* Cut off bit from the front */
152 q->num = q->base + q->num - base - num;
153 q->base = base + num;
154 }
155 } else if (q->base+q->num <= base+num) {
156 /* Cut off bit from the end */
157 q->num = base - q->base;
158 } else {
159 /* Split the block into two pieces */
160 p = kmalloc(sizeof(struct resource_map),
161 GFP_KERNEL);
162 if (!p) {
163 printk(KERN_WARNING "out of memory to update resources\n");
164 return -ENOMEM;
165 }
166 p->base = base+num;
167 p->num = q->base+q->num - p->base;
168 q->num = base - q->base;
169 p->next = q->next ; q->next = p;
170 }
1168386a 171 }
9fea84f4
DB
172 }
173 return 0;
1da177e4
LT
174}
175
176/*======================================================================
177
178 These routines examine a region of IO or memory addresses to
179 determine what ranges might be genuinely available.
180
181======================================================================*/
182
183#ifdef CONFIG_PCMCIA_PROBE
906da809
OJ
184static void do_io_probe(struct pcmcia_socket *s, unsigned int base,
185 unsigned int num)
1da177e4 186{
9fea84f4
DB
187 struct resource *res;
188 struct socket_data *s_data = s->resource_data;
189 unsigned int i, j, bad;
190 int any;
191 u_char *b, hole, most;
192
193 dev_printk(KERN_INFO, &s->dev, "cs: IO port probe %#x-%#x:",
194 base, base+num-1);
195
196 /* First, what does a floating port look like? */
197 b = kzalloc(256, GFP_KERNEL);
198 if (!b) {
199 printk("\n");
200 dev_printk(KERN_ERR, &s->dev,
201 "do_io_probe: unable to kmalloc 256 bytes");
202 return;
203 }
204 for (i = base, most = 0; i < base+num; i += 8) {
509b0865 205 res = claim_region(s, i, 8, IORESOURCE_IO, "PCMCIA ioprobe");
9fea84f4
DB
206 if (!res)
207 continue;
208 hole = inb(i);
209 for (j = 1; j < 8; j++)
210 if (inb(i+j) != hole)
211 break;
212 free_region(res);
213 if ((j == 8) && (++b[hole] > b[most]))
214 most = hole;
215 if (b[most] == 127)
216 break;
217 }
218 kfree(b);
219
220 bad = any = 0;
221 for (i = base; i < base+num; i += 8) {
509b0865
DB
222 res = claim_region(s, i, 8, IORESOURCE_IO, "PCMCIA ioprobe");
223 if (!res) {
224 if (!any)
225 printk(" excluding");
226 if (!bad)
227 bad = any = i;
9fea84f4 228 continue;
509b0865 229 }
9fea84f4
DB
230 for (j = 0; j < 8; j++)
231 if (inb(i+j) != most)
232 break;
233 free_region(res);
234 if (j < 8) {
235 if (!any)
236 printk(" excluding");
237 if (!bad)
238 bad = any = i;
239 } else {
240 if (bad) {
241 sub_interval(&s_data->io_db, bad, i-bad);
242 printk(" %#x-%#x", bad, i-1);
243 bad = 0;
244 }
245 }
246 }
247 if (bad) {
248 if ((num > 16) && (bad == base) && (i == base+num)) {
509b0865 249 sub_interval(&s_data->io_db, bad, i-bad);
9fea84f4
DB
250 printk(" nothing: probe failed.\n");
251 return;
252 } else {
253 sub_interval(&s_data->io_db, bad, i-bad);
254 printk(" %#x-%#x", bad, i-1);
255 }
256 }
257
258 printk(any ? "\n" : " clean.\n");
1da177e4
LT
259}
260#endif
261
3f32b3c0 262/*======================================================================*/
1da177e4 263
3f32b3c0
DB
264/**
265 * readable() - iomem validation function for cards with a valid CIS
266 */
c5081d5f
DB
267static int readable(struct pcmcia_socket *s, struct resource *res,
268 unsigned int *count)
1da177e4 269{
3f32b3c0 270 int ret = -EINVAL;
1da177e4 271
7ab24855
DB
272 if (s->fake_cis) {
273 dev_dbg(&s->dev, "fake CIS is being used: can't validate mem\n");
274 return 0;
275 }
1da177e4
LT
276
277 s->cis_mem.res = res;
278 s->cis_virt = ioremap(res->start, s->map_size);
279 if (s->cis_virt) {
6b8e087b 280 mutex_unlock(&s->ops_mutex);
6e7b51a7
DB
281 /* as we're only called from pcmcia.c, we're safe */
282 if (s->callback->validate)
283 ret = s->callback->validate(s, count);
904e3777 284 /* invalidate mapping */
6b8e087b 285 mutex_lock(&s->ops_mutex);
1da177e4
LT
286 iounmap(s->cis_virt);
287 s->cis_virt = NULL;
1da177e4
LT
288 }
289 s->cis_mem.res = NULL;
3f32b3c0
DB
290 if ((ret) || (*count == 0))
291 return -EINVAL;
292 return 0;
1da177e4
LT
293}
294
3f32b3c0
DB
295/**
296 * checksum() - iomem validation function for simple memory cards
297 */
298static int checksum(struct pcmcia_socket *s, struct resource *res,
299 unsigned int *value)
1da177e4
LT
300{
301 pccard_mem_map map;
302 int i, a = 0, b = -1, d;
303 void __iomem *virt;
304
305 virt = ioremap(res->start, s->map_size);
306 if (virt) {
307 map.map = 0;
308 map.flags = MAP_ACTIVE;
309 map.speed = 0;
310 map.res = res;
311 map.card_start = 0;
312 s->ops->set_mem_map(s, &map);
313
314 /* Don't bother checking every word... */
315 for (i = 0; i < s->map_size; i += 44) {
316 d = readl(virt+i);
317 a += d;
318 b &= d;
319 }
320
321 map.flags = 0;
322 s->ops->set_mem_map(s, &map);
323
324 iounmap(virt);
325 }
326
3f32b3c0
DB
327 if (b == -1)
328 return -EINVAL;
1da177e4 329
3f32b3c0 330 *value = a;
1da177e4 331
3f32b3c0 332 return 0;
1da177e4
LT
333}
334
3f32b3c0
DB
335/**
336 * do_validate_mem() - low level validate a memory region for PCMCIA use
337 * @s: PCMCIA socket to validate
338 * @base: start address of resource to check
339 * @size: size of resource to check
340 * @validate: validation function to use
341 *
342 * do_validate_mem() splits up the memory region which is to be checked
343 * into two parts. Both are passed to the @validate() function. If
344 * @validate() returns non-zero, or the value parameter to @validate()
345 * is zero, or the value parameter is different between both calls,
346 * the check fails, and -EINVAL is returned. Else, 0 is returned.
347 */
348static int do_validate_mem(struct pcmcia_socket *s,
349 unsigned long base, unsigned long size,
350 int validate (struct pcmcia_socket *s,
351 struct resource *res,
352 unsigned int *value))
1da177e4 353{
7b4884ca 354 struct socket_data *s_data = s->resource_data;
1da177e4 355 struct resource *res1, *res2;
3f32b3c0
DB
356 unsigned int info1 = 1, info2 = 1;
357 int ret = -EINVAL;
1da177e4 358
9fea84f4
DB
359 res1 = claim_region(s, base, size/2, IORESOURCE_MEM, "PCMCIA memprobe");
360 res2 = claim_region(s, base + size/2, size/2, IORESOURCE_MEM,
361 "PCMCIA memprobe");
1da177e4
LT
362
363 if (res1 && res2) {
3f32b3c0
DB
364 ret = 0;
365 if (validate) {
366 ret = validate(s, res1, &info1);
367 ret += validate(s, res2, &info2);
368 }
1da177e4
LT
369 }
370
371 free_region(res2);
372 free_region(res1);
373
3f32b3c0
DB
374 dev_dbg(&s->dev, "cs: memory probe 0x%06lx-0x%06lx: %p %p %u %u %u",
375 base, base+size-1, res1, res2, ret, info1, info2);
1da177e4 376
3f32b3c0
DB
377 if ((ret) || (info1 != info2) || (info1 == 0))
378 return -EINVAL;
1da177e4 379
7b4884ca
DB
380 if (validate && !s->fake_cis) {
381 /* move it to the validated data set */
382 add_interval(&s_data->mem_db_valid, base, size);
383 sub_interval(&s_data->mem_db, base, size);
1da177e4
LT
384 }
385
3f32b3c0 386 return 0;
1da177e4
LT
387}
388
1da177e4 389
3f32b3c0
DB
390/**
391 * do_mem_probe() - validate a memory region for PCMCIA use
392 * @s: PCMCIA socket to validate
393 * @base: start address of resource to check
394 * @num: size of resource to check
395 * @validate: validation function to use
396 * @fallback: validation function to use if validate fails
397 *
398 * do_mem_probe() checks a memory region for use by the PCMCIA subsystem.
399 * To do so, the area is split up into sensible parts, and then passed
400 * into the @validate() function. Only if @validate() and @fallback() fail,
401 * the area is marked as unavaibale for use by the PCMCIA subsystem. The
402 * function returns the size of the usable memory area.
403 */
404static int do_mem_probe(struct pcmcia_socket *s, u_long base, u_long num,
405 int validate (struct pcmcia_socket *s,
406 struct resource *res,
407 unsigned int *value),
408 int fallback (struct pcmcia_socket *s,
409 struct resource *res,
410 unsigned int *value))
1da177e4 411{
9fea84f4
DB
412 struct socket_data *s_data = s->resource_data;
413 u_long i, j, bad, fail, step;
414
415 dev_printk(KERN_INFO, &s->dev, "cs: memory probe 0x%06lx-0x%06lx:",
416 base, base+num-1);
417 bad = fail = 0;
418 step = (num < 0x20000) ? 0x2000 : ((num>>4) & ~0x1fff);
419 /* don't allow too large steps */
420 if (step > 0x800000)
421 step = 0x800000;
422 /* cis_readable wants to map 2x map_size */
423 if (step < 2 * s->map_size)
424 step = 2 * s->map_size;
425 for (i = j = base; i < base+num; i = j + step) {
426 if (!fail) {
427 for (j = i; j < base+num; j += step) {
3f32b3c0 428 if (!do_validate_mem(s, j, step, validate))
9fea84f4
DB
429 break;
430 }
431 fail = ((i == base) && (j == base+num));
432 }
3f32b3c0
DB
433 if ((fail) && (fallback)) {
434 for (j = i; j < base+num; j += step)
435 if (!do_validate_mem(s, j, step, fallback))
9fea84f4
DB
436 break;
437 }
438 if (i != j) {
439 if (!bad)
440 printk(" excluding");
441 printk(" %#05lx-%#05lx", i, j-1);
442 sub_interval(&s_data->mem_db, i, j-i);
443 bad += j-i;
444 }
445 }
446 printk(bad ? "\n" : " clean.\n");
447 return num - bad;
1da177e4
LT
448}
449
3f32b3c0 450
1da177e4
LT
451#ifdef CONFIG_PCMCIA_PROBE
452
3f32b3c0
DB
453/**
454 * inv_probe() - top-to-bottom search for one usuable high memory area
455 * @s: PCMCIA socket to validate
456 * @m: resource_map to check
457 */
1da177e4
LT
458static u_long inv_probe(struct resource_map *m, struct pcmcia_socket *s)
459{
de75914e
DB
460 struct socket_data *s_data = s->resource_data;
461 u_long ok;
462 if (m == &s_data->mem_db)
463 return 0;
464 ok = inv_probe(m->next, s);
465 if (ok) {
466 if (m->base >= 0x100000)
467 sub_interval(&s_data->mem_db, m->base, m->num);
468 return ok;
469 }
470 if (m->base < 0x100000)
471 return 0;
3f32b3c0 472 return do_mem_probe(s, m->base, m->num, readable, checksum);
1da177e4
LT
473}
474
3f32b3c0
DB
475/**
476 * validate_mem() - memory probe function
477 * @s: PCMCIA socket to validate
478 * @probe_mask: MEM_PROBE_LOW | MEM_PROBE_HIGH
479 *
480 * The memory probe. If the memory list includes a 64K-aligned block
481 * below 1MB, we probe in 64K chunks, and as soon as we accumulate at
482 * least mem_limit free space, we quit. Returns 0 on usuable ports.
483 */
de75914e 484static int validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
1da177e4 485{
de75914e
DB
486 struct resource_map *m, mm;
487 static unsigned char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 };
488 unsigned long b, i, ok = 0;
489 struct socket_data *s_data = s->resource_data;
1da177e4 490
de75914e
DB
491 /* We do up to four passes through the list */
492 if (probe_mask & MEM_PROBE_HIGH) {
493 if (inv_probe(s_data->mem_db.next, s) > 0)
494 return 0;
7b4884ca
DB
495 if (s_data->mem_db_valid.next != &s_data->mem_db_valid)
496 return 0;
dbe4ea5f
DB
497 dev_printk(KERN_NOTICE, &s->dev,
498 "cs: warning: no high memory space available!\n");
de75914e 499 return -ENODEV;
1da177e4 500 }
de75914e
DB
501
502 for (m = s_data->mem_db.next; m != &s_data->mem_db; m = mm.next) {
503 mm = *m;
504 /* Only probe < 1 MB */
505 if (mm.base >= 0x100000)
506 continue;
507 if ((mm.base | mm.num) & 0xffff) {
3f32b3c0
DB
508 ok += do_mem_probe(s, mm.base, mm.num, readable,
509 checksum);
de75914e
DB
510 continue;
511 }
512 /* Special probe for 64K-aligned block */
513 for (i = 0; i < 4; i++) {
514 b = order[i] << 12;
515 if ((b >= mm.base) && (b+0x10000 <= mm.base+mm.num)) {
516 if (ok >= mem_limit)
517 sub_interval(&s_data->mem_db, b, 0x10000);
518 else
3f32b3c0
DB
519 ok += do_mem_probe(s, b, 0x10000,
520 readable, checksum);
de75914e
DB
521 }
522 }
1da177e4 523 }
de75914e
DB
524
525 if (ok > 0)
526 return 0;
527
528 return -ENODEV;
1da177e4
LT
529}
530
531#else /* CONFIG_PCMCIA_PROBE */
532
3f32b3c0
DB
533/**
534 * validate_mem() - memory probe function
535 * @s: PCMCIA socket to validate
536 * @probe_mask: ignored
537 *
538 * Returns 0 on usuable ports.
539 */
2cff9447 540static int validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
1da177e4
LT
541{
542 struct resource_map *m, mm;
543 struct socket_data *s_data = s->resource_data;
2cff9447 544 unsigned long ok = 0;
1da177e4
LT
545
546 for (m = s_data->mem_db.next; m != &s_data->mem_db; m = mm.next) {
547 mm = *m;
3f32b3c0 548 ok += do_mem_probe(s, mm.base, mm.num, readable, checksum);
1da177e4 549 }
2cff9447
AM
550 if (ok > 0)
551 return 0;
552 return -ENODEV;
1da177e4
LT
553}
554
555#endif /* CONFIG_PCMCIA_PROBE */
556
557
3f32b3c0
DB
558/**
559 * pcmcia_nonstatic_validate_mem() - try to validate iomem for PCMCIA use
560 * @s: PCMCIA socket to validate
561 *
562 * This is tricky... when we set up CIS memory, we try to validate
563 * the memory window space allocations.
564 *
7fe908dd 565 * Locking note: Must be called with skt_mutex held!
1da177e4 566 */
de75914e 567static int pcmcia_nonstatic_validate_mem(struct pcmcia_socket *s)
1da177e4
LT
568{
569 struct socket_data *s_data = s->resource_data;
de75914e 570 unsigned int probe_mask = MEM_PROBE_LOW;
7b4884ca 571 int ret;
de75914e 572
7b4884ca 573 if (!probe_mem || !(s->state & SOCKET_PRESENT))
de75914e 574 return 0;
1da177e4 575
de75914e
DB
576 if (s->features & SS_CAP_PAGE_REGS)
577 probe_mask = MEM_PROBE_HIGH;
1da177e4 578
7b4884ca 579 ret = validate_mem(s, probe_mask);
1da177e4 580
7b4884ca
DB
581 if (s_data->mem_db_valid.next != &s_data->mem_db_valid)
582 return 0;
1da177e4 583
de75914e 584 return ret;
1da177e4
LT
585}
586
587struct pcmcia_align_data {
588 unsigned long mask;
589 unsigned long offset;
590 struct resource_map *map;
591};
592
147a2746
DB
593static resource_size_t pcmcia_common_align(struct pcmcia_align_data *align_data,
594 resource_size_t start)
1da177e4 595{
147a2746 596 resource_size_t ret;
1da177e4
LT
597 /*
598 * Ensure that we have the correct start address
599 */
147a2746
DB
600 ret = (start & ~align_data->mask) + align_data->offset;
601 if (ret < start)
602 ret += align_data->mask + 1;
603 return ret;
1da177e4
LT
604}
605
b26b2d49 606static resource_size_t
3b7a17fc
DB
607pcmcia_align(void *align_data, const struct resource *res,
608 resource_size_t size, resource_size_t align)
1da177e4
LT
609{
610 struct pcmcia_align_data *data = align_data;
611 struct resource_map *m;
b26b2d49 612 resource_size_t start;
1da177e4 613
147a2746 614 start = pcmcia_common_align(data, res->start);
1da177e4
LT
615
616 for (m = data->map->next; m != data->map; m = m->next) {
147a2746
DB
617 unsigned long map_start = m->base;
618 unsigned long map_end = m->base + m->num - 1;
1da177e4
LT
619
620 /*
621 * If the lower resources are not available, try aligning
622 * to this entry of the resource database to see if it'll
623 * fit here.
624 */
147a2746
DB
625 if (start < map_start)
626 start = pcmcia_common_align(data, map_start);
1da177e4
LT
627
628 /*
629 * If we're above the area which was passed in, there's
630 * no point proceeding.
631 */
147a2746 632 if (start >= res->end)
1da177e4
LT
633 break;
634
147a2746 635 if ((start + size - 1) <= map_end)
1da177e4
LT
636 break;
637 }
638
639 /*
640 * If we failed to find something suitable, ensure we fail.
641 */
642 if (m == data->map)
b26b2d49
DB
643 start = res->end;
644
645 return start;
1da177e4
LT
646}
647
648/*
649 * Adjust an existing IO region allocation, but making sure that we don't
650 * encroach outside the resources which the user supplied.
651 */
652static int nonstatic_adjust_io_region(struct resource *res, unsigned long r_start,
653 unsigned long r_end, struct pcmcia_socket *s)
654{
655 struct resource_map *m;
656 struct socket_data *s_data = s->resource_data;
657 int ret = -ENOMEM;
658
1da177e4
LT
659 for (m = s_data->io_db.next; m != &s_data->io_db; m = m->next) {
660 unsigned long start = m->base;
661 unsigned long end = m->base + m->num - 1;
662
663 if (start > r_start || r_end > end)
664 continue;
665
666 ret = adjust_resource(res, r_start, r_end - r_start + 1);
667 break;
668 }
1da177e4
LT
669
670 return ret;
671}
672
673/*======================================================================
674
675 These find ranges of I/O ports or memory addresses that are not
676 currently allocated by other devices.
677
678 The 'align' field should reflect the number of bits of address
679 that need to be preserved from the initial value of *base. It
680 should be a power of two, greater than or equal to 'num'. A value
681 of 0 means that all bits of *base are significant. *base should
682 also be strictly less than 'align'.
683
684======================================================================*/
685
e94e15f7 686static struct resource *nonstatic_find_io_region(unsigned long base, int num,
1da177e4
LT
687 unsigned long align, struct pcmcia_socket *s)
688{
49b1153a
DB
689 struct resource *res = pcmcia_make_resource(0, num, IORESOURCE_IO,
690 dev_name(&s->dev));
1da177e4
LT
691 struct socket_data *s_data = s->resource_data;
692 struct pcmcia_align_data data;
693 unsigned long min = base;
694 int ret;
695
696 if (align == 0)
697 align = 0x10000;
698
699 data.mask = align - 1;
700 data.offset = base & data.mask;
701 data.map = &s_data->io_db;
702
1da177e4
LT
703#ifdef CONFIG_PCI
704 if (s->cb_dev) {
705 ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num, 1,
706 min, 0, pcmcia_align, &data);
707 } else
708#endif
709 ret = allocate_resource(&ioport_resource, res, num, min, ~0UL,
710 1, pcmcia_align, &data);
1da177e4
LT
711
712 if (ret != 0) {
713 kfree(res);
714 res = NULL;
715 }
716 return res;
717}
718
9fea84f4 719static struct resource *nonstatic_find_mem_region(u_long base, u_long num,
e94e15f7 720 u_long align, int low, struct pcmcia_socket *s)
1da177e4 721{
49b1153a
DB
722 struct resource *res = pcmcia_make_resource(0, num, IORESOURCE_MEM,
723 dev_name(&s->dev));
1da177e4
LT
724 struct socket_data *s_data = s->resource_data;
725 struct pcmcia_align_data data;
726 unsigned long min, max;
7b4884ca 727 int ret, i, j;
1da177e4
LT
728
729 low = low || !(s->features & SS_CAP_PAGE_REGS);
730
731 data.mask = align - 1;
732 data.offset = base & data.mask;
1da177e4
LT
733
734 for (i = 0; i < 2; i++) {
7b4884ca 735 data.map = &s_data->mem_db_valid;
1da177e4
LT
736 if (low) {
737 max = 0x100000UL;
738 min = base < max ? base : 0;
739 } else {
740 max = ~0UL;
741 min = 0x100000UL + base;
742 }
743
7b4884ca 744 for (j = 0; j < 2; j++) {
1da177e4 745#ifdef CONFIG_PCI
7b4884ca
DB
746 if (s->cb_dev) {
747 ret = pci_bus_alloc_resource(s->cb_dev->bus,
748 res, num, 1, min, 0,
749 pcmcia_align, &data);
750 } else
1da177e4 751#endif
7b4884ca
DB
752 {
753 ret = allocate_resource(&iomem_resource,
754 res, num, min, max, 1,
755 pcmcia_align, &data);
756 }
757 if (ret == 0)
758 break;
759 data.map = &s_data->mem_db;
760 }
1da177e4
LT
761 if (ret == 0 || low)
762 break;
763 low = 1;
764 }
765
766 if (ret != 0) {
767 kfree(res);
768 res = NULL;
769 }
770 return res;
771}
772
773
22916638 774static int adjust_memory(struct pcmcia_socket *s, unsigned int action, unsigned long start, unsigned long end)
1da177e4 775{
1da177e4 776 struct socket_data *data = s->resource_data;
22916638
DB
777 unsigned long size = end - start + 1;
778 int ret = 0;
1da177e4 779
1146bc74 780 if (end < start)
22916638 781 return -EINVAL;
1da177e4 782
22916638 783 switch (action) {
1da177e4 784 case ADD_MANAGED_RESOURCE:
22916638 785 ret = add_interval(&data->mem_db, start, size);
3f32b3c0
DB
786 if (!ret)
787 do_mem_probe(s, start, size, NULL, NULL);
1da177e4
LT
788 break;
789 case REMOVE_MANAGED_RESOURCE:
22916638 790 ret = sub_interval(&data->mem_db, start, size);
1da177e4
LT
791 break;
792 default:
22916638 793 ret = -EINVAL;
1da177e4 794 }
1da177e4
LT
795
796 return ret;
797}
798
799
22916638 800static int adjust_io(struct pcmcia_socket *s, unsigned int action, unsigned long start, unsigned long end)
1da177e4
LT
801{
802 struct socket_data *data = s->resource_data;
41b97ab5 803 unsigned long size;
22916638 804 int ret = 0;
1da177e4 805
9713ab28
DB
806#if defined(CONFIG_X86)
807 /* on x86, avoid anything < 0x100 for it is often used for
808 * legacy platform devices */
809 if (start < 0x100)
810 start = 0x100;
811#endif
812
41b97ab5
DB
813 size = end - start + 1;
814
1146bc74 815 if (end < start)
22916638
DB
816 return -EINVAL;
817
818 if (end > IO_SPACE_LIMIT)
819 return -EINVAL;
1da177e4 820
22916638 821 switch (action) {
1da177e4 822 case ADD_MANAGED_RESOURCE:
22916638
DB
823 if (add_interval(&data->io_db, start, size) != 0) {
824 ret = -EBUSY;
1da177e4
LT
825 break;
826 }
827#ifdef CONFIG_PCMCIA_PROBE
828 if (probe_io)
22916638 829 do_io_probe(s, start, size);
1da177e4
LT
830#endif
831 break;
832 case REMOVE_MANAGED_RESOURCE:
22916638 833 sub_interval(&data->io_db, start, size);
1da177e4
LT
834 break;
835 default:
22916638 836 ret = -EINVAL;
1da177e4
LT
837 break;
838 }
1da177e4
LT
839
840 return ret;
841}
842
843
3c29976a
DB
844#ifdef CONFIG_PCI
845static int nonstatic_autoadd_resources(struct pcmcia_socket *s)
846{
847 struct resource *res;
848 int i, done = 0;
849
850 if (!s->cb_dev || !s->cb_dev->bus)
851 return -ENODEV;
852
0d078f6f 853#if defined(CONFIG_X86)
b6d00f0d
DB
854 /* If this is the root bus, the risk of hitting
855 * some strange system devices which aren't protected
856 * by either ACPI resource tables or properly requested
857 * resources is too big. Therefore, don't do auto-adding
858 * of resources at the moment.
859 */
860 if (s->cb_dev->bus->number == 0)
861 return -EINVAL;
862#endif
863
89a74ecc 864 pci_bus_for_each_resource(s->cb_dev->bus, res, i) {
3c29976a
DB
865 if (!res)
866 continue;
867
868 if (res->flags & IORESOURCE_IO) {
869 if (res == &ioport_resource)
870 continue;
dbe4ea5f 871 dev_printk(KERN_INFO, &s->cb_dev->dev,
e1944c6b
BH
872 "pcmcia: parent PCI bridge window: %pR\n",
873 res);
3c29976a
DB
874 if (!adjust_io(s, ADD_MANAGED_RESOURCE, res->start, res->end))
875 done |= IORESOURCE_IO;
876
877 }
878
879 if (res->flags & IORESOURCE_MEM) {
880 if (res == &iomem_resource)
881 continue;
dbe4ea5f 882 dev_printk(KERN_INFO, &s->cb_dev->dev,
e1944c6b
BH
883 "pcmcia: parent PCI bridge window: %pR\n",
884 res);
3c29976a
DB
885 if (!adjust_memory(s, ADD_MANAGED_RESOURCE, res->start, res->end))
886 done |= IORESOURCE_MEM;
887 }
888 }
889
890 /* if we got at least one of IO, and one of MEM, we can be glad and
891 * activate the PCMCIA subsystem */
54bb5675 892 if (done == (IORESOURCE_MEM | IORESOURCE_IO))
3c29976a
DB
893 s->resource_setup_done = 1;
894
895 return 0;
896}
897
898#else
899
900static inline int nonstatic_autoadd_resources(struct pcmcia_socket *s)
901{
902 return -ENODEV;
903}
904
905#endif
906
907
1da177e4
LT
908static int nonstatic_init(struct pcmcia_socket *s)
909{
910 struct socket_data *data;
911
8084b372 912 data = kzalloc(sizeof(struct socket_data), GFP_KERNEL);
1da177e4
LT
913 if (!data)
914 return -ENOMEM;
1da177e4
LT
915
916 data->mem_db.next = &data->mem_db;
7b4884ca 917 data->mem_db_valid.next = &data->mem_db_valid;
1da177e4
LT
918 data->io_db.next = &data->io_db;
919
920 s->resource_data = (void *) data;
921
3c29976a
DB
922 nonstatic_autoadd_resources(s);
923
1da177e4
LT
924 return 0;
925}
926
927static void nonstatic_release_resource_db(struct pcmcia_socket *s)
928{
929 struct socket_data *data = s->resource_data;
930 struct resource_map *p, *q;
931
7b4884ca
DB
932 for (p = data->mem_db_valid.next; p != &data->mem_db_valid; p = q) {
933 q = p->next;
934 kfree(p);
935 }
1da177e4
LT
936 for (p = data->mem_db.next; p != &data->mem_db; p = q) {
937 q = p->next;
938 kfree(p);
939 }
940 for (p = data->io_db.next; p != &data->io_db; p = q) {
941 q = p->next;
942 kfree(p);
943 }
1da177e4
LT
944}
945
946
947struct pccard_resource_ops pccard_nonstatic_ops = {
948 .validate_mem = pcmcia_nonstatic_validate_mem,
949 .adjust_io_region = nonstatic_adjust_io_region,
950 .find_io = nonstatic_find_io_region,
951 .find_mem = nonstatic_find_mem_region,
c5023801
DB
952 .add_io = adjust_io,
953 .add_mem = adjust_memory,
1da177e4
LT
954 .init = nonstatic_init,
955 .exit = nonstatic_release_resource_db,
956};
957EXPORT_SYMBOL(pccard_nonstatic_ops);
958
959
960/* sysfs interface to the resource database */
961
87373318
GKH
962static ssize_t show_io_db(struct device *dev,
963 struct device_attribute *attr, char *buf)
1da177e4 964{
87373318 965 struct pcmcia_socket *s = dev_get_drvdata(dev);
1da177e4
LT
966 struct socket_data *data;
967 struct resource_map *p;
968 ssize_t ret = 0;
969
cfe5d809 970 mutex_lock(&s->ops_mutex);
1da177e4
LT
971 data = s->resource_data;
972
973 for (p = data->io_db.next; p != &data->io_db; p = p->next) {
974 if (ret > (PAGE_SIZE - 10))
975 continue;
9fea84f4
DB
976 ret += snprintf(&buf[ret], (PAGE_SIZE - ret - 1),
977 "0x%08lx - 0x%08lx\n",
978 ((unsigned long) p->base),
979 ((unsigned long) p->base + p->num - 1));
1da177e4
LT
980 }
981
cfe5d809 982 mutex_unlock(&s->ops_mutex);
9fea84f4 983 return ret;
1da177e4
LT
984}
985
87373318
GKH
986static ssize_t store_io_db(struct device *dev,
987 struct device_attribute *attr,
988 const char *buf, size_t count)
1da177e4 989{
87373318 990 struct pcmcia_socket *s = dev_get_drvdata(dev);
1da177e4 991 unsigned long start_addr, end_addr;
22916638 992 unsigned int add = ADD_MANAGED_RESOURCE;
1da177e4
LT
993 ssize_t ret = 0;
994
9fea84f4 995 ret = sscanf(buf, "+ 0x%lx - 0x%lx", &start_addr, &end_addr);
1da177e4 996 if (ret != 2) {
9fea84f4 997 ret = sscanf(buf, "- 0x%lx - 0x%lx", &start_addr, &end_addr);
22916638 998 add = REMOVE_MANAGED_RESOURCE;
1da177e4 999 if (ret != 2) {
9fea84f4
DB
1000 ret = sscanf(buf, "0x%lx - 0x%lx", &start_addr,
1001 &end_addr);
22916638 1002 add = ADD_MANAGED_RESOURCE;
1da177e4
LT
1003 if (ret != 2)
1004 return -EINVAL;
1005 }
1006 }
1146bc74 1007 if (end_addr < start_addr)
1da177e4
LT
1008 return -EINVAL;
1009
cfe5d809 1010 mutex_lock(&s->ops_mutex);
22916638 1011 ret = adjust_io(s, add, start_addr, end_addr);
3c29976a
DB
1012 if (!ret)
1013 s->resource_setup_new = 1;
cfe5d809 1014 mutex_unlock(&s->ops_mutex);
1da177e4
LT
1015
1016 return ret ? ret : count;
1017}
87373318 1018static DEVICE_ATTR(available_resources_io, 0600, show_io_db, store_io_db);
1da177e4 1019
87373318
GKH
1020static ssize_t show_mem_db(struct device *dev,
1021 struct device_attribute *attr, char *buf)
1da177e4 1022{
87373318 1023 struct pcmcia_socket *s = dev_get_drvdata(dev);
1da177e4
LT
1024 struct socket_data *data;
1025 struct resource_map *p;
1026 ssize_t ret = 0;
1027
cfe5d809 1028 mutex_lock(&s->ops_mutex);
1da177e4
LT
1029 data = s->resource_data;
1030
7b4884ca
DB
1031 for (p = data->mem_db_valid.next; p != &data->mem_db_valid;
1032 p = p->next) {
1033 if (ret > (PAGE_SIZE - 10))
1034 continue;
1035 ret += snprintf(&buf[ret], (PAGE_SIZE - ret - 1),
1036 "0x%08lx - 0x%08lx\n",
1037 ((unsigned long) p->base),
1038 ((unsigned long) p->base + p->num - 1));
1039 }
1040
1da177e4
LT
1041 for (p = data->mem_db.next; p != &data->mem_db; p = p->next) {
1042 if (ret > (PAGE_SIZE - 10))
1043 continue;
9fea84f4
DB
1044 ret += snprintf(&buf[ret], (PAGE_SIZE - ret - 1),
1045 "0x%08lx - 0x%08lx\n",
1046 ((unsigned long) p->base),
1047 ((unsigned long) p->base + p->num - 1));
1da177e4
LT
1048 }
1049
cfe5d809 1050 mutex_unlock(&s->ops_mutex);
9fea84f4 1051 return ret;
1da177e4
LT
1052}
1053
87373318
GKH
1054static ssize_t store_mem_db(struct device *dev,
1055 struct device_attribute *attr,
1056 const char *buf, size_t count)
1da177e4 1057{
87373318 1058 struct pcmcia_socket *s = dev_get_drvdata(dev);
1da177e4 1059 unsigned long start_addr, end_addr;
22916638 1060 unsigned int add = ADD_MANAGED_RESOURCE;
1da177e4
LT
1061 ssize_t ret = 0;
1062
9fea84f4 1063 ret = sscanf(buf, "+ 0x%lx - 0x%lx", &start_addr, &end_addr);
1da177e4 1064 if (ret != 2) {
9fea84f4 1065 ret = sscanf(buf, "- 0x%lx - 0x%lx", &start_addr, &end_addr);
22916638 1066 add = REMOVE_MANAGED_RESOURCE;
1da177e4 1067 if (ret != 2) {
9fea84f4
DB
1068 ret = sscanf(buf, "0x%lx - 0x%lx", &start_addr,
1069 &end_addr);
22916638 1070 add = ADD_MANAGED_RESOURCE;
1da177e4
LT
1071 if (ret != 2)
1072 return -EINVAL;
1073 }
1074 }
1146bc74 1075 if (end_addr < start_addr)
1da177e4
LT
1076 return -EINVAL;
1077
cfe5d809 1078 mutex_lock(&s->ops_mutex);
22916638 1079 ret = adjust_memory(s, add, start_addr, end_addr);
3c29976a
DB
1080 if (!ret)
1081 s->resource_setup_new = 1;
cfe5d809 1082 mutex_unlock(&s->ops_mutex);
1da177e4
LT
1083
1084 return ret ? ret : count;
1085}
87373318 1086static DEVICE_ATTR(available_resources_mem, 0600, show_mem_db, store_mem_db);
1da177e4 1087
7d578961
DB
1088static struct attribute *pccard_rsrc_attributes[] = {
1089 &dev_attr_available_resources_io.attr,
1090 &dev_attr_available_resources_mem.attr,
1da177e4
LT
1091 NULL,
1092};
1093
7d578961
DB
1094static const struct attribute_group rsrc_attributes = {
1095 .attrs = pccard_rsrc_attributes,
1096};
1097
87373318 1098static int __devinit pccard_sysfs_add_rsrc(struct device *dev,
d8539d81 1099 struct class_interface *class_intf)
1da177e4 1100{
87373318 1101 struct pcmcia_socket *s = dev_get_drvdata(dev);
7d578961 1102
1da177e4
LT
1103 if (s->resource_ops != &pccard_nonstatic_ops)
1104 return 0;
7d578961 1105 return sysfs_create_group(&dev->kobj, &rsrc_attributes);
1da177e4
LT
1106}
1107
87373318 1108static void __devexit pccard_sysfs_remove_rsrc(struct device *dev,
d8539d81 1109 struct class_interface *class_intf)
1da177e4 1110{
87373318 1111 struct pcmcia_socket *s = dev_get_drvdata(dev);
1da177e4
LT
1112
1113 if (s->resource_ops != &pccard_nonstatic_ops)
1114 return;
7d578961 1115 sysfs_remove_group(&dev->kobj, &rsrc_attributes);
1da177e4
LT
1116}
1117
ed49f5d0 1118static struct class_interface pccard_rsrc_interface __refdata = {
1da177e4 1119 .class = &pcmcia_socket_class,
87373318
GKH
1120 .add_dev = &pccard_sysfs_add_rsrc,
1121 .remove_dev = __devexit_p(&pccard_sysfs_remove_rsrc),
1da177e4
LT
1122};
1123
1124static int __init nonstatic_sysfs_init(void)
1125{
1126 return class_interface_register(&pccard_rsrc_interface);
1127}
1128
1129static void __exit nonstatic_sysfs_exit(void)
1130{
1131 class_interface_unregister(&pccard_rsrc_interface);
1132}
1133
1134module_init(nonstatic_sysfs_init);
1135module_exit(nonstatic_sysfs_exit);