Subversion Repositories Kolibri OS

Rev

Rev 4429 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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