diff --git a/kernel/trunk/core/irq.inc b/kernel/trunk/core/irq.inc new file mode 100644 index 0000000000..89ad1d9005 --- /dev/null +++ b/kernel/trunk/core/irq.inc @@ -0,0 +1,260 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; ;; +;; Copyright (C) KolibriOS team 2004-2011. All rights reserved. ;; +;; Distributed under terms of the GNU General Public License ;; +;; ;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +IRQ_RESERVED equ 16 + +IRQ_POOL_SIZE equ 48 + + +macro __list_add new, prev, next +{ + mov [next+LHEAD.prev], new + mov [new+LHEAD.next], next + mov [new+LHEAD.prev], prev + mov [prev+LHEAD.next], new +} + +macro list_add new, head +{ + mov eax, [head+LHEAD.next] + __list_add new, head, eax +} + +macro list_add_tail new, head +{ + mov eax, [head+LHEAD.prev] + __list_add new, eax, head +} + +uglobal + +align 16 +irqh_tab rd LHEAD.sizeof * IRQ_RESERVED / 4 + +irqh_pool rd IRQH.sizeof * IRQ_POOL_SIZE /4 +next_irqh rd 1 + +irq_active_set rd 1 +irq_failed rd IRQ_RESERVED + +endg + +align 4 +init_irqs: + + mov ecx, IRQ_RESERVED + mov edi, irqh_tab +@@: + mov eax, edi + stosd + stosd + loop @B + + mov ecx, IRQ_POOL_SIZE-1 + mov eax, irqh_pool+IRQH.sizeof + mov [next_irqh], irqh_pool +@@: + mov [eax-IRQH.sizeof], eax + add eax, IRQH.sizeof + loop @B + + mov [eax-IRQH.sizeof], dword 0 + ret + + +align 4 +proc attach_int_handler stdcall, irq:dword, handler:dword, user_data:dword + locals + .irqh dd ? + endl + + xchg bx, bx + + and [.irqh], 0 + + push ebx + + mov ebx, [irq] ;irq num + test ebx, ebx + jz .err + + cmp ebx, IRQ_RESERVED + jae .err + + mov edx, [handler] + test edx, edx + jz .err + + pushfd + cli + +;allocate handler + + mov ecx, [next_irqh] + test ecx, ecx + jz .fail + + mov eax, [ecx] + mov [next_irqh], eax + + mov [.irqh], ecx + + mov eax, [user_data] + mov [ecx+IRQH.handler], edx + mov [ecx+IRQH.data], eax + + lea edx, [irqh_tab+ebx*8] + list_add_tail ecx, edx ;clobber eax + + stdcall enable_irq, [irq] + +.fail: + popfd +.err: + pop ebx + mov eax, [.irqh] + ret + +endp + +if 0 +align 4 +proc get_int_handler stdcall, irq:dword + + mov eax, [irq] + cmp eax, 15 + ja .fail + mov eax, [irq_tab + 4 * eax] + ret +.fail: + xor eax, eax + ret +endp +end if + + +align 4 +proc detach_int_handler + + ret +endp + +align 4 +proc enable_irq stdcall, irq_line:dword + mov ebx, [irq_line] + mov edx, 0x21 + cmp ebx, 8 + jb @F + mov edx, 0xA1 + sub ebx,8 +@@: + in al,dx + btr eax, ebx + out dx, al + ret +endp + + +macro irq_serv_h [num] { + forward +align 4 + .irq_#num : + push num + jmp .main +} + +align 16 +irq_serv: + +; .irq_1: +; push 1 +; jmp .main +; etc... + +irq_serv_h 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15 +irq_serv_h 16, 17, 18, 19, 20, 21, 22, 23 + +purge irq_serv_h + +align 16 +.main: + save_ring3_context + + mov ebp, [esp + 32] + mov bx, app_data ;os_data + mov ds, bx + mov es, bx + + cmp [v86_irqhooks+ebp*8], 0 + jnz v86_irq + + cmp bp, 6 + jnz @f + push ebp + call [fdc_irq_func] + pop ebp +@@: + + cmp bp, 14 + jnz @f + push ebp + call [irq14_func] + pop ebp +@@: + cmp bp, 15 + jnz @f + push ebp + call [irq15_func] + pop ebp +@@: + bts [irq_active_set], ebp + + lea esi, [irqh_tab+ebp*8] ; esi= list head + mov ebx, esi +.next: + mov ebx, [ebx+IRQH.list.next] ; ebx= irqh pointer + cmp ebx, esi + je .done + + push ebx ; FIX THIS + push edi + push esi + + push [ebx+IRQH.data] + call [ebx+IRQH.handler] + add esp, 4 + + pop esi + pop edi + pop ebx + + test eax, eax + jz .next + + btr [irq_active_set], ebp + jmp .next + +.done: + btr [irq_active_set], ebp + jnc .exit + + inc [irq_failed+ebp*4] +.exit: + mov [check_idle_semaphore],5 + + cmp bp, 8 + mov al, 0x20 + jb @f + out 0xa0, al +@@: + out 0x20, al + + restore_ring3_context + add esp, 4 + iret + +