This source file includes following definitions.
- ios
- dump_io_bitmap
- set_bitmap
- get_ioport_list
- sys_ioperm
- sys_iopl
- find_gap
- request_region
- snarf_region
- release_region
- check_region
- reserve_setup
1
2
3
4
5
6
7
8 #include <linux/sched.h>
9 #include <linux/kernel.h>
10 #include <linux/errno.h>
11 #include <linux/types.h>
12 #include <linux/ioport.h>
13
14 #define IOTABLE_SIZE 32
15
16 typedef struct resource_entry_t {
17 u_long from, num;
18 const char *name;
19 struct resource_entry_t *next;
20 } resource_entry_t;
21
22 static resource_entry_t iolist = { 0, 0, "", NULL };
23
24 static resource_entry_t iotable[IOTABLE_SIZE];
25
26 #define _IODEBUG
27
28 #ifdef IODEBUG
29 static char * ios(unsigned long l)
30 {
31 static char str[33] = { '\0' };
32 int i;
33 unsigned long mask;
34
35 for (i = 0, mask = 0x80000000; i < 32; ++i, mask >>= 1)
36 str[i] = (l & mask) ? '1' : '0';
37 return str;
38 }
39
40 static void dump_io_bitmap(void)
41 {
42 int i, j;
43 int numl = sizeof(current->tss.io_bitmap) >> 2;
44
45 for (i = j = 0; j < numl; ++i)
46 {
47 printk("%4d [%3x]: ", 64*i, 64*i);
48 printk("%s ", ios(current->tss.io_bitmap[j++]));
49 if (j < numl)
50 printk("%s", ios(current->tss.io_bitmap[j++]));
51 printk("\n");
52 }
53 }
54 #endif
55
56
57 asmlinkage void set_bitmap(unsigned long *bitmap, short base, short extent, int new_value)
58 {
59 int mask;
60 unsigned long *bitmap_base = bitmap + (base >> 5);
61 unsigned short low_index = base & 0x1f;
62 int length = low_index + extent;
63
64 if (low_index != 0) {
65 mask = (~0 << low_index);
66 if (length < 32)
67 mask &= ~(~0 << length);
68 if (new_value)
69 *bitmap_base++ |= mask;
70 else
71 *bitmap_base++ &= ~mask;
72 length -= 32;
73 }
74
75 mask = (new_value ? ~0 : 0);
76 while (length >= 32) {
77 *bitmap_base++ = mask;
78 length -= 32;
79 }
80
81 if (length > 0) {
82 mask = ~(~0 << length);
83 if (new_value)
84 *bitmap_base++ |= mask;
85 else
86 *bitmap_base++ &= ~mask;
87 }
88 }
89
90
91
92
93 int get_ioport_list(char *buf)
94 {
95 resource_entry_t *p;
96 int len = 0;
97
98 for (p = iolist.next; (p) && (len < 4000); p = p->next)
99 len += sprintf(buf+len, "%04lx-%04lx : %s\n",
100 p->from, p->from+p->num-1, p->name);
101 if (p)
102 len += sprintf(buf+len, "4K limit reached!\n");
103 return len;
104 }
105
106
107
108
109 asmlinkage int sys_ioperm(unsigned long from, unsigned long num, int turn_on)
110 {
111 if (from + num <= from)
112 return -EINVAL;
113 if (from + num > IO_BITMAP_SIZE*32)
114 return -EINVAL;
115 if (!suser())
116 return -EPERM;
117
118 #ifdef IODEBUG
119 printk("io: from=%d num=%d %s\n", from, num, (turn_on ? "on" : "off"));
120 #endif
121 set_bitmap((unsigned long *)current->tss.io_bitmap, from, num, !turn_on);
122 return 0;
123 }
124
125 unsigned int *stack;
126
127
128
129
130
131
132
133
134
135
136
137 asmlinkage int sys_iopl(long ebx,long ecx,long edx,
138 long esi, long edi, long ebp, long eax, long ds,
139 long es, long fs, long gs, long orig_eax,
140 long eip,long cs,long eflags,long esp,long ss)
141 {
142 unsigned int level = ebx;
143
144 if (level > 3)
145 return -EINVAL;
146 if (!suser())
147 return -EPERM;
148 *(&eflags) = (eflags & 0xffffcfff) | (level << 12);
149 return 0;
150 }
151
152
153
154
155 static resource_entry_t *find_gap(resource_entry_t *root,
156 u_long from, u_long num)
157 {
158 unsigned long flags;
159 resource_entry_t *p;
160
161 if (from > from+num-1)
162 return NULL;
163 save_flags(flags);
164 cli();
165 for (p = root; ; p = p->next) {
166 if ((p != root) && (p->from+p->num-1 >= from)) {
167 p = NULL;
168 break;
169 }
170 if ((p->next == NULL) || (p->next->from > from+num-1))
171 break;
172 }
173 restore_flags(flags);
174 return p;
175 }
176
177
178
179
180 void request_region(unsigned int from, unsigned int num, const char *name)
181 {
182 resource_entry_t *p;
183 int i;
184
185 for (i = 0; i < IOTABLE_SIZE; i++)
186 if (iotable[i].num == 0)
187 break;
188 if (i == IOTABLE_SIZE)
189 printk("warning: ioport table is full\n");
190 else {
191 p = find_gap(&iolist, from, num);
192 if (p == NULL)
193 return;
194 iotable[i].name = name;
195 iotable[i].from = from;
196 iotable[i].num = num;
197 iotable[i].next = p->next;
198 p->next = &iotable[i];
199 return;
200 }
201 }
202
203
204
205
206
207 void snarf_region(unsigned int from, unsigned int num)
208 {
209 request_region(from,num,"No name given.");
210 }
211
212
213
214
215 void release_region(unsigned int from, unsigned int num)
216 {
217 resource_entry_t *p, *q;
218
219 for (p = &iolist; ; p = q) {
220 q = p->next;
221 if (q == NULL)
222 break;
223 if ((q->from == from) && (q->num == num)) {
224 q->num = 0;
225 p->next = q->next;
226 return;
227 }
228 }
229 }
230
231
232
233
234 int check_region(unsigned int from, unsigned int num)
235 {
236 return (find_gap(&iolist, from, num) == NULL) ? -EBUSY : 0;
237 }
238
239
240 void reserve_setup(char *str, int *ints)
241 {
242 int i;
243
244 for (i = 1; i < ints[0]; i += 2)
245 request_region(ints[i], ints[i+1], "reserved");
246 }