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
jz .err
pushfd
cli
spin_lock_irqsave IrqsList
;allocate handler
@ -84,13 +83,14 @@ proc attach_int_handler stdcall, irq:dword, handler:dword, user_data:dword
mov eax, [user_data]
mov [ecx+IRQH.handler], edx
mov [ecx+IRQH.data], eax
and [ecx+IRQH.num_ints], 0
lea edx, [irqh_tab+ebx*8]
list_add_tail ecx, edx ;clobber eax
stdcall enable_irq, ebx
.fail:
popfd
spin_unlock_irqrestore IrqsList
.err:
pop ebx
mov eax, [.irqh]
@ -188,7 +188,7 @@ align 16
push [ebx+IRQH.data]
call [ebx+IRQH.handler]
add esp, 4
pop ecx
pop esi
pop edi
@ -197,6 +197,7 @@ align 16
test eax, eax
jz .next
inc [ebx+IRQH.num_ints]
btr [irq_active_set], ebp
jmp .next
@ -204,6 +205,42 @@ align 16
btr [irq_active_set], ebp
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]
.exit:
mov [check_idle_semaphore], 5
@ -215,6 +252,17 @@ align 16
add esp, 4
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
irqD:
push eax