nckernel
0.1
Main Page
Related Pages
Modules
Data Structures
Files
File List
Globals
All
Data Structures
Files
Functions
Variables
Typedefs
Enumerations
Enumerator
Macros
Groups
Pages
arch
x86
src
isr.c
Go to the documentation of this file.
1
#include <
sys/types.h
>
2
#include <
stdio.h
>
3
#include <
stdint.h
>
4
#include <
stdlib.h
>
5
#include <
string.h
>
6
#include <
errno.h
>
7
#include <
stddef.h
>
8
#include <
pthread.h
>
9
#include <
assert.h
>
10
#include <
unistd.h
>
11
12
#include <
object.h
>
13
#include <
list.h
>
14
#include <
thread.h
>
15
#include <
interrupt.h
>
16
#include <
isr.h
>
17
#include <
arch.h
>
18
#include <
x86_util.h
>
19
20
#include <
segment.h
>
/* for USER, KERNEL macro definitions */
21
#include <
paging.h
>
/* for cr3 structure - x86.h references this */
22
#include <
x86.h
>
23
24
#include <
debug.h
>
25
26
struct
irq_handler
{
27
struct
list_head
head
;
28
int (*
handler
)(
int
sub_irq,
void
*
info
,
void
*
data
);
29
int
priority
;
30
void
*
data
;
31
};
32
33
struct
list
{
34
struct
list_head
head
;
35
int
idx
;
36
int
cnt
;
37
int
max_priority
;
38
struct
list_head
list
;
39
};
40
41
static
LIST_HEAD
(s_list);
42
43
int
register_irq
(
int
idx,
int
priority,
int
(*handler)(
int
,
void
*,
void
*),
void
*data)
44
{
45
struct
list_head
*pos;
46
struct
list
*
entry
;
47
struct
irq_handler
*item;
48
struct
irq_handler
*tmp;
49
unsigned
long
flags;
50
51
irq_local_save
(&flags);
52
item =
malloc
(
sizeof
(*item));
53
if
(!item) {
54
irq_local_restore
(flags);
55
return
-
ENOMEM
;
56
}
57
58
entry =
NULL
;
59
list_for_each
(pos, &s_list) {
60
entry =
list_entry
(pos,
struct
list
,
head
);
61
if
(entry->
idx
== idx) {
62
break
;
63
}
64
entry =
NULL
;
65
}
66
67
if
(!entry) {
68
entry =
malloc
(
sizeof
(*entry));
69
if
(!entry) {
70
free
(item);
71
irq_local_restore
(flags);
72
return
-
ENOMEM
;
73
}
74
75
entry->
idx
= idx;
76
entry->
cnt
= 0;
77
entry->
max_priority
= 0;
78
INIT_LIST_HEAD(&entry->
list
);
79
80
list_add_tail(&entry->
head
, &s_list);
81
}
82
83
entry->
cnt
++;
84
if
(priority > entry->
max_priority
) {
85
entry->
max_priority
=
priority
;
86
}
87
89
list_for_each
(pos, &entry->
list
) {
90
tmp =
list_entry
(pos,
struct
irq_handler
,
head
);
91
92
if
(tmp->
priority
>= priority) {
93
break
;
94
}
95
}
96
97
item->
handler
=
handler
;
98
item->
priority
=
priority
;
99
item->
data
=
data
;
100
101
list_add_tail(&item->
head
, pos);
102
irq_local_restore
(flags);
103
return
0;
104
}
105
106
int
unregister_irq
(
int
idx,
int
(*
handler
)(
int
,
void
*,
void
*),
void
*
data
)
107
{
108
struct
list_head
*n;
109
struct
list_head
*pos;
110
struct
list
*
entry
;
111
struct
irq_handler
*item;
112
unsigned
long
flags;
113
114
irq_local_save
(&flags);
115
entry =
NULL
;
116
list_for_each_safe
(pos, n, &s_list) {
117
entry =
list_entry
(pos,
struct
list
,
head
);
118
if
(entry->
idx
== idx) {
119
break
;
120
}
121
entry =
NULL
;
122
}
123
124
if
(!entry) {
125
irq_local_restore
(flags);
126
return
-
ENOENT
;
127
}
128
129
list_for_each_safe
(pos, n, &entry->
list
) {
130
item =
list_entry
(pos,
struct
irq_handler
,
head
);
131
if
(item->
handler
==
handler
&& item->
data
== data) {
132
entry->
cnt
--;
133
134
list_del(&item->
head
);
135
free
(item);
136
137
if
(!entry->
cnt
) {
138
list_del(&entry->
head
);
139
free
(entry);
140
}
141
irq_local_restore
(flags);
142
return
0;
143
}
144
}
145
146
irq_local_restore
(flags);
147
return
-
ENOENT
;
148
}
149
150
static
inline
struct
thread
*select_next_thread(
struct
thread
*tcb)
151
{
152
struct
x86_arch_data
*arch_data;
153
struct
list_head
*n;
154
struct
thread
*it;
155
int
status
;
156
157
it = tcb;
158
n =
LIST_NEXT
(&it->
link
);
159
while
(1) {
160
it =
list_entry
(n,
struct
thread
,
link
);
161
if
(tcb == it) {
/* 쓰레드가 하나 뿐 인 경우 */
162
break
;
163
}
164
165
n =
LIST_NEXT
(n);
/* 다음 쓰레드를 찾아 놓고 */
166
167
if
(it->
sem
) {
/* 세마포어가 있는 쓰레드는 스킵! */
168
continue
;
169
}
170
171
status =
thread_get_status
(it);
172
if
(status ==
RUNNING
) {
/* 실행 중인 쓰레드를 선택 */
173
break
;
174
}
175
176
if
(status ==
DELETED
) {
177
pthread_cancel
(it);
178
}
else
if
(status ==
CREATED
) {
179
}
else
if
(status ==
READY
) {
180
thread_set_status
(it,
RUNNING
);
181
}
182
}
183
184
arch_data =
thread_get_arch_data
(it);
185
assert
(arch_data &&
"Arch data is not valid"
);
186
187
if
(
x86_util_get_ring
(it) ==
USER
) {
188
unsigned
long
sp;
189
struct
x86_user_data
*user_data;
190
unsigned
char
*
io_bitmap
;
191
198
sp =
thread_get_stack_pointer
(it);
199
user_data =
thread_get_user_data
(it);
200
assert
(user_data &&
"User data is not valid"
);
201
202
tss_update_kernel_stack
(sp);
203
io_bitmap =
tss_io_bitmap_get
();
204
assert
(io_bitmap &&
"I/O Bitmap is not valid"
);
205
206
memcpy
(io_bitmap, user_data->
io_bitmap
,
207
sizeof
(user_data->
io_bitmap
));
208
}
209
load_cr3(arch_data->
pma_pgd
);
210
211
return
it;
212
}
213
214
static
inline
void
create_info(
struct
pt_regs
*reg,
struct
intr_info
*
info
)
215
{
216
if
(reg->
irq
!=
IRQ_NR_SW
) {
217
info->
argc
= 0;
218
info->
argv
=
NULL
;
219
info->
irq
= -1;
220
info->
ret
= -
ENOSYS
;
221
return
;
222
}
223
224
info->
irq
= reg->
pushad
.
eax
;
225
info->
argc
= reg->
pushad
.
ecx
;
226
if
(info->
argc
) {
227
int
size;
228
229
size =
sizeof
(*info->
argv
) * info->
argc
;
230
231
info->
argv
=
malloc
(size);
232
assert
(info->
argv
);
233
243
memcpy
(info->
argv
, (
void
*)reg->
pushad
.
esp
, size);
244
}
else
{
245
info->
argv
=
NULL
;
246
}
247
248
return
;
249
}
250
251
static
inline
void
destroy_info(
struct
pt_regs
*reg,
struct
intr_info
*info)
252
{
253
if
(reg->
irq
!=
IRQ_NR_SW
) {
254
return
;
255
}
256
257
reg->
pushad
.
eax
= info->
ret
;
258
259
if
(info->
argv
) {
260
free
(info->
argv
);
261
}
262
}
263
264
asmlinkage
struct
pt_regs
*
do_irq
(
struct
pt_regs
*reg)
265
{
266
struct
list_head
*pos;
267
struct
list
*
entry
;
268
struct
thread
*tcb;
269
270
tcb = (
struct
thread
*)
pthread_self
();
271
if
(!tcb) {
272
dbg_printf
(
"[%s:%d]\n"
, __func__, __LINE__);
273
halt
();
274
}
275
276
tcb->
esp
= (
uint32_t
*)reg;
277
278
list_for_each
(pos, &s_list) {
279
entry =
list_entry
(pos,
struct
list
, head);
280
if
(entry->
idx
== reg->
irq
) {
281
break
;
282
}
283
284
entry =
NULL
;
285
}
286
287
if
(entry) {
288
struct
intr_info
info;
289
struct
irq_handler
*item;
290
301
create_info(reg, &info);
302
303
list_for_each
(pos, &entry->
list
) {
304
item =
list_entry
(pos,
struct
irq_handler
,
head
);
305
if
(!item->
handler
) {
306
continue
;
307
}
308
309
info.
ret
= item->
handler
(info.
irq
, &info, item->
data
);
310
}
311
312
destroy_info(reg, &info);
313
}
else
{
314
dbg_printf
(
"[%s:%d] IRQ 0x%x has no handler\r"
,
315
__func__, __LINE__, reg->
irq
);
316
}
317
318
tcb = select_next_thread(tcb);
319
if
(!tcb) {
320
dbg_printf
(
"[%s:%d]\n"
, __func__, __LINE__);
321
halt
();
322
}
323
324
reg = (
struct
pt_regs
*)tcb->
esp
;
325
return
reg;
326
}
327
328
/* End of a file */
Generated on Thu Nov 7 2013 02:45:25 for nckernel by
1.8.4