debuggers.hg

view xen/common/resource.c @ 3705:4294cfa9fad3

bitkeeper revision 1.1159.212.95 (4204aa0ee0re5Xx1zWrJ9ejxzgRs3w)

Various cleanups. Remove PDB pending simpler GDB stub and/or NetBSD debugger.
Force emacs mode to appropriate tabbing in various files.
Signed-off-by: keir.fraser@cl.cam.ac.uk
author kaf24@scramble.cl.cam.ac.uk
date Sat Feb 05 11:12:14 2005 +0000 (2005-02-05)
parents 0ef6e8e6e85d
children 88957a238191 a00d7a994a59
line source
1 /* -*- Mode:C; c-basic-offset:8; tab-width:8; indent-tabs-mode:t -*- */
2 /*
3 * linux/kernel/resource.c
4 *
5 * Copyright (C) 1999 Linus Torvalds
6 * Copyright (C) 1999 Martin Mares <mj@ucw.cz>
7 *
8 * Arbitrary resource management.
9 */
11 #include <xen/config.h>
12 #include <xen/lib.h>
13 #include <xen/sched.h>
14 #include <xen/errno.h>
15 #include <xen/ioport.h>
16 #include <xen/init.h>
17 #include <xen/slab.h>
18 #include <xen/spinlock.h>
19 #include <asm/io.h>
21 struct resource ioport_resource = { "PCI IO", 0x0000, IO_SPACE_LIMIT, IORESOURCE_IO };
22 struct resource iomem_resource = { "PCI mem", 0x00000000, 0xffffffff, IORESOURCE_MEM };
24 static rwlock_t resource_lock = RW_LOCK_UNLOCKED;
26 /*
27 * This generates reports for /proc/ioports and /proc/iomem
28 */
29 static char * do_resource_list(struct resource *entry, const char *fmt, int offset, char *buf, char *end)
30 {
31 if (offset < 0)
32 offset = 0;
34 while (entry) {
35 const char *name = entry->name;
36 unsigned long from, to;
38 if ((int) (end-buf) < 80)
39 return buf;
41 from = entry->start;
42 to = entry->end;
43 if (!name)
44 name = "<BAD>";
46 buf += sprintf(buf, fmt + offset, from, to, name);
47 if (entry->child)
48 buf = do_resource_list(entry->child, fmt, offset-2, buf, end);
49 entry = entry->sibling;
50 }
52 return buf;
53 }
55 int get_resource_list(struct resource *root, char *buf, int size)
56 {
57 char *fmt;
58 int retval;
60 fmt = " %08lx-%08lx : %s\n";
61 if (root->end < 0x10000)
62 fmt = " %04lx-%04lx : %s\n";
63 read_lock(&resource_lock);
64 retval = do_resource_list(root->child, fmt, 8, buf, buf + size) - buf;
65 read_unlock(&resource_lock);
66 return retval;
67 }
69 /* Return the conflict entry if you can't request it */
70 static struct resource * __request_resource(struct resource *root, struct resource *new)
71 {
72 unsigned long start = new->start;
73 unsigned long end = new->end;
74 struct resource *tmp, **p;
76 if (end < start)
77 return root;
78 if (start < root->start)
79 return root;
80 if (end > root->end)
81 return root;
82 p = &root->child;
83 for (;;) {
84 tmp = *p;
85 if (!tmp || tmp->start > end) {
86 new->sibling = tmp;
87 *p = new;
88 new->parent = root;
89 return NULL;
90 }
91 p = &tmp->sibling;
92 if (tmp->end < start)
93 continue;
94 return tmp;
95 }
96 }
98 static int __release_resource(struct resource *old)
99 {
100 struct resource *tmp, **p;
102 p = &old->parent->child;
103 for (;;) {
104 tmp = *p;
105 if (!tmp)
106 break;
107 if (tmp == old) {
108 *p = tmp->sibling;
109 old->parent = NULL;
110 return 0;
111 }
112 p = &tmp->sibling;
113 }
114 return -EINVAL;
115 }
117 int request_resource(struct resource *root, struct resource *new)
118 {
119 struct resource *conflict;
121 write_lock(&resource_lock);
122 conflict = __request_resource(root, new);
123 write_unlock(&resource_lock);
124 return conflict ? -EBUSY : 0;
125 }
127 int release_resource(struct resource *old)
128 {
129 int retval;
131 write_lock(&resource_lock);
132 retval = __release_resource(old);
133 write_unlock(&resource_lock);
134 return retval;
135 }
137 int check_resource(struct resource *root, unsigned long start, unsigned long len)
138 {
139 struct resource *conflict, tmp;
141 tmp.start = start;
142 tmp.end = start + len - 1;
143 write_lock(&resource_lock);
144 conflict = __request_resource(root, &tmp);
145 if (!conflict)
146 __release_resource(&tmp);
147 write_unlock(&resource_lock);
148 return conflict ? -EBUSY : 0;
149 }
151 /*
152 * Find empty slot in the resource tree given range and alignment.
153 */
154 static int find_resource(struct resource *root, struct resource *new,
155 unsigned long size,
156 unsigned long min, unsigned long max,
157 unsigned long align,
158 void (*alignf)(void *, struct resource *,
159 unsigned long, unsigned long),
160 void *alignf_data)
161 {
162 struct resource *this = root->child;
164 new->start = root->start;
165 for(;;) {
166 if (this)
167 new->end = this->start;
168 else
169 new->end = root->end;
170 if (new->start < min)
171 new->start = min;
172 if (new->end > max)
173 new->end = max;
174 new->start = (new->start + align - 1) & ~(align - 1);
175 if (alignf)
176 alignf(alignf_data, new, size, align);
177 if (new->start < new->end && new->end - new->start + 1 >= size) {
178 new->end = new->start + size - 1;
179 return 0;
180 }
181 if (!this)
182 break;
183 new->start = this->end + 1;
184 this = this->sibling;
185 }
186 return -EBUSY;
187 }
189 /*
190 * Allocate empty slot in the resource tree given range and alignment.
191 */
192 int allocate_resource(struct resource *root, struct resource *new,
193 unsigned long size,
194 unsigned long min, unsigned long max,
195 unsigned long align,
196 void (*alignf)(void *, struct resource *,
197 unsigned long, unsigned long),
198 void *alignf_data)
199 {
200 int err;
202 write_lock(&resource_lock);
203 err = find_resource(root, new, size, min, max, align, alignf, alignf_data);
204 if (err >= 0 && __request_resource(root, new))
205 err = -EBUSY;
206 write_unlock(&resource_lock);
207 return err;
208 }
210 /*
211 * This is compatibility stuff for IO resources.
212 *
213 * Note how this, unlike the above, knows about
214 * the IO flag meanings (busy etc).
215 *
216 * Request-region creates a new busy region.
217 *
218 * Check-region returns non-zero if the area is already busy
219 *
220 * Release-region releases a matching busy region.
221 */
222 struct resource * __request_region(struct resource *parent, unsigned long start, unsigned long n, const char *name)
223 {
224 struct resource *res = xmalloc(struct resource);
226 if (res) {
227 memset(res, 0, sizeof(*res));
228 res->name = name;
229 res->start = start;
230 res->end = start + n - 1;
231 res->flags = IORESOURCE_BUSY;
233 write_lock(&resource_lock);
235 for (;;) {
236 struct resource *conflict;
238 conflict = __request_resource(parent, res);
239 if (!conflict)
240 break;
241 if (conflict != parent) {
242 parent = conflict;
243 if (!(conflict->flags & IORESOURCE_BUSY))
244 continue;
245 }
247 /* Uhhuh, that didn't work out.. */
248 xfree(res);
249 res = NULL;
250 break;
251 }
252 write_unlock(&resource_lock);
253 }
254 return res;
255 }
257 int __check_region(struct resource *parent, unsigned long start, unsigned long n)
258 {
259 struct resource * res;
261 res = __request_region(parent, start, n, "check-region");
262 if (!res)
263 return -EBUSY;
265 release_resource(res);
266 xfree(res);
267 return 0;
268 }
270 void __release_region(struct resource *parent, unsigned long start, unsigned long n)
271 {
272 struct resource **p;
273 unsigned long end;
275 p = &parent->child;
276 end = start + n - 1;
278 for (;;) {
279 struct resource *res = *p;
281 if (!res)
282 break;
283 if (res->start <= start && res->end >= end) {
284 if (!(res->flags & IORESOURCE_BUSY)) {
285 p = &res->child;
286 continue;
287 }
288 if (res->start != start || res->end != end)
289 break;
290 *p = res->sibling;
291 xfree(res);
292 return;
293 }
294 p = &res->sibling;
295 }
296 printk("Trying to free nonexistent resource <%08lx-%08lx>\n", start, end);
297 }
300 #if 0
301 /*
302 * Called from init/main.c to reserve IO ports.
303 */
304 #define MAXRESERVE 4
305 static int __init reserve_setup(char *str)
306 {
307 static int reserved = 0;
308 static struct resource reserve[MAXRESERVE];
310 for (;;) {
311 int io_start, io_num;
312 int x = reserved;
314 if (get_option (&str, &io_start) != 2)
315 break;
316 if (get_option (&str, &io_num) == 0)
317 break;
318 if (x < MAXRESERVE) {
319 struct resource *res = reserve + x;
320 res->name = "reserved";
321 res->start = io_start;
322 res->end = io_start + io_num - 1;
323 res->flags = IORESOURCE_BUSY;
324 res->child = NULL;
325 if (request_resource(res->start >= 0x10000 ? &iomem_resource : &ioport_resource, res) == 0)
326 reserved = x+1;
327 }
328 }
329 return 1;
330 }
332 __setup("reserve=", reserve_setup);
333 #endif