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