Subversion Repositories Kolibri OS

Rev

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