Subversion Repositories Kolibri OS

Rev

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

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