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>
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);
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
{
77 struct resource_map_t
*next
;
80 /* Memory resource database */
81 static resource_map_t mem_db
= {
85 /* IO port resource database */
86 static resource_map_t 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
{
99 int time_share
, dyn_share
;
100 struct pcmcia_socket
*Socket
;
103 /* Table of IRQ assignments */
104 static irq_info_t irq_table
[NR_IRQS
];
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
);
120 memset(res
, 0, sizeof(*res
));
123 res
->end
= b
+ n
- 1;
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
);
141 parent
= pci_find_parent_resource(s
->cb_dev
, res
);
143 if (!parent
|| request_resource(parent
, res
)) {
151 static void free_region(struct resource
*res
)
154 release_resource(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
))
172 if ((p
->next
== map
) || (p
->next
->base
> base
+num
-1))
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
;
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
) {
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 */
198 /* don't advance the pointer yet */
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
;
209 /* Split the block into two pieces */
210 p
= kmalloc(sizeof(resource_map_t
), GFP_KERNEL
);
211 if (!p
) return CS_OUT_OF_RESOURCE
;
213 p
->num
= q
->base
+q
->num
- p
->base
;
214 q
->num
= base
- q
->base
;
215 p
->next
= q
->next
; q
->next
= p
;
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:",
239 /* First, what does a floating port look like? */
240 b
= kmalloc(256, GFP_KERNEL
);
242 printk(KERN_ERR
"do_io_probe: unable to kmalloc 256 bytes");
246 for (i
= base
, most
= 0; i
< base
+num
; i
+= 8) {
247 res
= claim_region(NULL
, i
, 8, IORESOURCE_IO
, "PCMCIA IO probe");
251 for (j
= 1; j
< 8; j
++)
252 if (inb(i
+j
) != hole
) break;
254 if ((j
== 8) && (++b
[hole
] > b
[most
]))
256 if (b
[most
] == 127) break;
261 for (i
= base
; i
< base
+num
; i
+= 8) {
262 res
= claim_region(NULL
, i
, 8, IORESOURCE_IO
, "PCMCIA IO probe");
265 for (j
= 0; j
< 8; j
++)
266 if (inb(i
+j
) != most
) break;
270 printk(" excluding");
275 sub_interval(&io_db
, bad
, i
-bad
);
276 printk(" %#04x-%#04x", bad
, i
-1);
282 if ((num
> 16) && (bad
== base
) && (i
== base
+num
)) {
283 printk(" nothing: probe failed.\n");
286 sub_interval(&io_db
, bad
, i
-bad
);
287 printk(" %#04x-%#04x", bad
, i
-1);
291 printk(any
? "\n" : " clean.\n");
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
)
307 s
->cis_mem
.res
= res
;
308 s
->cis_virt
= ioremap(res
->start
, s
->map_size
);
310 ret
= pcmcia_validate_cis(s
->clients
, info
);
311 /* invalidate mapping and CIS cache */
312 iounmap(s
->cis_virt
);
314 destroy_cis_cache(s
);
316 s
->cis_mem
.res
= NULL
;
317 if ((ret
!= 0) || (info
->Chains
== 0))
322 /* Validation function for simple memory cards */
323 static int checksum(struct pcmcia_socket
*s
, struct resource
*res
)
326 int i
, a
= 0, b
= -1, d
;
329 virt
= ioremap(res
->start
, s
->map_size
);
332 map
.flags
= MAP_ACTIVE
;
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) {
346 s
->ops
->set_mem_map(s
, &map
);
351 return (b
== -1) ? -1 : (a
>>1);
355 cis_readable(struct pcmcia_socket
*s
, unsigned long base
, unsigned long size
)
357 struct resource
*res1
, *res2
;
358 cisinfo_t info1
, info2
;
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");
365 ret
= readable(s
, res1
, &info1
);
366 ret
+= readable(s
, res2
, &info2
);
372 return (ret
== 2) && (info1
.Chains
== info2
.Chains
);
376 checksum_match(struct pcmcia_socket
*s
, unsigned long base
, unsigned long size
)
378 struct resource
*res1
, *res2
;
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");
385 a
= checksum(s
, res1
);
386 b
= checksum(s
, res2
);
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:",
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
) {
416 for (j
= i
; j
< base
+num
; j
+= step
) {
417 if (cis_readable(s
, j
, step
))
420 fail
= ((i
== base
) && (j
== base
+num
));
423 for (j
= i
; j
< base
+num
; j
+= 2*step
)
424 if (checksum_match(s
, j
, step
) &&
425 checksum_match(s
, j
+ step
, step
))
429 if (!bad
) printk(" excluding");
430 printk(" %#05lx-%#05lx", i
, j
-1);
431 sub_interval(&mem_db
, i
, j
-i
);
435 printk(bad
? "\n" : " clean.\n");
439 #ifdef CONFIG_PCMCIA_PROBE
441 static u_long
inv_probe(resource_map_t
*m
, struct pcmcia_socket
*s
)
446 ok
= inv_probe(m
->next
, s
);
448 if (m
->base
>= 0x100000)
449 sub_interval(&mem_db
, m
->base
, m
->num
);
452 if (m
->base
< 0x100000)
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 };
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)
467 printk(KERN_NOTICE
"cs: warning: no high memory space "
470 if ((probe_mask
& MEM_PROBE_LOW
) == 0)
472 for (m
= mem_db
.next
; m
!= &mem_db
; m
= mm
.next
) {
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
);
480 /* Special probe for 64K-aligned block */
481 for (i
= 0; i
< 4; i
++) {
483 if ((b
>= mm
.base
) && (b
+0x10000 <= mm
.base
+mm
.num
)) {
485 sub_interval(&mem_db
, b
, 0x10000);
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
) {
501 if (do_mem_probe(mm
.base
, mm
.num
, s
))
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
)
515 unsigned int probe_mask
;
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
;
528 if (s
->state
& SOCKET_PRESENT
)
529 validate_mem(s
, probe_mask
);
538 EXPORT_SYMBOL(pcmcia_validate_mem
);
540 struct pcmcia_align_data
{
542 unsigned long offset
;
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
;
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;
562 pcmcia_align(void *align_data
, struct resource
*res
,
563 unsigned long size
, unsigned long align
)
565 struct pcmcia_align_data
*data
= align_data
;
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
579 if (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
)
591 if ((res
->start
+ size
- 1) <= end
)
596 * If we failed to find something suitable, ensure we fail.
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
)
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
)
620 ret
= adjust_resource(res
, r_start
, r_end
- r_start
+ 1);
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
;
652 data
.mask
= align
- 1;
653 data
.offset
= base
& data
.mask
;
659 ret
= pci_bus_alloc_resource(s
->cb_dev
->bus
, res
, num
, 1,
660 min
, 0, pcmcia_align
, &data
);
663 ret
= allocate_resource(&ioport_resource
, res
, num
, min
, ~0UL,
664 1, pcmcia_align
, &data
);
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
;
682 low
= low
|| !(s
->features
& SS_CAP_PAGE_REGS
);
684 data
.mask
= align
- 1;
685 data
.offset
= base
& data
.mask
;
688 for (i
= 0; i
< 2; i
++) {
691 min
= base
< max
? base
: 0;
694 min
= 0x100000UL
+ base
;
700 ret
= pci_bus_alloc_resource(s
->cb_dev
->bus
, res
, num
,
702 pcmcia_align
, &data
);
705 ret
= allocate_resource(&iomem_resource
, res
, num
, min
,
706 max
, 1, pcmcia_align
, &data
);
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)
739 int try_irq(u_int Attributes
, int irq
, int specific
)
741 irq_info_t
*info
= &irq_table
[irq
];
745 if (info
->Attributes
& RES_ALLOCATED
) {
746 switch (Attributes
& IRQ_TYPE
) {
747 case IRQ_TYPE_EXCLUSIVE
:
751 if ((info
->Attributes
& RES_IRQ_TYPE
)
752 != RES_IRQ_TYPE_TIME
) {
756 if (Attributes
& IRQ_FIRST_SHARED
) {
757 ret
= CS_BAD_ATTRIBUTE
;
760 info
->Attributes
|= RES_IRQ_TYPE_TIME
| RES_ALLOCATED
;
763 case IRQ_TYPE_DYNAMIC_SHARING
:
764 if ((info
->Attributes
& RES_IRQ_TYPE
)
765 != RES_IRQ_TYPE_DYNAMIC
) {
769 if (Attributes
& IRQ_FIRST_SHARED
) {
770 ret
= CS_BAD_ATTRIBUTE
;
773 info
->Attributes
|= RES_IRQ_TYPE_DYNAMIC
| RES_ALLOCATED
;
778 if ((info
->Attributes
& RES_RESERVED
) && !specific
) {
782 if (check_irq(irq
) != 0) {
786 switch (Attributes
& IRQ_TYPE
) {
787 case IRQ_TYPE_EXCLUSIVE
:
788 info
->Attributes
|= RES_ALLOCATED
;
791 if (!(Attributes
& IRQ_FIRST_SHARED
)) {
792 ret
= CS_BAD_ATTRIBUTE
;
795 info
->Attributes
|= RES_IRQ_TYPE_TIME
| RES_ALLOCATED
;
796 info
->time_share
= 1;
798 case IRQ_TYPE_DYNAMIC_SHARING
:
799 if (!(Attributes
& IRQ_FIRST_SHARED
)) {
800 ret
= CS_BAD_ATTRIBUTE
;
803 info
->Attributes
|= RES_IRQ_TYPE_DYNAMIC
| RES_ALLOCATED
;
815 /*====================================================================*/
817 #ifdef CONFIG_PCMCIA_PROBE
819 void undo_irq(u_int Attributes
, int irq
)
823 info
= &irq_table
[irq
];
825 switch (Attributes
& IRQ_TYPE
) {
826 case IRQ_TYPE_EXCLUSIVE
:
827 info
->Attributes
&= RES_RESERVED
;
831 if (info
->time_share
== 0)
832 info
->Attributes
&= RES_RESERVED
;
834 case IRQ_TYPE_DYNAMIC_SHARING
:
836 if (info
->dyn_share
== 0)
837 info
->Attributes
&= RES_RESERVED
;
845 /*======================================================================
847 The various adjust_* calls form the external interface to the
850 ======================================================================*/
852 static int adjust_memory(adjust_t
*adj
)
857 base
= adj
->resource
.memory
.Base
;
858 num
= adj
->resource
.memory
.Size
;
859 if ((num
== 0) || (base
+num
-1 < base
))
865 switch (adj
->Action
) {
866 case ADD_MANAGED_RESOURCE
:
867 ret
= add_interval(&mem_db
, base
, num
);
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
);
880 ret
= CS_UNSUPPORTED_FUNCTION
;
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))
897 if ((num
<= 0) || (base
+num
> 0x10000) || (base
+num
<= base
))
901 switch (adj
->Action
) {
902 case ADD_MANAGED_RESOURCE
:
903 if (add_interval(&io_db
, base
, num
) != 0) {
907 #ifdef CONFIG_PCMCIA_PROBE
909 do_io_probe(base
, num
);
912 case REMOVE_MANAGED_RESOURCE
:
913 sub_interval(&io_db
, base
, num
);
916 ret
= CS_UNSUPPORTED_FUNCTION
;
924 /*====================================================================*/
926 static int adjust_irq(adjust_t
*adj
)
928 int ret
= CS_SUCCESS
;
929 #ifdef CONFIG_PCMCIA_PROBE
933 irq
= adj
->resource
.irq
.IRQ
;
934 if ((irq
< 0) || (irq
> 15))
936 info
= &irq_table
[irq
];
939 switch (adj
->Action
) {
940 case ADD_MANAGED_RESOURCE
:
941 if (info
->Attributes
& RES_REMOVED
)
942 info
->Attributes
&= ~(RES_REMOVED
|RES_ALLOCATED
);
944 if (adj
->Attributes
& RES_ALLOCATED
) {
948 if (adj
->Attributes
& RES_RESERVED
)
949 info
->Attributes
|= RES_RESERVED
;
951 info
->Attributes
&= ~RES_RESERVED
;
953 case REMOVE_MANAGED_RESOURCE
:
954 if (info
->Attributes
& RES_REMOVED
) {
958 if (info
->Attributes
& RES_ALLOCATED
) {
962 info
->Attributes
|= RES_ALLOCATED
|RES_REMOVED
;
963 info
->Attributes
&= ~RES_RESERVED
;
966 ret
= CS_UNSUPPORTED_FUNCTION
;
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
);
986 return adjust_io(adj
);
989 return adjust_irq(adj
);
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
) {
1005 for (p
= io_db
.next
; p
!= &io_db
; p
= q
) {