Subversion Repositories Kolibri OS

Rev

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

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