Subversion Repositories Kolibri OS

Rev

Rev 8111 | Rev 8120 | Go to most recent revision | 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: 8117 $
  9.  
  10. MAX_IOAPICS = 2
  11.  
  12. uglobal
  13. IRQ_COUNT    rd  MAX_IOAPICS
  14. irq_mode     rd  1              ; PIC/(IO)APIC
  15. IOAPIC_base  rd  MAX_IOAPICS
  16. ioapic_gsi_base rd MAX_IOAPICS  ; zero-based, i.e. not vector
  17. ioapic_cnt   dd  ?              ; from MADT aka APIC table
  18. ioapic_cur   dd  ?
  19. LAPIC_BASE   rd  1
  20. endg
  21.  
  22. APIC_ID         = 0x20
  23. APIC_TPR        = 0x80
  24. APIC_EOI        = 0xb0
  25. APIC_LDR        = 0xd0
  26. APIC_DFR        = 0xe0
  27. APIC_SVR        = 0xf0
  28. APIC_ISR        = 0x100
  29. APIC_ESR        = 0x280
  30. APIC_ICRL       = 0x300
  31. APIC_ICRH       = 0x310
  32. APIC_LVT_LINT0  = 0x350
  33. APIC_LVT_LINT1  = 0x360
  34. APIC_LVT_err    = 0x370
  35.  
  36. ; APIC timer
  37. APIC_LVT_timer  = 0x320
  38. APIC_timer_div  = 0x3e0
  39. APIC_timer_init = 0x380
  40. APIC_timer_cur  = 0x390
  41. ; IOAPIC
  42. IOAPIC_ID       = 0x0
  43. IOAPIC_VER      = 0x1
  44. IOAPIC_ARB      = 0x2
  45. IOAPIC_REDTBL   = 0x10
  46.  
  47. align 4
  48. APIC_init:
  49.         push    ebx
  50.         mov     [irq_mode], IRQ_PIC
  51.  
  52.         cmp     [acpi_ioapic_base], 0
  53.         jz      .no_apic
  54.  
  55.         cmp     [acpi_lapic_base], 0
  56.         jz      .no_apic
  57.  
  58. ; non-UEFI loaders don't load DEVICES.DAT and don't initialize [acpi_dev_size]
  59. if defined UEFI
  60.         cmp     [acpi_dev_size], 0
  61.         jz      @f
  62.         stdcall map_io_mem, [acpi_dev_data], [acpi_dev_size], PG_SWR
  63.         mov     [acpi_dev_data], eax
  64.         jmp     .loaded
  65. @@:
  66. end if
  67.  
  68.         stdcall load_file, dev_data_path
  69.         test    eax, eax
  70.         jz      .no_apic
  71.  
  72.         mov     [acpi_dev_data], eax
  73.         mov     [acpi_dev_size], ebx
  74. .loaded:
  75.  
  76. ; IOAPIC init
  77.         xor     ebx, ebx
  78. @@:
  79.         stdcall map_io_mem, [acpi_ioapic_base+ebx*4], 0x20, PG_GLOBAL+PG_NOCACHE+PG_SWR
  80.         mov     [IOAPIC_base+ebx*4], eax
  81.         inc     ebx
  82.         cmp     ebx, [ioapic_cnt]
  83.         jnz     @b
  84.  
  85.         call    IRQ_mask_all
  86.         mov     [ioapic_cur], 0
  87. .next_ioapic:
  88.         mov     edx, [ioapic_cur]
  89.         mov     eax, IOAPIC_VER
  90.         call    IOAPIC_read
  91.         shr     eax, 16
  92.         inc     al
  93.         movzx   eax, al
  94.         mov     ecx, [ioapic_gsi_base+edx*4]
  95.         cmp     ecx, IRQ_RESERVED
  96.         jae     .lapic_init
  97.         add     ecx, eax
  98.         sub     ecx, IRQ_RESERVED
  99.         jbe     @f
  100.         sub     eax, ecx
  101. @@:
  102.         mov     [IRQ_COUNT+edx*4], eax
  103.  
  104.         ; Reroute IOAPIC & mask all interrupts
  105.         xor     ecx, ecx
  106.         mov     eax, IOAPIC_REDTBL
  107. .next_irq:
  108.         mov     ebx, eax
  109.         call    IOAPIC_read
  110.         mov     ah, 0x08; Delivery Mode: Fixed, Destination Mode: Logical
  111.         mov     al, cl
  112.         add     al, 0x20; vector
  113.         add     eax, [ioapic_gsi_base+edx*4]
  114.         or      eax, 0x1a000; Mask Interrupt, level-triggered active-low
  115.         cmp     [ioapic_cur], 0
  116.         jnz     @f
  117.         cmp     ecx, 16
  118.         jae     @f
  119.         and     eax, NOT 0xa000 ; edge-triggered active-high for IRQ0-15
  120. @@:
  121.         xchg    eax, ebx
  122.         call    IOAPIC_write
  123.         inc     eax
  124.         mov     ebx, eax
  125.         call    IOAPIC_read
  126.         or      eax, 0xff000000; Destination Field
  127.         xchg    eax, ebx
  128.         call    IOAPIC_write
  129.         inc     eax
  130.         inc     ecx
  131.         cmp     ecx, [IRQ_COUNT+edx*4]
  132.         jb      .next_irq
  133.  
  134.         inc     [ioapic_cur]
  135.         inc     edx
  136.         cmp     edx, [ioapic_cnt]
  137.         jnz     .next_ioapic
  138.  
  139. .lapic_init:
  140.         call    LAPIC_init
  141.  
  142.         mov     [irq_mode], IRQ_APIC
  143.  
  144.         mov     al, 0x70
  145.         out     0x22, al
  146.         mov     al, 1
  147.         out     0x23, al
  148.  
  149.         call    pci_irq_fixup
  150. .no_apic:
  151.         pop     ebx
  152.         ret
  153.  
  154. ;===========================================================
  155. align 4
  156. LAPIC_init:
  157.  
  158.         cmp     [LAPIC_BASE], 0
  159.         jne     .done
  160.  
  161.         stdcall map_io_mem, [acpi_lapic_base], 0x1000, PG_GLOBAL+PG_NOCACHE+PG_SWR
  162.         mov     [LAPIC_BASE], eax
  163.         mov     esi, eax
  164.  
  165.         ; Program Destination Format Register for Flat mode.
  166.         mov     eax, [esi + APIC_DFR]
  167.         or      eax, 0xf0000000
  168.         mov     [esi + APIC_DFR], eax
  169.  
  170.         ; Program Logical Destination Register.
  171.         mov     eax, [esi + APIC_LDR]
  172.         ;and  eax, 0xff000000
  173.         and     eax, 0x00ffffff
  174.         or      eax, 0x01000000;!!!!!!!!!!!!
  175.         mov     [esi + APIC_LDR], eax
  176.  
  177.         ; Task Priority Register initialization.
  178.         mov     eax, [esi + APIC_TPR]
  179.         and     eax, 0xffffff00
  180.         mov     [esi + APIC_TPR], eax
  181.  
  182.         ; Flush the queue
  183.         mov     edx, 0
  184. .nxt2:
  185.         mov     ecx, 32
  186.         mov     eax, [esi + APIC_ISR + edx]
  187. .nxt:
  188.         shr     eax, 1
  189.         jnc     @f
  190.         mov     dword [esi + APIC_EOI], 0; EOI
  191. @@:
  192.         loop    .nxt
  193.  
  194.         add     edx, 0x10
  195.         cmp     edx, 0x170
  196.         jbe     .nxt2
  197.  
  198.         ; Spurious-Interrupt Vector Register initialization.
  199.         mov     eax, [esi + APIC_SVR]
  200.         or      eax, 0x1ff
  201.         and     eax, 0xfffffdff
  202.         mov     [esi + APIC_SVR], eax
  203.  
  204.         ; Initialize LVT LINT0 register. (INTR)
  205.         mov     eax, 0x00700
  206.         ; mov eax, 0x10700
  207.         mov     [esi + APIC_LVT_LINT0], eax
  208.  
  209.         ; Initialize LVT LINT1 register. (NMI)
  210.         mov     eax, 0x00400
  211.         mov     [esi + APIC_LVT_LINT1], eax
  212.  
  213.         ; Initialize LVT Error register.
  214.         mov     eax, [esi + APIC_LVT_err]
  215.         or      eax, 0x10000; bit 16
  216.         mov     [esi + APIC_LVT_err], eax
  217.  
  218.         ; LAPIC timer
  219.         ; pre init
  220.         mov     dword[esi + APIC_timer_div], 1011b; 1
  221.         mov     dword[esi + APIC_timer_init], 0xffffffff; max val
  222.         push    esi
  223.         mov     esi, 640    ; wait 0.64 sec
  224.         call    delay_ms
  225.         pop     esi
  226.         mov     eax, [esi + APIC_timer_cur]; read current tick couner
  227.         xor     eax, 0xffffffff   ; eax = 0xffffffff - eax
  228.         shr     eax, 6      ; eax /= 64; APIC ticks per 0.01 sec
  229.  
  230.         ; Start (every 0.01 sec)
  231.         mov     dword[esi + APIC_LVT_timer], 0x30020; periodic int 0x20
  232.         mov     dword[esi + APIC_timer_init], eax
  233.  
  234. .done:
  235.         ret
  236.  
  237. ;===========================================================
  238. ; IOAPIC implementation
  239. align 4
  240. IOAPIC_read:
  241. ; in : EAX - IOAPIC register
  242. ; out: EAX - readed value
  243.         push    esi
  244.         mov     esi, [ioapic_cur]
  245.         mov     esi, [IOAPIC_base+esi*4]
  246.         mov     [esi], eax
  247.         mov     eax, [esi + 0x10]
  248.         pop     esi
  249.         ret
  250.  
  251. align 4
  252. IOAPIC_write:
  253. ; in :  EAX - IOAPIC register
  254. ;       EBX - value
  255. ; out:  none
  256.         push    esi
  257.         mov     esi, [ioapic_cur]
  258.         mov     esi, [IOAPIC_base+esi*4]
  259.         mov     [esi], eax
  260.         mov     [esi + 0x10], ebx
  261.         pop     esi
  262.         ret
  263. ;===========================================================
  264. ; Remap all IRQ to 0x20+ Vectors
  265. ; IRQ0 to vector 0x20, IRQ1 to vector 0x21....
  266. align 4
  267. PIC_init:
  268.         mov     [IRQ_COUNT], 16
  269.         cli
  270.         mov     al, 0x11        ;  icw4, edge triggered
  271.         out     0x20, al
  272.         out     0xA0, al
  273.  
  274.         mov     al, 0x20        ;  generate 0x20 +
  275.         out     0x21, al
  276.         mov     al, 0x28        ;  generate 0x28 +
  277.         out     0xA1, al
  278.  
  279.         mov     al, 0x04        ;  slave at irq2
  280.         out     0x21, al
  281.         mov     al, 0x02        ;  at irq9
  282.         out     0xA1, al
  283.  
  284.         mov     al, 0x01        ;  8086 mode
  285.         out     0x21, al
  286.         out     0xA1, al
  287.  
  288.         call    IRQ_mask_all
  289.         ret
  290.  
  291. ; -----------------------------------------
  292. ; TIMER SET TO 1/100 S
  293. align 4
  294. PIT_init:
  295.         mov     al, 0x34   ; set to 100Hz
  296.         out     0x43, al
  297.         mov     al, 0x9b   ; lsb    1193180 / 1193
  298.         out     0x40, al
  299.         mov     al, 0x2e   ; msb
  300.         out     0x40, al
  301.         ret
  302.  
  303. ; -----------------------------------------
  304. align 4
  305. unmask_timer:
  306.         cmp     [irq_mode], IRQ_APIC
  307.         je      @f
  308.  
  309.         stdcall enable_irq, 0
  310.         ret
  311. @@:
  312.         ; use PIT
  313.         ; in some systems PIT no connected to IOAPIC
  314.         ; mov   eax, 0x14
  315.         ; call  IOAPIC_read
  316.         ; mov   ah, 0x09                ; Delivery Mode: Lowest Priority, Destination Mode: Logical
  317.         ; mov   al, 0x20
  318.         ; or    eax, 0x10000            ; Mask Interrupt
  319.         ; mov   ebx, eax
  320.         ; mov   eax, 0x14
  321.         ; call  IOAPIC_write
  322.         ; stdcall enable_irq, 2
  323.         ; ret
  324.  
  325.         ; use LAPIC timer
  326.         mov     esi, [LAPIC_BASE]
  327.         mov     eax, [esi + APIC_LVT_timer]
  328.         and     eax, 0xfffeffff
  329.         mov     [esi + APIC_LVT_timer], eax
  330.         ret
  331.  
  332. ; -----------------------------------------
  333. ; Disable all IRQ
  334. align 4
  335. IRQ_mask_all:
  336.         cmp     [irq_mode], IRQ_APIC
  337.         je      .APIC
  338.  
  339.         mov     al, 0xFF
  340.         out     0x21, al
  341.         out     0xA1, al
  342.         mov     ecx, 0x1000
  343.         ret
  344. .APIC:
  345.         cmp     [IOAPIC_base], 0
  346.         jz      .done
  347.         mov     [ioapic_cur], 0
  348. .next_ioapic:
  349.         mov     edx, [ioapic_cur]
  350.         mov     ecx, [IRQ_COUNT+edx*4]
  351.         mov     eax, 0x10
  352. @@:
  353.         mov     ebx, eax
  354.         call    IOAPIC_read
  355.         or      eax, 0x10000; bit 16
  356.         xchg    eax, ebx
  357.         call    IOAPIC_write
  358.         inc     eax
  359.         inc     eax
  360.         loop    @b
  361.  
  362.         inc     [ioapic_cur]
  363.         inc     edx
  364.         cmp     edx, [ioapic_cnt]
  365.         jnz     .next_ioapic
  366. .done:
  367.         ret
  368.  
  369. ; -----------------------------------------
  370. ; End Of Interrupt
  371. ; cl - IRQ number
  372. align 4
  373. irq_eoi:         ; __fastcall
  374.         cmp     [irq_mode], IRQ_APIC
  375.         je      .APIC
  376.  
  377.         cmp     cl, 8
  378.         mov     al, 0x20
  379.         jb      @f
  380.         out     0xa0, al
  381. @@:
  382.         out     0x20, al
  383.         ret
  384.  
  385. .APIC:
  386.         mov     eax, [LAPIC_BASE]
  387.         mov     dword [eax + APIC_EOI], 0; EOI
  388.         ret
  389.  
  390. ; -----------------------------------------
  391. ; from dll.inc
  392. align 4
  393. proc enable_irq stdcall, irq_line:dword
  394.         mov     ebx, [irq_line]
  395.         cmp     [irq_mode], IRQ_APIC
  396.         je      .APIC
  397.  
  398.         mov     edx, 0x21
  399.         cmp     ebx, 8
  400.         jb      @F
  401.  
  402.         mov     edx, 0xA1
  403.         sub     ebx, 8
  404. @@:
  405.         in      al, dx
  406.         btr     eax, ebx
  407.         out     dx, al
  408.         ret
  409. .APIC:
  410.         push    [ioapic_cur]
  411.         xor     eax, eax
  412. .next_ioapic:
  413.         mov     ecx, [ioapic_gsi_base+eax*4]
  414.         add     ecx, [IRQ_COUNT+eax*4]
  415.         cmp     ebx, ecx
  416.         jb      .found
  417.         inc     eax
  418.         cmp     eax, [ioapic_cnt]
  419.         jnz     .next_ioapic
  420.         jmp     .done
  421. .found:
  422.         mov     [ioapic_cur], eax
  423.         sub     ebx, [ioapic_gsi_base+eax*4]
  424.         shl     ebx, 1
  425.         add     ebx, 0x10
  426.         mov     eax, ebx
  427.         call    IOAPIC_read
  428.         and     eax, 0xfffeffff; bit 16
  429.         xchg    eax, ebx
  430.         call    IOAPIC_write
  431. .done:
  432.         pop     [ioapic_cur]
  433.         ret
  434. endp
  435.  
  436. proc disable_irq stdcall, irq_line:dword
  437.         mov     ebx, [irq_line]
  438.         cmp     [irq_mode], IRQ_APIC
  439.         je      .APIC
  440.  
  441.         mov     edx, 0x21
  442.         cmp     ebx, 8
  443.         jb      @F
  444.  
  445.         mov     edx, 0xA1
  446.         sub     ebx, 8
  447. @@:
  448.         in      al, dx
  449.         bts     eax, ebx
  450.         out     dx, al
  451.         ret
  452. .APIC:
  453.         push    [ioapic_cur]
  454.         xor     eax, eax
  455. .next_ioapic:
  456.         mov     ecx, [ioapic_gsi_base+eax*4]
  457.         add     ecx, [IRQ_COUNT+eax*4]
  458.         cmp     ebx, ecx
  459.         jae     .found
  460.         inc     eax
  461.         cmp     eax, [ioapic_cnt]
  462.         jnz     .next_ioapic
  463.         jmp     .done
  464. .found:
  465.         mov     [ioapic_cur], eax
  466.         sub     ebx, [ioapic_gsi_base+eax*4]
  467.         shl     ebx, 1
  468.         add     ebx, 0x10
  469.         mov     eax, ebx
  470.         call    IOAPIC_read
  471.         or      eax, 0x10000; bit 16
  472.         xchg    eax, ebx
  473.         call    IOAPIC_write
  474. .done:
  475.         pop     [ioapic_cur]
  476.         ret
  477. endp
  478.  
  479. align 4
  480. pci_irq_fixup:
  481.  
  482.         push    ebp
  483.  
  484.         mov     esi, [acpi_dev_data]
  485.         mov     ebx, [acpi_dev_size]
  486.  
  487.         lea     edi, [esi+ebx]
  488.  
  489. .iterate:
  490.  
  491.         cmp     esi, edi
  492.         jae     .done
  493.  
  494.         mov     eax, [esi]
  495.  
  496.         cmp     eax, -1
  497.         je      .done
  498.  
  499.         movzx   ebx, al
  500.         movzx   ebp, ah
  501.  
  502.         stdcall pci_read32, ebp, ebx, 0
  503.  
  504.         cmp     eax, [esi+4]
  505.         jne     .skip
  506.  
  507.         mov     eax, [esi+8]
  508.         stdcall pci_write8, ebp, ebx, 0x3C, eax
  509. .skip:
  510.         add     esi, 16
  511.         jmp     .iterate
  512.  
  513. .done:
  514. .fail:
  515.         pop     ebp
  516.         ret
  517.  
  518. align 4
  519. get_clock_ns:
  520.  
  521.         mov     eax, [hpet_base]
  522.         test    eax, eax
  523.         jz      .old_tics
  524.  
  525.         push    ebx
  526.         push    esi
  527.         pushfd
  528.         cli
  529.  
  530.         mov     ebx, eax
  531. @@:
  532.         mov     edx, [ebx+0xF4]
  533.         mov     eax, [ebx+0xF0]
  534.         mov     ecx, [ebx+0xF4]
  535.         cmp     ecx, edx
  536.         jne     @B
  537.         popfd
  538.  
  539. ;96-bit arithmetic
  540. ;ebx - low dword
  541. ;esi - medium dword
  542. ;edx - high dword
  543.  
  544.         mul     [hpet_period]
  545.         mov     ebx, eax
  546.         mov     esi, edx
  547.  
  548.         mov     eax, ecx
  549.         mul     [hpet_period]
  550.         add     esi, eax
  551.         adc     edx, 0
  552.         mov     eax, ebx
  553.         mov     ebx, esi
  554.         shrd    eax, ebx, 10
  555.         shrd    esi, edx, 10
  556.         mov     edx, esi
  557.  
  558.         pop     esi
  559.         pop     ebx
  560.         ret
  561.  
  562. .old_tics:
  563.         mov     eax, [timer_ticks]
  564.         mov     edx, 10000000
  565.         mul     edx
  566.         ret
  567.