Subversion Repositories Kolibri OS

Rev

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

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