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>
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
*, unsigned long),
158 struct resource
*this = root
->child
;
160 new->start
= root
->start
;
163 new->end
= this->start
;
165 new->end
= root
->end
;
166 if (new->start
< min
)
170 new->start
= (new->start
+ align
- 1) & ~(align
- 1);
172 alignf(alignf_data
, new, size
);
173 if (new->start
< new->end
&& new->end
- new->start
+ 1 >= size
) {
174 new->end
= new->start
+ size
- 1;
179 new->start
= this->end
+ 1;
180 this = this->sibling
;
186 * Allocate empty slot in the resource tree given range and alignment.
188 int allocate_resource(struct resource
*root
, struct resource
*new,
190 unsigned long min
, unsigned long max
,
192 void (*alignf
)(void *, struct resource
*, unsigned long),
197 write_lock(&resource_lock
);
198 err
= find_resource(root
, new, size
, min
, max
, align
, alignf
, alignf_data
);
199 if (err
>= 0 && __request_resource(root
, new))
201 write_unlock(&resource_lock
);
206 * This is compatibility stuff for IO resources.
208 * Note how this, unlike the above, knows about
209 * the IO flag meanings (busy etc).
211 * Request-region creates a new busy region.
213 * Check-region returns non-zero if the area is already busy
215 * Release-region releases a matching busy region.
217 struct resource
* __request_region(struct resource
*parent
, unsigned long start
, unsigned long n
, const char *name
)
219 struct resource
*res
= kmalloc(sizeof(*res
), GFP_KERNEL
);
222 memset(res
, 0, sizeof(*res
));
225 res
->end
= start
+ n
- 1;
226 res
->flags
= IORESOURCE_BUSY
;
228 write_lock(&resource_lock
);
231 struct resource
*conflict
;
233 conflict
= __request_resource(parent
, res
);
236 if (conflict
!= parent
) {
238 if (!(conflict
->flags
& IORESOURCE_BUSY
))
242 /* Uhhuh, that didn't work out.. */
247 write_unlock(&resource_lock
);
252 int __check_region(struct resource
*parent
, unsigned long start
, unsigned long n
)
254 struct resource
* res
;
256 res
= __request_region(parent
, start
, n
, "check-region");
260 release_resource(res
);
265 void __release_region(struct resource
*parent
, unsigned long start
, unsigned long n
)
274 struct resource
*res
= *p
;
278 if (res
->start
<= start
&& res
->end
>= end
) {
279 if (!(res
->flags
& IORESOURCE_BUSY
)) {
283 if (res
->start
!= start
|| res
->end
!= end
)
291 printk("Trying to free nonexistent resource <%08lx-%08lx>\n", start
, end
);
295 * Called from init/main.c to reserve IO ports.
298 static int __init
reserve_setup(char *str
)
300 int opt
= 2, io_start
, io_num
;
301 static int reserved
= 0;
302 static struct resource reserve
[MAXRESERVE
];
307 if (get_option (&str
, &io_start
) != 2) break;
308 if (get_option (&str
, &io_num
) == 0) break;
309 if (x
< MAXRESERVE
) {
310 struct resource
*res
= reserve
+ x
;
311 res
->name
= "reserved";
312 res
->start
= io_start
;
313 res
->end
= io_start
+ io_num
- 1;
315 if (request_resource(res
->start
>= 0x10000 ? &iomem_resource
: &ioport_resource
, res
) == 0)
322 __setup("reserve=", reserve_setup
);