1
2
3
4
5
6
7
8
9
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>
16
17#define IOTABLE_SIZE 128
18
19typedef struct resource_entry_t {
20 u_long from, num;
21 const char *name;
22 struct resource_entry_t *next;
23} resource_entry_t;
24
25static resource_entry_t iolist = { 0, 0, "", NULL };
26
27static resource_entry_t iotable[IOTABLE_SIZE];
28
29
30
31
32int get_ioport_list(char *buf)
33{
34 resource_entry_t *p;
35 int len = 0;
36
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;
43}
44
45
46
47
48static resource_entry_t *find_gap(resource_entry_t *root,
49 u_long from, u_long num)
50{
51 unsigned long flags;
52 resource_entry_t *p;
53
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;
62 }
63 if ((p->next == NULL) || (p->next->from > from+num-1))
64 break;
65 }
66 restore_flags(flags);
67 return p;
68}
69
70
71
72
73void request_region(unsigned long from, unsigned long num, const char *name)
74{
75 resource_entry_t *p;
76 int i;
77
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;
93 }
94}
95
96
97
98
99void release_region(unsigned long from, unsigned long num)
100{
101 resource_entry_t *p, *q;
102
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;
111 }
112 }
113}
114
115
116
117
118int check_region(unsigned long from, unsigned long num)
119{
120 return (find_gap(&iolist, from, num) == NULL) ? -EBUSY : 0;
121}
122
123#ifdef __sparc__
124
125
126
127unsigned long occupy_region(unsigned long base, unsigned long end,
128 unsigned long num, unsigned int align, const char *name)
129{
130 unsigned long from = 0, till;
131 unsigned long flags;
132 int i;
133 resource_entry_t *p;
134 resource_entry_t *p1;
135 resource_entry_t *s;
136
137 if (base > end-1)
138 return 0;
139 if (num > end - base)
140 return 0;
141
142 for (i = 0; i < IOTABLE_SIZE; i++)
143 if (iotable[i].num == 0)
144 break;
145 if (i == IOTABLE_SIZE) {
146
147 return 0;
148 }
149
150 save_flags(flags);
151 cli();
152
153 s = NULL;
154 for (p = &iolist; p != NULL; p = p1) {
155 p1 = p->next;
156
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
160
161 if (from < base) from = base;
162 if (till > end) till = end;
163
164 if (from < till && from + num < till) {
165 s = p;
166 break;
167 }
168 }
169
170 restore_flags(flags);
171
172 if (s == NULL)
173 return 0;
174
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;
181}
182#endif
183
184
185__initfunc(void reserve_setup(char *str, int *ints))
186{
187 int i;
188
189 for (i = 1; i < ints[0]; i += 2)
190 request_region(ints[i], ints[i+1], "reserved");
191}
192