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/slab.h>
15 #include <linux/spinlock.h>
18 struct resource ioport_resource = { "PCI IO", 0x0000, IO_SPACE_LIMIT, IORESOURCE_IO };
19 struct resource iomem_resource = { "PCI mem", 0x00000000, 0xffffffff, IORESOURCE_MEM };
21 static rwlock_t resource_lock = RW_LOCK_UNLOCKED;
24 * This generates reports for /proc/ioports and /proc/iomem
26 static char * do_resource_list(struct resource *entry, const char *fmt, int offset, char *buf, char *end)
32 const char *name = entry->name;
33 unsigned long from, to;
35 if ((int) (end-buf) < 80)
43 buf += sprintf(buf, fmt + offset, from, to, name);
45 buf = do_resource_list(entry->child, fmt, offset-2, buf, end);
46 entry = entry->sibling;
52 int get_resource_list(struct resource *root, char *buf, int size)
57 fmt = " %08lx-%08lx : %s\n";
58 if (root->end < 0x10000)
59 fmt = " %04lx-%04lx : %s\n";
60 read_lock(&resource_lock);
61 retval = do_resource_list(root->child, fmt, 8, buf, buf + size) - buf;
62 read_unlock(&resource_lock);
66 /* Return the conflict entry if you can't request it */
67 static struct resource * __request_resource(struct resource *root, struct resource *new)
69 unsigned long start = new->start;
70 unsigned long end = new->end;
71 struct resource *tmp, **p;
75 if (start < root->start)
82 if (!tmp || tmp->start > end) {
95 static int __release_resource(struct resource *old)
97 struct resource *tmp, **p;
99 p = &old->parent->child;
114 int request_resource(struct resource *root, struct resource *new)
116 struct resource *conflict;
118 write_lock(&resource_lock);
119 conflict = __request_resource(root, new);
120 write_unlock(&resource_lock);
121 return conflict ? -EBUSY : 0;
124 int release_resource(struct resource *old)
128 write_lock(&resource_lock);
129 retval = __release_resource(old);
130 write_unlock(&resource_lock);
134 int check_resource(struct resource *root, unsigned long start, unsigned long len)
136 struct resource *conflict, tmp;
139 tmp.end = start + len - 1;
140 write_lock(&resource_lock);
141 conflict = __request_resource(root, &tmp);
143 __release_resource(&tmp);
144 write_unlock(&resource_lock);
145 return conflict ? -EBUSY : 0;
149 * Find empty slot in the resource tree given range and alignment.
151 static int find_resource(struct resource *root, struct resource *new,
153 unsigned long min, unsigned long max,
155 void (*alignf)(void *, struct resource *,
156 unsigned long, unsigned long),
159 struct resource *this = root->child;
161 new->start = root->start;
164 new->end = this->start;
166 new->end = root->end;
167 if (new->start < min)
171 new->start = (new->start + align - 1) & ~(align - 1);
173 alignf(alignf_data, new, size, align);
174 if (new->start < new->end && new->end - new->start + 1 >= size) {
175 new->end = new->start + size - 1;
180 new->start = this->end + 1;
181 this = this->sibling;
187 * Allocate empty slot in the resource tree given range and alignment.
189 int allocate_resource(struct resource *root, struct resource *new,
191 unsigned long min, unsigned long max,
193 void (*alignf)(void *, struct resource *,
194 unsigned long, unsigned long),
199 write_lock(&resource_lock);
200 err = find_resource(root, new, size, min, max, align, alignf, alignf_data);
201 if (err >= 0 && __request_resource(root, new))
203 write_unlock(&resource_lock);
208 * This is compatibility stuff for IO resources.
210 * Note how this, unlike the above, knows about
211 * the IO flag meanings (busy etc).
213 * Request-region creates a new busy region.
215 * Check-region returns non-zero if the area is already busy
217 * Release-region releases a matching busy region.
219 struct resource * __request_region(struct resource *parent, unsigned long start, unsigned long n, const char *name)
221 struct resource *res = kmalloc(sizeof(*res), GFP_KERNEL);
224 memset(res, 0, sizeof(*res));
227 res->end = start + n - 1;
228 res->flags = IORESOURCE_BUSY;
230 write_lock(&resource_lock);
233 struct resource *conflict;
235 conflict = __request_resource(parent, res);
238 if (conflict != parent) {
240 if (!(conflict->flags & IORESOURCE_BUSY))
244 /* Uhhuh, that didn't work out.. */
249 write_unlock(&resource_lock);
254 int __check_region(struct resource *parent, unsigned long start, unsigned long n)
256 struct resource * res;
258 res = __request_region(parent, start, n, "check-region");
262 release_resource(res);
267 void __release_region(struct resource *parent, unsigned long start, unsigned long n)
276 struct resource *res = *p;
280 if (res->start <= start && res->end >= end) {
281 if (!(res->flags & IORESOURCE_BUSY)) {
285 if (res->start != start || res->end != end)
293 printk("Trying to free nonexistent resource <%08lx-%08lx>\n", start, end);
297 * Called from init/main.c to reserve IO ports.
300 static int __init reserve_setup(char *str)
302 static int reserved = 0;
303 static struct resource reserve[MAXRESERVE];
306 int io_start, io_num;
309 if (get_option (&str, &io_start) != 2)
311 if (get_option (&str, &io_num) == 0)
313 if (x < MAXRESERVE) {
314 struct resource *res = reserve + x;
315 res->name = "reserved";
316 res->start = io_start;
317 res->end = io_start + io_num - 1;
318 res->flags = IORESOURCE_BUSY;
320 if (request_resource(res->start >= 0x10000 ? &iomem_resource : &ioport_resource, res) == 0)
327 __setup("reserve=", reserve_setup);