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