Subversion Repositories Kolibri OS

Rev

Rev 2465 | Rev 3626 | 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
 
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
2434 Serge 37
        mov     eax, irqh_pool+sizeof.IRQH
2229 Serge 38
    mov [next_irqh], irqh_pool
39
@@:
2434 Serge 40
        mov     [eax-sizeof.IRQH], eax
41
        add     eax, sizeof.IRQH
2229 Serge 42
    loop @B
43
 
2434 Serge 44
        mov     [eax-sizeof.IRQH], dword 0
2229 Serge 45
    ret
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
 
54
         and [.irqh], 0
55
 
56
         push ebx
57
 
58
         mov  ebx, [irq]            ;irq num
59
         test ebx, ebx
60
         jz   .err
61
 
2130 serge 62
         cmp  ebx, IRQ_RESERVED
2106 serge 63
         jae  .err
64
 
65
         mov  edx, [handler]
66
         test edx, edx
67
         jz   .err
68
 
3555 Serge 69
        spin_lock_irqsave IrqsList
2106 serge 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
 
2434 Serge 81
        mov     [irq_failed+ebx*4], 0;clear counter
2130 serge 82
 
2106 serge 83
         mov eax, [user_data]
84
         mov [ecx+IRQH.handler], edx
85
         mov [ecx+IRQH.data],    eax
3555 Serge 86
        and     [ecx+IRQH.num_ints], 0
2106 serge 87
 
88
         lea edx, [irqh_tab+ebx*8]
89
         list_add_tail ecx, edx     ;clobber eax
2130 serge 90
         stdcall enable_irq, ebx
2106 serge 91
 
92
.fail:
3555 Serge 93
        spin_unlock_irqrestore IrqsList
2106 serge 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:
147
       save_ring3_context
148
 
149
       mov   ebp, [esp + 32]
2434 Serge 150
        mov     bx, app_data;os_data
2106 serge 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
 
164
       cmp   bp, 14
165
       jnz   @f
166
       push  ebp
167
       call  [irq14_func]
168
       pop   ebp
169
@@:
170
       cmp   bp, 15
171
       jnz   @f
172
       push  ebp
173
       call  [irq15_func]
174
       pop   ebp
175
@@:
176
       bts [irq_active_set], ebp
177
 
178
       lea esi, [irqh_tab+ebp*8]        ; esi= list head
179
       mov ebx, esi
180
.next:
2434 Serge 181
        mov     ebx, [ebx+IRQH.list.next]; ebx= irqh pointer
2106 serge 182
       cmp ebx, esi
183
       je .done
184
 
185
       push ebx                         ; FIX THIS
186
       push edi
187
       push esi
188
 
189
       push [ebx+IRQH.data]
190
       call [ebx+IRQH.handler]
3555 Serge 191
        pop     ecx
2106 serge 192
 
193
       pop esi
194
       pop edi
195
       pop ebx
196
 
197
       test eax, eax
198
       jz .next
199
 
3555 Serge 200
        inc     [ebx+IRQH.num_ints]
2106 serge 201
       btr [irq_active_set], ebp
202
       jmp .next
203
 
204
.done:
205
       btr [irq_active_set], ebp
206
       jnc .exit
207
 
3555 Serge 208
; There is at least one configuration with one device which generates IRQ
209
; that is not the same as it should be according to PCI config space.
210
; For that device, the handler is registered at wrong IRQ.
211
; As a workaround, when nobody acknowledges the generated IRQ,
212
; try to ask all other registered handlers; if some handler acknowledges
213
; the IRQ this time, relink it to the current IRQ list.
214
; To make this more reliable, for every handler keep number of times
215
; that it has acknowledged an IRQ, and assume that handlers with at least one
216
; acknowledged IRQ are registered properly.
217
; Note: this still isn't 100% correct, because two IRQs can fire simultaneously,
218
; the better way would be to find the correct IRQ, but I don't know how to do
219
; this in that case.
220
; Also, [fdc_irq_func], [irq14_func], [irq15_func] could process interrupt
221
; but do not return whether they did it, so just ignore IRQs 6, 14, 15.
222
        cmp     ebp, 6
223
        jz      .fail
224
        cmp     ebp, 14
225
        jz      .fail
226
        cmp     ebp, 15
227
        jz      .fail
228
        push    ebp
229
        xor     ebp, ebp
230
.try_other_irqs:
231
        cmp     ebp, [esp]
232
        jz      .try_next_irq
233
        cmp     ebp, 1
234
        jz      .try_next_irq
235
        cmp     ebp, 12
236
        jz      .try_next_irq
237
        lea     esi, [irqh_tab+ebp*8]
238
        mov     ebx, esi
239
.try_next_handler:
240
        mov     ebx, [ebx+IRQH.list.next]
241
        cmp     ebx, esi
242
        je      .try_next_irq
243
        cmp     [ebx+IRQH.num_ints], 0
244
        jne     .try_next_handler
245
; keyboard handler acknowledges everything
246
        push    [ebx+IRQH.data]
247
        call    [ebx+IRQH.handler]
248
        pop     ecx
249
        test    eax, eax
250
        jz      .try_next_handler
251
 
252
.found_in_wrong_list:
253
        DEBUGF 1,'K : warning: relinking handler from IRQ%d to IRQ%d\n',\
254
                ebp, [esp]
255
        pop     ebp
256
        spin_lock_irqsave IrqsList
257
        list_del ebx
258
        lea     edx, [irqh_tab+ebp*8]
259
        list_add_tail ebx, edx
260
        spin_unlock_irqrestore IrqsList
261
        jmp     .exit
262
 
263
.try_next_irq:
264
        inc     ebp
265
        cmp     ebp, 16
266
        jb      .try_other_irqs
267
        pop     ebp
268
 
269
.fail:
2106 serge 270
       inc [irq_failed+ebp*4]
271
.exit:
272
 
2166 serge 273
       mov ecx, ebp
274
       call irq_eoi
275
 
2106 serge 276
       restore_ring3_context
277
       add   esp, 4
278
       iret
279
 
2130 serge 280
align 4
281
irqD:
282
        push  eax
283
        push  ecx
2434 Serge 284
        xor     eax, eax
285
        out     0xf0, al
2166 serge 286
        mov   cl, 13
287
        call  irq_eoi
2130 serge 288
        pop   ecx
289
        pop   eax
290
        iret
2106 serge 291