vserver 1.9.3
[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 static unsigned int rsrc_mem_probe;
92 #define MEM_PROBE_LOW   (1 << 0)
93 #define MEM_PROBE_HIGH  (1 << 1)
94
95 #ifdef CONFIG_PCMCIA_PROBE
96
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;
102
103 /* Table of IRQ assignments */
104 static irq_info_t irq_table[NR_IRQS];
105
106 #endif
107
108 /*======================================================================
109
110     Linux resource management extensions
111
112 ======================================================================*/
113
114 static struct resource *
115 make_resource(unsigned long b, unsigned long n, int flags, char *name)
116 {
117         struct resource *res = kmalloc(sizeof(*res), GFP_KERNEL);
118
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;
125         }
126         return res;
127 }
128
129 static struct resource *
130 claim_region(struct pcmcia_socket *s, unsigned long base, unsigned long size,
131              int type, char *name)
132 {
133         struct resource *res, *parent;
134
135         parent = type & IORESOURCE_MEM ? &iomem_resource : &ioport_resource;
136         res = make_resource(base, size, type | IORESOURCE_BUSY, name);
137
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;
146                 }
147         }
148         return res;
149 }
150
151 static void free_region(struct resource *res)
152 {
153         if (res) {
154                 release_resource(res);
155                 kfree(res);
156         }
157 }
158
159 /*======================================================================
160
161     These manage the internal databases of available resources.
162     
163 ======================================================================*/
164
165 static int add_interval(resource_map_t *map, u_long base, u_long num)
166 {
167     resource_map_t *p, *q;
168
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;
174     }
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;
180 }
181
182 /*====================================================================*/
183
184 static int sub_interval(resource_map_t *map, u_long base, u_long num)
185 {
186     resource_map_t *p, *q;
187
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;
204                 }
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;
216             }
217         }
218     }
219     return CS_SUCCESS;
220 }
221
222 /*======================================================================
223
224     These routines examine a region of IO or memory addresses to
225     determine what ranges might be genuinely available.
226     
227 ======================================================================*/
228
229 #ifdef CONFIG_PCMCIA_PROBE
230 static void do_io_probe(ioaddr_t base, ioaddr_t num)
231 {
232     struct resource *res;
233     ioaddr_t i, j, bad, any;
234     u_char *b, hole, most;
235     
236     printk(KERN_INFO "cs: IO port probe 0x%04x-0x%04x:",
237            base, base+num-1);
238     
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;
244     }   
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;
257     }
258     kfree(b);
259
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;
278             }
279         }
280     }
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);
288         }
289     }
290     
291     printk(any ? "\n" : " clean.\n");
292 }
293 #endif
294
295 /*======================================================================
296
297     This is tricky... when we set up CIS memory, we try to validate
298     the memory window space allocations.
299     
300 ======================================================================*/
301
302 /* Validation function for cards with a valid CIS */
303 static int readable(struct pcmcia_socket *s, struct resource *res, cisinfo_t *info)
304 {
305         int ret = -1;
306
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);
315         }
316         s->cis_mem.res = NULL;
317         if ((ret != 0) || (info->Chains == 0))
318                 return 0;
319         return 1;
320 }
321
322 /* Validation function for simple memory cards */
323 static int checksum(struct pcmcia_socket *s, struct resource *res)
324 {
325         pccard_mem_map map;
326         int i, a = 0, b = -1, d;
327         void __iomem *virt;
328
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);
337
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;
343                 }
344
345                 map.flags = 0;
346                 s->ops->set_mem_map(s, &map);
347
348                 iounmap(virt);
349         }
350
351         return (b == -1) ? -1 : (a>>1);
352 }
353
354 static int
355 cis_readable(struct pcmcia_socket *s, unsigned long base, unsigned long size)
356 {
357         struct resource *res1, *res2;
358         cisinfo_t info1, info2;
359         int ret = 0;
360
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");
363
364         if (res1 && res2) {
365                 ret = readable(s, res1, &info1);
366                 ret += readable(s, res2, &info2);
367         }
368
369         free_region(res2);
370         free_region(res1);
371
372         return (ret == 2) && (info1.Chains == info2.Chains);
373 }
374
375 static int
376 checksum_match(struct pcmcia_socket *s, unsigned long base, unsigned long size)
377 {
378         struct resource *res1, *res2;
379         int a = -1, b = -1;
380
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");
383
384         if (res1 && res2) {
385                 a = checksum(s, res1);
386                 b = checksum(s, res2);
387         }
388
389         free_region(res2);
390         free_region(res1);
391
392         return (a == b) && (a >= 0);
393 }
394
395 /*======================================================================
396
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.
400     
401 ======================================================================*/
402
403 static int do_mem_probe(u_long base, u_long num, struct pcmcia_socket *s)
404 {
405     u_long i, j, bad, fail, step;
406
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;
419             }
420             fail = ((i == base) && (j == base+num));
421         }
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;
427         }
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;
433         }
434     }
435     printk(bad ? "\n" : " clean.\n");
436     return (num - bad);
437 }
438
439 #ifdef CONFIG_PCMCIA_PROBE
440
441 static u_long inv_probe(resource_map_t *m, struct pcmcia_socket *s)
442 {
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;
451     }
452     if (m->base < 0x100000)
453         return 0;
454     return do_mem_probe(m->base, m->num, s);
455 }
456
457 static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
458 {
459     resource_map_t *m, mm;
460     static u_char order[] = { 0xd0, 0xe0, 0xc0, 0xf0 };
461     u_long b, i, ok = 0;
462
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");
469     }
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;
479         }
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);
488             }
489         }
490     }
491 }
492
493 #else /* CONFIG_PCMCIA_PROBE */
494
495 static void validate_mem(struct pcmcia_socket *s, unsigned int probe_mask)
496 {
497         resource_map_t *m, mm;
498     
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;
503         }
504 }
505
506 #endif /* CONFIG_PCMCIA_PROBE */
507
508 /*
509  * Locking note: this is the only place where we take
510  * both rsrc_sem and skt_sem.
511  */
512 void pcmcia_validate_mem(struct pcmcia_socket *s)
513 {
514         if (probe_mem) {
515                 unsigned int probe_mask;
516
517                 down(&rsrc_sem);
518
519                 probe_mask = MEM_PROBE_LOW;
520                 if (s->features & SS_CAP_PAGE_REGS)
521                         probe_mask = MEM_PROBE_HIGH;
522
523                 if (probe_mask & ~rsrc_mem_probe) {
524                         rsrc_mem_probe |= probe_mask;
525
526                         down(&s->skt_sem);
527
528                         if (s->state & SOCKET_PRESENT)
529                                 validate_mem(s, probe_mask);
530
531                         up(&s->skt_sem);
532                 }
533
534                 up(&rsrc_sem);
535         }
536 }
537
538 EXPORT_SYMBOL(pcmcia_validate_mem);
539
540 struct pcmcia_align_data {
541         unsigned long   mask;
542         unsigned long   offset;
543         resource_map_t  *map;
544 };
545
546 static void
547 pcmcia_common_align(void *align_data, struct resource *res,
548                     unsigned long size, unsigned long align)
549 {
550         struct pcmcia_align_data *data = align_data;
551         unsigned long start;
552         /*
553          * Ensure that we have the correct start address
554          */
555         start = (res->start & ~data->mask) + data->offset;
556         if (start < res->start)
557                 start += data->mask + 1;
558         res->start = start;
559 }
560
561 static void
562 pcmcia_align(void *align_data, struct resource *res,
563              unsigned long size, unsigned long align)
564 {
565         struct pcmcia_align_data *data = align_data;
566         resource_map_t *m;
567
568         pcmcia_common_align(data, res, size, align);
569
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;
573
574                 /*
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.
578                  */
579                 if (res->start < start) {
580                         res->start = start;
581                         pcmcia_common_align(data, res, size, align);
582                 }
583
584                 /*
585                  * If we're above the area which was passed in, there's
586                  * no point proceeding.
587                  */
588                 if (res->start >= res->end)
589                         break;
590
591                 if ((res->start + size - 1) <= end)
592                         break;
593         }
594
595         /*
596          * If we failed to find something suitable, ensure we fail.
597          */
598         if (m == data->map)
599                 res->start = res->end;
600 }
601
602 /*
603  * Adjust an existing IO region allocation, but making sure that we don't
604  * encroach outside the resources which the user supplied.
605  */
606 int adjust_io_region(struct resource *res, unsigned long r_start,
607                      unsigned long r_end, struct pcmcia_socket *s)
608 {
609         resource_map_t *m;
610         int ret = -ENOMEM;
611
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;
616
617                 if (start > r_start || r_end > end)
618                         continue;
619
620                 ret = adjust_resource(res, r_start, r_end - r_start + 1);
621                 break;
622         }
623         up(&rsrc_sem);
624
625         return ret;
626 }
627
628 /*======================================================================
629
630     These find ranges of I/O ports or memory addresses that are not
631     currently allocated by other devices.
632
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'.
638     
639 ======================================================================*/
640
641 struct resource *find_io_region(unsigned long base, int num,
642                    unsigned long align, char *name, struct pcmcia_socket *s)
643 {
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;
648
649         if (align == 0)
650                 align = 0x10000;
651
652         data.mask = align - 1;
653         data.offset = base & data.mask;
654         data.map = &io_db;
655
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);
666
667         if (ret != 0) {
668                 kfree(res);
669                 res = NULL;
670         }
671         return res;
672 }
673
674 struct resource *find_mem_region(u_long base, u_long num, u_long align,
675                                  int low, char *name, struct pcmcia_socket *s)
676 {
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;
681
682         low = low || !(s->features & SS_CAP_PAGE_REGS);
683
684         data.mask = align - 1;
685         data.offset = base & data.mask;
686         data.map = &mem_db;
687
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;
695                 }
696
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;
711         }
712
713         if (ret != 0) {
714                 kfree(res);
715                 res = NULL;
716         }
717         return res;
718 }
719
720 /*======================================================================
721
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.
725     
726 ======================================================================*/
727
728 #ifdef CONFIG_PCMCIA_PROBE
729
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)
732 {
733     if (request_irq(irq, fake_irq, 0, "bogus", NULL) != 0)
734         return -1;
735     free_irq(irq, NULL);
736     return 0;
737 }
738
739 int try_irq(u_int Attributes, int irq, int specific)
740 {
741     irq_info_t *info = &irq_table[irq];
742     int ret = 0;
743
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;
755             }
756             if (Attributes & IRQ_FIRST_SHARED) {
757                 ret = CS_BAD_ATTRIBUTE;
758                 break;
759             }
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;
768             }
769             if (Attributes & IRQ_FIRST_SHARED) {
770                 ret = CS_BAD_ATTRIBUTE;
771                 break;
772             }
773             info->Attributes |= RES_IRQ_TYPE_DYNAMIC | RES_ALLOCATED;
774             info->dyn_share++;
775             break;
776         }
777     } else {
778         if ((info->Attributes & RES_RESERVED) && !specific) {
779             ret = CS_IN_USE;
780             goto out;
781         }
782         if (check_irq(irq) != 0) {
783             ret = CS_IN_USE;
784             goto out;
785         }
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;
794             }
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;
802             }
803             info->Attributes |= RES_IRQ_TYPE_DYNAMIC | RES_ALLOCATED;
804             info->dyn_share = 1;
805             break;
806         }
807     }
808  out:
809     up(&rsrc_sem);
810     return ret;
811 }
812
813 #endif
814
815 /*====================================================================*/
816
817 #ifdef CONFIG_PCMCIA_PROBE
818
819 void undo_irq(u_int Attributes, int irq)
820 {
821     irq_info_t *info;
822
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;
839     }
840     up(&rsrc_sem);
841 }
842
843 #endif
844
845 /*======================================================================
846
847     The various adjust_* calls form the external interface to the
848     resource database.
849     
850 ======================================================================*/
851
852 static int adjust_memory(adjust_t *adj)
853 {
854     u_long base, num;
855     int ret;
856
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;
861
862     ret = CS_SUCCESS;
863
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);
877         }
878         break;
879     default:
880         ret = CS_UNSUPPORTED_FUNCTION;
881     }
882     up(&rsrc_sem);
883     
884     return ret;
885 }
886
887 /*====================================================================*/
888
889 static int adjust_io(adjust_t *adj)
890 {
891     int base, num, ret = CS_SUCCESS;
892     
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;
899
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;
906         }
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;
918     }
919     up(&rsrc_sem);
920
921     return ret;
922 }
923
924 /*====================================================================*/
925
926 static int adjust_irq(adjust_t *adj)
927 {
928     int ret = CS_SUCCESS;
929 #ifdef CONFIG_PCMCIA_PROBE
930     int irq;
931     irq_info_t *info;
932     
933     irq = adj->resource.irq.IRQ;
934     if ((irq < 0) || (irq > 15))
935         return CS_BAD_IRQ;
936     info = &irq_table[irq];
937
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;
947             }
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;
957         }
958         if (info->Attributes & RES_ALLOCATED) {
959             ret = CS_IN_USE;
960             break;
961         }
962         info->Attributes |= RES_ALLOCATED|RES_REMOVED;
963         info->Attributes &= ~RES_RESERVED;
964         break;
965     default:
966         ret = CS_UNSUPPORTED_FUNCTION;
967         break;
968     }
969     up(&rsrc_sem);
970 #endif
971     return ret;
972 }
973
974 /*====================================================================*/
975
976 int pcmcia_adjust_resource_info(client_handle_t handle, adjust_t *adj)
977 {
978     if (CHECK_HANDLE(handle))
979         return CS_BAD_HANDLE;
980     
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;
991     }
992     return CS_UNSUPPORTED_FUNCTION;
993 }
994
995 /*====================================================================*/
996
997 void release_resource_db(void)
998 {
999     resource_map_t *p, *q;
1000     
1001     for (p = mem_db.next; p != &mem_db; p = q) {
1002         q = p->next;
1003         kfree(p);
1004     }
1005     for (p = io_db.next; p != &io_db; p = q) {
1006         q = p->next;
1007         kfree(p);
1008     }
1009 }