workaround for handlers registered with wrong IRQ

git-svn-id: svn://kolibrios.org@3505 a494cfbc-eb01-0410-851d-a64ba20cac60
This commit is contained in:
CleverMouse 2013-05-15 15:10:55 +00:00
parent f3b083075c
commit 9bae783f11

View File

@ -66,8 +66,7 @@ proc attach_int_handler stdcall, irq:dword, handler:dword, user_data:dword
test edx, edx test edx, edx
jz .err jz .err
pushfd spin_lock_irqsave IrqsList
cli
;allocate handler ;allocate handler
@ -84,13 +83,14 @@ proc attach_int_handler stdcall, irq:dword, handler:dword, user_data:dword
mov eax, [user_data] mov eax, [user_data]
mov [ecx+IRQH.handler], edx mov [ecx+IRQH.handler], edx
mov [ecx+IRQH.data], eax mov [ecx+IRQH.data], eax
and [ecx+IRQH.num_ints], 0
lea edx, [irqh_tab+ebx*8] lea edx, [irqh_tab+ebx*8]
list_add_tail ecx, edx ;clobber eax list_add_tail ecx, edx ;clobber eax
stdcall enable_irq, ebx stdcall enable_irq, ebx
.fail: .fail:
popfd spin_unlock_irqrestore IrqsList
.err: .err:
pop ebx pop ebx
mov eax, [.irqh] mov eax, [.irqh]
@ -144,7 +144,7 @@ purge irq_serv_h
align 16 align 16
.main: .main:
save_ring3_context save_ring3_context
mov ebp, [esp + 32] mov ebp, [esp + 32]
mov bx, app_data;os_data mov bx, app_data;os_data
@ -188,7 +188,7 @@ align 16
push [ebx+IRQH.data] push [ebx+IRQH.data]
call [ebx+IRQH.handler] call [ebx+IRQH.handler]
add esp, 4 pop ecx
pop esi pop esi
pop edi pop edi
@ -197,6 +197,7 @@ align 16
test eax, eax test eax, eax
jz .next jz .next
inc [ebx+IRQH.num_ints]
btr [irq_active_set], ebp btr [irq_active_set], ebp
jmp .next jmp .next
@ -204,6 +205,42 @@ align 16
btr [irq_active_set], ebp btr [irq_active_set], ebp
jnc .exit jnc .exit
; There is at least one configuration with one device which generates IRQ
; that is not the same as it should be according to PCI config space.
; For that device, the handler is registered at wrong IRQ.
; As a workaround, when nobody acknowledges the generated IRQ,
; try to ask all other registered handlers; if some handler acknowledges
; the IRQ this time, relink it to the current IRQ list.
; To make this more reliable, for every handler keep number of times
; that it has acknowledged an IRQ, and assume that handlers with at least one
; acknowledged IRQ are registered properly.
; Note: this still isn't 100% correct, because two IRQs can fire simultaneously,
; the better way would be to find the correct IRQ, but I don't know how to do
; this in that case.
push ebp
xor ebp, ebp
.try_other_irqs:
cmp ebp, [esp]
jz .try_next_irq
lea esi, [irqh_tab+ebp*8]
mov ebx, esi
.try_next_handler:
mov ebx, [ebx+IRQH.list.next]
cmp ebx, esi
je .try_next_irq
cmp [ebx+IRQH.num_ints], 0
jne .try_next_irq
push [ebx+IRQH.data]
call [ebx+IRQH.handler]
pop ecx
test eax, eax
jnz .found_in_wrong_list
.try_next_irq:
inc ebp
cmp ebp, 16
jb .try_other_irqs
pop ebp
inc [irq_failed+ebp*4] inc [irq_failed+ebp*4]
.exit: .exit:
mov [check_idle_semaphore], 5 mov [check_idle_semaphore], 5
@ -211,10 +248,21 @@ align 16
mov ecx, ebp mov ecx, ebp
call irq_eoi call irq_eoi
restore_ring3_context restore_ring3_context
add esp, 4 add esp, 4
iret iret
.found_in_wrong_list:
DEBUGF 1,'K : warning: relinking handler from IRQ%d to IRQ%d\n',\
ebp, [esp]
spin_lock_irqsave IrqsList
list_del ebx
pop ebp
lea edx, [irqh_tab+ebp*8]
list_add_tail ebx, edx
spin_unlock_irqrestore IrqsList
jmp .exit
align 4 align 4
irqD: irqD:
push eax push eax