Subversion Repositories Kolibri OS

Rev

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

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