Import 2.3.11pre3
[davej-history.git] / kernel / resource.c
blobce15021e30e6512688f38b1988b84f5889e3e047
1 /*
2 * linux/kernel/resource.c
4 * Copyright (C) 1999 Linus Torvalds
6 * Arbitrary resource management.
7 */
9 #include <linux/sched.h>
10 #include <linux/errno.h>
11 #include <linux/ioport.h>
12 #include <linux/init.h>
13 #include <linux/malloc.h>
15 struct resource pci_io_resource = { "PCI IO", 0x0000, 0xFFFF };
16 struct resource pci_mem_resource = { "PCI mem", 0x00000000, 0xFFFFFFFF };
19 * This generates reports for /proc/ioports and /proc/memory
21 static char * do_resource_list(struct resource *entry, const char *fmt, int offset, char *buf, char *end)
23 if (offset < 0)
24 offset = 0;
26 while (entry) {
27 const char *name = entry->name;
28 unsigned long from, to;
30 if ((int) (end-buf) < 80)
31 return buf;
33 from = entry->start;
34 to = entry->end;
35 if (!name)
36 name = "<BAD>";
38 buf += sprintf(buf, fmt + offset, from, to, name);
39 if (entry->child)
40 buf = do_resource_list(entry->child, fmt, offset-2, buf, end);
41 entry = entry->sibling;
44 return buf;
47 int get_resource_list(struct resource *root, char *buf, int size)
49 char *fmt;
51 fmt = " %08lx-%08lx : %s\n";
52 if (root == &pci_io_resource)
53 fmt = " %04lx-%04lx : %s\n";
54 return do_resource_list(root->child, fmt, 8, buf, buf + size) - buf;
57 int request_resource(struct resource *root, struct resource *new)
59 unsigned long start = new->start;
60 unsigned long end = new->end;
61 struct resource *tmp, **p;
63 if (end < start)
64 return -EINVAL;
65 if (start < root->start)
66 return -EINVAL;
67 if (end > root->end)
68 return -EINVAL;
69 p = &root->child;
70 for (;;) {
71 tmp = *p;
72 if (!tmp || tmp->start > end) {
73 new->sibling = tmp;
74 *p = new;
75 new->parent = root;
76 return 0;
78 p = &tmp->sibling;
79 if (tmp->end < start)
80 continue;
81 return -EBUSY;
85 int release_resource(struct resource *old)
87 struct resource *tmp, **p;
89 p = &old->parent->child;
90 for (;;) {
91 tmp = *p;
92 if (!tmp)
93 break;
94 if (tmp == old) {
95 *p = tmp->sibling;
96 old->parent = NULL;
97 return 0;
99 p = &tmp->sibling;
101 return -EINVAL;
104 struct resource * __request_region(struct resource *parent, unsigned long start, unsigned long n, const char *name)
106 struct resource *res = kmalloc(sizeof(*res), GFP_KERNEL);
108 if (res) {
109 memset(res, 0, sizeof(*res));
110 res->name = name;
111 res->start = start;
112 res->end = start + n - 1;
113 if (request_resource(parent, res) != 0) {
114 kfree(res);
115 res = NULL;
118 return res;
122 * Compatibility cruft.
124 * Check-region returns non-zero if something already exists.
126 * Release-region releases an anonymous region that matches
127 * the IO port range.
129 int __check_region(struct resource *parent, unsigned long start, unsigned long n)
131 struct resource * res;
133 res = __request_region(parent, start, n, "check-region");
134 if (!res)
135 return -EBUSY;
137 release_resource(res);
138 kfree(res);
139 return 0;
142 void __release_region(struct resource *parent, unsigned long start, unsigned long n)
144 struct resource **p;
145 unsigned long end;
147 p = &parent->child;
148 end = start + n - 1;
150 for (;;) {
151 struct resource *res = *p;
153 if (!res)
154 break;
155 if (res->start == start && res->end == end) {
156 *p = res->sibling;
157 kfree(res);
158 break;
160 p = &res->sibling;
165 * Called from init/main.c to reserve IO ports.
167 #define MAXRESERVE 4
168 void __init reserve_setup(char *str, int *ints)
170 int i;
171 static int reserved = 0;
172 static struct resource reserve[MAXRESERVE];
174 for (i = 1; i < ints[0]; i += 2) {
175 int x = reserved;
176 if (x < MAXRESERVE) {
177 struct resource *res = reserve + x;
178 res->name = "reserved";
179 res->start = ints[i];
180 res->end = res->start + ints[i] - 1;
181 res->child = NULL;
182 if (request_resource(&pci_io_resource, res) == 0)
183 reserved = x+1;