2 * linux/kernel/resource.c
4 * Copyright (C) 1999 Linus Torvalds
5 * Copyright (C) 1999 Martin Mares <mj@ucw.cz>
7 * Arbitrary resource management.
10 #include <linux/sched.h>
11 #include <linux/errno.h>
12 #include <linux/ioport.h>
13 #include <linux/init.h>
14 #include <linux/malloc.h>
15 #include <linux/spinlock.h>
17 struct resource ioport_resource
= { "PCI IO", 0x0000, 0xFFFF, IORESOURCE_IO
};
18 struct resource iomem_resource
= { "PCI mem", 0x00000000, 0xFFFFFFFF, IORESOURCE_MEM
};
20 static rwlock_t resource_lock
= RW_LOCK_UNLOCKED
;
23 * This generates reports for /proc/ioports and /proc/memory
25 static char * do_resource_list(struct resource
*entry
, const char *fmt
, int offset
, char *buf
, char *end
)
31 const char *name
= entry
->name
;
32 unsigned long from
, to
;
34 if ((int) (end
-buf
) < 80)
42 buf
+= sprintf(buf
, fmt
+ offset
, from
, to
, name
);
44 buf
= do_resource_list(entry
->child
, fmt
, offset
-2, buf
, end
);
45 entry
= entry
->sibling
;
51 int get_resource_list(struct resource
*root
, char *buf
, int size
)
56 fmt
= " %08lx-%08lx : %s\n";
57 if (root
== &ioport_resource
)
58 fmt
= " %04lx-%04lx : %s\n";
59 read_lock(&resource_lock
);
60 retval
= do_resource_list(root
->child
, fmt
, 8, buf
, buf
+ size
) - buf
;
61 read_unlock(&resource_lock
);
65 /* Return the conflict entry if you can't request it */
66 static struct resource
* __request_resource(struct resource
*root
, struct resource
*new)
68 unsigned long start
= new->start
;
69 unsigned long end
= new->end
;
70 struct resource
*tmp
, **p
;
74 if (start
< root
->start
)
81 if (!tmp
|| tmp
->start
> end
) {
94 int request_resource(struct resource
*root
, struct resource
*new)
96 struct resource
*conflict
;
98 write_lock(&resource_lock
);
99 conflict
= __request_resource(root
, new);
100 write_unlock(&resource_lock
);
101 return conflict
? -EBUSY
: 0;
104 int release_resource(struct resource
*old
)
106 struct resource
*tmp
, **p
;
108 p
= &old
->parent
->child
;
124 * Find empty slot in the resource tree given range and alignment.
126 static int find_resource(struct resource
*root
, struct resource
*new,
128 unsigned long min
, unsigned long max
,
131 struct resource
*this = root
->child
;
132 unsigned long start
, end
;
144 start
= (start
+ align
- 1) & ~(align
- 1);
145 if (start
< end
&& end
- start
+ 1 >= size
) {
147 new->end
= start
+ size
- 1;
152 start
= this->end
+ 1;
153 this = this->sibling
;
159 * Allocate empty slot in the resource tree given range and alignment.
161 int allocate_resource(struct resource
*root
, struct resource
*new,
163 unsigned long min
, unsigned long max
,
168 write_lock(&resource_lock
);
169 err
= find_resource(root
, new, size
, min
, max
, align
);
170 if (err
>= 0 && __request_resource(root
, new))
172 write_unlock(&resource_lock
);
177 * This is compatibility stuff for IO resources.
179 * Note how this, unlike the above, knows about
180 * the IO flag meanings (busy etc).
182 * Request-region creates a new busy region.
184 * Check-region returns non-zero if the area is already busy
186 * Release-region releases a matching busy region.
188 struct resource
* __request_region(struct resource
*parent
, unsigned long start
, unsigned long n
, const char *name
)
190 struct resource
*res
= kmalloc(sizeof(*res
), GFP_KERNEL
);
193 memset(res
, 0, sizeof(*res
));
196 res
->end
= start
+ n
- 1;
197 res
->flags
= IORESOURCE_BUSY
;
199 write_lock(&resource_lock
);
202 struct resource
*conflict
;
204 conflict
= __request_resource(parent
, res
);
207 if (conflict
!= parent
) {
209 if (!(conflict
->flags
& IORESOURCE_BUSY
))
213 /* Uhhuh, that didn't work out.. */
218 write_unlock(&resource_lock
);
223 int __check_region(struct resource
*parent
, unsigned long start
, unsigned long n
)
225 struct resource
* res
;
227 res
= __request_region(parent
, start
, n
, "check-region");
231 release_resource(res
);
236 void __release_region(struct resource
*parent
, unsigned long start
, unsigned long n
)
245 struct resource
*res
= *p
;
249 if (res
->start
<= start
&& res
->end
>= end
) {
250 if (!(res
->flags
& IORESOURCE_BUSY
)) {
254 if (res
->start
!= start
|| res
->end
!= end
)
262 printk("Trying to free nonexistent resource <%04lx-%04lx>\n", start
, end
);
266 * Called from init/main.c to reserve IO ports.
269 static int __init
reserve_setup(char *str
)
271 int opt
= 2, io_start
, io_num
;
272 static int reserved
= 0;
273 static struct resource reserve
[MAXRESERVE
];
278 if (get_option (&str
, &io_start
) != 2) break;
279 if (get_option (&str
, &io_num
) == 0) break;
280 if (x
< MAXRESERVE
) {
281 struct resource
*res
= reserve
+ x
;
282 res
->name
= "reserved";
283 res
->start
= io_start
;
284 res
->end
= io_start
+ io_num
- 1;
286 if (request_resource(res
->start
>= 0x10000 ? &iomem_resource
: &ioport_resource
, res
) == 0)
293 __setup("reserve=", reserve_setup
);