Subversion Repositories Kolibri OS

Rev

Rev 5201 | Go to most recent revision | 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.
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
3908 Serge 213
        cmp     ebp, 6
214
        jz      .try_next_irq
3555 Serge 215
        cmp     ebp, 12
216
        jz      .try_next_irq
3908 Serge 217
        cmp     ebp, 14
218
        jz      .try_next_irq
219
        cmp     ebp, 15
220
        jz      .try_next_irq
3555 Serge 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:
3908 Serge 254
        inc     [irq_failed+ebp*4]
2106 serge 255
.exit:
256
 
3908 Serge 257
        mov     ecx, ebp
258
        call    irq_eoi
2166 serge 259
 
3626 Serge 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:
3908 Serge 266
        restore_ring3_context
267
        add     esp, 4
268
        iret
2106 serge 269
 
2130 serge 270
align 4
271
irqD:
3908 Serge 272
        push    eax
273
        push    ecx
2434 Serge 274
        xor     eax, eax
275
        out     0xf0, al
3908 Serge 276
        mov     cl, 13
277
        call    irq_eoi
278
        pop     ecx
279
        pop     eax
2130 serge 280
        iret
2106 serge 281