Subversion Repositories Kolibri OS

Rev

Rev 3555 | Rev 3908 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  2. ;;                                                              ;;
  3. ;; Copyright (C) KolibriOS team 2004-2012. All rights reserved. ;;
  4. ;; Distributed under terms of the GNU General Public License    ;;
  5. ;;                                                              ;;
  6. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  7.  
  8. IRQ_RESERVED   equ 24
  9.  
  10. IRQ_POOL_SIZE  equ 48
  11.  
  12. uglobal
  13.  
  14. align 16
  15. irqh_tab            rd sizeof.LHEAD * IRQ_RESERVED / 4
  16.  
  17. irqh_pool           rd sizeof.IRQH * IRQ_POOL_SIZE /4
  18. next_irqh           rd 1
  19.  
  20. irq_active_set      rd 1
  21. irq_failed          rd IRQ_RESERVED
  22.  
  23. endg
  24.  
  25. align 4
  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
  37.         mov     eax, irqh_pool+sizeof.IRQH
  38.     mov [next_irqh], irqh_pool
  39. @@:
  40.         mov     [eax-sizeof.IRQH], eax
  41.         add     eax, sizeof.IRQH
  42.     loop @B
  43.  
  44.         mov     [eax-sizeof.IRQH], dword 0
  45.     ret
  46.  
  47.  
  48. align 4
  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.  
  62.          cmp  ebx, IRQ_RESERVED
  63.          jae  .err
  64.  
  65.          mov  edx, [handler]
  66.          test edx, edx
  67.          jz   .err
  68.  
  69.         spin_lock_irqsave IrqsList
  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.  
  81.         mov     [irq_failed+ebx*4], 0;clear counter
  82.  
  83.          mov eax, [user_data]
  84.          mov [ecx+IRQH.handler], edx
  85.          mov [ecx+IRQH.data],    eax
  86.         and     [ecx+IRQH.num_ints], 0
  87.  
  88.          lea edx, [irqh_tab+ebx*8]
  89.          list_add_tail ecx, edx     ;clobber eax
  90.          stdcall enable_irq, ebx
  91.  
  92. .fail:
  93.         spin_unlock_irqrestore IrqsList
  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]
  150.         mov     bx, app_data;os_data
  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:
  181.         mov     ebx, [ebx+IRQH.list.next]; ebx= irqh pointer
  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]
  191.         pop     ecx
  192.  
  193.        pop esi
  194.        pop edi
  195.        pop ebx
  196.  
  197.        test eax, eax
  198.        jz .next
  199.  
  200.         inc     [ebx+IRQH.num_ints]
  201.        btr [irq_active_set], ebp
  202.        jmp .next
  203.  
  204. .done:
  205.        btr [irq_active_set], ebp
  206.        jnc .exit
  207.  
  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:
  270.        inc [irq_failed+ebp*4]
  271. .exit:
  272.  
  273.        mov ecx, ebp
  274.        call irq_eoi
  275.  
  276. ; IRQ handler could make some kernel thread ready; reschedule
  277.         mov     bl, SCHEDULE_HIGHER_PRIORITY
  278.         call    find_next_task
  279.         jz      .return  ; if there is only one running process
  280.         call    do_change_task
  281.   .return:
  282.        restore_ring3_context
  283.        add   esp, 4
  284.        iret
  285.  
  286. align 4
  287. irqD:
  288.         push  eax
  289.         push  ecx
  290.         xor     eax, eax
  291.         out     0xf0, al
  292.         mov   cl, 13
  293.         call  irq_eoi
  294.         pop   ecx
  295.         pop   eax
  296.         iret
  297.  
  298.