Subversion Repositories Kolibri OS

Rev

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

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