Rev 6015 | Rev 7733 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 6015 | Rev 7136 | ||
---|---|---|---|
1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
1 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
2 | ;; ;; |
2 | ;; ;; |
3 | ;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;; |
3 | ;; Copyright (C) KolibriOS team 2004-2015. All rights reserved. ;; |
4 | ;; Distributed under terms of the GNU General Public License ;; |
4 | ;; Distributed under terms of the GNU General Public License ;; |
5 | ;; ;; |
5 | ;; ;; |
6 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
6 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; |
7 | 7 | ||
8 | $Revision: 6015 $ |
8 | $Revision: 7136 $ |
9 | 9 | ||
10 | 10 | ||
11 | IRQ_RESERVED equ 24 |
11 | IRQ_RESERVED = 24 |
12 | 12 | ||
13 | IRQ_POOL_SIZE equ 48 |
13 | IRQ_POOL_SIZE = 48 |
14 | 14 | ||
15 | uglobal |
15 | uglobal |
16 | 16 | ||
17 | align 16 |
17 | align 16 |
18 | irqh_tab rd sizeof.LHEAD * IRQ_RESERVED / 4 |
18 | irqh_tab rd sizeof.LHEAD * IRQ_RESERVED / 4 |
19 | 19 | ||
20 | irqh_pool rd sizeof.IRQH * IRQ_POOL_SIZE /4 |
20 | irqh_pool rd sizeof.IRQH * IRQ_POOL_SIZE /4 |
21 | next_irqh rd 1 |
21 | next_irqh rd 1 |
22 | 22 | ||
23 | irq_active_set rd 1 |
23 | irq_active_set rd 1 |
24 | irq_failed rd IRQ_RESERVED |
24 | irq_failed rd IRQ_RESERVED |
25 | 25 | ||
26 | endg |
26 | endg |
27 | 27 | ||
28 | align 4 |
28 | align 4 |
29 | init_irqs: |
29 | init_irqs: |
30 | 30 | ||
31 | mov ecx, IRQ_RESERVED |
31 | mov ecx, IRQ_RESERVED |
32 | mov edi, irqh_tab |
32 | mov edi, irqh_tab |
33 | @@: |
33 | @@: |
34 | mov eax, edi |
34 | mov eax, edi |
35 | stosd |
35 | stosd |
36 | stosd |
36 | stosd |
37 | loop @B |
37 | loop @B |
38 | 38 | ||
39 | mov ecx, IRQ_POOL_SIZE-1 |
39 | mov ecx, IRQ_POOL_SIZE-1 |
40 | mov eax, irqh_pool+sizeof.IRQH |
40 | mov eax, irqh_pool+sizeof.IRQH |
41 | mov [next_irqh], irqh_pool |
41 | mov [next_irqh], irqh_pool |
42 | @@: |
42 | @@: |
43 | mov [eax-sizeof.IRQH], eax |
43 | mov [eax-sizeof.IRQH], eax |
44 | add eax, sizeof.IRQH |
44 | add eax, sizeof.IRQH |
45 | loop @B |
45 | loop @B |
46 | 46 | ||
47 | mov [eax-sizeof.IRQH], dword 0 |
47 | mov [eax-sizeof.IRQH], dword 0 |
48 | ret |
48 | ret |
49 | 49 | ||
50 | 50 | ||
51 | align 4 |
51 | align 4 |
52 | proc attach_int_handler stdcall, irq:dword, handler:dword, user_data:dword |
52 | proc attach_int_handler stdcall, irq:dword, handler:dword, user_data:dword |
53 | locals |
53 | locals |
54 | .irqh dd ? |
54 | .irqh dd ? |
55 | endl |
55 | endl |
56 | 56 | ||
57 | DEBUGF 1, "K : Attach Interrupt %d Handler %x\n", [irq], [handler] |
57 | DEBUGF 1, "K : Attach Interrupt %d Handler %x\n", [irq], [handler] |
58 | 58 | ||
59 | and [.irqh], 0 |
59 | and [.irqh], 0 |
60 | 60 | ||
61 | push ebx |
61 | push ebx |
62 | 62 | ||
63 | mov ebx, [irq] ;irq num |
63 | mov ebx, [irq] ;irq num |
64 | test ebx, ebx |
64 | test ebx, ebx |
65 | jz .err |
65 | jz .err |
66 | 66 | ||
67 | cmp ebx, IRQ_RESERVED |
67 | cmp ebx, IRQ_RESERVED |
68 | jae .err |
68 | jae .err |
69 | 69 | ||
70 | mov edx, [handler] |
70 | mov edx, [handler] |
71 | test edx, edx |
71 | test edx, edx |
72 | jz .err |
72 | jz .err |
73 | 73 | ||
74 | spin_lock_irqsave IrqsList |
74 | spin_lock_irqsave IrqsList |
75 | 75 | ||
76 | ;allocate handler |
76 | ;allocate handler |
77 | 77 | ||
78 | mov ecx, [next_irqh] |
78 | mov ecx, [next_irqh] |
79 | test ecx, ecx |
79 | test ecx, ecx |
80 | jz .fail |
80 | jz .fail |
81 | 81 | ||
82 | mov eax, [ecx] |
82 | mov eax, [ecx] |
83 | mov [next_irqh], eax |
83 | mov [next_irqh], eax |
84 | mov [.irqh], ecx |
84 | mov [.irqh], ecx |
85 | 85 | ||
86 | mov [irq_failed+ebx*4], 0;clear counter |
86 | mov [irq_failed+ebx*4], 0;clear counter |
87 | 87 | ||
88 | mov eax, [user_data] |
88 | mov eax, [user_data] |
89 | mov [ecx+IRQH.handler], edx |
89 | mov [ecx+IRQH.handler], edx |
90 | mov [ecx+IRQH.data], eax |
90 | mov [ecx+IRQH.data], eax |
91 | and [ecx+IRQH.num_ints], 0 |
91 | and [ecx+IRQH.num_ints], 0 |
92 | 92 | ||
93 | lea edx, [irqh_tab+ebx*8] |
93 | lea edx, [irqh_tab+ebx*8] |
94 | list_add_tail ecx, edx ;clobber eax |
94 | list_add_tail ecx, edx ;clobber eax |
95 | stdcall enable_irq, ebx |
95 | stdcall enable_irq, ebx |
96 | 96 | ||
97 | .fail: |
97 | .fail: |
98 | spin_unlock_irqrestore IrqsList |
98 | spin_unlock_irqrestore IrqsList |
99 | .err: |
99 | .err: |
100 | pop ebx |
100 | pop ebx |
101 | mov eax, [.irqh] |
101 | mov eax, [.irqh] |
102 | ret |
102 | ret |
103 | 103 | ||
104 | endp |
104 | endp |
105 | 105 | ||
106 | if 0 |
106 | if 0 |
107 | align 4 |
107 | align 4 |
108 | proc get_int_handler stdcall, irq:dword |
108 | proc get_int_handler stdcall, irq:dword |
109 | 109 | ||
110 | mov eax, [irq] |
110 | mov eax, [irq] |
111 | cmp eax, 15 |
111 | cmp eax, 15 |
112 | ja .fail |
112 | ja .fail |
113 | mov eax, [irq_tab + 4 * eax] |
113 | mov eax, [irq_tab + 4 * eax] |
114 | ret |
114 | ret |
115 | .fail: |
115 | .fail: |
116 | xor eax, eax |
116 | xor eax, eax |
117 | ret |
117 | ret |
118 | endp |
118 | endp |
119 | end if |
119 | end if |
120 | 120 | ||
121 | 121 | ||
122 | align 4 |
122 | align 4 |
123 | proc detach_int_handler |
123 | proc detach_int_handler |
124 | 124 | ||
125 | ret |
125 | ret |
126 | endp |
126 | endp |
127 | 127 | ||
128 | 128 | ||
129 | macro irq_serv_h [num] { |
129 | macro irq_serv_h [num] { |
130 | forward |
130 | forward |
131 | align 4 |
131 | align 4 |
132 | .irq_#num : |
132 | .irq_#num : |
133 | push num |
133 | push num |
134 | jmp .main |
134 | jmp .main |
135 | } |
135 | } |
136 | 136 | ||
137 | align 16 |
137 | align 16 |
138 | irq_serv: |
138 | irq_serv: |
139 | 139 | ||
140 | ; .irq_1: |
140 | ; .irq_1: |
141 | ; push 1 |
141 | ; push 1 |
142 | ; jmp .main |
142 | ; jmp .main |
143 | ; etc... |
143 | ; etc... |
144 | 144 | ||
145 | irq_serv_h 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15 |
145 | irq_serv_h 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15 |
146 | irq_serv_h 16, 17, 18, 19, 20, 21, 22, 23 |
146 | irq_serv_h 16, 17, 18, 19, 20, 21, 22, 23 |
147 | 147 | ||
148 | purge irq_serv_h |
148 | purge irq_serv_h |
149 | 149 | ||
150 | align 16 |
150 | align 16 |
151 | .main: |
151 | .main: |
152 | save_ring3_context |
152 | save_ring3_context |
153 | 153 | ||
154 | mov ebp, [esp + 32] |
154 | mov ebp, [esp + 32] |
155 | mov bx, app_data;os_data |
155 | mov bx, app_data;os_data |
156 | mov ds, bx |
156 | mov ds, bx |
157 | mov es, bx |
157 | mov es, bx |
158 | 158 | ||
159 | cmp [v86_irqhooks+ebp*8], 0 |
159 | cmp [v86_irqhooks+ebp*8], 0 |
160 | jnz v86_irq |
160 | jnz v86_irq |
161 | 161 | ||
162 | bts [irq_active_set], ebp |
162 | bts [irq_active_set], ebp |
163 | 163 | ||
164 | lea esi, [irqh_tab+ebp*8] ; esi= list head |
164 | lea esi, [irqh_tab+ebp*8] ; esi= list head |
165 | mov ebx, esi |
165 | mov ebx, esi |
166 | .next: |
166 | .next: |
167 | mov ebx, [ebx+IRQH.list.next]; ebx= irqh pointer |
167 | mov ebx, [ebx+IRQH.list.next]; ebx= irqh pointer |
168 | cmp ebx, esi |
168 | cmp ebx, esi |
169 | je .done |
169 | je .done |
170 | 170 | ||
171 | push ebx ; FIX THIS |
171 | push ebx ; FIX THIS |
172 | push edi |
172 | push edi |
173 | push esi |
173 | push esi |
174 | 174 | ||
175 | push [ebx+IRQH.data] |
175 | push [ebx+IRQH.data] |
176 | call [ebx+IRQH.handler] |
176 | call [ebx+IRQH.handler] |
177 | pop ecx |
177 | pop ecx |
178 | 178 | ||
179 | pop esi |
179 | pop esi |
180 | pop edi |
180 | pop edi |
181 | pop ebx |
181 | pop ebx |
182 | 182 | ||
183 | test eax, eax |
183 | test eax, eax |
184 | jz .next |
184 | jz .next |
185 | 185 | ||
186 | inc [ebx+IRQH.num_ints] |
186 | inc [ebx+IRQH.num_ints] |
187 | btr [irq_active_set], ebp |
187 | btr [irq_active_set], ebp |
188 | jmp .next |
188 | jmp .next |
189 | 189 | ||
190 | .done: |
190 | .done: |
191 | btr [irq_active_set], ebp |
191 | btr [irq_active_set], ebp |
192 | jnc .exit |
192 | jnc .exit |
193 | 193 | ||
194 | ; There is at least one configuration with one device which generates IRQ |
194 | ; There is at least one configuration with one device which generates IRQ |
195 | ; that is not the same as it should be according to PCI config space. |
195 | ; that is not the same as it should be according to PCI config space. |
196 | ; For that device, the handler is registered at wrong IRQ. |
196 | ; For that device, the handler is registered at wrong IRQ. |
197 | ; As a workaround, when nobody acknowledges the generated IRQ, |
197 | ; As a workaround, when nobody acknowledges the generated IRQ, |
198 | ; try to ask all other registered handlers; if some handler acknowledges |
198 | ; try to ask all other registered handlers; if some handler acknowledges |
199 | ; the IRQ this time, relink it to the current IRQ list. |
199 | ; the IRQ this time, relink it to the current IRQ list. |
200 | ; To make this more reliable, for every handler keep number of times |
200 | ; To make this more reliable, for every handler keep number of times |
201 | ; that it has acknowledged an IRQ, and assume that handlers with at least one |
201 | ; that it has acknowledged an IRQ, and assume that handlers with at least one |
202 | ; acknowledged IRQ are registered properly. |
202 | ; acknowledged IRQ are registered properly. |
203 | ; Note: this still isn't 100% correct, because two IRQs can fire simultaneously, |
203 | ; Note: this still isn't 100% correct, because two IRQs can fire simultaneously, |
204 | ; the better way would be to find the correct IRQ, but I don't know how to do |
204 | ; the better way would be to find the correct IRQ, but I don't know how to do |
205 | ; this in that case. |
205 | ; this in that case. |
206 | cmp ebp, 1 |
206 | cmp ebp, 1 |
207 | jz .fail |
207 | jz .fail |
208 | push ebp |
208 | push ebp |
209 | xor ebp, ebp |
209 | xor ebp, ebp |
210 | .try_other_irqs: |
210 | .try_other_irqs: |
211 | cmp ebp, [esp] |
211 | cmp ebp, [esp] |
212 | jz .try_next_irq |
212 | jz .try_next_irq |
213 | cmp ebp, 1 |
213 | cmp ebp, 1 |
214 | jz .try_next_irq |
214 | jz .try_next_irq |
215 | cmp ebp, 6 |
215 | cmp ebp, 6 |
216 | jz .try_next_irq |
216 | jz .try_next_irq |
217 | cmp ebp, 12 |
217 | cmp ebp, 12 |
218 | jz .try_next_irq |
218 | jz .try_next_irq |
219 | cmp ebp, 14 |
219 | cmp ebp, 14 |
220 | jz .try_next_irq |
220 | jz .try_next_irq |
221 | cmp ebp, 15 |
221 | cmp ebp, 15 |
222 | jz .try_next_irq |
222 | jz .try_next_irq |
223 | lea esi, [irqh_tab+ebp*8] |
223 | lea esi, [irqh_tab+ebp*8] |
224 | mov ebx, esi |
224 | mov ebx, esi |
225 | .try_next_handler: |
225 | .try_next_handler: |
226 | mov ebx, [ebx+IRQH.list.next] |
226 | mov ebx, [ebx+IRQH.list.next] |
227 | cmp ebx, esi |
227 | cmp ebx, esi |
228 | je .try_next_irq |
228 | je .try_next_irq |
229 | cmp [ebx+IRQH.num_ints], 0 |
229 | cmp [ebx+IRQH.num_ints], 0 |
230 | jne .try_next_handler |
230 | jne .try_next_handler |
231 | ; keyboard handler acknowledges everything |
231 | ; keyboard handler acknowledges everything |
232 | push [ebx+IRQH.data] |
232 | push [ebx+IRQH.data] |
233 | call [ebx+IRQH.handler] |
233 | call [ebx+IRQH.handler] |
234 | pop ecx |
234 | pop ecx |
235 | test eax, eax |
235 | test eax, eax |
236 | jz .try_next_handler |
236 | jz .try_next_handler |
237 | 237 | ||
238 | .found_in_wrong_list: |
238 | .found_in_wrong_list: |
239 | DEBUGF 1,'K : warning: relinking handler from IRQ%d to IRQ%d\n',\ |
239 | DEBUGF 1,'K : warning: relinking handler from IRQ%d to IRQ%d\n',\ |
240 | ebp, [esp] |
240 | ebp, [esp] |
241 | pop ebp |
241 | pop ebp |
242 | spin_lock_irqsave IrqsList |
242 | spin_lock_irqsave IrqsList |
243 | list_del ebx |
243 | list_del ebx |
244 | lea edx, [irqh_tab+ebp*8] |
244 | lea edx, [irqh_tab+ebp*8] |
245 | list_add_tail ebx, edx |
245 | list_add_tail ebx, edx |
246 | spin_unlock_irqrestore IrqsList |
246 | spin_unlock_irqrestore IrqsList |
247 | jmp .exit |
247 | jmp .exit |
248 | 248 | ||
249 | .try_next_irq: |
249 | .try_next_irq: |
250 | inc ebp |
250 | inc ebp |
251 | cmp ebp, 16 |
251 | cmp ebp, 16 |
252 | jb .try_other_irqs |
252 | jb .try_other_irqs |
253 | pop ebp |
253 | pop ebp |
254 | 254 | ||
255 | .fail: |
255 | .fail: |
256 | inc [irq_failed+ebp*4] |
256 | inc [irq_failed+ebp*4] |
257 | .exit: |
257 | .exit: |
258 | 258 | ||
259 | mov ecx, ebp |
259 | mov ecx, ebp |
260 | call irq_eoi |
260 | call irq_eoi |
261 | 261 | ||
262 | ; IRQ handler could make some kernel thread ready; reschedule |
262 | ; IRQ handler could make some kernel thread ready; reschedule |
263 | mov bl, SCHEDULE_HIGHER_PRIORITY |
263 | mov bl, SCHEDULE_HIGHER_PRIORITY |
264 | call find_next_task |
264 | call find_next_task |
265 | jz .return ; if there is only one running process |
265 | jz .return ; if there is only one running process |
266 | call do_change_task |
266 | call do_change_task |
267 | .return: |
267 | .return: |
268 | restore_ring3_context |
268 | restore_ring3_context |
269 | add esp, 4 |
269 | add esp, 4 |
270 | iret |
270 | iret |
271 | 271 | ||
272 | align 4 |
272 | align 4 |
273 | irqD: |
273 | irqD: |
274 | push eax |
274 | push eax |
275 | push ecx |
275 | push ecx |
276 | xor eax, eax |
276 | xor eax, eax |
277 | out 0xf0, al |
277 | out 0xf0, al |
278 | mov cl, 13 |
278 | mov cl, 13 |
279 | call irq_eoi |
279 | call irq_eoi |
280 | pop ecx |
280 | pop ecx |
281 | pop eax |
281 | pop eax |
282 | iret |
282 | iret |