Cleanup syscall code to look more like it's mips64 equivalent.
[linux-2.6/linux-mips.git] / kernel / resource.c
blobf5a9b5b492cc015323dc4607446b8c1a1c92d89b
1 /*
2 * linux/kernel/resource.c
4 * Copyright (C) 1999 Linus Torvalds
5 * Copyright (C) 1999 Martin Mares <mj@ucw.cz>
7 * Arbitrary resource management.
8 */
10 #include <linux/config.h>
11 #include <linux/sched.h>
12 #include <linux/errno.h>
13 #include <linux/ioport.h>
14 #include <linux/init.h>
15 #include <linux/slab.h>
16 #include <linux/spinlock.h>
17 #include <linux/fs.h>
18 #include <linux/proc_fs.h>
19 #include <linux/seq_file.h>
20 #include <asm/io.h>
23 struct resource ioport_resource = {
24 .name = "PCI IO",
25 .start = 0x0000,
26 .end = IO_SPACE_LIMIT,
27 .flags = IORESOURCE_IO,
30 struct resource iomem_resource = {
31 .name = "PCI mem",
32 .start = 0UL,
33 .end = ~0UL,
34 .flags = IORESOURCE_MEM,
37 static rwlock_t resource_lock = RW_LOCK_UNLOCKED;
39 #ifdef CONFIG_PROC_FS
41 #define MAX_IORES_LEVEL 5
44 * do_resource_list():
45 * for reports of /proc/ioports and /proc/iomem;
46 * do current entry, then children, then siblings;
48 static int do_resource_list(struct seq_file *m, struct resource *res, const char *fmt, int level)
50 while (res) {
51 const char *name;
53 name = res->name ? res->name : "<BAD>";
54 if (level > MAX_IORES_LEVEL)
55 level = MAX_IORES_LEVEL;
56 seq_printf (m, fmt + 2 * MAX_IORES_LEVEL - 2 * level,
57 res->start, res->end, name);
59 if (res->child)
60 do_resource_list(m, res->child, fmt, level + 1);
62 res = res->sibling;
65 return 0;
68 static int ioresources_show(struct seq_file *m, void *v)
70 struct resource *root = m->private;
71 char *fmt;
72 int retval;
74 fmt = root->end < 0x10000
75 ? " %04lx-%04lx : %s\n"
76 : " %08lx-%08lx : %s\n";
77 read_lock(&resource_lock);
78 retval = do_resource_list(m, root->child, fmt, 0);
79 read_unlock(&resource_lock);
80 return retval;
83 static int ioresources_open(struct file *file, struct resource *root)
85 return single_open(file, ioresources_show, root);
88 static int ioports_open(struct inode *inode, struct file *file)
90 return ioresources_open(file, &ioport_resource);
93 static struct file_operations proc_ioports_operations = {
94 .open = ioports_open,
95 .read = seq_read,
96 .llseek = seq_lseek,
97 .release = single_release,
100 static int iomem_open(struct inode *inode, struct file *file)
102 return ioresources_open(file, &iomem_resource);
105 static struct file_operations proc_iomem_operations = {
106 .open = iomem_open,
107 .read = seq_read,
108 .llseek = seq_lseek,
109 .release = single_release,
112 static int __init ioresources_init(void)
114 struct proc_dir_entry *entry;
116 entry = create_proc_entry("ioports", 0, NULL);
117 if (entry)
118 entry->proc_fops = &proc_ioports_operations;
119 entry = create_proc_entry("iomem", 0, NULL);
120 if (entry)
121 entry->proc_fops = &proc_iomem_operations;
122 return 0;
124 __initcall(ioresources_init);
126 #endif /* CONFIG_PROC_FS */
128 /* Return the conflict entry if you can't request it */
129 static struct resource * __request_resource(struct resource *root, struct resource *new)
131 unsigned long start = new->start;
132 unsigned long end = new->end;
133 struct resource *tmp, **p;
135 if (end < start)
136 return root;
137 if (start < root->start)
138 return root;
139 if (end > root->end)
140 return root;
141 p = &root->child;
142 for (;;) {
143 tmp = *p;
144 if (!tmp || tmp->start > end) {
145 new->sibling = tmp;
146 *p = new;
147 new->parent = root;
148 return NULL;
150 p = &tmp->sibling;
151 if (tmp->end < start)
152 continue;
153 return tmp;
157 static int __release_resource(struct resource *old)
159 struct resource *tmp, **p;
161 p = &old->parent->child;
162 for (;;) {
163 tmp = *p;
164 if (!tmp)
165 break;
166 if (tmp == old) {
167 *p = tmp->sibling;
168 old->parent = NULL;
169 return 0;
171 p = &tmp->sibling;
173 return -EINVAL;
176 int request_resource(struct resource *root, struct resource *new)
178 struct resource *conflict;
180 write_lock(&resource_lock);
181 conflict = __request_resource(root, new);
182 write_unlock(&resource_lock);
183 return conflict ? -EBUSY : 0;
186 int release_resource(struct resource *old)
188 int retval;
190 write_lock(&resource_lock);
191 retval = __release_resource(old);
192 write_unlock(&resource_lock);
193 return retval;
197 * Find empty slot in the resource tree given range and alignment.
199 static int find_resource(struct resource *root, struct resource *new,
200 unsigned long size,
201 unsigned long min, unsigned long max,
202 unsigned long align,
203 void (*alignf)(void *, struct resource *,
204 unsigned long, unsigned long),
205 void *alignf_data)
207 struct resource *this = root->child;
209 new->start = root->start;
210 for(;;) {
211 if (this)
212 new->end = this->start;
213 else
214 new->end = root->end;
215 if (new->start < min)
216 new->start = min;
217 if (new->end > max)
218 new->end = max;
219 new->start = (new->start + align - 1) & ~(align - 1);
220 if (alignf)
221 alignf(alignf_data, new, size, align);
222 if (new->start < new->end && new->end - new->start + 1 >= size) {
223 new->end = new->start + size - 1;
224 return 0;
226 if (!this)
227 break;
228 new->start = this->end + 1;
229 this = this->sibling;
231 return -EBUSY;
235 * Allocate empty slot in the resource tree given range and alignment.
237 int allocate_resource(struct resource *root, struct resource *new,
238 unsigned long size,
239 unsigned long min, unsigned long max,
240 unsigned long align,
241 void (*alignf)(void *, struct resource *,
242 unsigned long, unsigned long),
243 void *alignf_data)
245 int err;
247 write_lock(&resource_lock);
248 err = find_resource(root, new, size, min, max, align, alignf, alignf_data);
249 if (err >= 0 && __request_resource(root, new))
250 err = -EBUSY;
251 write_unlock(&resource_lock);
252 return err;
256 * This is compatibility stuff for IO resources.
258 * Note how this, unlike the above, knows about
259 * the IO flag meanings (busy etc).
261 * Request-region creates a new busy region.
263 * Check-region returns non-zero if the area is already busy
265 * Release-region releases a matching busy region.
267 struct resource * __request_region(struct resource *parent, unsigned long start, unsigned long n, const char *name)
269 struct resource *res = kmalloc(sizeof(*res), GFP_KERNEL);
271 if (res) {
272 memset(res, 0, sizeof(*res));
273 res->name = name;
274 res->start = start;
275 res->end = start + n - 1;
276 res->flags = IORESOURCE_BUSY;
278 write_lock(&resource_lock);
280 for (;;) {
281 struct resource *conflict;
283 conflict = __request_resource(parent, res);
284 if (!conflict)
285 break;
286 if (conflict != parent) {
287 parent = conflict;
288 if (!(conflict->flags & IORESOURCE_BUSY))
289 continue;
292 /* Uhhuh, that didn't work out.. */
293 kfree(res);
294 res = NULL;
295 break;
297 write_unlock(&resource_lock);
299 return res;
302 int __deprecated __check_region(struct resource *parent, unsigned long start, unsigned long n)
304 struct resource * res;
306 res = __request_region(parent, start, n, "check-region");
307 if (!res)
308 return -EBUSY;
310 release_resource(res);
311 kfree(res);
312 return 0;
315 void __release_region(struct resource *parent, unsigned long start, unsigned long n)
317 struct resource **p;
318 unsigned long end;
320 p = &parent->child;
321 end = start + n - 1;
323 for (;;) {
324 struct resource *res = *p;
326 if (!res)
327 break;
328 if (res->start <= start && res->end >= end) {
329 if (!(res->flags & IORESOURCE_BUSY)) {
330 p = &res->child;
331 continue;
333 if (res->start != start || res->end != end)
334 break;
335 *p = res->sibling;
336 kfree(res);
337 return;
339 p = &res->sibling;
341 printk(KERN_WARNING "Trying to free nonexistent resource <%08lx-%08lx>\n", start, end);
345 * Called from init/main.c to reserve IO ports.
347 #define MAXRESERVE 4
348 static int __init reserve_setup(char *str)
350 static int reserved = 0;
351 static struct resource reserve[MAXRESERVE];
353 for (;;) {
354 int io_start, io_num;
355 int x = reserved;
357 if (get_option (&str, &io_start) != 2)
358 break;
359 if (get_option (&str, &io_num) == 0)
360 break;
361 if (x < MAXRESERVE) {
362 struct resource *res = reserve + x;
363 res->name = "reserved";
364 res->start = io_start;
365 res->end = io_start + io_num - 1;
366 res->flags = IORESOURCE_BUSY;
367 res->child = NULL;
368 if (request_resource(res->start >= 0x10000 ? &iomem_resource : &ioport_resource, res) == 0)
369 reserved = x+1;
372 return 1;
375 __setup("reserve=", reserve_setup);