Import 2.1.118
[davej-history.git] / kernel / resource.c
blob2d6b56eb0fd49158515be7f81a6250a83509e027
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/kernel.h>
12 #include <linux/errno.h>
13 #include <linux/types.h>
14 #include <linux/ioport.h>
15 #include <linux/init.h>
17 #define IOTABLE_SIZE 128
19 typedef struct resource_entry_t {
20 u_long from, num;
21 const char *name;
22 struct resource_entry_t *next;
23 } resource_entry_t;
25 static resource_entry_t iolist = { 0, 0, "", NULL };
27 static resource_entry_t iotable[IOTABLE_SIZE];
30 * This generates the report for /proc/ioports
32 int get_ioport_list(char *buf)
34 resource_entry_t *p;
35 int len = 0;
37 for (p = iolist.next; (p) && (len < 4000); p = p->next)
38 len += sprintf(buf+len, "%04lx-%04lx : %s\n",
39 p->from, p->from+p->num-1, p->name);
40 if (p)
41 len += sprintf(buf+len, "4K limit reached!\n");
42 return len;
46 * The workhorse function: find where to put a new entry
48 static resource_entry_t *find_gap(resource_entry_t *root,
49 u_long from, u_long num)
51 unsigned long flags;
52 resource_entry_t *p;
54 if (from > from+num-1)
55 return NULL;
56 save_flags(flags);
57 cli();
58 for (p = root; ; p = p->next) {
59 if ((p != root) && (p->from+p->num-1 >= from)) {
60 p = NULL;
61 break;
63 if ((p->next == NULL) || (p->next->from > from+num-1))
64 break;
66 restore_flags(flags);
67 return p;
71 * Call this from the device driver to register the ioport region.
73 void request_region(unsigned long from, unsigned long num, const char *name)
75 resource_entry_t *p;
76 int i;
78 for (i = 0; i < IOTABLE_SIZE; i++)
79 if (iotable[i].num == 0)
80 break;
81 if (i == IOTABLE_SIZE)
82 printk("warning: ioport table is full\n");
83 else {
84 p = find_gap(&iolist, from, num);
85 if (p == NULL)
86 return;
87 iotable[i].name = name;
88 iotable[i].from = from;
89 iotable[i].num = num;
90 iotable[i].next = p->next;
91 p->next = &iotable[i];
92 return;
96 /*
97 * Call this when the device driver is unloaded
99 void release_region(unsigned long from, unsigned long num)
101 resource_entry_t *p, *q;
103 for (p = &iolist; ; p = q) {
104 q = p->next;
105 if (q == NULL)
106 break;
107 if ((q->from == from) && (q->num == num)) {
108 q->num = 0;
109 p->next = q->next;
110 return;
116 * Call this to check the ioport region before probing
118 int check_region(unsigned long from, unsigned long num)
120 return (find_gap(&iolist, from, num) == NULL) ? -EBUSY : 0;
123 #ifdef __sparc__ /* Why to carry unused code on other architectures? */
125 * This is for architectures with MMU-managed ports (sparc).
127 unsigned long occupy_region(unsigned long base, unsigned long end,
128 unsigned long num, unsigned int align, const char *name)
130 unsigned long from = 0, till;
131 unsigned long flags;
132 int i;
133 resource_entry_t *p; /* Scanning ptr */
134 resource_entry_t *p1; /* === p->next */
135 resource_entry_t *s; /* Found slot */
137 if (base > end-1)
138 return 0;
139 if (num > end - base)
140 return 0;
142 for (i = 0; i < IOTABLE_SIZE; i++)
143 if (iotable[i].num == 0)
144 break;
145 if (i == IOTABLE_SIZE) {
146 /* Driver prints a warning typically. */
147 return 0;
150 save_flags(flags);
151 cli();
152 /* printk("occupy: search in %08lx[%08lx] ", base, end - base); */
153 s = NULL;
154 for (p = &iolist; p != NULL; p = p1) {
155 p1 = p->next;
156 /* Find window in list */
157 from = (p->from+p->num + align-1) & ~((unsigned long)align-1);
158 till = (p1 == NULL)? (unsigned long) (0 - (unsigned long)align): p1->from;
159 /* printk(" %08lx:%08lx", from, till); */
160 /* Clip window with base and end */
161 if (from < base) from = base;
162 if (till > end) till = end;
163 /* See if result is large enougth */
164 if (from < till && from + num < till) {
165 s = p;
166 break;
169 /* printk("\r\n"); */
170 restore_flags(flags);
172 if (s == NULL)
173 return 0;
175 iotable[i].name = name;
176 iotable[i].from = from;
177 iotable[i].num = num;
178 iotable[i].next = s->next;
179 s->next = &iotable[i];
180 return from;
182 #endif
184 /* Called from init/main.c to reserve IO ports. */
185 void __init reserve_setup(char *str, int *ints)
187 int i;
189 for (i = 1; i < ints[0]; i += 2)
190 request_region(ints[i], ints[i+1], "reserved");