MOXA linux-2.6.x / linux-2.6.9-uc0 from sdlinux-moxaart.tgz
[linux-2.6.9-moxart.git] / drivers / pcmcia / rsrc_mgr.c
blob620b20f7e040457c7b0bf2bd8aec75d393e0e35f
1 /*======================================================================
3 Resource management routines
5 rsrc_mgr.c 1.79 2000/08/30 20:23:58
7 The contents of this file are subject to the Mozilla Public
8 License Version 1.1 (the "License"); you may not use this file
9 except in compliance with the License. You may obtain a copy of
10 the License at http://www.mozilla.org/MPL/
12 Software distributed under the License is distributed on an "AS
13 IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
14 implied. See the License for the specific language governing
15 rights and limitations under the License.
17 The initial developer of the original code is David A. Hinds
18 <dahinds@users.sourceforge.net>. Portions created by David A. Hinds
19 are Copyright (C) 1999 David A. Hinds. All Rights Reserved.
21 Alternatively, the contents of this file may be used under the
22 terms of the GNU General Public License version 2 (the "GPL"), in which
23 case the provisions of the GPL are applicable instead of the
24 above. If you wish to allow the use of your version of this file
25 only under the terms of the GPL and not to allow others to use
26 your version of this file under the MPL, indicate your decision
27 by deleting the provisions above and replace them with the notice
28 and other provisions required by the GPL. If you do not delete
29 the provisions above, a recipient may use your version of this
30 file under either the MPL or the GPL.
32 ======================================================================*/
34 #include <linux/config.h>
35 #include <linux/module.h>
36 #include <linux/moduleparam.h>
37 #include <linux/init.h>
38 #include <linux/interrupt.h>
39 #include <linux/kernel.h>
40 #include <linux/errno.h>
41 #include <linux/types.h>
42 #include <linux/slab.h>
43 #include <linux/ioport.h>
44 #include <linux/timer.h>
45 #include <linux/pci.h>
46 #include <asm/irq.h>
47 #include <asm/io.h>
49 #include <pcmcia/cs_types.h>
50 #include <pcmcia/ss.h>
51 #include <pcmcia/cs.h>
52 #include <pcmcia/bulkmem.h>
53 #include <pcmcia/cistpl.h>
54 #include "cs_internal.h"
56 /*====================================================================*/
58 /* Parameters that can be set with 'insmod' */
60 #define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0444)
62 INT_MODULE_PARM(probe_mem, 1); /* memory probe? */
63 #ifdef CONFIG_PCMCIA_PROBE
64 INT_MODULE_PARM(probe_io, 1); /* IO port probe? */
65 INT_MODULE_PARM(mem_limit, 0x10000);
66 #endif
68 /*======================================================================
70 The resource_map_t structures are used to track what resources are
71 available for allocation for PC Card devices.
73 ======================================================================*/
75 typedef struct resource_map_t {
76 u_long base, num;
77 struct resource_map_t *next;
78 } resource_map_t;
80 /* Memory resource database */
81 static resource_map_t mem_db = {
82 .next = &mem_db,
85 /* IO port resource database */
86 static resource_map_t io_db = {
87 .next = &io_db,
90 static DECLARE_MUTEX(rsrc_sem);
91 static unsigned int rsrc_mem_probe;
92 #define MEM_PROBE_LOW (1 << 0)
93 #define MEM_PROBE_HIGH (1 << 1)
95 #ifdef CONFIG_PCMCIA_PROBE
97 typedef struct irq_info_t {
98 u_int Attributes;
99 int time_share, dyn_share;
100 struct pcmcia_socket *Socket;
101 } irq_info_t;
103 /* Table of IRQ assignments */
104 static irq_info_t irq_table[NR_IRQS];
106 #endif
108 /*======================================================================
110 Linux resource management extensions
112 ======================================================================*/
114 static struct resource *
115 make_resource(unsigned long b, unsigned long n, int flags, char *name)
117 struct resource *res = kmalloc(sizeof(*res), GFP_KERNEL);
119 if (res) {
120 memset(res, 0, sizeof(*res));
121 res->name = name;
122 res->start = b;
123 res->end = b + n - 1;
124 res->flags = flags;
126 return res;
129 static struct resource *
130 claim_region(struct pcmcia_socket *s, unsigned long base, unsigned long size,
131 int type, char *name)
133 struct resource *res, *parent;
135 parent = type & IORESOURCE_MEM ? &iomem_resource : &ioport_resource;
136 res = make_resource(base, size, type | IORESOURCE_BUSY, name);
138 if (res) {
139 #ifdef CONFIG_PCI
140 if (s && s->cb_dev)
141 parent = pci_find_parent_resource(s->cb_dev, res);
142 #endif
143 if (!parent || request_resource(parent, res)) {
144 kfree(res);
145 res = NULL;
148 return res;
151 static void free_region(struct resource *res)
153 if (res) {
154 release_resource(res);
155 kfree(res);
159 /*======================================================================
161 These manage the internal databases of available resources.
163 ======================================================================*/
165 static int add_interval(resource_map_t *map, u_long base, u_long num)
167 resource_map_t *p, *q;
169 for (p = map; ; p = p->next) {
170 if ((p != map) && (p->base+p->num-1 >= base))
171 return -1;
172 if ((p->next == map) || (p->next->base > base+num-1))
173 break;
175 q = kmalloc(sizeof(resource_map_t), GFP_KERNEL);
176 if (!q) return CS_OUT_OF_RESOURCE;
177 q->base = base; q->num = num;
178 q->next = p->next; p->next = q;
179 return CS_SUCCESS;
182 /*====================================================================*/
184 static int sub_interval(resource_map_t *map, u_long base, u_long num)
186 resource_map_t *p, *q;
188 for (p = map; ; p = q) {
189 q = p->next;
190 if (q == map)
191 break;
192 if ((q->base+q->num > base) && (base+num > q->base)) {
193 if (q->base >= base) {
194 if (q->base+q->num <= base+num) {
195 /* Delete whole block */
196 p->next = q->next;
197 kfree(q);
198 /* don't advance the pointer yet */
199 q = p;
200 } else {
201 /* Cut off bit from the front */
202 q->num = q->base + q->num - base - num;
203 q->base = base + num;
205 } else if (q->base+q->num <= base+num) {
206 /* Cut off bit from the end */
207 q->num = base - q->base;
208 } else {
209 /* Split the block into two pieces */
210 p = kmalloc(sizeof(resource_map_t), GFP_KERNEL);
211 if (!p) return CS_OUT_OF_RESOURCE;
212 p->base = base+num;
213 p->num = q->base+q->num - p->base;
214 q->num = base - q->base;
215 p->next = q->next ; q->next = p;
219 return CS_SUCCESS;
222 /*======================================================================
224 These routines examine a region of IO or memory addresses to
225 determine what ranges might be genuinely available.
227 ======================================================================*/
229 #ifdef CONFIG_PCMCIA_PROBE
230 static void do_io_probe(ioaddr_t base, ioaddr_t num)
232 struct resource *res;
233 ioaddr_t i, j, bad, any;
234 u_char *b, hole, most;
236 printk(KERN_INFO "cs: IO port probe 0x%04x-0x%04x:",
237 base, base+num-1);
239 /* First, what does a floating port look like? */
240 b = kmalloc(256, GFP_KERNEL);
241 if (!b) {
242 printk(KERN_ERR "do_io_probe: unable to kmalloc 256 bytes");
243 return;
245 memset(b, 0, 256);
246 for (i = base, most = 0; i < base+num; i += 8) {
247 res = claim_region(NULL, i, 8, IORESOURCE_IO, "PCMCIA IO probe");
248 if (!res)
249 continue;
250 hole = inb(i);
251 for (j = 1; j < 8; j++)
252 if (inb(i+j) != hole) break;
253 free_region(res);
254 if ((j == 8) && (++b[hole] > b[most]))
255 most = hole;
256 if (b[most] == 127) break;
258 kfree(b);
260 bad = any = 0;
261 for (i = base; i < base+num; i += 8) {
262 res = claim_region(NULL, i, 8, IORESOURCE_IO, "PCMCIA IO probe");
263 if (!res)
264 continue;
265 for (j = 0; j < 8; j++)
266 if (inb(i+j) != most) break;
267 free_region(res);
268 if (j < 8) {
269 if (!any)
270 printk(" excluding");
271 if (!bad)
272 bad = any = i;
273 } else {
274 if (bad) {
275 sub_interval(&io_db, bad, i-bad);
276 printk(" %#04x-%#04x", bad, i-1);
277 bad = 0;
281 if (bad) {
282 if ((num > 16) && (bad == base) && (i == base+num)) {
283 printk(" nothing: probe failed.\n");
284 return;
285 } else {
286 sub_interval(&io_db, bad, i-bad);
287 printk(" %#04x-%#04x", bad, i-1);
291 printk(any ? "\n" : " clean.\n");
293 #endif
295 /*======================================================================
297 This is tricky... when we set up CIS memory, we try to validate
298 the memory window space allocations.
300 ======================================================================*/
302 /* Validation function for cards with a valid CIS */
303 static int readable(struct pcmcia_socket *s, struct resource *res, cisinfo_t *info)
305 int ret = -1;
307 s->cis_mem.res = res;
308 s->cis_virt = ioremap(res->start, s->map_size);
309 if (s->cis_virt) {
310 ret = pcmcia_validate_cis(s->clients, info);
311 /* invalidate mapping and CIS cache */
312 iounmap(s->cis_virt);
313 s->cis_virt = NULL;
314 destroy_cis_cache(s);
316 s->cis_mem.res = NULL;
317 if ((ret != 0) || (info->Chains == 0))
318 return 0;
319 return 1;
322 /* Validation function for simple memory cards */
323 static int checksum(struct pcmcia_socket *s, struct resource *res)
325 pccard_mem_map map;
326 int i, a = 0, b = -1, d;
327 void __iomem *virt;
329 virt = ioremap(res->start, s->map_size);
330 if (virt) {
331 map.map = 0;
332 map.flags = MAP_ACTIVE;
333 map.speed = 0;
334 map.res = res;
335 map.card_start = 0;
336 s->ops->set_mem_map(s, &map);
338 /* Don't bother checking every word... */
339 for (i = 0; i < s->map_size; i += 44) {
340 d = readl(virt+i);
341 a += d;
342 b &= d;
345 map.flags = 0;
346 s->ops->set_mem_map(s, &map);
348 iounmap(virt);
351 return (b == -1) ? -1 : (a>>1);
354 static int
355 cis_readable(struct pcmcia_socket *s, unsigned long base, unsigned long size)
357 struct resource *res1, *res2;
358 cisinfo_t info1, info2;
359 int ret = 0;
361 res1 = claim_region(s, base, size/2, IORESOURCE_MEM, "cs memory probe");
362 res2 = claim_region(s, base + size/2, size/2, IORESOURCE_MEM, "cs memory probe");
364 if (res1 && res2) {
365 ret = readable(s, res1, &info1);
366 ret += readable(s, res2, &info2);
369 free_region(res2);
370 free_region(res1);
372 return (ret == 2) && (info1.Chains == info2.Chains);
375 static int
376 checksum_match(struct pcmcia_socket *s, unsigned long base, unsigned long size)
378 struct resource *res1, *res2;
379 int a = -1, b = -1;
381 res1 = claim_region(s, base, size/2, IORESOURCE_MEM, "cs memory probe");
382 res2 = claim_region(s, base + size/2, size/2, IORESOURCE_MEM, "cs memory probe");
384 if (res1 && res2) {
385 a = checksum(s, res1);
386 b = checksum(s, res2);
389 free_region(res2);
390 free_region(res1);
392 return (a == b) && (a >= 0);
395 /*======================================================================
397 The memory probe. If the memory list includes a 64K-aligned block
398 below 1MB, we probe in 64K chunks, and as soon as we accumulate at
399 least mem_limit free space, we quit.
401 ======================================================================*/
403 static int do_mem_probe(u_long base, u_long num, struct pcmcia_socket *s)
405 u_long i, j, bad, fail, step;
407 printk(KERN_INFO "cs: memory probe 0x%06lx-0x%06lx:",
408 base, base+num-1);
409 bad = fail = 0;
410 step = (num < 0x20000) ? 0x2000 : ((num>>4) & ~0x1fff);
411 /* cis_readable wants to map 2x map_size */
412 if (step < 2 * s->map_size)
413 step = 2 * s->map_size;
414 for (i = j = base; i < base+num; i = j + step) {
415 if (!fail) {
416 for (j = i; j < base+num; j += step) {
417 if (cis_readable(s, j, step))
418 break;
420 fail = ((i == base) && (j == base+num));
422 if (fail) {
423 for (j = i; j < base+num; j += 2*step)
424 if (checksum_match(s, j, step) &&
425 checksum_match(s, j + step, step))
426 break;
428 if (i != j) {
429 if (!bad) printk(" excluding");
430 printk(" %#05lx-%#05lx", i, j-1);
431 sub_interval(&mem_db, i, j-i);
432 bad += j-i;
435 printk(bad ? "\n" : " clean.\n");
436 return (num - bad);
439 #ifdef CONFIG_PCMCIA_PROBE
441 static u_long inv_probe(resource_map_t *m, struct pcmcia_socket *s)
443 u_long ok;
444 if (m == &mem_db)
445 return 0;
446 ok = inv_probe(m->next, s);
447 if (ok) {
448 if (m->base >= 0x100000)
449 sub_interval(&mem_db, m->base, m->num);
450 return ok;
452 if (m->base < 0x100000)
453 return 0;
454 return do_mem_probe(m->base, m->num, s);
457 static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
459 resource_map_t *m, mm;
460 static u_char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 };
461 u_long b, i, ok = 0;
463 /* We do up to four passes through the list */
464 if (probe_mask & MEM_PROBE_HIGH) {
465 if (inv_probe(mem_db.next, s) > 0)
466 return;
467 printk(KERN_NOTICE "cs: warning: no high memory space "
468 "available!\n");
470 if ((probe_mask & MEM_PROBE_LOW) == 0)
471 return;
472 for (m = mem_db.next; m != &mem_db; m = mm.next) {
473 mm = *m;
474 /* Only probe < 1 MB */
475 if (mm.base >= 0x100000) continue;
476 if ((mm.base | mm.num) & 0xffff) {
477 ok += do_mem_probe(mm.base, mm.num, s);
478 continue;
480 /* Special probe for 64K-aligned block */
481 for (i = 0; i < 4; i++) {
482 b = order[i] << 12;
483 if ((b >= mm.base) && (b+0x10000 <= mm.base+mm.num)) {
484 if (ok >= mem_limit)
485 sub_interval(&mem_db, b, 0x10000);
486 else
487 ok += do_mem_probe(b, 0x10000, s);
493 #else /* CONFIG_PCMCIA_PROBE */
495 static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
497 resource_map_t *m, mm;
499 for (m = mem_db.next; m != &mem_db; m = mm.next) {
500 mm = *m;
501 if (do_mem_probe(mm.base, mm.num, s))
502 break;
506 #endif /* CONFIG_PCMCIA_PROBE */
509 * Locking note: this is the only place where we take
510 * both rsrc_sem and skt_sem.
512 void pcmcia_validate_mem(struct pcmcia_socket *s)
514 if (probe_mem) {
515 unsigned int probe_mask;
517 down(&rsrc_sem);
519 probe_mask = MEM_PROBE_LOW;
520 if (s->features & SS_CAP_PAGE_REGS)
521 probe_mask = MEM_PROBE_HIGH;
523 if (probe_mask & ~rsrc_mem_probe) {
524 rsrc_mem_probe |= probe_mask;
526 down(&s->skt_sem);
528 if (s->state & SOCKET_PRESENT)
529 validate_mem(s, probe_mask);
531 up(&s->skt_sem);
534 up(&rsrc_sem);
538 EXPORT_SYMBOL(pcmcia_validate_mem);
540 struct pcmcia_align_data {
541 unsigned long mask;
542 unsigned long offset;
543 resource_map_t *map;
546 static void
547 pcmcia_common_align(void *align_data, struct resource *res,
548 unsigned long size, unsigned long align)
550 struct pcmcia_align_data *data = align_data;
551 unsigned long start;
553 * Ensure that we have the correct start address
555 start = (res->start & ~data->mask) + data->offset;
556 if (start < res->start)
557 start += data->mask + 1;
558 res->start = start;
561 static void
562 pcmcia_align(void *align_data, struct resource *res,
563 unsigned long size, unsigned long align)
565 struct pcmcia_align_data *data = align_data;
566 resource_map_t *m;
568 pcmcia_common_align(data, res, size, align);
570 for (m = data->map->next; m != data->map; m = m->next) {
571 unsigned long start = m->base;
572 unsigned long end = m->base + m->num - 1;
575 * If the lower resources are not available, try aligning
576 * to this entry of the resource database to see if it'll
577 * fit here.
579 if (res->start < start) {
580 res->start = start;
581 pcmcia_common_align(data, res, size, align);
585 * If we're above the area which was passed in, there's
586 * no point proceeding.
588 if (res->start >= res->end)
589 break;
591 if ((res->start + size - 1) <= end)
592 break;
596 * If we failed to find something suitable, ensure we fail.
598 if (m == data->map)
599 res->start = res->end;
603 * Adjust an existing IO region allocation, but making sure that we don't
604 * encroach outside the resources which the user supplied.
606 int adjust_io_region(struct resource *res, unsigned long r_start,
607 unsigned long r_end, struct pcmcia_socket *s)
609 resource_map_t *m;
610 int ret = -ENOMEM;
612 down(&rsrc_sem);
613 for (m = io_db.next; m != &io_db; m = m->next) {
614 unsigned long start = m->base;
615 unsigned long end = m->base + m->num - 1;
617 if (start > r_start || r_end > end)
618 continue;
620 ret = adjust_resource(res, r_start, r_end - r_start + 1);
621 break;
623 up(&rsrc_sem);
625 return ret;
628 /*======================================================================
630 These find ranges of I/O ports or memory addresses that are not
631 currently allocated by other devices.
633 The 'align' field should reflect the number of bits of address
634 that need to be preserved from the initial value of *base. It
635 should be a power of two, greater than or equal to 'num'. A value
636 of 0 means that all bits of *base are significant. *base should
637 also be strictly less than 'align'.
639 ======================================================================*/
641 struct resource *find_io_region(unsigned long base, int num,
642 unsigned long align, char *name, struct pcmcia_socket *s)
644 struct resource *res = make_resource(0, num, IORESOURCE_IO, s->dev.class_id);
645 struct pcmcia_align_data data;
646 unsigned long min = base;
647 int ret;
649 if (align == 0)
650 align = 0x10000;
652 data.mask = align - 1;
653 data.offset = base & data.mask;
654 data.map = &io_db;
656 down(&rsrc_sem);
657 #ifdef CONFIG_PCI
658 if (s->cb_dev) {
659 ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num, 1,
660 min, 0, pcmcia_align, &data);
661 } else
662 #endif
663 ret = allocate_resource(&ioport_resource, res, num, min, ~0UL,
664 1, pcmcia_align, &data);
665 up(&rsrc_sem);
667 if (ret != 0) {
668 kfree(res);
669 res = NULL;
671 return res;
674 struct resource *find_mem_region(u_long base, u_long num, u_long align,
675 int low, char *name, struct pcmcia_socket *s)
677 struct resource *res = make_resource(0, num, IORESOURCE_MEM, s->dev.class_id);
678 struct pcmcia_align_data data;
679 unsigned long min, max;
680 int ret, i;
682 low = low || !(s->features & SS_CAP_PAGE_REGS);
684 data.mask = align - 1;
685 data.offset = base & data.mask;
686 data.map = &mem_db;
688 for (i = 0; i < 2; i++) {
689 if (low) {
690 max = 0x100000UL;
691 min = base < max ? base : 0;
692 } else {
693 max = ~0UL;
694 min = 0x100000UL + base;
697 down(&rsrc_sem);
698 #ifdef CONFIG_PCI
699 if (s->cb_dev) {
700 ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num,
701 1, min, 0,
702 pcmcia_align, &data);
703 } else
704 #endif
705 ret = allocate_resource(&iomem_resource, res, num, min,
706 max, 1, pcmcia_align, &data);
707 up(&rsrc_sem);
708 if (ret == 0 || low)
709 break;
710 low = 1;
713 if (ret != 0) {
714 kfree(res);
715 res = NULL;
717 return res;
720 /*======================================================================
722 This checks to see if an interrupt is available, with support
723 for interrupt sharing. We don't support reserving interrupts
724 yet. If the interrupt is available, we allocate it.
726 ======================================================================*/
728 #ifdef CONFIG_PCMCIA_PROBE
730 static irqreturn_t fake_irq(int i, void *d, struct pt_regs *r) { return IRQ_NONE; }
731 static inline int check_irq(int irq)
733 if (request_irq(irq, fake_irq, 0, "bogus", NULL) != 0)
734 return -1;
735 free_irq(irq, NULL);
736 return 0;
739 int try_irq(u_int Attributes, int irq, int specific)
741 irq_info_t *info = &irq_table[irq];
742 int ret = 0;
744 down(&rsrc_sem);
745 if (info->Attributes & RES_ALLOCATED) {
746 switch (Attributes & IRQ_TYPE) {
747 case IRQ_TYPE_EXCLUSIVE:
748 ret = CS_IN_USE;
749 break;
750 case IRQ_TYPE_TIME:
751 if ((info->Attributes & RES_IRQ_TYPE)
752 != RES_IRQ_TYPE_TIME) {
753 ret = CS_IN_USE;
754 break;
756 if (Attributes & IRQ_FIRST_SHARED) {
757 ret = CS_BAD_ATTRIBUTE;
758 break;
760 info->Attributes |= RES_IRQ_TYPE_TIME | RES_ALLOCATED;
761 info->time_share++;
762 break;
763 case IRQ_TYPE_DYNAMIC_SHARING:
764 if ((info->Attributes & RES_IRQ_TYPE)
765 != RES_IRQ_TYPE_DYNAMIC) {
766 ret = CS_IN_USE;
767 break;
769 if (Attributes & IRQ_FIRST_SHARED) {
770 ret = CS_BAD_ATTRIBUTE;
771 break;
773 info->Attributes |= RES_IRQ_TYPE_DYNAMIC | RES_ALLOCATED;
774 info->dyn_share++;
775 break;
777 } else {
778 if ((info->Attributes & RES_RESERVED) && !specific) {
779 ret = CS_IN_USE;
780 goto out;
782 if (check_irq(irq) != 0) {
783 ret = CS_IN_USE;
784 goto out;
786 switch (Attributes & IRQ_TYPE) {
787 case IRQ_TYPE_EXCLUSIVE:
788 info->Attributes |= RES_ALLOCATED;
789 break;
790 case IRQ_TYPE_TIME:
791 if (!(Attributes & IRQ_FIRST_SHARED)) {
792 ret = CS_BAD_ATTRIBUTE;
793 break;
795 info->Attributes |= RES_IRQ_TYPE_TIME | RES_ALLOCATED;
796 info->time_share = 1;
797 break;
798 case IRQ_TYPE_DYNAMIC_SHARING:
799 if (!(Attributes & IRQ_FIRST_SHARED)) {
800 ret = CS_BAD_ATTRIBUTE;
801 break;
803 info->Attributes |= RES_IRQ_TYPE_DYNAMIC | RES_ALLOCATED;
804 info->dyn_share = 1;
805 break;
808 out:
809 up(&rsrc_sem);
810 return ret;
813 #endif
815 /*====================================================================*/
817 #ifdef CONFIG_PCMCIA_PROBE
819 void undo_irq(u_int Attributes, int irq)
821 irq_info_t *info;
823 info = &irq_table[irq];
824 down(&rsrc_sem);
825 switch (Attributes & IRQ_TYPE) {
826 case IRQ_TYPE_EXCLUSIVE:
827 info->Attributes &= RES_RESERVED;
828 break;
829 case IRQ_TYPE_TIME:
830 info->time_share--;
831 if (info->time_share == 0)
832 info->Attributes &= RES_RESERVED;
833 break;
834 case IRQ_TYPE_DYNAMIC_SHARING:
835 info->dyn_share--;
836 if (info->dyn_share == 0)
837 info->Attributes &= RES_RESERVED;
838 break;
840 up(&rsrc_sem);
843 #endif
845 /*======================================================================
847 The various adjust_* calls form the external interface to the
848 resource database.
850 ======================================================================*/
852 static int adjust_memory(adjust_t *adj)
854 u_long base, num;
855 int ret;
857 base = adj->resource.memory.Base;
858 num = adj->resource.memory.Size;
859 if ((num == 0) || (base+num-1 < base))
860 return CS_BAD_SIZE;
862 ret = CS_SUCCESS;
864 down(&rsrc_sem);
865 switch (adj->Action) {
866 case ADD_MANAGED_RESOURCE:
867 ret = add_interval(&mem_db, base, num);
868 break;
869 case REMOVE_MANAGED_RESOURCE:
870 ret = sub_interval(&mem_db, base, num);
871 if (ret == CS_SUCCESS) {
872 struct pcmcia_socket *socket;
873 down_read(&pcmcia_socket_list_rwsem);
874 list_for_each_entry(socket, &pcmcia_socket_list, socket_list)
875 release_cis_mem(socket);
876 up_read(&pcmcia_socket_list_rwsem);
878 break;
879 default:
880 ret = CS_UNSUPPORTED_FUNCTION;
882 up(&rsrc_sem);
884 return ret;
887 /*====================================================================*/
889 static int adjust_io(adjust_t *adj)
891 int base, num, ret = CS_SUCCESS;
893 base = adj->resource.io.BasePort;
894 num = adj->resource.io.NumPorts;
895 if ((base < 0) || (base > 0xffff))
896 return CS_BAD_BASE;
897 if ((num <= 0) || (base+num > 0x10000) || (base+num <= base))
898 return CS_BAD_SIZE;
900 down(&rsrc_sem);
901 switch (adj->Action) {
902 case ADD_MANAGED_RESOURCE:
903 if (add_interval(&io_db, base, num) != 0) {
904 ret = CS_IN_USE;
905 break;
907 #ifdef CONFIG_PCMCIA_PROBE
908 if (probe_io)
909 do_io_probe(base, num);
910 #endif
911 break;
912 case REMOVE_MANAGED_RESOURCE:
913 sub_interval(&io_db, base, num);
914 break;
915 default:
916 ret = CS_UNSUPPORTED_FUNCTION;
917 break;
919 up(&rsrc_sem);
921 return ret;
924 /*====================================================================*/
926 static int adjust_irq(adjust_t *adj)
928 int ret = CS_SUCCESS;
929 #ifdef CONFIG_PCMCIA_PROBE
930 int irq;
931 irq_info_t *info;
933 irq = adj->resource.irq.IRQ;
934 if ((irq < 0) || (irq > 15))
935 return CS_BAD_IRQ;
936 info = &irq_table[irq];
938 down(&rsrc_sem);
939 switch (adj->Action) {
940 case ADD_MANAGED_RESOURCE:
941 if (info->Attributes & RES_REMOVED)
942 info->Attributes &= ~(RES_REMOVED|RES_ALLOCATED);
943 else
944 if (adj->Attributes & RES_ALLOCATED) {
945 ret = CS_IN_USE;
946 break;
948 if (adj->Attributes & RES_RESERVED)
949 info->Attributes |= RES_RESERVED;
950 else
951 info->Attributes &= ~RES_RESERVED;
952 break;
953 case REMOVE_MANAGED_RESOURCE:
954 if (info->Attributes & RES_REMOVED) {
955 ret = 0;
956 break;
958 if (info->Attributes & RES_ALLOCATED) {
959 ret = CS_IN_USE;
960 break;
962 info->Attributes |= RES_ALLOCATED|RES_REMOVED;
963 info->Attributes &= ~RES_RESERVED;
964 break;
965 default:
966 ret = CS_UNSUPPORTED_FUNCTION;
967 break;
969 up(&rsrc_sem);
970 #endif
971 return ret;
974 /*====================================================================*/
976 int pcmcia_adjust_resource_info(client_handle_t handle, adjust_t *adj)
978 if (CHECK_HANDLE(handle))
979 return CS_BAD_HANDLE;
981 switch (adj->Resource) {
982 case RES_MEMORY_RANGE:
983 return adjust_memory(adj);
984 break;
985 case RES_IO_RANGE:
986 return adjust_io(adj);
987 break;
988 case RES_IRQ:
989 return adjust_irq(adj);
990 break;
992 return CS_UNSUPPORTED_FUNCTION;
995 /*====================================================================*/
997 void release_resource_db(void)
999 resource_map_t *p, *q;
1001 for (p = mem_db.next; p != &mem_db; p = q) {
1002 q = p->next;
1003 kfree(p);
1005 for (p = io_db.next; p != &io_db; p = q) {
1006 q = p->next;
1007 kfree(p);