Subversion Repositories Kolibri OS

Rev

Rev 3771 | Rev 3786 | 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.         DEBUGF  1, "K : Attach Interrupt %d Handler %x\n", [irq], [handler]
  55.  
  56.         and     [.irqh], 0
  57.  
  58.         push    ebx
  59.  
  60.         mov     ebx, [irq]          ;irq num
  61.         test    ebx, ebx
  62.         jz      .err
  63.  
  64.         cmp     ebx, IRQ_RESERVED
  65.         jae     .err
  66.  
  67.         mov     edx, [handler]
  68.         test    edx, edx
  69.         jz      .err
  70.  
  71.         spin_lock_irqsave IrqsList
  72.  
  73. ;allocate handler
  74.  
  75.         mov     ecx, [next_irqh]
  76.         test    ecx, ecx
  77.         jz      .fail
  78.  
  79.         mov     eax, [ecx]
  80.         mov     [next_irqh], eax
  81.         mov     [.irqh], ecx
  82.  
  83.         mov     [irq_failed+ebx*4], 0;clear counter
  84.  
  85.         mov     eax, [user_data]
  86.         mov     [ecx+IRQH.handler], edx
  87.         mov     [ecx+IRQH.data], eax
  88.         and     [ecx+IRQH.num_ints], 0
  89.  
  90.         lea     edx, [irqh_tab+ebx*8]
  91.         list_add_tail ecx, edx     ;clobber eax
  92.         stdcall enable_irq, ebx
  93.  
  94. .fail:
  95.         spin_unlock_irqrestore IrqsList
  96. .err:
  97.         pop     ebx
  98.         mov     eax, [.irqh]
  99.         ret
  100.  
  101. endp
  102.  
  103. if 0
  104. align 4
  105. proc get_int_handler stdcall, irq:dword
  106.  
  107.         mov     eax, [irq]
  108.         cmp     eax, 15
  109.         ja      .fail
  110.         mov     eax, [irq_tab + 4 * eax]
  111.         ret
  112. .fail:
  113.         xor     eax, eax
  114.         ret
  115. endp
  116. end if
  117.  
  118.  
  119. align 4
  120. proc  detach_int_handler
  121.  
  122.         ret
  123. endp
  124.  
  125.  
  126. macro irq_serv_h [num] {
  127.     forward
  128. align 4
  129.   .irq_#num :
  130.         push    num
  131.         jmp     .main
  132. }
  133.  
  134. align 16
  135. irq_serv:
  136.  
  137. ; .irq_1:
  138. ;      push 1
  139. ;      jmp .main
  140. ; etc...
  141.  
  142. irq_serv_h 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15
  143. irq_serv_h 16, 17, 18, 19, 20, 21, 22, 23
  144.  
  145. purge irq_serv_h
  146.  
  147. align 16
  148. .main:
  149.         save_ring3_context
  150.  
  151.         mov     ebp, [esp + 32]
  152.         mov     bx, app_data;os_data
  153.         mov     ds, bx
  154.         mov     es, bx
  155.  
  156.         cmp     [v86_irqhooks+ebp*8], 0
  157.         jnz     v86_irq
  158.  
  159.         bts     [irq_active_set], ebp
  160.  
  161.         lea     esi, [irqh_tab+ebp*8]   ; esi= list head
  162.         mov     ebx, esi
  163. .next:
  164.         mov     ebx, [ebx+IRQH.list.next]; ebx= irqh pointer
  165.         cmp     ebx, esi
  166.         je      .done
  167.  
  168.         push    ebx                     ; FIX THIS
  169.         push    edi
  170.         push    esi
  171.  
  172.         push    [ebx+IRQH.data]
  173.         call    [ebx+IRQH.handler]
  174.         pop     ecx
  175.  
  176.         pop     esi
  177.         pop     edi
  178.         pop     ebx
  179.  
  180.         test    eax, eax
  181.         jz      .next
  182.  
  183.         inc     [ebx+IRQH.num_ints]
  184.         btr     [irq_active_set], ebp
  185.         jmp     .next
  186.  
  187. .done:
  188.         btr     [irq_active_set], ebp
  189.         jnc     .exit
  190.  
  191. ; There is at least one configuration with one device which generates IRQ
  192. ; that is not the same as it should be according to PCI config space.
  193. ; For that device, the handler is registered at wrong IRQ.
  194. ; As a workaround, when nobody acknowledges the generated IRQ,
  195. ; try to ask all other registered handlers; if some handler acknowledges
  196. ; the IRQ this time, relink it to the current IRQ list.
  197. ; To make this more reliable, for every handler keep number of times
  198. ; that it has acknowledged an IRQ, and assume that handlers with at least one
  199. ; acknowledged IRQ are registered properly.
  200. ; Note: this still isn't 100% correct, because two IRQs can fire simultaneously,
  201. ; the better way would be to find the correct IRQ, but I don't know how to do
  202. ; this in that case.
  203.         push    ebp
  204.         xor     ebp, ebp
  205. .try_other_irqs:
  206.         cmp     ebp, [esp]
  207.         jz      .try_next_irq
  208.         cmp     ebp, 1
  209.         jz      .try_next_irq
  210.         cmp     ebp, 6
  211.         jz      .try_next_irq
  212.         cmp     ebp, 12
  213.         jz      .try_next_irq
  214.         cmp     ebp, 14
  215.         jz      .try_next_irq
  216.         cmp     ebp, 15
  217.         jz      .try_next_irq
  218.         lea     esi, [irqh_tab+ebp*8]
  219.         mov     ebx, esi
  220. .try_next_handler:
  221.         mov     ebx, [ebx+IRQH.list.next]
  222.         cmp     ebx, esi
  223.         je      .try_next_irq
  224.         cmp     [ebx+IRQH.num_ints], 0
  225.         jne     .try_next_handler
  226. ; keyboard handler acknowledges everything
  227.         push    [ebx+IRQH.data]
  228.         call    [ebx+IRQH.handler]
  229.         pop     ecx
  230.         test    eax, eax
  231.         jz      .try_next_handler
  232.  
  233. .found_in_wrong_list:
  234.         DEBUGF 1,'K : warning: relinking handler from IRQ%d to IRQ%d\n',\
  235.                 ebp, [esp]
  236.         pop     ebp
  237.         spin_lock_irqsave IrqsList
  238.         list_del ebx
  239.         lea     edx, [irqh_tab+ebp*8]
  240.         list_add_tail ebx, edx
  241.         spin_unlock_irqrestore IrqsList
  242.         jmp     .exit
  243.  
  244. .try_next_irq:
  245.         inc     ebp
  246.         cmp     ebp, 16
  247.         jb      .try_other_irqs
  248.         pop     ebp
  249.  
  250. .fail:
  251.         inc     [irq_failed+ebp*4]
  252. .exit:
  253.  
  254.         mov     ecx, ebp
  255.         call    irq_eoi
  256.  
  257. ; IRQ handler could make some kernel thread ready; reschedule
  258.         mov     bl, SCHEDULE_HIGHER_PRIORITY
  259.         call    find_next_task
  260.         jz      .return  ; if there is only one running process
  261.         call    do_change_task
  262.   .return:
  263.         restore_ring3_context
  264.         add     esp, 4
  265.         iret
  266.  
  267. align 4
  268. irqD:
  269.         push    eax
  270.         push    ecx
  271.         xor     eax, eax
  272.         out     0xf0, al
  273.         mov     cl, 13
  274.         call    irq_eoi
  275.         pop     ecx
  276.         pop     eax
  277.         iret
  278.  
  279.