Subversion Repositories Kolibri OS

Rev

Rev 7136 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

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