Import 2.3.1pre2
[davej-history.git] / kernel / resource.c
blobfa607edf8a71061396ef3838a2c8ef0b0927e045
1 /*
2 * linux/kernel/resource.c
4 * Copyright (C) 1995 Linus Torvalds
5 * David Hinds
7 * Kernel io-region resource management
8 */
10 #include <linux/sched.h>
11 #include <linux/errno.h>
12 #include <linux/ioport.h>
13 #include <linux/init.h>
15 #define IOTABLE_SIZE 128
17 typedef struct resource_entry_t {
18 u_long from, num;
19 const char *name;
20 struct resource_entry_t *next;
21 } resource_entry_t;
23 static resource_entry_t iolist = { 0, 0, "", NULL };
25 static resource_entry_t iotable[IOTABLE_SIZE];
28 * This generates the report for /proc/ioports
30 int get_ioport_list(char *buf)
32 resource_entry_t *p;
33 int len = 0;
35 for (p = iolist.next; (p) && (len < 4000); p = p->next)
36 len += sprintf(buf+len, "%04lx-%04lx : %s\n",
37 p->from, p->from+p->num-1, p->name);
38 if (p)
39 len += sprintf(buf+len, "4K limit reached!\n");
40 return len;
44 * The workhorse function: find where to put a new entry
46 static resource_entry_t *find_gap(resource_entry_t *root,
47 u_long from, u_long num)
49 unsigned long flags;
50 resource_entry_t *p;
52 if (from > from+num-1)
53 return NULL;
54 save_flags(flags);
55 cli();
56 for (p = root; ; p = p->next) {
57 if ((p != root) && (p->from+p->num-1 >= from)) {
58 p = NULL;
59 break;
61 if ((p->next == NULL) || (p->next->from > from+num-1))
62 break;
64 restore_flags(flags);
65 return p;
69 * Call this from the device driver to register the ioport region.
71 void request_region(unsigned long from, unsigned long num, const char *name)
73 resource_entry_t *p;
74 int i;
76 for (i = 0; i < IOTABLE_SIZE; i++)
77 if (iotable[i].num == 0)
78 break;
79 if (i == IOTABLE_SIZE)
80 printk("warning: ioport table is full\n");
81 else {
82 p = find_gap(&iolist, from, num);
83 if (p == NULL)
84 return;
85 iotable[i].name = name;
86 iotable[i].from = from;
87 iotable[i].num = num;
88 iotable[i].next = p->next;
89 p->next = &iotable[i];
90 return;
94 /*
95 * Call this when the device driver is unloaded
97 void release_region(unsigned long from, unsigned long num)
99 resource_entry_t *p, *q;
101 for (p = &iolist; ; p = q) {
102 q = p->next;
103 if (q == NULL)
104 break;
105 if ((q->from == from) && (q->num == num)) {
106 q->num = 0;
107 p->next = q->next;
108 return;
114 * Call this to check the ioport region before probing
116 int check_region(unsigned long from, unsigned long num)
118 return (find_gap(&iolist, from, num) == NULL) ? -EBUSY : 0;
121 #ifdef __sparc__ /* Why to carry unused code on other architectures? */
123 * This is for architectures with MMU-managed ports (sparc).
125 unsigned long occupy_region(unsigned long base, unsigned long end,
126 unsigned long num, unsigned int align, const char *name)
128 unsigned long from = 0, till;
129 unsigned long flags;
130 int i;
131 resource_entry_t *p; /* Scanning ptr */
132 resource_entry_t *p1; /* === p->next */
133 resource_entry_t *s; /* Found slot */
135 if (base > end-1)
136 return 0;
137 if (num > end - base)
138 return 0;
140 for (i = 0; i < IOTABLE_SIZE; i++)
141 if (iotable[i].num == 0)
142 break;
143 if (i == IOTABLE_SIZE) {
144 /* Driver prints a warning typically. */
145 return 0;
148 save_flags(flags);
149 cli();
150 /* printk("occupy: search in %08lx[%08lx] ", base, end - base); */
151 s = NULL;
152 for (p = &iolist; p != NULL; p = p1) {
153 p1 = p->next;
154 /* Find window in list */
155 from = (p->from+p->num + align-1) & ~((unsigned long)align-1);
156 till = (p1 == NULL)? (unsigned long) (0 - (unsigned long)align): p1->from;
157 /* printk(" %08lx:%08lx", from, till); */
158 /* Clip window with base and end */
159 if (from < base) from = base;
160 if (till > end) till = end;
161 /* See if result is large enougth */
162 if (from < till && from + num < till) {
163 s = p;
164 break;
167 /* printk("\r\n"); */
168 restore_flags(flags);
170 if (s == NULL)
171 return 0;
173 iotable[i].name = name;
174 iotable[i].from = from;
175 iotable[i].num = num;
176 iotable[i].next = s->next;
177 s->next = &iotable[i];
178 return from;
180 #endif
182 /* Called from init/main.c to reserve IO ports. */
183 void __init reserve_setup(char *str, int *ints)
185 int i;
187 for (i = 1; i < ints[0]; i += 2)
188 request_region(ints[i], ints[i+1], "reserved");