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/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>
18 #include <linux/proc_fs.h>
19 #include <linux/seq_file.h>
23 struct resource ioport_resource
= {
26 .end
= IO_SPACE_LIMIT
,
27 .flags
= IORESOURCE_IO
,
30 struct resource iomem_resource
= {
34 .flags
= IORESOURCE_MEM
,
37 static rwlock_t resource_lock
= RW_LOCK_UNLOCKED
;
41 #define MAX_IORES_LEVEL 5
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
)
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
);
60 do_resource_list(m
, res
->child
, fmt
, level
+ 1);
68 static int ioresources_show(struct seq_file
*m
, void *v
)
70 struct resource
*root
= m
->private;
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
);
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
= {
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
= {
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
);
118 entry
->proc_fops
= &proc_ioports_operations
;
119 entry
= create_proc_entry("iomem", 0, NULL
);
121 entry
->proc_fops
= &proc_iomem_operations
;
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
;
137 if (start
< root
->start
)
144 if (!tmp
|| tmp
->start
> end
) {
151 if (tmp
->end
< start
)
157 static int __release_resource(struct resource
*old
)
159 struct resource
*tmp
, **p
;
161 p
= &old
->parent
->child
;
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
)
190 write_lock(&resource_lock
);
191 retval
= __release_resource(old
);
192 write_unlock(&resource_lock
);
197 * Find empty slot in the resource tree given range and alignment.
199 static int find_resource(struct resource
*root
, struct resource
*new,
201 unsigned long min
, unsigned long max
,
203 void (*alignf
)(void *, struct resource
*,
204 unsigned long, unsigned long),
207 struct resource
*this = root
->child
;
209 new->start
= root
->start
;
212 new->end
= this->start
;
214 new->end
= root
->end
;
215 if (new->start
< min
)
219 new->start
= (new->start
+ align
- 1) & ~(align
- 1);
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;
228 new->start
= this->end
+ 1;
229 this = this->sibling
;
235 * Allocate empty slot in the resource tree given range and alignment.
237 int allocate_resource(struct resource
*root
, struct resource
*new,
239 unsigned long min
, unsigned long max
,
241 void (*alignf
)(void *, struct resource
*,
242 unsigned long, unsigned long),
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))
251 write_unlock(&resource_lock
);
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
);
272 memset(res
, 0, sizeof(*res
));
275 res
->end
= start
+ n
- 1;
276 res
->flags
= IORESOURCE_BUSY
;
278 write_lock(&resource_lock
);
281 struct resource
*conflict
;
283 conflict
= __request_resource(parent
, res
);
286 if (conflict
!= parent
) {
288 if (!(conflict
->flags
& IORESOURCE_BUSY
))
292 /* Uhhuh, that didn't work out.. */
297 write_unlock(&resource_lock
);
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");
310 release_resource(res
);
315 void __release_region(struct resource
*parent
, unsigned long start
, unsigned long n
)
324 struct resource
*res
= *p
;
328 if (res
->start
<= start
&& res
->end
>= end
) {
329 if (!(res
->flags
& IORESOURCE_BUSY
)) {
333 if (res
->start
!= start
|| res
->end
!= end
)
341 printk(KERN_WARNING
"Trying to free nonexistent resource <%08lx-%08lx>\n", start
, end
);
345 * Called from init/main.c to reserve IO ports.
348 static int __init
reserve_setup(char *str
)
350 static int reserved
= 0;
351 static struct resource reserve
[MAXRESERVE
];
354 int io_start
, io_num
;
357 if (get_option (&str
, &io_start
) != 2)
359 if (get_option (&str
, &io_num
) == 0)
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
;
368 if (request_resource(res
->start
>= 0x10000 ? &iomem_resource
: &ioport_resource
, res
) == 0)
375 __setup("reserve=", reserve_setup
);