VServer 1.9.2 (patch-2.6.8.1-vs1.9.2.diff)
[linux-2.6.git] / drivers / pcmcia / rsrc_mgr.c
1 /*======================================================================
2
3     Resource management routines
4
5     rsrc_mgr.c 1.79 2000/08/30 20:23:58
6
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/
11
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.
16
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.
20
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.
31     
32 ======================================================================*/
33
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>
48
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"
55
56 /*====================================================================*/
57
58 /* Parameters that can be set with 'insmod' */
59
60 #define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0444)
61
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
67
68 /*======================================================================
69
70     The resource_map_t structures are used to track what resources are
71     available for allocation for PC Card devices.
72
73 ======================================================================*/
74
75 typedef struct resource_map_t {
76     u_long                      base, num;
77     struct resource_map_t       *next;
78 } resource_map_t;
79
80 /* Memory resource database */
81 static resource_map_t mem_db = {
82         .next   = &mem_db,
83 };
84
85 /* IO port resource database */
86 static resource_map_t io_db = {
87         .next   = &io_db,
88 };
89
90 static DECLARE_MUTEX(rsrc_sem);
91
92 #ifdef CONFIG_PCMCIA_PROBE
93
94 typedef struct irq_info_t {
95     u_int                       Attributes;
96     int                         time_share, dyn_share;
97     struct pcmcia_socket        *Socket;
98 } irq_info_t;
99
100 /* Table of IRQ assignments */
101 static irq_info_t irq_table[NR_IRQS];
102
103 #endif
104
105 /*======================================================================
106
107     Linux resource management extensions
108
109 ======================================================================*/
110
111 static struct resource *
112 make_resource(unsigned long b, unsigned long n, int flags, char *name)
113 {
114         struct resource *res = kmalloc(sizeof(*res), GFP_KERNEL);
115
116         if (res) {
117                 memset(res, 0, sizeof(*res));
118                 res->name = name;
119                 res->start = b;
120                 res->end = b + n - 1;
121                 res->flags = flags;
122         }
123         return res;
124 }
125
126 static struct resource *
127 claim_region(struct pcmcia_socket *s, unsigned long base, unsigned long size,
128              int type, char *name)
129 {
130         struct resource *res, *parent;
131
132         parent = type & IORESOURCE_MEM ? &iomem_resource : &ioport_resource;
133         res = make_resource(base, size, type | IORESOURCE_BUSY, name);
134
135         if (res) {
136 #ifdef CONFIG_PCI
137                 if (s && s->cb_dev)
138                         parent = pci_find_parent_resource(s->cb_dev, res);
139 #endif
140                 if (!parent || request_resource(parent, res)) {
141                         kfree(res);
142                         res = NULL;
143                 }
144         }
145         return res;
146 }
147
148 static void free_region(struct resource *res)
149 {
150         if (res) {
151                 release_resource(res);
152                 kfree(res);
153         }
154 }
155
156 /*======================================================================
157
158     These manage the internal databases of available resources.
159     
160 ======================================================================*/
161
162 static int add_interval(resource_map_t *map, u_long base, u_long num)
163 {
164     resource_map_t *p, *q;
165
166     for (p = map; ; p = p->next) {
167         if ((p != map) && (p->base+p->num-1 >= base))
168             return -1;
169         if ((p->next == map) || (p->next->base > base+num-1))
170             break;
171     }
172     q = kmalloc(sizeof(resource_map_t), GFP_KERNEL);
173     if (!q) return CS_OUT_OF_RESOURCE;
174     q->base = base; q->num = num;
175     q->next = p->next; p->next = q;
176     return CS_SUCCESS;
177 }
178
179 /*====================================================================*/
180
181 static int sub_interval(resource_map_t *map, u_long base, u_long num)
182 {
183     resource_map_t *p, *q;
184
185     for (p = map; ; p = q) {
186         q = p->next;
187         if (q == map)
188             break;
189         if ((q->base+q->num > base) && (base+num > q->base)) {
190             if (q->base >= base) {
191                 if (q->base+q->num <= base+num) {
192                     /* Delete whole block */
193                     p->next = q->next;
194                     kfree(q);
195                     /* don't advance the pointer yet */
196                     q = p;
197                 } else {
198                     /* Cut off bit from the front */
199                     q->num = q->base + q->num - base - num;
200                     q->base = base + num;
201                 }
202             } else if (q->base+q->num <= base+num) {
203                 /* Cut off bit from the end */
204                 q->num = base - q->base;
205             } else {
206                 /* Split the block into two pieces */
207                 p = kmalloc(sizeof(resource_map_t), GFP_KERNEL);
208                 if (!p) return CS_OUT_OF_RESOURCE;
209                 p->base = base+num;
210                 p->num = q->base+q->num - p->base;
211                 q->num = base - q->base;
212                 p->next = q->next ; q->next = p;
213             }
214         }
215     }
216     return CS_SUCCESS;
217 }
218
219 /*======================================================================
220
221     These routines examine a region of IO or memory addresses to
222     determine what ranges might be genuinely available.
223     
224 ======================================================================*/
225
226 #ifdef CONFIG_PCMCIA_PROBE
227 static void do_io_probe(ioaddr_t base, ioaddr_t num)
228 {
229     struct resource *res;
230     ioaddr_t i, j, bad, any;
231     u_char *b, hole, most;
232     
233     printk(KERN_INFO "cs: IO port probe 0x%04x-0x%04x:",
234            base, base+num-1);
235     
236     /* First, what does a floating port look like? */
237     b = kmalloc(256, GFP_KERNEL);
238     if (!b) {
239             printk(KERN_ERR "do_io_probe: unable to kmalloc 256 bytes");
240             return;
241     }   
242     memset(b, 0, 256);
243     for (i = base, most = 0; i < base+num; i += 8) {
244         res = claim_region(NULL, i, 8, IORESOURCE_IO, "PCMCIA IO probe");
245         if (!res)
246             continue;
247         hole = inb(i);
248         for (j = 1; j < 8; j++)
249             if (inb(i+j) != hole) break;
250         free_region(res);
251         if ((j == 8) && (++b[hole] > b[most]))
252             most = hole;
253         if (b[most] == 127) break;
254     }
255     kfree(b);
256
257     bad = any = 0;
258     for (i = base; i < base+num; i += 8) {
259         res = claim_region(NULL, i, 8, IORESOURCE_IO, "PCMCIA IO probe");
260         if (!res)
261             continue;
262         for (j = 0; j < 8; j++)
263             if (inb(i+j) != most) break;
264         free_region(res);
265         if (j < 8) {
266             if (!any)
267                 printk(" excluding");
268             if (!bad)
269                 bad = any = i;
270         } else {
271             if (bad) {
272                 sub_interval(&io_db, bad, i-bad);
273                 printk(" %#04x-%#04x", bad, i-1);
274                 bad = 0;
275             }
276         }
277     }
278     if (bad) {
279         if ((num > 16) && (bad == base) && (i == base+num)) {
280             printk(" nothing: probe failed.\n");
281             return;
282         } else {
283             sub_interval(&io_db, bad, i-bad);
284             printk(" %#04x-%#04x", bad, i-1);
285         }
286     }
287     
288     printk(any ? "\n" : " clean.\n");
289 }
290 #endif
291
292 /*======================================================================
293
294     This is tricky... when we set up CIS memory, we try to validate
295     the memory window space allocations.
296     
297 ======================================================================*/
298
299 /* Validation function for cards with a valid CIS */
300 static int readable(struct pcmcia_socket *s, struct resource *res, cisinfo_t *info)
301 {
302         int ret = -1;
303
304         s->cis_mem.sys_start = res->start;
305         s->cis_mem.sys_stop = res->end;
306         s->cis_mem.res = res;
307         s->cis_virt = ioremap(res->start, s->map_size);
308         if (s->cis_virt) {
309                 ret = pcmcia_validate_cis(s->clients, info);
310                 /* invalidate mapping and CIS cache */
311                 iounmap(s->cis_virt);
312                 s->cis_virt = NULL;
313                 destroy_cis_cache(s);
314         }
315         s->cis_mem.sys_start = 0;
316         s->cis_mem.sys_stop = 0;
317         s->cis_mem.res = NULL;
318         if ((ret != 0) || (info->Chains == 0))
319                 return 0;
320         return 1;
321 }
322
323 /* Validation function for simple memory cards */
324 static int checksum(struct pcmcia_socket *s, struct resource *res)
325 {
326         pccard_mem_map map;
327         int i, a = 0, b = -1, d;
328         void *virt;
329
330         virt = ioremap(res->start, s->map_size);
331         if (virt) {
332                 map.map = 0;
333                 map.flags = MAP_ACTIVE;
334                 map.speed = 0;
335                 map.sys_start = res->start;
336                 map.sys_stop = res->end;
337                 map.res = res;
338                 map.card_start = 0;
339                 s->ops->set_mem_map(s, &map);
340
341                 /* Don't bother checking every word... */
342                 for (i = 0; i < s->map_size; i += 44) {
343                         d = readl(virt+i);
344                         a += d;
345                         b &= d;
346                 }
347
348                 map.flags = 0;
349                 s->ops->set_mem_map(s, &map);
350
351                 iounmap(virt);
352         }
353
354         return (b == -1) ? -1 : (a>>1);
355 }
356
357 static int
358 cis_readable(struct pcmcia_socket *s, unsigned long base, unsigned long size)
359 {
360         struct resource *res1, *res2;
361         cisinfo_t info1, info2;
362         int ret = 0;
363
364         res1 = claim_region(s, base, size/2, IORESOURCE_MEM, "cs memory probe");
365         res2 = claim_region(s, base + size/2, size/2, IORESOURCE_MEM, "cs memory probe");
366
367         if (res1 && res2) {
368                 ret = readable(s, res1, &info1);
369                 ret += readable(s, res2, &info2);
370         }
371
372         free_region(res2);
373         free_region(res1);
374
375         return (ret == 2) && (info1.Chains == info2.Chains);
376 }
377
378 static int
379 checksum_match(struct pcmcia_socket *s, unsigned long base, unsigned long size)
380 {
381         struct resource *res1, *res2;
382         int a = -1, b = -1;
383
384         res1 = claim_region(s, base, size/2, IORESOURCE_MEM, "cs memory probe");
385         res2 = claim_region(s, base + size/2, size/2, IORESOURCE_MEM, "cs memory probe");
386
387         if (res1 && res2) {
388                 a = checksum(s, res1);
389                 b = checksum(s, res2);
390         }
391
392         free_region(res2);
393         free_region(res1);
394
395         return (a == b) && (a >= 0);
396 }
397
398 /*======================================================================
399
400     The memory probe.  If the memory list includes a 64K-aligned block
401     below 1MB, we probe in 64K chunks, and as soon as we accumulate at
402     least mem_limit free space, we quit.
403     
404 ======================================================================*/
405
406 static int do_mem_probe(u_long base, u_long num, struct pcmcia_socket *s)
407 {
408     u_long i, j, bad, fail, step;
409
410     printk(KERN_INFO "cs: memory probe 0x%06lx-0x%06lx:",
411            base, base+num-1);
412     bad = fail = 0;
413     step = (num < 0x20000) ? 0x2000 : ((num>>4) & ~0x1fff);
414     /* cis_readable wants to map 2x map_size */
415     if (step < 2 * s->map_size)
416         step = 2 * s->map_size;
417     for (i = j = base; i < base+num; i = j + step) {
418         if (!fail) {    
419             for (j = i; j < base+num; j += step) {
420                 if (cis_readable(s, j, step))
421                     break;
422             }
423             fail = ((i == base) && (j == base+num));
424         }
425         if (fail) {
426             for (j = i; j < base+num; j += 2*step)
427                 if (checksum_match(s, j, step) &&
428                     checksum_match(s, j + step, step))
429                     break;
430         }
431         if (i != j) {
432             if (!bad) printk(" excluding");
433             printk(" %#05lx-%#05lx", i, j-1);
434             sub_interval(&mem_db, i, j-i);
435             bad += j-i;
436         }
437     }
438     printk(bad ? "\n" : " clean.\n");
439     return (num - bad);
440 }
441
442 #ifdef CONFIG_PCMCIA_PROBE
443
444 static u_long inv_probe(resource_map_t *m, struct pcmcia_socket *s)
445 {
446     u_long ok;
447     if (m == &mem_db)
448         return 0;
449     ok = inv_probe(m->next, s);
450     if (ok) {
451         if (m->base >= 0x100000)
452             sub_interval(&mem_db, m->base, m->num);
453         return ok;
454     }
455     if (m->base < 0x100000)
456         return 0;
457     return do_mem_probe(m->base, m->num, s);
458 }
459
460 static void validate_mem(struct pcmcia_socket *s)
461 {
462     resource_map_t *m, mm;
463     static u_char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 };
464     static int hi = 0, lo = 0;
465     u_long b, i, ok = 0;
466     int force_low = !(s->features & SS_CAP_PAGE_REGS);
467
468     down(&rsrc_sem);
469     /* We do up to four passes through the list */
470     if (!force_low) {
471         if (hi++ || (inv_probe(mem_db.next, s) > 0))
472             goto out;
473         printk(KERN_NOTICE "cs: warning: no high memory space "
474                "available!\n");
475     }
476     if (lo++)
477         goto out;
478     for (m = mem_db.next; m != &mem_db; m = mm.next) {
479         mm = *m;
480         /* Only probe < 1 MB */
481         if (mm.base >= 0x100000) continue;
482         if ((mm.base | mm.num) & 0xffff) {
483             ok += do_mem_probe(mm.base, mm.num, s);
484             continue;
485         }
486         /* Special probe for 64K-aligned block */
487         for (i = 0; i < 4; i++) {
488             b = order[i] << 12;
489             if ((b >= mm.base) && (b+0x10000 <= mm.base+mm.num)) {
490                 if (ok >= mem_limit)
491                     sub_interval(&mem_db, b, 0x10000);
492                 else
493                     ok += do_mem_probe(b, 0x10000, s);
494             }
495         }
496     }
497  out:
498     up(&rsrc_sem);
499 }
500
501 #else /* CONFIG_PCMCIA_PROBE */
502
503 static void validate_mem(struct pcmcia_socket *s)
504 {
505     resource_map_t *m, mm;
506     static int done = 0;
507     
508     if (done++ == 0) {
509         down(&rsrc_sem);
510         for (m = mem_db.next; m != &mem_db; m = mm.next) {
511             mm = *m;
512             if (do_mem_probe(mm.base, mm.num, s))
513                 break;
514         }
515         up(&rsrc_sem);
516     }
517 }
518
519 #endif /* CONFIG_PCMCIA_PROBE */
520
521 void pcmcia_validate_mem(struct pcmcia_socket *s)
522 {
523         down(&s->skt_sem);
524
525         if (probe_mem && s->state & SOCKET_PRESENT)
526                 validate_mem(s);
527
528         up(&s->skt_sem);
529 }
530
531 EXPORT_SYMBOL(pcmcia_validate_mem);
532
533 struct pcmcia_align_data {
534         unsigned long   mask;
535         unsigned long   offset;
536         resource_map_t  *map;
537 };
538
539 static void
540 pcmcia_common_align(void *align_data, struct resource *res,
541                     unsigned long size, unsigned long align)
542 {
543         struct pcmcia_align_data *data = align_data;
544         unsigned long start;
545         /*
546          * Ensure that we have the correct start address
547          */
548         start = (res->start & ~data->mask) + data->offset;
549         if (start < res->start)
550                 start += data->mask + 1;
551         res->start = start;
552 }
553
554 static void
555 pcmcia_align(void *align_data, struct resource *res,
556              unsigned long size, unsigned long align)
557 {
558         struct pcmcia_align_data *data = align_data;
559         resource_map_t *m;
560
561         pcmcia_common_align(data, res, size, align);
562
563         for (m = data->map->next; m != data->map; m = m->next) {
564                 unsigned long start = m->base;
565                 unsigned long end = m->base + m->num - 1;
566
567                 /*
568                  * If the lower resources are not available, try aligning
569                  * to this entry of the resource database to see if it'll
570                  * fit here.
571                  */
572                 if (res->start < start) {
573                         res->start = start;
574                         pcmcia_common_align(data, res, size, align);
575                 }
576
577                 /*
578                  * If we're above the area which was passed in, there's
579                  * no point proceeding.
580                  */
581                 if (res->start >= res->end)
582                         break;
583
584                 if ((res->start + size - 1) <= end)
585                         break;
586         }
587
588         /*
589          * If we failed to find something suitable, ensure we fail.
590          */
591         if (m == data->map)
592                 res->start = res->end;
593 }
594
595 /*
596  * Adjust an existing IO region allocation, but making sure that we don't
597  * encroach outside the resources which the user supplied.
598  */
599 int adjust_io_region(struct resource *res, unsigned long r_start,
600                      unsigned long r_end, struct pcmcia_socket *s)
601 {
602         resource_map_t *m;
603         int ret = -ENOMEM;
604
605         down(&rsrc_sem);
606         for (m = io_db.next; m != &io_db; m = m->next) {
607                 unsigned long start = m->base;
608                 unsigned long end = m->base + m->num - 1;
609
610                 if (start > r_start || r_end > end)
611                         continue;
612
613                 ret = adjust_resource(res, r_start, r_end - r_start + 1);
614                 break;
615         }
616         up(&rsrc_sem);
617
618         return ret;
619 }
620
621 /*======================================================================
622
623     These find ranges of I/O ports or memory addresses that are not
624     currently allocated by other devices.
625
626     The 'align' field should reflect the number of bits of address
627     that need to be preserved from the initial value of *base.  It
628     should be a power of two, greater than or equal to 'num'.  A value
629     of 0 means that all bits of *base are significant.  *base should
630     also be strictly less than 'align'.
631     
632 ======================================================================*/
633
634 struct resource *find_io_region(unsigned long base, int num,
635                    unsigned long align, char *name, struct pcmcia_socket *s)
636 {
637         struct resource *res = make_resource(0, num, IORESOURCE_IO, s->dev.class_id);
638         struct pcmcia_align_data data;
639         unsigned long min = base;
640         int ret;
641
642         if (align == 0)
643                 align = 0x10000;
644
645         data.mask = align - 1;
646         data.offset = base & data.mask;
647         data.map = &io_db;
648
649         down(&rsrc_sem);
650 #ifdef CONFIG_PCI
651         if (s->cb_dev) {
652                 ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num, 1,
653                                              min, 0, pcmcia_align, &data);
654         } else
655 #endif
656                 ret = allocate_resource(&ioport_resource, res, num, min, ~0UL,
657                                         1, pcmcia_align, &data);
658         up(&rsrc_sem);
659
660         if (ret != 0) {
661                 kfree(res);
662                 res = NULL;
663         }
664         return res;
665 }
666
667 struct resource *find_mem_region(u_long base, u_long num, u_long align,
668                                  int low, char *name, struct pcmcia_socket *s)
669 {
670         struct resource *res = make_resource(0, num, IORESOURCE_MEM, s->dev.class_id);
671         struct pcmcia_align_data data;
672         unsigned long min, max;
673         int ret, i;
674
675         low = low || !(s->features & SS_CAP_PAGE_REGS);
676
677         data.mask = align - 1;
678         data.offset = base & data.mask;
679         data.map = &mem_db;
680
681         for (i = 0; i < 2; i++) {
682                 if (low) {
683                         max = 0x100000UL;
684                         min = base < max ? base : 0;
685                 } else {
686                         max = ~0UL;
687                         min = 0x100000UL + base;
688                 }
689
690                 down(&rsrc_sem);
691 #ifdef CONFIG_PCI
692                 if (s->cb_dev) {
693                         ret = pci_bus_alloc_resource(s->cb_dev->bus, res, num,
694                                                      1, min, 0,
695                                                      pcmcia_align, &data);
696                 } else
697 #endif
698                         ret = allocate_resource(&iomem_resource, res, num, min,
699                                                 max, 1, pcmcia_align, &data);
700                 up(&rsrc_sem);
701                 if (ret == 0 || low)
702                         break;
703                 low = 1;
704         }
705
706         if (ret != 0) {
707                 kfree(res);
708                 res = NULL;
709         }
710         return res;
711 }
712
713 /*======================================================================
714
715     This checks to see if an interrupt is available, with support
716     for interrupt sharing.  We don't support reserving interrupts
717     yet.  If the interrupt is available, we allocate it.
718     
719 ======================================================================*/
720
721 #ifdef CONFIG_PCMCIA_PROBE
722
723 static irqreturn_t fake_irq(int i, void *d, struct pt_regs *r) { return IRQ_NONE; }
724 static inline int check_irq(int irq)
725 {
726     if (request_irq(irq, fake_irq, 0, "bogus", NULL) != 0)
727         return -1;
728     free_irq(irq, NULL);
729     return 0;
730 }
731
732 int try_irq(u_int Attributes, int irq, int specific)
733 {
734     irq_info_t *info = &irq_table[irq];
735     int ret = 0;
736
737     down(&rsrc_sem);
738     if (info->Attributes & RES_ALLOCATED) {
739         switch (Attributes & IRQ_TYPE) {
740         case IRQ_TYPE_EXCLUSIVE:
741             ret = CS_IN_USE;
742             break;
743         case IRQ_TYPE_TIME:
744             if ((info->Attributes & RES_IRQ_TYPE)
745                 != RES_IRQ_TYPE_TIME) {
746                 ret = CS_IN_USE;
747                 break;
748             }
749             if (Attributes & IRQ_FIRST_SHARED) {
750                 ret = CS_BAD_ATTRIBUTE;
751                 break;
752             }
753             info->Attributes |= RES_IRQ_TYPE_TIME | RES_ALLOCATED;
754             info->time_share++;
755             break;
756         case IRQ_TYPE_DYNAMIC_SHARING:
757             if ((info->Attributes & RES_IRQ_TYPE)
758                 != RES_IRQ_TYPE_DYNAMIC) {
759                 ret = CS_IN_USE;
760                 break;
761             }
762             if (Attributes & IRQ_FIRST_SHARED) {
763                 ret = CS_BAD_ATTRIBUTE;
764                 break;
765             }
766             info->Attributes |= RES_IRQ_TYPE_DYNAMIC | RES_ALLOCATED;
767             info->dyn_share++;
768             break;
769         }
770     } else {
771         if ((info->Attributes & RES_RESERVED) && !specific) {
772             ret = CS_IN_USE;
773             goto out;
774         }
775         if (check_irq(irq) != 0) {
776             ret = CS_IN_USE;
777             goto out;
778         }
779         switch (Attributes & IRQ_TYPE) {
780         case IRQ_TYPE_EXCLUSIVE:
781             info->Attributes |= RES_ALLOCATED;
782             break;
783         case IRQ_TYPE_TIME:
784             if (!(Attributes & IRQ_FIRST_SHARED)) {
785                 ret = CS_BAD_ATTRIBUTE;
786                 break;
787             }
788             info->Attributes |= RES_IRQ_TYPE_TIME | RES_ALLOCATED;
789             info->time_share = 1;
790             break;
791         case IRQ_TYPE_DYNAMIC_SHARING:
792             if (!(Attributes & IRQ_FIRST_SHARED)) {
793                 ret = CS_BAD_ATTRIBUTE;
794                 break;
795             }
796             info->Attributes |= RES_IRQ_TYPE_DYNAMIC | RES_ALLOCATED;
797             info->dyn_share = 1;
798             break;
799         }
800     }
801  out:
802     up(&rsrc_sem);
803     return ret;
804 }
805
806 #endif
807
808 /*====================================================================*/
809
810 #ifdef CONFIG_PCMCIA_PROBE
811
812 void undo_irq(u_int Attributes, int irq)
813 {
814     irq_info_t *info;
815
816     info = &irq_table[irq];
817     down(&rsrc_sem);
818     switch (Attributes & IRQ_TYPE) {
819     case IRQ_TYPE_EXCLUSIVE:
820         info->Attributes &= RES_RESERVED;
821         break;
822     case IRQ_TYPE_TIME:
823         info->time_share--;
824         if (info->time_share == 0)
825             info->Attributes &= RES_RESERVED;
826         break;
827     case IRQ_TYPE_DYNAMIC_SHARING:
828         info->dyn_share--;
829         if (info->dyn_share == 0)
830             info->Attributes &= RES_RESERVED;
831         break;
832     }
833     up(&rsrc_sem);
834 }
835
836 #endif
837
838 /*======================================================================
839
840     The various adjust_* calls form the external interface to the
841     resource database.
842     
843 ======================================================================*/
844
845 static int adjust_memory(adjust_t *adj)
846 {
847     u_long base, num;
848     int ret;
849
850     base = adj->resource.memory.Base;
851     num = adj->resource.memory.Size;
852     if ((num == 0) || (base+num-1 < base))
853         return CS_BAD_SIZE;
854
855     ret = CS_SUCCESS;
856
857     down(&rsrc_sem);
858     switch (adj->Action) {
859     case ADD_MANAGED_RESOURCE:
860         ret = add_interval(&mem_db, base, num);
861         break;
862     case REMOVE_MANAGED_RESOURCE:
863         ret = sub_interval(&mem_db, base, num);
864         if (ret == CS_SUCCESS) {
865                 struct pcmcia_socket *socket;
866                 down_read(&pcmcia_socket_list_rwsem);
867                 list_for_each_entry(socket, &pcmcia_socket_list, socket_list)
868                         release_cis_mem(socket);
869                 up_read(&pcmcia_socket_list_rwsem);
870         }
871         break;
872     default:
873         ret = CS_UNSUPPORTED_FUNCTION;
874     }
875     up(&rsrc_sem);
876     
877     return ret;
878 }
879
880 /*====================================================================*/
881
882 static int adjust_io(adjust_t *adj)
883 {
884     int base, num, ret = CS_SUCCESS;
885     
886     base = adj->resource.io.BasePort;
887     num = adj->resource.io.NumPorts;
888     if ((base < 0) || (base > 0xffff))
889         return CS_BAD_BASE;
890     if ((num <= 0) || (base+num > 0x10000) || (base+num <= base))
891         return CS_BAD_SIZE;
892
893     down(&rsrc_sem);
894     switch (adj->Action) {
895     case ADD_MANAGED_RESOURCE:
896         if (add_interval(&io_db, base, num) != 0) {
897             ret = CS_IN_USE;
898             break;
899         }
900 #ifdef CONFIG_PCMCIA_PROBE
901         if (probe_io)
902             do_io_probe(base, num);
903 #endif
904         break;
905     case REMOVE_MANAGED_RESOURCE:
906         sub_interval(&io_db, base, num);
907         break;
908     default:
909         ret = CS_UNSUPPORTED_FUNCTION;
910         break;
911     }
912     up(&rsrc_sem);
913
914     return ret;
915 }
916
917 /*====================================================================*/
918
919 static int adjust_irq(adjust_t *adj)
920 {
921     int ret = CS_SUCCESS;
922 #ifdef CONFIG_PCMCIA_PROBE
923     int irq;
924     irq_info_t *info;
925     
926     irq = adj->resource.irq.IRQ;
927     if ((irq < 0) || (irq > 15))
928         return CS_BAD_IRQ;
929     info = &irq_table[irq];
930
931     down(&rsrc_sem);
932     switch (adj->Action) {
933     case ADD_MANAGED_RESOURCE:
934         if (info->Attributes & RES_REMOVED)
935             info->Attributes &= ~(RES_REMOVED|RES_ALLOCATED);
936         else
937             if (adj->Attributes & RES_ALLOCATED) {
938                 ret = CS_IN_USE;
939                 break;
940             }
941         if (adj->Attributes & RES_RESERVED)
942             info->Attributes |= RES_RESERVED;
943         else
944             info->Attributes &= ~RES_RESERVED;
945         break;
946     case REMOVE_MANAGED_RESOURCE:
947         if (info->Attributes & RES_REMOVED) {
948             ret = 0;
949             break;
950         }
951         if (info->Attributes & RES_ALLOCATED) {
952             ret = CS_IN_USE;
953             break;
954         }
955         info->Attributes |= RES_ALLOCATED|RES_REMOVED;
956         info->Attributes &= ~RES_RESERVED;
957         break;
958     default:
959         ret = CS_UNSUPPORTED_FUNCTION;
960         break;
961     }
962     up(&rsrc_sem);
963 #endif
964     return ret;
965 }
966
967 /*====================================================================*/
968
969 int pcmcia_adjust_resource_info(client_handle_t handle, adjust_t *adj)
970 {
971     if (CHECK_HANDLE(handle))
972         return CS_BAD_HANDLE;
973     
974     switch (adj->Resource) {
975     case RES_MEMORY_RANGE:
976         return adjust_memory(adj);
977         break;
978     case RES_IO_RANGE:
979         return adjust_io(adj);
980         break;
981     case RES_IRQ:
982         return adjust_irq(adj);
983         break;
984     }
985     return CS_UNSUPPORTED_FUNCTION;
986 }
987
988 /*====================================================================*/
989
990 void release_resource_db(void)
991 {
992     resource_map_t *p, *q;
993     
994     for (p = mem_db.next; p != &mem_db; p = q) {
995         q = p->next;
996         kfree(p);
997     }
998     for (p = io_db.next; p != &io_db; p = q) {
999         q = p->next;
1000         kfree(p);
1001     }
1002 }