Subversion Repositories Kolibri OS

Rev

Rev 5565 | Details | Compare with Previous | Last modification | View Log | RSS feed

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