Subversion Repositories Kolibri OS

Rev

Rev 8117 | 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: 8120 $
  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.         mov     eax, [LAPIC_BASE]
  159.         test    eax, eax
  160.         jnz     @f
  161.         stdcall map_io_mem, [acpi_lapic_base], 0x1000, PG_GLOBAL+PG_NOCACHE+PG_SWR
  162.         mov     [LAPIC_BASE], eax
  163. @@:
  164.         mov     esi, eax
  165.  
  166.         ; Program Destination Format Register for Flat mode.
  167.         mov     eax, [esi + APIC_DFR]
  168.         or      eax, 0xf0000000
  169.         mov     [esi + APIC_DFR], eax
  170.  
  171.         ; Program Logical Destination Register.
  172.         mov     eax, [esi + APIC_LDR]
  173.         ;and  eax, 0xff000000
  174.         and     eax, 0x00ffffff
  175.         or      eax, 0x01000000;!!!!!!!!!!!!
  176.         mov     [esi + APIC_LDR], eax
  177.  
  178.         ; Task Priority Register initialization.
  179.         mov     eax, [esi + APIC_TPR]
  180.         and     eax, 0xffffff00
  181.         mov     [esi + APIC_TPR], eax
  182.  
  183.         ; Flush the queue
  184.         mov     edx, 0
  185. .nxt2:
  186.         mov     ecx, 32
  187.         mov     eax, [esi + APIC_ISR + edx]
  188. .nxt:
  189.         shr     eax, 1
  190.         jnc     @f
  191.         mov     dword [esi + APIC_EOI], 0; EOI
  192. @@:
  193.         loop    .nxt
  194.  
  195.         add     edx, 0x10
  196.         cmp     edx, 0x170
  197.         jbe     .nxt2
  198.  
  199.         ; Spurious-Interrupt Vector Register initialization.
  200.         mov     eax, [esi + APIC_SVR]
  201.         or      eax, 0x1ff
  202.         and     eax, 0xfffffdff
  203.         mov     [esi + APIC_SVR], eax
  204.  
  205.         ; Initialize LVT LINT0 register. (INTR)
  206.         mov     eax, 0x00700
  207.         ; mov eax, 0x10700
  208.         mov     [esi + APIC_LVT_LINT0], eax
  209.  
  210.         ; Initialize LVT LINT1 register. (NMI)
  211.         mov     eax, 0x00400
  212.         mov     [esi + APIC_LVT_LINT1], eax
  213.  
  214.         ; Initialize LVT Error register.
  215.         mov     eax, [esi + APIC_LVT_err]
  216.         or      eax, 0x10000; bit 16
  217.         mov     [esi + APIC_LVT_err], eax
  218.  
  219.         ; LAPIC timer
  220.         ; pre init
  221.         mov     dword[esi + APIC_timer_div], 1011b; 1
  222.         mov     dword[esi + APIC_timer_init], 0xffffffff; max val
  223.         push    esi
  224.         mov     esi, 640    ; wait 0.64 sec
  225.         call    delay_ms
  226.         pop     esi
  227.         mov     eax, [esi + APIC_timer_cur]; read current tick couner
  228.         xor     eax, 0xffffffff   ; eax = 0xffffffff - eax
  229.         shr     eax, 6      ; eax /= 64; APIC ticks per 0.01 sec
  230.  
  231.         ; Start (every 0.01 sec)
  232.         mov     dword[esi + APIC_LVT_timer], 0x30020; periodic int 0x20
  233.         mov     dword[esi + APIC_timer_init], eax
  234.  
  235. .done:
  236.         ret
  237.  
  238. ;===========================================================
  239. ; IOAPIC implementation
  240. align 4
  241. IOAPIC_read:
  242. ; in : EAX - IOAPIC register
  243. ; out: EAX - readed value
  244.         push    esi
  245.         mov     esi, [ioapic_cur]
  246.         mov     esi, [IOAPIC_base+esi*4]
  247.         mov     [esi], eax
  248.         mov     eax, [esi + 0x10]
  249.         pop     esi
  250.         ret
  251.  
  252. align 4
  253. IOAPIC_write:
  254. ; in :  EAX - IOAPIC register
  255. ;       EBX - value
  256. ; out:  none
  257.         push    esi
  258.         mov     esi, [ioapic_cur]
  259.         mov     esi, [IOAPIC_base+esi*4]
  260.         mov     [esi], eax
  261.         mov     [esi + 0x10], ebx
  262.         pop     esi
  263.         ret
  264. ;===========================================================
  265. ; Remap all IRQ to 0x20+ Vectors
  266. ; IRQ0 to vector 0x20, IRQ1 to vector 0x21....
  267. align 4
  268. PIC_init:
  269.         mov     [IRQ_COUNT], 16
  270.         cli
  271.         mov     al, 0x11        ;  icw4, edge triggered
  272.         out     0x20, al
  273.         out     0xA0, al
  274.  
  275.         mov     al, 0x20        ;  generate 0x20 +
  276.         out     0x21, al
  277.         mov     al, 0x28        ;  generate 0x28 +
  278.         out     0xA1, al
  279.  
  280.         mov     al, 0x04        ;  slave at irq2
  281.         out     0x21, al
  282.         mov     al, 0x02        ;  at irq9
  283.         out     0xA1, al
  284.  
  285.         mov     al, 0x01        ;  8086 mode
  286.         out     0x21, al
  287.         out     0xA1, al
  288.  
  289.         call    IRQ_mask_all
  290.         ret
  291.  
  292. ; -----------------------------------------
  293. ; TIMER SET TO 1/100 S
  294. align 4
  295. PIT_init:
  296.         mov     al, 0x34   ; set to 100Hz
  297.         out     0x43, al
  298.         mov     al, 0x9b   ; lsb    1193180 / 1193
  299.         out     0x40, al
  300.         mov     al, 0x2e   ; msb
  301.         out     0x40, al
  302.         ret
  303.  
  304. ; -----------------------------------------
  305. align 4
  306. unmask_timer:
  307.         cmp     [irq_mode], IRQ_APIC
  308.         je      @f
  309.  
  310.         stdcall enable_irq, 0
  311.         ret
  312. @@:
  313.         ; use PIT
  314.         ; in some systems PIT no connected to IOAPIC
  315.         ; mov   eax, 0x14
  316.         ; call  IOAPIC_read
  317.         ; mov   ah, 0x09                ; Delivery Mode: Lowest Priority, Destination Mode: Logical
  318.         ; mov   al, 0x20
  319.         ; or    eax, 0x10000            ; Mask Interrupt
  320.         ; mov   ebx, eax
  321.         ; mov   eax, 0x14
  322.         ; call  IOAPIC_write
  323.         ; stdcall enable_irq, 2
  324.         ; ret
  325.  
  326.         ; use LAPIC timer
  327.         mov     esi, [LAPIC_BASE]
  328.         mov     eax, [esi + APIC_LVT_timer]
  329.         and     eax, 0xfffeffff
  330.         mov     [esi + APIC_LVT_timer], eax
  331.         ret
  332.  
  333. ; -----------------------------------------
  334. ; Disable all IRQ
  335. align 4
  336. IRQ_mask_all:
  337.         cmp     [irq_mode], IRQ_APIC
  338.         je      .APIC
  339.  
  340.         mov     al, 0xFF
  341.         out     0x21, al
  342.         out     0xA1, al
  343.         mov     ecx, 0x1000
  344.         ret
  345. .APIC:
  346.         cmp     [IOAPIC_base], 0
  347.         jz      .done
  348.         mov     [ioapic_cur], 0
  349. .next_ioapic:
  350.         mov     edx, [ioapic_cur]
  351.         mov     ecx, [IRQ_COUNT+edx*4]
  352.         mov     eax, 0x10
  353. @@:
  354.         mov     ebx, eax
  355.         call    IOAPIC_read
  356.         or      eax, 0x10000; bit 16
  357.         xchg    eax, ebx
  358.         call    IOAPIC_write
  359.         inc     eax
  360.         inc     eax
  361.         loop    @b
  362.  
  363.         inc     [ioapic_cur]
  364.         inc     edx
  365.         cmp     edx, [ioapic_cnt]
  366.         jnz     .next_ioapic
  367. .done:
  368.         ret
  369.  
  370. ; -----------------------------------------
  371. ; End Of Interrupt
  372. ; cl - IRQ number
  373. align 4
  374. irq_eoi:         ; __fastcall
  375.         cmp     [irq_mode], IRQ_APIC
  376.         je      .APIC
  377.  
  378.         cmp     cl, 8
  379.         mov     al, 0x20
  380.         jb      @f
  381.         out     0xa0, al
  382. @@:
  383.         out     0x20, al
  384.         ret
  385.  
  386. .APIC:
  387.         mov     eax, [LAPIC_BASE]
  388.         mov     dword [eax + APIC_EOI], 0; EOI
  389.         ret
  390.  
  391. ; -----------------------------------------
  392. ; from dll.inc
  393. align 4
  394. proc enable_irq stdcall, irq_line:dword
  395.         mov     ebx, [irq_line]
  396.         cmp     [irq_mode], IRQ_APIC
  397.         je      .APIC
  398.  
  399.         mov     edx, 0x21
  400.         cmp     ebx, 8
  401.         jb      @F
  402.  
  403.         mov     edx, 0xA1
  404.         sub     ebx, 8
  405. @@:
  406.         in      al, dx
  407.         btr     eax, ebx
  408.         out     dx, al
  409.         ret
  410. .APIC:
  411.         push    [ioapic_cur]
  412.         xor     eax, eax
  413. .next_ioapic:
  414.         mov     ecx, [ioapic_gsi_base+eax*4]
  415.         add     ecx, [IRQ_COUNT+eax*4]
  416.         cmp     ebx, ecx
  417.         jb      .found
  418.         inc     eax
  419.         cmp     eax, [ioapic_cnt]
  420.         jnz     .next_ioapic
  421.         jmp     .done
  422. .found:
  423.         mov     [ioapic_cur], eax
  424.         sub     ebx, [ioapic_gsi_base+eax*4]
  425.         shl     ebx, 1
  426.         add     ebx, 0x10
  427.         mov     eax, ebx
  428.         call    IOAPIC_read
  429.         and     eax, 0xfffeffff; bit 16
  430.         xchg    eax, ebx
  431.         call    IOAPIC_write
  432. .done:
  433.         pop     [ioapic_cur]
  434.         ret
  435. endp
  436.  
  437. proc disable_irq stdcall, irq_line:dword
  438.         mov     ebx, [irq_line]
  439.         cmp     [irq_mode], IRQ_APIC
  440.         je      .APIC
  441.  
  442.         mov     edx, 0x21
  443.         cmp     ebx, 8
  444.         jb      @F
  445.  
  446.         mov     edx, 0xA1
  447.         sub     ebx, 8
  448. @@:
  449.         in      al, dx
  450.         bts     eax, ebx
  451.         out     dx, al
  452.         ret
  453. .APIC:
  454.         push    [ioapic_cur]
  455.         xor     eax, eax
  456. .next_ioapic:
  457.         mov     ecx, [ioapic_gsi_base+eax*4]
  458.         add     ecx, [IRQ_COUNT+eax*4]
  459.         cmp     ebx, ecx
  460.         jae     .found
  461.         inc     eax
  462.         cmp     eax, [ioapic_cnt]
  463.         jnz     .next_ioapic
  464.         jmp     .done
  465. .found:
  466.         mov     [ioapic_cur], eax
  467.         sub     ebx, [ioapic_gsi_base+eax*4]
  468.         shl     ebx, 1
  469.         add     ebx, 0x10
  470.         mov     eax, ebx
  471.         call    IOAPIC_read
  472.         or      eax, 0x10000; bit 16
  473.         xchg    eax, ebx
  474.         call    IOAPIC_write
  475. .done:
  476.         pop     [ioapic_cur]
  477.         ret
  478. endp
  479.  
  480. align 4
  481. pci_irq_fixup:
  482.  
  483.         push    ebp
  484.  
  485.         mov     esi, [acpi_dev_data]
  486.         mov     ebx, [acpi_dev_size]
  487.  
  488.         lea     edi, [esi+ebx]
  489.  
  490. .iterate:
  491.  
  492.         cmp     esi, edi
  493.         jae     .done
  494.  
  495.         mov     eax, [esi]
  496.  
  497.         cmp     eax, -1
  498.         je      .done
  499.  
  500.         movzx   ebx, al
  501.         movzx   ebp, ah
  502.  
  503.         stdcall pci_read32, ebp, ebx, 0
  504.  
  505.         cmp     eax, [esi+4]
  506.         jne     .skip
  507.  
  508.         mov     eax, [esi+8]
  509.         stdcall pci_write8, ebp, ebx, 0x3C, eax
  510. .skip:
  511.         add     esi, 16
  512.         jmp     .iterate
  513.  
  514. .done:
  515. .fail:
  516.         pop     ebp
  517.         ret
  518.  
  519. align 4
  520. get_clock_ns:
  521.  
  522.         mov     eax, [hpet_base]
  523.         test    eax, eax
  524.         jz      .old_tics
  525.  
  526.         push    ebx
  527.         push    esi
  528.         pushfd
  529.         cli
  530.  
  531.         mov     ebx, eax
  532. @@:
  533.         mov     edx, [ebx+0xF4]
  534.         mov     eax, [ebx+0xF0]
  535.         mov     ecx, [ebx+0xF4]
  536.         cmp     ecx, edx
  537.         jne     @B
  538.         popfd
  539.  
  540. ;96-bit arithmetic
  541. ;ebx - low dword
  542. ;esi - medium dword
  543. ;edx - high dword
  544.  
  545.         mul     [hpet_period]
  546.         mov     ebx, eax
  547.         mov     esi, edx
  548.  
  549.         mov     eax, ecx
  550.         mul     [hpet_period]
  551.         add     esi, eax
  552.         adc     edx, 0
  553.         mov     eax, ebx
  554.         mov     ebx, esi
  555.         shrd    eax, ebx, 10
  556.         shrd    esi, edx, 10
  557.         mov     edx, esi
  558.  
  559.         pop     esi
  560.         pop     ebx
  561.         ret
  562.  
  563. .old_tics:
  564.         mov     eax, [timer_ticks]
  565.         mov     edx, 10000000
  566.         mul     edx
  567.         ret
  568.